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

📄 umc_mpeg2_muxer_linbuf.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-2006 Intel Corporation. All Rights Reserved.
//
*/

#include "ipps.h"
#include "vm_debug.h"
#include "umc_automatic_mutex.h"
#include "umc_mpeg2_muxer_linbuf.h"

using namespace UMC;

#define IS_WRAPPED (m_iFirstUsedByte > m_iFirstFreeByte)

MPEG2MuxerLinearBuffer::MPEG2MuxerLinearBuffer()
{
    m_pBuf = NULL;
    m_pAllocBuf = NULL;
    m_pFirstUsedSample = NULL;
    m_pFirstFreeSample = NULL;
    m_pLastUsedSample = NULL;
    m_pLastFreeSample = NULL;
    m_uiAlignmentFlags = 0;
    m_uiInputSize = 0;
    m_iBufferSize = 0;
    m_iUsedSize = 0;
    m_iUnusedSizeAtTheEnd = 0;
    m_iFirstFreeByte = 0;
    m_iFirstUsedByte = 0;
    m_uiNOfUsedSamples = 0;
    m_uiNOfAllocatedSamples = 0;
    m_dNextDTS = -1.0;
    m_bEndOfStream = false;
    vm_mutex_set_invalid(&m_synchro);
} //MPEG2MuxerLinearBuffer::MPEG2MuxerLinearBuffer()

MPEG2MuxerLinearBuffer::~MPEG2MuxerLinearBuffer()
{
    Close();

    if (1 == vm_mutex_is_valid(&m_synchro))
        vm_mutex_destroy(&m_synchro);
} //MPEG2MuxerLinearBuffer::~MPEG2MuxerLinearBuffer()

Status MPEG2MuxerLinearBuffer::Init(MediaReceiverParams *pInit)
{
    MPEG2MuxerLinearBufferParams *pParams = DynamicCast<MPEG2MuxerLinearBufferParams> (pInit);

    if (NULL == pParams)
        return UMC_ERR_NULL_PTR;

    if (0 == pParams->uiOfFrames || 0 == pParams->uiBufferSize || 0 == pParams->uiInputSize)
        return UMC_ERR_INVALID_PARAMS;

    Close();

    // init mutex
    if (0 == vm_mutex_is_valid(&m_synchro))
        if (VM_OK != vm_mutex_init(&m_synchro))
            return UMC_ERR_INIT;

    // allocate buffer
    m_iBufferSize = (Ipp32s)pParams->uiBufferSize;
    UMC_ALLOC_ARR(m_pAllocBuf, Ipp8u, m_iBufferSize + m_iMaxOutputSize)

    m_pBuf = m_pAllocBuf + m_iMaxOutputSize;
    m_uiInputSize = pParams->uiInputSize;
    m_uiAlignmentFlags = pParams->uiAlignmentFlags;

    // allocate sample structures
    UMC_NEW(m_pFirstUsedSample, MPEG2MuxerSample);

    m_pFirstFreeSample = m_pLastFreeSample = m_pLastUsedSample = m_pFirstUsedSample;
    for (m_uiNOfAllocatedSamples = 1; m_uiNOfAllocatedSamples < pParams->uiOfFrames; m_uiNOfAllocatedSamples++)
    {
        UMC_NEW(m_pLastFreeSample->pNext, MPEG2MuxerSample);
        m_pLastFreeSample->pNext->pPrev = m_pLastFreeSample;
        m_pLastFreeSample = m_pLastFreeSample->pNext;
    }

    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::Init(MediaReceiverParams *pInit)

Status MPEG2MuxerLinearBuffer::Close(void)
{
    AutomaticMutex guard(m_synchro);

    UMC_FREE(m_pAllocBuf);

    while (m_pFirstUsedSample)
    {
        MPEG2MuxerSample *curSample = m_pFirstUsedSample;
        m_pFirstUsedSample = m_pFirstUsedSample->pNext;
        UMC_DELETE(curSample);
    }

    m_pBuf = NULL;
    m_uiAlignmentFlags = 0;
    m_uiInputSize = 0;
    m_iBufferSize = 0;
    m_iFirstFreeByte = 0;
    m_iFirstUsedByte = 0;
    m_iUsedSize = 0;
    m_iUnusedSizeAtTheEnd = 0;
    m_uiNOfUsedSamples = 0;
    m_uiNOfAllocatedSamples = 0;
    m_dNextDTS = -1.0;
    m_bEndOfStream = false;

    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::Close(void)

Status MPEG2MuxerLinearBuffer::Reset(void)
{
    AutomaticMutex guard(m_synchro);
    m_uiNOfUsedSamples = 0;
    m_iUsedSize = 0;
    m_iUnusedSizeAtTheEnd = 0;
    m_pFirstFreeSample = m_pLastUsedSample = m_pFirstUsedSample;
    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::Reset(void)

Status MPEG2MuxerLinearBuffer::LockInputBuffer(MPEG2MuxerSample *pData)
{
    AutomaticMutex guard(m_synchro);

    // check error(s)
    if (NULL == pData)
        return UMC_ERR_NULL_PTR;

    // case of wrapped data
    if ((IS_WRAPPED) && (m_iFirstFreeByte + m_uiInputSize >= m_iFirstUsedByte))
         return UMC_ERR_NOT_ENOUGH_BUFFER;

    // case of linear data
    if ((!IS_WRAPPED) && (m_iFirstFreeByte + m_uiInputSize > m_iBufferSize))
    {
        // is there enough space at the beginning of buffer?
        if (m_uiInputSize >= m_iFirstUsedByte)
            return UMC_ERR_NOT_ENOUGH_BUFFER;

        m_iUnusedSizeAtTheEnd = m_iBufferSize - m_iFirstFreeByte;
        m_iFirstFreeByte = 0;
    }

    pData->pData = m_pBuf + m_iFirstFreeByte;
    pData->uiSize = IS_WRAPPED ? (m_iFirstUsedByte - m_iFirstFreeByte) : (m_iBufferSize - m_iFirstFreeByte);
    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::LockInputBuffer(MPEG2MuxerSample *pData)

Status MPEG2MuxerLinearBuffer::UnLockInputBuffer(MPEG2MuxerSample *pData, Status streamStatus)
{
    AutomaticMutex guard(m_synchro);

    if (UMC_OK != streamStatus)
    {
        m_bEndOfStream = true;
        return UMC_OK;
    }

    if (NULL == pData)
        return UMC_ERR_NULL_PTR;

    Ipp32s iInputSize = (Ipp32s)pData->uiSize;
    if (iInputSize <= 0)
        return UMC_OK;

    // check if too much data was written (wrapped)
    if ((IS_WRAPPED) && (m_iFirstFreeByte + iInputSize >= m_iFirstUsedByte))
        return UMC_ERR_FAILED;

    // check if too much data was written (linear)
    if ((!IS_WRAPPED) && (m_iFirstFreeByte + iInputSize > m_iBufferSize))
        return UMC_ERR_FAILED;

    m_pFirstFreeSample->pData = m_pBuf + m_iFirstFreeByte;
    m_pFirstFreeSample->uiSize = iInputSize;
    m_pFirstFreeSample->uiTSOffset = pData->uiTSOffset;
    m_pFirstFreeSample->dPTS = pData->dPTS;
    m_pFirstFreeSample->dDTS = pData->dDTS;
    m_pFirstFreeSample->dDuration = pData->dDuration;
    m_pFirstFreeSample->uiFrameType = pData->uiFrameType;
    m_pFirstFreeSample->dExactDTS = (pData->dDTS > 0.0) ? pData->dDTS : (pData->dPTS > 0.0) ? pData->dPTS : m_dNextDTS;
    m_dNextDTS = m_pFirstFreeSample->dExactDTS + m_pFirstFreeSample->dDuration;

    m_uiNOfUsedSamples++;

    if (NULL == m_pFirstFreeSample->pNext)
    {
        //if there is no free sample create new one
        UMC_NEW(m_pFirstFreeSample->pNext, MPEG2MuxerSample);
        m_pLastFreeSample = m_pFirstFreeSample->pNext;
        m_pLastFreeSample->pPrev = m_pFirstFreeSample;
        m_uiNOfAllocatedSamples++;
    }

    m_pFirstFreeSample = m_pFirstFreeSample->pNext;
    m_iFirstFreeByte += iInputSize;
    m_iUsedSize += iInputSize;

    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::UnLockInputBuffer(MPEG2MuxerSample *pData, Status streamStatus)

Status MPEG2MuxerLinearBuffer::LockOutputBuffer(MPEG2MuxerSample *pData)
{
    if (NULL == pData)
        return UMC_ERR_NULL_PTR;

    if (0 == m_uiNOfUsedSamples)
        return UMC_ERR_NOT_ENOUGH_DATA;

    Ipp32s i, iRequestedSize = (Ipp32s)pData->uiSize;
    if (iRequestedSize > m_iUsedSize && !m_bEndOfStream && !m_uiAlignmentFlags)
        return UMC_ERR_NOT_ENOUGH_DATA;

    if ((IS_WRAPPED) && (m_iFirstUsedByte + iRequestedSize > m_iBufferSize - m_iUnusedSizeAtTheEnd))
    { // not enough data at the end in case of wrapped buffer
        Ipp8u *pFrom = m_pBuf + m_iFirstUsedByte;
        Ipp8u *pTo = m_pBuf - (m_iBufferSize - m_iUnusedSizeAtTheEnd - m_iFirstUsedByte);
        Ipp32u uiSize = m_iBufferSize - m_iUnusedSizeAtTheEnd - m_iFirstUsedByte;
        ippsCopy_8u(pFrom, pTo, uiSize);

        // update moved samples
        while (m_pFirstUsedSample->pData >= m_pBuf + m_iFirstUsedByte)
            m_pFirstUsedSample->pData += pTo - pFrom;

        m_iFirstUsedByte = m_iBufferSize;
        m_iUnusedSizeAtTheEnd = 0;
    }

    *pData = *m_pFirstUsedSample;
    pData->pData = m_pFirstUsedSample->pData;
    pData->uiSize = 0;

    bool bIsDataEnough = false;
    MPEG2MuxerSample *pSample = m_pFirstUsedSample;
    for (i = 0; i < (Ipp32s)m_uiNOfUsedSamples; i++)
    { // this loop update real time stamps
        if (pData->dPTS < 0.0 && iRequestedSize - pData->uiSize > (Ipp32s)pSample->uiTSOffset)
        {
            pData->dPTS = pSample->dPTS;
            pData->dDTS = pSample->dDTS;
            pData->uiTSOffset = pData->uiSize + pSample->uiTSOffset;
        }

        pData->uiSize += pSample->uiSize;

        // enough amount of data has been accumulated
        if ((Ipp32s)pData->uiSize >= iRequestedSize)
        {
            pData->uiSize = iRequestedSize;
            bIsDataEnough = true;
            break;
        }

        // check type of next sample (for padding) if exists
        pSample = pSample->pNext;
        if ((pSample->uiSize > 0) && (m_uiAlignmentFlags & pSample->uiFrameType))
        {
            bIsDataEnough = true;
            break;
        }
    }

    if (!bIsDataEnough && !m_bEndOfStream)
        return UMC_ERR_NOT_ENOUGH_DATA;

    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::LockOutputBuffer(MPEG2MuxerSample *pData)

Status MPEG2MuxerLinearBuffer::UnLockOutputBuffer(MPEG2MuxerSample *pData)
{
    if (NULL == pData)
        return UMC_ERR_NULL_PTR;

    Ipp32s iUnlockSize = (Ipp32s)pData->uiSize;
    if (iUnlockSize <= 0)
        return UMC_OK;

    while (m_pFirstUsedSample->uiSize > 0 && (Ipp32s)m_pFirstUsedSample->uiSize <= iUnlockSize)
    { // unlock whole samples
        iUnlockSize -= m_pFirstUsedSample->uiSize;
        m_iUsedSize -= m_pFirstUsedSample->uiSize;
        m_pFirstUsedSample->uiSize = 0;
        m_uiNOfUsedSamples--;

        // update sample links
        m_pLastFreeSample->pNext = m_pFirstUsedSample;
        m_pLastFreeSample->pNext->pPrev = m_pLastFreeSample;
        m_pLastFreeSample = m_pLastFreeSample->pNext;
        m_pFirstUsedSample = m_pFirstUsedSample->pNext;
        m_pFirstUsedSample->pPrev->pNext = NULL;
        m_pFirstUsedSample->pPrev = NULL;
    }

    if (iUnlockSize > 0 && iUnlockSize < (Ipp32s)m_pFirstUsedSample->uiSize)
    { // unlock part of the last sample
        Ipp64f dUnlockTime = ((Ipp64f)iUnlockSize / m_pFirstUsedSample->uiSize) * m_pFirstUsedSample->dDuration;
        m_pFirstUsedSample->dExactDTS += dUnlockTime;
        m_pFirstUsedSample->dDuration -= dUnlockTime;
        m_pFirstUsedSample->uiSize -= iUnlockSize;
        m_pFirstUsedSample->pData += iUnlockSize;
        m_iUsedSize -= iUnlockSize;

        if ((Ipp32s)m_pFirstUsedSample->uiTSOffset >= iUnlockSize)
        {
            m_pFirstUsedSample->uiTSOffset -= iUnlockSize;
        }
        else
        {
            m_pFirstUsedSample->uiTSOffset = 0;
            m_pFirstUsedSample->dPTS = -1.0;
            m_pFirstUsedSample->dDTS = -1.0;
        }
    }

    if (m_uiNOfUsedSamples > 0)
        m_iFirstUsedByte = m_pFirstUsedSample->pData - m_pBuf;
    else
        m_iFirstUsedByte = m_iFirstFreeByte;
    return UMC_OK;
} //Status MPEG2MuxerLinearBuffer::UnLockOutputBuffer(MPEG2MuxerSample *pData)

⌨️ 快捷键说明

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