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

📄 umc_avs_splitter_buffer.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 2 页
字号:

    // unlock the main buffer
    return m_mainBuffer.UnLockOutputBuffer(&m_latestSample);

} // Status AVSSampleBuffer::UnLockOutputBuffer(MediaData *pSrc)

void AVSSampleBuffer::CollectStartCodes(size_t nSourceSize)
{
    Ipp8u *pbSource = m_pbSampleEnd;

    // update end of the being collected sample
    m_pbSampleEnd += nSourceSize;

    // set up pointer to the beginning of the current frame
    {
        size_t iRollBack = IPP_MIN(pbSource - m_pbSample, 3);

        // roll back the pointer a little bit
        // to handle splitted start codes
        pbSource -= iRollBack;
    }

    // check amount of data
    if (4 > (m_pbSampleEnd - pbSource))
        return;

    // skip first 3 bytes
    pbSource += 3;

    // try to find all start codes
    do
    {
        // we can skip 3 bytes when
        // the previous byte is greater than 1
        if (1 < pbSource[-1])
        {
            pbSource += 3;
        }
        // we can skip 2 bytes when
        // two precending the previous byte byte is not 0
        else if (0 < pbSource[-2])
        {
            pbSource += 2;
        }
        // in other case we have to analyze stream byte by byte
        else
        {
            if (1 == pbSource[-1])
            {
                if (0 == pbSource[-3])
                {
                    // fill start code's info
                    m_startCodes[m_iNumberOfStartCodes].m_startCode = pbSource[0];
                    m_startCodes[m_iNumberOfStartCodes].m_startCodeOffset = (Ipp32u) (pbSource - 3 - m_pbSample);

                    // increment number of start codes
                    m_iNumberOfStartCodes += 1;

                    pbSource += 3;
                }
                else
                {
                    pbSource += 2;
                }
            }

            pbSource += 1;
        }

    } while (pbSource < m_pbSampleEnd);

    // we have read garbage
    if (0 == m_iNumberOfStartCodes)
    {
        size_t iRollBack = IPP_MIN(m_pbSample - m_pbBuffer, 3);

        m_pbSample = m_pbSampleEnd - iRollBack;
    }

} // void AVSSampleBuffer::CollectStartCodes(size_t nSourceSize)

Status AVSSampleBuffer::MoveCollectedSample(Status streamStatus)
{
    Ipp32s iNALUnits;
    Status umcRes;

    // sometimes we need to set 'EOB' having zero data
    if ((UMC_OK != streamStatus) &&
        (0 == m_iNumberOfStartCodes))
    {
        m_mainBuffer.UnLockInputBuffer(NULL, UMC_ERR_END_OF_STREAM);
        return UMC_OK;
    }

    // move collected samples to the main buffer
    iNALUnits = GetNALUnitsNumber();
    while (iNALUnits)
    {
        size_t nSampleSize, nEncodedDataSize;
        MediaData mediaDst;
        Ipp32s i;

        // calculate the sample's size
        nEncodedDataSize = m_startCodes[iNALUnits].m_startCodeOffset -
                           m_startCodes[0].m_startCodeOffset;
        nSampleSize = align_value<size_t> (nEncodedDataSize, sizeof(Ipp32u)) +
                      sizeof(Ipp32u) * (iNALUnits * 2 + 2);

        // get the destination
        umcRes = m_mainBuffer.LockInputBuffer(&mediaDst, nSampleSize);
        if (UMC_OK != umcRes)
            return umcRes;

        // copy sample & start codes' info
        {
            Ipp8u *pbDst = (Ipp8u *) mediaDst.GetBufferPointer();
            Ipp32u *pCodes;

            // copy sample
            memcpy(pbDst, m_pbSample + m_startCodes[0].m_startCodeOffset, nEncodedDataSize);
            pbDst += nEncodedDataSize;

            // align destination pointer
            while ((pbDst - (Ipp8u *) 0) & 3)
            {
                *pbDst = 0;
                pbDst += 1;
            }

            // copy start codes
            pCodes = (Ipp32u *) pbDst;
            for (i = 0; i < iNALUnits; i += 1)
            {
                pCodes[i] = m_startCodes[i].m_startCode;
                pCodes[i + iNALUnits] = m_startCodes[i].m_startCodeOffset - m_startCodes[0].m_startCodeOffset;
            }
            // set the number of start codes
            pCodes[iNALUnits * 2] = iNALUnits;
            // set the real data size
            pCodes[iNALUnits * 2 + 1] = (Ipp32u) nEncodedDataSize;
        }

        // finalize the sample
        mediaDst.SetDataSize(nSampleSize);
        m_mainBuffer.UnLockInputBuffer(&mediaDst, streamStatus);

        // update array of start codes
        SkipStartCodes(iNALUnits);

        // try to find the next sample
        iNALUnits = GetNALUnitsNumber();
    }

    // update the temporal buffer, move collected data to the beginning
    if (m_pbSample != m_pbBuffer)
    {
        Ipp8u *pbSrc, *pbDst;
        size_t nAvailable, nMaxChunk;

        nAvailable = m_pbSampleEnd - m_pbSample;
        nMaxChunk = m_pbSample - m_pbBuffer;
        pbDst = m_pbBuffer;
        pbSrc = m_pbSample;

        while (nAvailable)
        {
            size_t nToCopy = IPP_MIN(nMaxChunk, nAvailable);

            memcpy(pbDst, pbSrc, nToCopy);
            pbDst += nToCopy;
            pbSrc += nToCopy;
            nAvailable -= nToCopy;
        }

        m_pbSampleEnd = m_pbBuffer + (m_pbSampleEnd - m_pbSample);
        m_pbSample = m_pbBuffer;
    }

    return UMC_OK;

} // Status AVSSampleBuffer::MoveCollectedSample(Status streamStatus)

void AVSSampleBuffer::SkipStartCodes(Ipp32s numCodes)
{
    Ipp32s i;
    size_t nAdvanceSize;

    // check the following code
    if (VIDEO_SEQUENCE_END_CODE == m_startCodes[numCodes].m_startCode)
    {
        // skip filled buffer
        nAdvanceSize = m_startCodes[numCodes].m_startCodeOffset + sizeof(Ipp32u);
        numCodes += 1;
    }
    else
    {
        nAdvanceSize = m_startCodes[numCodes].m_startCodeOffset;
    }

    // skip filled buffer
    m_pbSample += nAdvanceSize;

    // skip codes info
    for (i = 0; i < (m_iNumberOfStartCodes - numCodes); i += 1)
    {
        m_startCodes[i].m_startCode = m_startCodes[i + numCodes].m_startCode;
        m_startCodes[i].m_startCodeOffset = (Ipp32u) (m_startCodes[i + numCodes].m_startCodeOffset - nAdvanceSize);
    }
    m_iNumberOfStartCodes -= numCodes;

} // void AVSSampleBuffer::SkipStartCodes(Ipp32s numCodes)

Ipp32s AVSSampleBuffer::GetNALUnitsNumber(void)
{
    Ipp32s i;
    bool bFoundPictureHeader = false;
    bool bFoundSequenceHeader = false;
    bool bFoundSlice = false;
    bool bPictureDone = false;

    if (0 >= m_iNumberOfStartCodes)
        return 0;

    // find the first slice start code or second other header
    for (i = 0; i < m_iNumberOfStartCodes; i += 1)
    {
        switch (m_startCodes[i].m_startCode)
        {
        case VIDEO_SEQUENCE_START_CODE:
            // the picture is complete, when it is not the first NAL unit
            if (i)
                bPictureDone = true;
            else
            {
                bFoundSequenceHeader = true;
                m_bFoundSequenceHeader = true;
            }
            break;

        case VIDEO_SEQUENCE_END_CODE:
            bPictureDone = true;
            break;

        case USER_DATA_START_CODE:
            // picture data before user data is not allowed
            if (bFoundSlice)
                bPictureDone = true;
            break;

        case I_PICTURE_START_CODE:
            // two header per frame is not allowed
            if ((bFoundSlice) || (bFoundPictureHeader))
                bPictureDone = true;
            else
                bFoundPictureHeader = true;
            break;

        case EXTENSION_START_CODE:
            // picture data before extension data is not allowed
            if (bFoundSlice)
                bPictureDone = true;
            break;

        case BP_PICTURE_START_CODE:
            if ((bFoundSlice) || (bFoundPictureHeader))
                bPictureDone = true;
            else
                bFoundPictureHeader = true;
            break;

        case VIDEO_EDIT_CODE:
            // video edit code shall be the beginning
            if ((bFoundSlice) || (bFoundPictureHeader))
                bPictureDone = true;
            break;

        // slices data
        default:
            // we should provide a sequence header as a single frame
            if ((bFoundSequenceHeader) && (false == bFoundPictureHeader))
                bPictureDone = true;
            else if (LAST_SLICE_START_CODE >= m_startCodes[i].m_startCode)
                bFoundSlice = true;
            break;
        }

        // is the picture composed
        if (bPictureDone)
        {
            // frame is incomplete.
            // there are only two conditions:
            // we found a sequence header or
            // we found a picture header and a sequence header had been found before
            if ((bFoundSequenceHeader) ||
                (bFoundPictureHeader && m_bFoundSequenceHeader))
                return i;
            else
            {
                SkipStartCodes(i);

                // try to compose another frame
                i = -1;
                bFoundPictureHeader = false;
                bFoundSequenceHeader = false;
                bFoundSlice = false;
                bPictureDone = false;
            }
        }
    }

    return 0;

} // Ipp32s AVSSampleBuffer::GetNALUnitsNumber(void)

} // namespace UMC

#endif // #if defined(UMC_ENABLE_AVS_SPLITTER)

⌨️ 快捷键说明

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