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

📄 umc_sample_buffer.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_linear_buffer.h"
#include "umc_sample_buffer.h"
#include "umc_automatic_mutex.h"

namespace UMC
{

enum
{
    ALIGN_VALUE                 = 128
};

MediaBuffer *CreateSampleBuffer(void)
{
    return new SampleBuffer();

} // MediaBuffer *CreateSampleBuffer(void)

SampleBuffer::SampleBuffer(void)
{
    // reset variables
    m_pbAllocatedBuffer = NULL;
    m_midAllocatedBuffer = MID_INVALID;
    m_lAllocatedBufferSize = 0;
    m_pbBuffer = NULL;
    m_lBufferSize = 0;
    m_pbFree = NULL;
    m_lFreeSize = 0;
    m_pbUsed = NULL;
    m_lUsedSize = 0;
    m_pSamples = NULL;

    m_bEndOfStream = false;
    m_bQuit = false;

    // reset the mutex
    vm_mutex_set_invalid(&m_synchro);

} // SampleBuffer::SampleBuffer(void)

SampleBuffer::~SampleBuffer(void)
{
    Close();

    // destroy mutex
    if (1 == vm_mutex_is_valid(&m_synchro))
        vm_mutex_destroy(&m_synchro);

} // SampleBuffer::~SampleBuffer(void)

Status SampleBuffer::Close(void)
{
    // stop all waiting(s)
    // actually, this method does nothing
    Stop();

    // delete buffer
    if (m_pbAllocatedBuffer)
        m_pMemoryAllocator->Unlock(m_midAllocatedBuffer);
    if (MID_INVALID != m_midAllocatedBuffer)
        m_pMemoryAllocator->Free(m_midAllocatedBuffer);
    m_midAllocatedBuffer = MID_INVALID;

    // reset variables
    m_pbAllocatedBuffer = NULL;
    m_lAllocatedBufferSize = 0;
    m_pbBuffer = NULL;
    m_lBufferSize = 0;
    m_pbFree = NULL;
    m_lFreeSize = 0;
    m_pbUsed = NULL;
    m_lUsedSize = 0;
    m_pSamples = NULL;

    m_bEndOfStream = false;
    m_bQuit = false;

    // call the parent's method
    MediaBuffer::Close();

    return UMC_OK;

} // Status SampleBuffer::Close(void)

Status SampleBuffer::Init(MediaReceiverParams *init)
{
    size_t lAllocate, lMaxSampleSize;
    MediaBufferParams *pParams = DynamicCast<MediaBufferParams> (init);
    Status umcRes;

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

    if ((0 == pParams->m_numberOfFrames) ||
        (0 == pParams->m_prefInputBufferSize))
        return UMC_ERR_INIT;

    // release the object before initialization
    Close();

    // call the parent's method
    umcRes = MediaBuffer::Init(init);
    if (UMC_OK != umcRes)
        return umcRes;

    m_Params = *pParams;
    // init the mutex
    if (0 == vm_mutex_is_valid(&m_synchro))
    {
        if (VM_OK != vm_mutex_init(&m_synchro))
            return UMC_ERR_INIT;
    }

    // allocate buffer
    lMaxSampleSize = IPP_MAX(pParams->m_prefInputBufferSize, pParams->m_prefOutputBufferSize) +
                     ALIGN_VALUE + sizeof(SampleInfo);
    lAllocate = lMaxSampleSize * IPP_MAX(pParams->m_numberOfFrames, 3);
    if (UMC_OK != m_pMemoryAllocator->Alloc(&m_midAllocatedBuffer, lAllocate + ALIGN_VALUE, UMC_ALLOC_PERSISTENT, 16))
        return UMC_ERR_ALLOC;
    m_pbAllocatedBuffer = (Ipp8u *) m_pMemoryAllocator->Lock(m_midAllocatedBuffer);
    if (NULL == m_pbAllocatedBuffer)
        return UMC_ERR_ALLOC;
    m_lAllocatedBufferSize = lAllocate + ALIGN_VALUE;

    // align buffer
    m_pbBuffer = align_pointer<Ipp8u *> (m_pbAllocatedBuffer, ALIGN_VALUE);
    m_lBufferSize = lAllocate;

    m_pbFree = m_pbBuffer;
    m_lFreeSize = m_lBufferSize;
    m_pbUsed = m_pbBuffer;
    m_lUsedSize = 0;

    // save preferred size(s)
    m_lInputSize = pParams->m_prefInputBufferSize;
    return UMC_OK;

} // Status SampleBuffer::Init(MediaReceiverParams *init)

Status SampleBuffer::LockInputBuffer(MediaData* in)
{
    AutomaticMutex guard(m_synchro);
    size_t lFreeSize;
    bool bAtEnd = false;

    // check error(s)
    if (NULL == in)
        return UMC_ERR_NULL_PTR;
    if (NULL == m_pbFree)
        return UMC_ERR_NOT_INITIALIZED;

    // get free size
    if (m_pbFree >= m_pbBuffer + (m_lBufferSize - m_lFreeSize))
    {
        lFreeSize = m_pbBuffer + m_lBufferSize - m_pbFree;
        bAtEnd = true;
    }
    else
        lFreeSize = m_lFreeSize;

    // check free size
    if (lFreeSize < m_lInputSize + ALIGN_VALUE + sizeof(SampleInfo))
    {
        if (false == bAtEnd)
            return UMC_ERR_NOT_ENOUGH_BUFFER;
        // free space at end is too small
        else
        {
            // when used data is present,
            // concatenate dummy bytes to the last sample info
            if (m_pSamples)
            {
                SampleInfo *pTemp;

                // find last sample info
                pTemp = m_pSamples;
                while (pTemp->m_pNext)
                    pTemp = pTemp->m_pNext;
                pTemp->m_lBufferSize += lFreeSize;

                // update variable(s)
                m_pbFree = m_pbBuffer;
                m_lFreeSize -= lFreeSize;

                // need to call Unlock to avoid double locking of
                // the mutex
                guard.Unlock();
                // and call again to lock space at the
                // beginning of the buffer
                return LockInputBuffer(in);
            }
            // when no used data,
            // simply move pointer(s)
            else
            {
                m_pbFree = m_pbBuffer;
                m_pbUsed = m_pbBuffer;
                lFreeSize = m_lFreeSize;
            }
        }
    }

    // set free pointer
    in->SetBufferPointer(m_pbFree, lFreeSize - ALIGN_VALUE - sizeof(SampleInfo));
    in->SetDataSize(0);
    return UMC_OK;

} // Status SampleBuffer::LockInputBuffer(MediaData* in)

Status SampleBuffer::UnLockInputBuffer(MediaData* in, Status StreamStatus)
{
    AutomaticMutex guard(m_synchro);
    size_t lFreeSize;
    SampleInfo *pTemp;
    Ipp8u *pb;

    // check END OF STREAM
    if (UMC_OK != StreamStatus)
        m_bEndOfStream = true;

    // check error(s)
    if (NULL == in)
        return UMC_ERR_NULL_PTR;
    if (NULL == m_pbFree)
        return UMC_ERR_NOT_INITIALIZED;

    // when no data is given
    if (0 == in->GetDataSize())
        return UMC_OK;

    // get free size
    if (m_pbFree >= m_pbBuffer + (m_lBufferSize - m_lFreeSize))
        lFreeSize = m_pbBuffer + m_lBufferSize - m_pbFree;
    else
        lFreeSize = m_lFreeSize;

    // check free size
    if (lFreeSize < m_lInputSize)
        return UMC_ERR_NOT_ENOUGH_BUFFER;

    // check used data
    if (in->GetDataSize() + ALIGN_VALUE + sizeof(SampleInfo) > lFreeSize)
        return UMC_ERR_FAILED;

    // get new sample info
    pb = align_pointer<Ipp8u *> (m_pbFree + in->GetDataSize(), ALIGN_VALUE);
    pTemp = reinterpret_cast<SampleInfo *> (pb);

    // fill sample info
    in->GetTime(pTemp->m_dTime, pTemp->m_dTimeAux);
    pTemp->m_FrameType = in->GetFrameType();
    pTemp->m_lBufferSize = align_value<size_t> (pb + sizeof(SampleInfo) - m_pbFree, ALIGN_VALUE);
    pTemp->m_lDataSize = in->GetDataSize();
    pTemp->m_pbData = m_pbFree;
    pTemp->m_pNext = NULL;

    // add sample to end of queue
    if (m_pSamples)
    {
        SampleInfo *pWork = m_pSamples;

        while (pWork->m_pNext)
            pWork = pWork->m_pNext;

        pWork->m_pNext = pTemp;
    }
    else
        m_pSamples = pTemp;

    // update variable(s)
    m_pbFree += pTemp->m_lBufferSize;
    if (m_pbBuffer + m_lBufferSize == m_pbFree)
        m_pbFree = m_pbBuffer;
    m_lFreeSize -= pTemp->m_lBufferSize;
    m_lUsedSize += pTemp->m_lDataSize;

    return UMC_OK;

} // Status SampleBuffer::UnLockInputBuffer(MediaData* in, Status StreamStatus)

Status SampleBuffer::LockOutputBuffer(MediaData* out)
{
    AutomaticMutex guard(m_synchro);

    // check error(s)
    if (NULL == out)
        return UMC_ERR_NULL_PTR;
    if (NULL == m_pbUsed)
        return UMC_ERR_NOT_INITIALIZED;

    // when END OF STREAM
    if (m_bEndOfStream)
    {
        // time to exit
        if ((m_bQuit) || (0 == m_lUsedSize))
        {
            // reset variables
            m_pbFree = m_pbBuffer;
            m_lFreeSize = m_lBufferSize;
            m_pbUsed = m_pbBuffer;
            m_lUsedSize = 0;
            m_pSamples = NULL;

            return UMC_ERR_END_OF_STREAM;
        }
        // set the last "lock output" request
        else
            m_bQuit = true;
    }

    if (NULL == m_pSamples)
        return UMC_ERR_NOT_ENOUGH_DATA;

    // set used pointer
    out->SetBufferPointer(m_pbUsed, m_pSamples->m_lDataSize);
    out->SetDataSize(m_pSamples->m_lDataSize);
    out->SetTime(m_pSamples->m_dTime, m_pSamples->m_dTimeAux);
    out->SetFrameType(m_pSamples->m_FrameType);
    return UMC_OK;

} // Status SampleBuffer::LockOutputBuffer(MediaData* out)

Status SampleBuffer::UnLockOutputBuffer(MediaData* out)
{
    AutomaticMutex guard(m_synchro);
    size_t lToSkip;

    // check error(s)
    if (NULL == out)
        return UMC_ERR_NULL_PTR;
    if (NULL == m_pbUsed)
        return UMC_ERR_NOT_INITIALIZED;

    // when END OF STREAM
    if (m_bEndOfStream)
        m_bQuit = false;

    // when 0 bytes to unlock
    lToSkip = out->GetBufferSize() - out->GetDataSize();
    if (0 == lToSkip)
        return UMC_OK;

    // no filled data is present
    if (NULL == m_pSamples)
        return UMC_ERR_FAILED;

    // error occurs
    if (lToSkip > m_pSamples->m_lDataSize)
        return UMC_ERR_FAILED;

    // skip part of sample
    if (lToSkip < m_pSamples->m_lDataSize)
    {
        // update variable(s)
        m_lFreeSize += lToSkip;
        m_pbUsed += lToSkip;
        m_lUsedSize -= lToSkip;

        m_pSamples->m_lBufferSize -= lToSkip;
        m_pSamples->m_lDataSize -= lToSkip;
        m_pSamples->m_dTime = out->GetTime();
    }
    // skip whole sample
    else
    {
        // update variable(s)
        m_lFreeSize += m_pSamples->m_lBufferSize;
        m_pbUsed += m_pSamples->m_lBufferSize;
        if (m_pbBuffer + m_lBufferSize == m_pbUsed)
            m_pbUsed = m_pbBuffer;
        m_lUsedSize -= m_pSamples->m_lDataSize;

        m_pSamples = m_pSamples->m_pNext;
    }
    return UMC_OK;

} // Status SampleBuffer::UnLockOutputBuffer(MediaData* out)

Status SampleBuffer::Stop(void)
{
    return UMC_OK;

} // Status SampleBuffer::Stop(void)

Status SampleBuffer::Reset(void)
{
    AutomaticMutex guard(m_synchro);

    // reset variables
    m_pbFree = m_pbBuffer;
    m_lFreeSize = m_lBufferSize;
    m_pbUsed = m_pbBuffer;
    m_lUsedSize = 0;

    m_pSamples = NULL;

    m_bEndOfStream = false;
    m_bQuit = false;

    return UMC_OK;

} //Status SampleBuffer::Reset(void)

Status SampleBuffer::DumpState()
{
  AutomaticMutex guard(m_synchro);
  SampleInfo *pTemp;
  double timeFirst = -1, timeLast = -1;
  int numSamples = 0;

  if (m_pSamples) timeFirst = m_pSamples->m_dTime;

  // find last sample info
  for (pTemp = m_pSamples; pTemp != NULL; pTemp = pTemp->m_pNext) {
    //fprintf(f, " (%.2f,%.2f)", pTemp->m_dTime, pTemp->m_dTimeAux);
    timeLast = pTemp->m_dTime;
    numSamples++;
  }

  vm_debug_trace_i(VM_DEBUG_PROGRESS, m_lBufferSize);
  vm_debug_trace_f(VM_DEBUG_PROGRESS, 100.0*m_lFreeSize/m_lBufferSize);
  vm_debug_trace_f(VM_DEBUG_PROGRESS, 100.0*(m_lInputSize + sizeof(SampleInfo))/m_lBufferSize);
  vm_debug_trace_i(VM_DEBUG_PROGRESS, numSamples);
  vm_debug_trace_f(VM_DEBUG_PROGRESS, timeFirst);
  vm_debug_trace_f(VM_DEBUG_PROGRESS, timeLast);

  /*
  vm_debug_trace_ex(VM_DEBUG_PROGRESS,
    VM_STRING("SampleBuffer::DumpState"),
    NULL, NULL, 0,
    VM_STRING("size %d, free %.2f%%, need %.2f%%, num samples %d, time: first %.2f, last %.2f"),
    m_lBufferSize,
    100.0*m_lFreeSize/m_lBufferSize,
    100.0*(m_lInputSize + sizeof(SampleInfo))/m_lBufferSize,
    numSamples,
    timeFirst,
    timeLast
    );
*/
  return UMC_OK;
}

} // namespace UMC

⌨️ 快捷键说明

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