⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umc_dual_thread_codec.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
字号:
/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//       Copyright(c) 2003-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_dual_thread_codec.h"
#include "vm_debug.h"
#include "vm_time.h"

namespace UMC
{

BaseCodec *CreateBufferingCodec(BaseCodec   *pCodec,
                                MediaBuffer *pInputBuffer,
                                MediaBuffer *pOutputBuffer)
{
    DualThreadedCodec *pBufferingCodec = new DualThreadedCodec;

    if (!pBufferingCodec) return NULL;

    if (UMC_OK != pBufferingCodec->Init(pCodec, pInputBuffer, pOutputBuffer))
    {
        UMC_DELETE(pBufferingCodec);
        return NULL;
    }

    return pBufferingCodec;
}

DualThreadCodecParams::DualThreadCodecParams()
{
    m_pMediaBufferParams = NULL;
    m_pMediaBuffer = NULL;
    m_pCodecInitParams = NULL;
    m_pCodec = NULL;

}

DualThreadedCodec::DualThreadedCodec(void)
{
    m_pCodec = NULL;
    m_pInputBuffer = NULL;
    m_pOutputBuffer = NULL;
    m_pPostponedParams = NULL;
    m_bDeleteResourcesOnClose = false;
    m_bGetFrameLoop = false;
}

DualThreadedCodec::~DualThreadedCodec(void)
{
    DualThreadedCodec::Close();
}

Status DualThreadedCodec::InitCodec(DualThreadCodecParams* init)
{
    BaseCodecParams    CodecParams;
    Status umcRes;

    // release codec
    Close();

    // check parameter(s)
    if ((NULL == init) ||
        (NULL == init->m_pCodec) ||
        (NULL == init->m_pMediaBuffer) ||
        (NULL == init->m_pCodecInitParams) || // really can be NULL for MP3 decoder
        (NULL == init->m_pMediaBufferParams)) // must keep at least number of frames
        return UMC_ERR_NULL_PTR;

    // init audio codec
    umcRes = init->m_pCodec->Init(init->m_pCodecInitParams);
    if (umcRes != UMC_OK) {
        vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed in m_pCodec->Init!\n"));
        return umcRes;
    }

    // get SuggestedInputSize
    umcRes = init->m_pCodec->GetInfo(&CodecParams);
    if (umcRes != UMC_OK) {
        vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed in m_pCodec->GetInfo!\n"));
        return umcRes;
    }

    // initialize media buffer

    // to have the possibility to increase InputSize from the app
    if (CodecParams.m_SuggestedInputSize > init->m_pMediaBufferParams->m_prefInputBufferSize)
        init->m_pMediaBufferParams->m_prefInputBufferSize = CodecParams.m_SuggestedInputSize;

    init->m_pMediaBufferParams->m_prefOutputBufferSize = CodecParams.m_SuggestedInputSize;

    umcRes = init->m_pMediaBuffer->Init(init->m_pMediaBufferParams);
    if (umcRes != UMC_OK) {
        vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed in m_pMediaBuffer->Init!\n"));
        return umcRes;
    }

    // save pointer(s)
    m_pCodec = init->m_pCodec;
    m_pInputBuffer = init->m_pMediaBuffer;

    return umcRes;
} // Status DualThreadedCodec::InitCodec(DualThreadCodecParams* init)

Status DualThreadedCodec::Init(BaseCodec   *pCodec,
                               MediaBuffer *pInputBuffer,
                               MediaBuffer *pOutputBuffer)
{
    UMC_CHECK_PTR(pCodec);

    m_pCodec = pCodec;
    m_pInputBuffer = pInputBuffer;
    m_pOutputBuffer = pOutputBuffer;

    m_bDeleteResourcesOnClose = true; //!!!
    m_bGetFrameLoop = true; //!!!

    if (pInputBuffer == NULL) m_bGetFrameLoop = false;

    return UMC_OK;
}

static MediaData** GetPointerToData(BaseCodecParams *pCodecParams)
{
    if (NULL != pCodecParams)
    {
       return &pCodecParams->m_pData;
    }
    return NULL;
}

Status DualThreadedCodec::Init(BaseCodecParams *pCodecParams)
{
    MediaData **ppData;
    UMC_CHECK(m_pCodec, UMC_ERR_NOT_INITIALIZED);

    ppData = GetPointerToData(pCodecParams);

    if (m_pInputBuffer && ppData && *ppData) // use postponed codec init
    {
        UMC_CALL(PutDataToBuffer(m_pInputBuffer, *ppData));
        *ppData = NULL;
        m_pPostponedParams = pCodecParams; // save pCodecParams for postponed Init()
        return PostponedInit();
    }
    else
    {
        return m_pCodec->Init(pCodecParams);
    }
}

Status DualThreadedCodec::PostponedInit()
{
    MediaData tmp[1];
    Status umcRes = UMC_OK;

    UMC_CHECK(m_pPostponedParams, UMC_OK);

    umcRes = m_pInputBuffer->LockOutputBuffer(tmp);
    if (UMC_ERR_NOT_ENOUGH_DATA == umcRes)
    {
        return UMC_OK;
    }
    UMC_CHECK_STATUS(umcRes);

    MediaData **ppData = GetPointerToData(m_pPostponedParams);
    UMC_CHECK_PTR(ppData);
    *ppData = tmp;

    UMC_CALL(m_pCodec->Init(m_pPostponedParams));
    *ppData = NULL;

    //UMC_CALL(
    m_pCodec->GetInfo(m_pPostponedParams);

    // Here means succesful initialiazation
    UMC_CALL(m_pInputBuffer->UnLockOutputBuffer(tmp));
    m_pPostponedParams = NULL;

    return UMC_OK;
}

Status DualThreadedCodec::GetFrame(MediaData *in, MediaData *out)
{
    MediaData *pInputData = in;
    MediaData *pOutputData = out;
    Status umcRes = UMC_OK;

    UMC_CHECK(m_pCodec, UMC_ERR_NOT_INITIALIZED);

    // Put data to InputBuffer
    if (m_pInputBuffer && in && in->GetDataSize())
    {
        umcRes = PutDataToBuffer(m_pInputBuffer, in);
    }

    if (m_pPostponedParams)
    {
        UMC_CALL(PostponedInit());
        if (m_pPostponedParams) return UMC_ERR_NOT_INITIALIZED; // not inilized yet
        return UMC_ERR_NOT_ENOUGH_DATA; // codec was initialized, waiting for data
    }

    // Lock output data
    if (m_pOutputBuffer && UMC_OK == umcRes)
    {
        umcRes = m_pOutputBuffer->LockInputBuffer(m_pTmpOutput);
        if (UMC_OK == umcRes) {
            pOutputData = m_pTmpOutput;
        }
    }

    // GetFrame
    if (UMC_OK == umcRes)
    {
        char s[256];
        double dStartTime = -1;
        int out_size = 0;

        for (;;)
        {
            bool bLocked = false;
            umcRes = UMC_OK;

            // Lock input data
            if (m_pInputBuffer)
            {
                pInputData = m_pTmpInput;
                umcRes = m_pInputBuffer->LockOutputBuffer(m_pTmpInput);
                bLocked = (UMC_OK == umcRes);
            }

            if (!pInputData->GetDataSize() && m_bGetFrameLoop)
            {
                umcRes = UMC_ERR_NOT_ENOUGH_DATA;
            }

            if (UMC_OK == umcRes)
            {
#ifdef VM_DEBUG
                sprintf(s, "BBB: %4d %.3f\n", pInputData->GetDataSize(), pInputData->GetTime());
                vm_debug_trace1(VM_DEBUG_VERBOSE, VM_STRING("##### %s"), s);
#endif
                umcRes = m_pCodec->GetFrame(pInputData, pOutputData);
            }

            // Unlock input data
            if (bLocked) // if input buffer was locked
            {
                if ((Ipp8u*)pInputData->GetDataPointer() != (Ipp8u*)pInputData->GetBufferPointer())
                {
                    m_pInputBuffer->UnLockOutputBuffer(pInputData);
                }
#if 0
                else if (pInputData->GetDataSize())
                {
                    umcRes = UMC_ERR_NOT_ENOUGH_DATA;
                }
#endif
            }

            if (UMC_OK != umcRes)
            {
                break;
            }

            if (!out_size)
            {
                dStartTime = pOutputData->GetTime();
            }

            int curr_size = pOutputData->GetDataSize();
            out_size += curr_size;
            pOutputData->MoveDataPointer(curr_size);

            if (!m_bGetFrameLoop)
            {
                break;
            }
        }

        if (out_size)
        {
            umcRes = UMC_OK;
            pOutputData->MoveDataPointer(-out_size);
            // correct start time
            double dTmp = -1, dEndTime = -1;
            pOutputData->GetTime(dTmp, dEndTime);
            pOutputData->SetTime(dStartTime, dEndTime);
#ifdef VM_DEBUG
            sprintf(s + strlen(s), " -> %4d %.3f -> (umcRes %d) (size %4d) %.3f - %.3f",
            pInputData->GetDataSize(), pInputData->GetTime(),
            umcRes, pOutputData->GetDataSize(), dStartTime, dEndTime);
            vm_debug_trace1(VM_DEBUG_VERBOSE, VM_STRING("##### %s"), s);
#endif
        }
    }

    // Unlock output data
    if (pOutputData == m_pTmpOutput) // if output buffer was locked
    {
        m_pOutputBuffer->UnLockInputBuffer(pOutputData);
    }

    // Get data from OutputBuffer
    if (m_pOutputBuffer && out && UMC_OK == umcRes)
    {
        umcRes = GetDataFromBuffer(m_pOutputBuffer, out);
    }

    return umcRes;
}

Status DualThreadedCodec::GetInfo(BaseCodecParams *info)
{
    UMC_CHECK(m_pCodec, UMC_ERR_NOT_INITIALIZED);
    UMC_CHECK(NULL == m_pPostponedParams, UMC_ERR_NOT_INITIALIZED);
    return m_pCodec->GetInfo(info);
}

Status DualThreadedCodec::Close(void)
{
    if (m_bDeleteResourcesOnClose)
    {
        UMC_DELETE(m_pCodec);
        UMC_DELETE(m_pInputBuffer);
        UMC_DELETE(m_pOutputBuffer);
    }
    return UMC_OK;
}

Status DualThreadedCodec::Reset(void)
{
    UMC_CHECK(m_pCodec, UMC_ERR_NOT_INITIALIZED);
    if (m_pInputBuffer)
    {
        m_pInputBuffer->Reset();
    }
    if (m_pOutputBuffer)
    {
        m_pOutputBuffer->Reset();
    }
    return m_pCodec->Reset();
}

Status DualThreadedCodec::SetParams(BaseCodecParams *params)
{
    UMC_CHECK(m_pCodec, UMC_ERR_NOT_INITIALIZED);
    return m_pCodec->SetParams(params);
}

Status DualThreadedCodec::LockInputBuffer(MediaData* in)
{
    UMC_CHECK(m_pInputBuffer, UMC_ERR_NOT_INITIALIZED);
    return m_pInputBuffer->LockInputBuffer(in);
}

Status DualThreadedCodec::UnLockInputBuffer(MediaData* in, Status StreamStatus)
{
    UMC_CHECK(m_pInputBuffer, UMC_ERR_NOT_INITIALIZED);
    return m_pInputBuffer->UnLockInputBuffer(in, StreamStatus);
}

Status DualThreadedCodec::GetFrame(MediaData* out)
{
    return GetFrame(NULL, out);
}

Status PutDataToBuffer(MediaBuffer *pBuffer, MediaData* in, Status StreamStatus)
{
    MediaData tmp[1];
    *tmp = *in;
    UMC_CALL(pBuffer->LockInputBuffer(tmp));
    UMC_CALL(in->MoveDataTo(tmp));
    //UMC_CALL( !!!
    pBuffer->UnLockInputBuffer(tmp, StreamStatus);
    UMC_CALL(in->SetTime(-1, -1)); // timestamps become incorrect after MoveDataTo()
    return UMC_OK;
}

Status GetDataFromBuffer(MediaBuffer *pBuffer, MediaData* out)
{
    MediaData tmp[1];
    UMC_CALL(pBuffer->LockOutputBuffer(tmp));
    UMC_CALL(tmp->MoveDataTo(out));
    UMC_CALL(pBuffer->UnLockOutputBuffer(tmp));
    return UMC_OK;
}

} // namespace UMC

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -