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

📄 umc_mpeg2_muxer_chunk.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
//
//              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 "ipps.h"
#include "ippdc.h"
#include "vm_debug.h"
#include "umc_mpeg2_muxer_chunk.h"

using namespace UMC;


/*
 * MPEG2ChunkWriter
 */

MPEG2ChunkWriter::MPEG2ChunkWriter()
{
    m_pDataWriter = NULL;
} //MPEG2ChunkWriter::MPEG2ChunkWriter()

MPEG2ChunkWriter::~MPEG2ChunkWriter()
{
    Close();
} //MPEG2ChunkWriter::~MPEG2ChunkWriter()

Status MPEG2ChunkWriter::Close(void)
{
    MPEG2MuxerLinearBuffer::Close();

    m_pDataWriter = NULL;
    m_ESType = MPEG2MUX_ES_UNKNOWN;
    m_dReferenceClock = 0.0;
    m_uiMuxRate = 0;
    m_dFrameRate = 0.0;
    m_uiBitRate = 0;
    return UMC_OK;
} //Status MPEG2ChunkWriter::Close(void)

Status MPEG2ChunkWriter::Init(MediaReceiverParams *pInit)
{
    UMC_CALL(MPEG2MuxerLinearBuffer::Init(pInit));

    MPEG2ChunkWriterParams *pParams = DynamicCast<MPEG2ChunkWriterParams>(pInit);
    if (!pParams || !pParams->pDataWriter)
        return UMC_ERR_NULL_PTR;

    m_pDataWriter = pParams->pDataWriter;
    m_ESType = pParams->esType;
    m_dFrameRate = pParams->dFrameRate;
    m_uiBitRate = pParams->uiBitRate;
    return UMC_OK;
} //Status MPEG2ChunkWriter::Init(MediaReceiverParams *pInit)

void MPEG2ChunkWriter::SetReferenceClock(Ipp64f dReferenceClock)
{
    m_dReferenceClock = dReferenceClock;
} //void MPEG2ChunkWriter::SetReferenceClock(Ipp64f dReferenceClock)

void MPEG2ChunkWriter::SetMuxRate(Ipp32u uiMuxRate)
{
    m_uiMuxRate = uiMuxRate;
} //void MPEG2ChunkWriter::SetMuxRate(Ipp32u uiMuxRate)

Status MPEG2ChunkWriter::GetOutputTime(Ipp64f &dTime)
{
    if (m_uiNOfUsedSamples < 1)
        return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;

    dTime = m_pFirstUsedSample->dExactDTS;
    return UMC_OK;
} //Status MPEG2ChunkWriter::GetOutputTime(Ipp64f &dTime)

Status MPEG2ChunkWriter::LockInputBuffer(MediaData *pData)
{
    Status umcRes;
    MPEG2MuxerSample sample;

    umcRes = MPEG2MuxerLinearBuffer::LockInputBuffer(&sample);
    pData->SetBufferPointer(sample.pData, sample.uiSize);
    return umcRes;
} //Status MPEG2ChunkWriter::LockInputBuffer(MediaData *pData)

Status MPEG2ChunkWriter::UnLockInputBuffer(MediaData *pData, Status streamStatus)
{
    if (UMC_OK != streamStatus)
        return MPEG2MuxerLinearBuffer::UnLockInputBuffer(NULL, streamStatus);

    MPEG2MuxerSample sample;
    pData->GetTime(sample.dPTS, sample.dDTS);

    // DTS should not be more or equal PTS
    if (sample.dDTS >= sample.dPTS)
        sample.dDTS = -1.0;

    // DTS should not present for non-video streams
    if (!IsVideo(m_ESType))
        sample.dDTS = -1.0;

    // first sample should have valid time stamp and it should be not earlier than 0.3 sec
    Ipp64f time = sample.dDTS > 0.0 ? sample.dDTS : sample.dPTS;
    if (m_dNextDTS < 0.0 && time < 0.0 && m_ESType != MPEG2MUX_ES_UNKNOWN)
        return UMC_ERR_INVALID_PARAMS;

    sample.uiFrameType = TYPE_UNDEF; // should be assigned for video frames
    sample.pData = (Ipp8u *)pData->GetDataPointer();
    sample.uiSize = pData->GetDataSize();
    sample.uiTSOffset = 0; // should refer to picture start code for video frames

    // estimate duration of the sample
    if (IsVideo(m_ESType))
    {
        sample.dDuration = 1.0 / m_dFrameRate;
        SetFrameTypeAndOffset(&sample);
    }
    else
        sample.dDuration = (8.0 * sample.uiSize) / m_uiBitRate;

    return MPEG2MuxerLinearBuffer::UnLockInputBuffer(&sample, streamStatus);
} //Status MPEG2ChunkWriter::UnLockInputBuffer(MediaData *pData, Status streamStatus)

Status MPEG2ChunkWriter::WriteChunk(void)
{
    if (m_uiNOfUsedSamples == 0)
        return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;

    Ipp8u *pBuf = m_pFirstUsedSample->pData;
    Ipp32s uiSize = (Ipp32s)m_pFirstUsedSample->uiSize;
    UMC_CALL(m_pDataWriter->PutData(pBuf, uiSize));

    return UnLockOutputBuffer(m_pFirstUsedSample);
} //Status MPEG2ChunkWriter::WriteChunk(void)

void MPEG2ChunkWriter::SetFrameTypeAndOffset(MPEG2MuxerSample *pData)
{
    Ipp8u *pBuf = pData->pData;
    Ipp32u uiSize = pData->uiSize;
    Ipp32u uiPos = 0;

    if (MPEG2MUX_ES_MPEG1_VIDEO == m_ESType ||
        MPEG2MUX_ES_MPEG2_VIDEO == m_ESType)
    {
        for (uiPos = 0; uiPos + 5 < uiSize; uiPos++)
        {
            if (pBuf[uiPos + 0] == 0x00 &&
                pBuf[uiPos + 1] == 0x00 &&
                pBuf[uiPos + 2] == 0x01 &&
                pBuf[uiPos + 3] == 0x00)
            {
                FrameType type = (FrameType)((pBuf[uiPos + 5] >> 3) & 0x07);
                if (I_PICTURE == type)
                    pData->uiFrameType = TYPE_I_PIC;
                else if (P_PICTURE == type)
                    pData->uiFrameType = TYPE_P_PIC;
                else if (B_PICTURE == type)
                    pData->uiFrameType = TYPE_B_PIC;
                else
                    pData->uiFrameType = TYPE_UNDEF;

                pData->uiTSOffset = uiPos;
                break;
            }
        }
    }
    else if (MPEG2MUX_ES_MPEG4_VIDEO == m_ESType)
    {
        for (uiPos = 0; uiPos + 4 < uiSize; uiPos++)
        {
            if (pBuf[uiPos + 0] == 0x00 &&
                pBuf[uiPos + 1] == 0x00 &&
                pBuf[uiPos + 2] == 0x01 &&
                pBuf[uiPos + 3] == 0xb6)
            {
                FrameType type = (FrameType)((pBuf[uiPos + 4] >> 6) + 1);
                if (I_PICTURE == type)
                    pData->uiFrameType = TYPE_I_PIC;
                else if (P_PICTURE == type)
                    pData->uiFrameType = TYPE_P_PIC;
                else if (B_PICTURE == type)
                    pData->uiFrameType = TYPE_B_PIC;
                else
                    pData->uiFrameType = TYPE_UNDEF;

                pData->uiTSOffset = uiPos;
                break;
            }
        }
    }
    else if (MPEG2MUX_ES_H264_VIDEO == m_ESType)
    {
        for (uiPos = 0; uiPos + 4 < uiSize; uiPos++)
        {
            if (pBuf[uiPos + 0] == 0x00 &&
                pBuf[uiPos + 1] == 0x00 &&
                pBuf[uiPos + 2] == 0x00 &&
                pBuf[uiPos + 3] == 0x01 &&
                ((pBuf[uiPos + 4] & 0x1f) == 0x01 || (pBuf[uiPos + 4] & 0x1f) == 0x05))
            {
                if ((pBuf[uiPos + 4] & 0x1f) == 0x05)
                    pData->uiFrameType = TYPE_I_PIC;
                else
                    pData->uiFrameType = TYPE_UNDEF;

                pData->uiTSOffset = uiPos;
                break;
            }
        }
    }
} //void MPEG2ChunkWriter::SetFrameTypeAndOffset(MPEG2MuxerSample *pData)

/*
 * MPEG2PSChunkWriter
 */

MPEG2PSChunkWriter::MPEG2PSChunkWriter(void)
{
    m_pHeaderBuf = NULL;
    m_pSystemStreamID = NULL;
    m_pSystemBoundScale = NULL;
    m_pSystemSizeBound = NULL;
} //MPEG2PSChunkWriter::MPEG2PSChunkWriter(void)

MPEG2PSChunkWriter::~MPEG2PSChunkWriter(void)
{
    Close();
} //MPEG2PSChunkWriter::~MPEG2PSChunkWriter(void)

Status MPEG2PSChunkWriter::Close(void)
{
    MPEG2ChunkWriter::Close();

    m_uiPacketSize = 0;
    m_uiSpecialHeaderSize = 0;
    m_uiPackHeaderSize = 0;

    // System header section
    m_uiSystemHeaderSize = 0;
    m_uiSystemHeaderLength = 0;
    m_uiSystemRateBound = 0;
    m_uiSystemAudioBound = 0;
    m_uiSystemVideoBound = 0;
    m_uiSystemNumberOfStreams = 0;

    UMC_FREE(m_pHeaderBuf);
    UMC_FREE(m_pSystemStreamID);
    UMC_FREE(m_pSystemBoundScale);
    UMC_FREE(m_pSystemSizeBound);

    m_uiStreamID = 0;
    m_uiSubStreamID = 0;
    m_uiOffset = 0;
    m_uiNextOffset = 0;
    m_uiNOfFrames = 0;
    m_uiFrameNumber = 0;

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

Status MPEG2PSChunkWriter::Init(MediaReceiverParams *pInit)
{
    UMC_CALL(MPEG2ChunkWriter::Init(pInit));

    MPEG2PSChunkWriterParams *pParams = DynamicCast<MPEG2PSChunkWriterParams>(pInit);
    UMC_CHECK_PTR(pParams);

    m_uiSpecialHeaderSize = 0;
    if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
        m_uiSpecialHeaderSize = 7;
    else if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
        m_uiSpecialHeaderSize = 4;

    m_uiPacketSize = IPP_MAX(pParams->uiPacketSize, MPEG2MUX_CHUNK_HEADER_SIZE);

    UMC_ALLOC_ARR(m_pHeaderBuf, Ipp8u, MPEG2MUX_CHUNK_HEADER_SIZE);
    m_uiHeaderBufSize = 0;

    // Pack header section
    m_uiPackHeaderSize = pParams->bPackHeaderPresent ? 14 : 0;
    m_dReferenceClock = 0.0;
    m_uiMuxRate = 0;

    // System header section
    m_uiSystemHeaderSize = 0;
    m_uiSystemHeaderLength = 0;

    // PES header section
    m_uiStreamID = pParams->uiStreamID;
    m_uiSubStreamID = pParams->uiSubStreamID;
    return UMC_OK;
} //Status MPEG2PSChunkWriter::Init(MediaReceiverParams *pInit)

Status MPEG2PSChunkWriter::SetSystemHeaderParams(SystemHeaderParams *pSysHeaderParams)
{
    UMC_CHECK_PTR(pSysHeaderParams);
    UMC_CHECK_PTR(pSysHeaderParams->pSystemStreamID);
    UMC_CHECK_PTR(pSysHeaderParams->pSystemSizeBound);

    // System header section
    m_uiSystemHeaderSize = 0;
    m_uiSystemHeaderLength = 0;
    m_uiSystemRateBound = pSysHeaderParams->uiSystemRateBound;
    m_uiSystemAudioBound = pSysHeaderParams->uiSystemAudioBound;
    m_uiSystemVideoBound = pSysHeaderParams->uiSystemVideoBound;
    m_uiSystemNumberOfStreams = pSysHeaderParams->uiSystemNumberOfStreams;
    m_uiSystemHeaderLength = 6 + 3 * m_uiSystemNumberOfStreams;

    UMC_ALLOC_ARR(m_pSystemStreamID, Ipp32u, m_uiSystemNumberOfStreams);
    UMC_ALLOC_ARR(m_pSystemSizeBound, Ipp32u, m_uiSystemNumberOfStreams);
    UMC_ALLOC_ARR(m_pSystemBoundScale, Ipp32u, m_uiSystemNumberOfStreams);

    ippsCopy_32s((Ipp32s *)pSysHeaderParams->pSystemStreamID, (Ipp32s *)m_pSystemStreamID, m_uiSystemNumberOfStreams);
    ippsCopy_32s((Ipp32s *)pSysHeaderParams->pSystemSizeBound, (Ipp32s *)m_pSystemSizeBound, m_uiSystemNumberOfStreams);

    Ipp32u i;
    for (i = 0; i < m_uiSystemNumberOfStreams; i++)
    {
        m_pSystemBoundScale[i] = 1; // means video
        if (m_pSystemStreamID[i] == 0xb8 ||
            m_pSystemStreamID[i] == 0xbf ||
            m_pSystemStreamID[i] >= 0xc0 && m_pSystemStreamID[i] <= 0xdf)
            m_pSystemBoundScale[i] = 0; // means audio
        m_pSystemSizeBound[i] /= m_pSystemBoundScale[i] ? 1024 : 128;
    }

    return UMC_OK;
} //Status MPEG2PSChunkWriter::SetSystemHeaderParams(SystemHeaderParams *pSysHeaderParams)

void MPEG2PSChunkWriter::ToggleSystemHeader(void)
{
    m_uiSystemHeaderSize = 6 + m_uiSystemHeaderLength;
} //void MPEG2PSChunkWriter::ToggleSystemHeader(void)

void MPEG2PSChunkWriter::GenerateNonPESHeaders(void)
{
    AdvancedBitStream bs;

    if (m_uiPackHeaderSize)
    {
        bs.Reset(m_pHeaderBuf, MPEG2MUX_CHUNK_HEADER_SIZE);

        Ipp32u scrExt = (Ipp32u)(((Ipp64u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ)) % 300);
        Ipp64u scrBase = ((Ipp64u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ)) / 300;

        bs.AddBits(0x000001BA, 32);                         // pack_start_code
        bs.AddBits(0x01, 2);                                // 01
        bs.AddBits((Ipp32u)((scrBase >> 30) & 0x7), 3);     // system_clock_reference_base [32..30]
        bs.AddBits(0x01, 1);                                // marker_bit
        bs.AddBits((Ipp32u)((scrBase >> 15) & 0x7FFF), 15); // system_clock_reference_base [29..15]
        bs.AddBits(0x01, 1);                                // marker_bit
        bs.AddBits((Ipp32u)(scrBase & 0x7FFF), 15);         // system_clock_reference_base [14..0]
        bs.AddBits(0x01, 1);                                // marker_bit
        bs.AddBits(scrExt & 0x1FF, 9);                      // system_clock_reference_extension
        bs.AddBits(0x01, 1);                                // marker_bit
        bs.AddBits(m_uiMuxRate / 50, 22);                   // program_mux_rate
        bs.AddBits(0x01, 1);                                // marker_bit
        bs.AddBits(0x01, 1);                                // marker_bit
        bs.AddBits(0x1f, 5);                                // reserved
        bs.AddBits(0x00, 3);                                // pack_stuffing_length

        m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
    }

    if (m_uiSystemHeaderSize > 0)
    {
        bs.Reset(&m_pHeaderBuf[m_uiHeaderBufSize], MPEG2MUX_CHUNK_HEADER_SIZE - m_uiHeaderBufSize);

        bs.AddBits(0x000001BB, 32);               // pack_start_code
        bs.AddBits(m_uiSystemHeaderLength, 16);   // header_length
        bs.AddBits(0x01, 1);                      // marker_bit
        bs.AddBits(m_uiSystemRateBound / 50, 22); // rate_bound
        bs.AddBits(0x01, 1);                      // marker_bit
        bs.AddBits(m_uiSystemAudioBound, 6);      // audio_bound
        bs.AddBits(0x00, 1);                      // fixed_flag
        bs.AddBits(0x00, 1);                      // CSPS_flag
        bs.AddBits(0x00, 1);                      // system_audio_lock_flag
        bs.AddBits(0x00, 1);                      // system_video_lock_flag
        bs.AddBits(0x01, 1);                      // marker_bit
        bs.AddBits(m_uiSystemVideoBound, 5);      // video_bound
        bs.AddBits(0x00, 1);                      // packet_rate_restriction_flag
        bs.AddBits(0x7f, 7);                      // reserved_byte

        Ipp32u i;
        for (i = 0; i < m_uiSystemNumberOfStreams; i++)
        {
            bs.AddBits(m_pSystemStreamID[i], 8);   // stream_id
            bs.AddBits(0x3, 2);                    // '11'
            bs.AddBits(m_pSystemBoundScale[i], 1); // P-STD_buffer_bound_scale
            bs.AddBits(m_pSystemSizeBound[i], 13); // P-STD_buffer_size_bound
        }

        m_uiSystemHeaderSize = 0;
        m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
    }
} //void MPEG2PSChunkWriter::GenerateNonPESHeaders(void)

void MPEG2PSChunkWriter::GeneratePESHeader(void)
{
    AdvancedBitStream bs;
    bs.Reset(&m_pHeaderBuf[m_uiHeaderBufSize], MPEG2MUX_CHUNK_HEADER_SIZE - m_uiHeaderBufSize);

    bs.AddBits(0x000001, 24);               // PES start code
    bs.AddBits(m_uiStreamID, 8);            // stream_id
    bs.AddBits(m_uiPESPacketLength, 16);    // PES_packet_length
    bs.AddBits(0x02, 2);                    // '10'

⌨️ 快捷键说明

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