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

📄 umc_mpeg2_muxer_chunk.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        if (m_uiPESPacketLength > 0xFFFF)
            m_uiPESPacketLength = 0;

        uiMaxPayloadSize -= m_uiSpecialHeaderSize;
        uiMaxPayloadSize -= m_uiPESHeaderDataLength; // PTS/DTS
        uiMaxPayloadSize -= 3; // PES flags and PES_header_data_length field
        uiMaxPayloadSize -= 6; // PES_start_code and PES_packet_length

        // prepare special header fields
        if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
        {
            m_uiNOfFrames = (payload.uiSize - m_uiOffset + MPEG2MUX_LPCM_FRAME_SIZE - 1) / MPEG2MUX_LPCM_FRAME_SIZE;
            m_uiNextOffset = m_uiOffset + m_uiNOfFrames * MPEG2MUX_LPCM_FRAME_SIZE - payload.uiSize;
        }
    }

    if (payload.uiSize < uiMaxPayloadSize)
    { // frame (or rest of frame) is smaller than available space
        if (0x03 == m_uiAdaptFieldCtrl)
        { // adapration field already exists, just add stuffing bytes
            m_uiNOfTSStuffingBytes = (Ipp8u)(m_uiNOfTSStuffingBytes + uiMaxPayloadSize - payload.uiSize);
            m_uiAdaptFieldLen = (Ipp8u)(m_uiAdaptFieldLen + m_uiNOfTSStuffingBytes);
        }
        else
        { // adapration field is needed to add stuffing bytes
            m_uiAdaptFieldCtrl = 0x03;
            m_uiAdaptFieldLen = (Ipp8u)(uiMaxPayloadSize - payload.uiSize - 1);
            if (m_uiAdaptFieldLen > 0)
                m_uiNOfTSStuffingBytes = m_uiAdaptFieldLen - 1;
        }
    }
    else
    {
        payload.uiSize = uiMaxPayloadSize;
    }

    if ((MPEG2MUX_ES_LPCM_AUDIO == m_ESType) && (payload.uiSize & 1))
    { // even number of byte of LPCM should be written
        payload.uiSize--;
        m_uiNOfStuffingBytes++;
        m_uiPESHeaderDataLength++;
    }

    return UMC_OK;
} //Status MPEG2TSChunkWriter::PrepareChunk(void)

void MPEG2TSChunkWriter::GenerateNonPESHeaders(void)
{
    AdvancedBitStream bs;
    bs.Reset(m_pHeaderBuf, MPEG2MUX_CHUNK_HEADER_SIZE);

    bs.AddBits(0x47, 8);                // sync_byte
    bs.AddBits(0x00, 1);                // transport_error_indicator
    bs.AddBits(m_uiStartIndicator, 1);  // payload_unit_start_indicator
    bs.AddBits(0x00, 1);                // transport_priority
    bs.AddBits(m_uiPID, 13);            // PID
    bs.AddBits(0x00, 2);                // transport_scrambling_control
    bs.AddBits(m_uiAdaptFieldCtrl, 2);  // adaptation_field_control
    bs.AddBits(m_uiCounter, 4);         // continuity_counter

    if (0x03 == m_uiAdaptFieldCtrl)
    {
        bs.AddBits(m_uiAdaptFieldLen, 8);   // adaptation_field_length

        if (m_uiAdaptFieldLen > 0)
        {
            bs.AddBits(0x00, 1);            // discontinuity_indicator
            bs.AddBits(0x00, 1);            // random_access_indicator
            bs.AddBits(0x00, 1);            // elementary_stream_priority_indicator
            bs.AddBits(m_uiPCRFlag, 1);     // PCR_flag
            bs.AddBits(0x00, 1);            // OPCR_flag
            bs.AddBits(0x00, 1);            // splicing_point_flag
            bs.AddBits(0x00, 1);            // transport_private_data_flag
            bs.AddBits(0x00, 1);            // adaptation_field_extension_flag

            if (m_uiPCRFlag)
            {
                Ipp64u pcr = (Ipp64u)(m_dPCR * 27000000 + 0.5);
                Ipp64u pcr_base = (pcr / 300) & CONST_LL(0x1FFFFFFFF);
                Ipp32u pcr_ext = (Ipp32u)((pcr % 300) & 0x1FF);

                bs.AddBits((Ipp32s)(pcr_base >> 32), 1);         // program_clock_reference_base[32..32]
                bs.AddBits((Ipp32s)(pcr_base & 0xFFFFFFFF), 32); // program_clock_reference_base[31..0]
                bs.AddBits(0x3F, 6);                             // reserved
                bs.AddBits((pcr_ext), 9);                        // program_clock_reference_extension
            }

            Ipp32u i;
            for (i = 0; i < m_uiNOfTSStuffingBytes; i++)
                bs.AddBits(0xFF, 8);        // stuffing byte
        }
    }

    m_uiCounter = (m_uiCounter + 1) & 0x0f;
    m_uiHeaderBufSize = bs.m_lpb - bs.m_lpbBuffer;
} //void MPEG2TSChunkWriter::GenerateNonPESHeaders(void)

void MPEG2TSChunkWriter::GenerateSpecialHeader(void)
{
    if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
    {
        AdvancedBitStream bs;
        bs.Reset(&m_pHeaderBuf[m_uiHeaderBufSize], MPEG2MUX_CHUNK_HEADER_SIZE - m_uiHeaderBufSize);

        bs.AddBits(m_uiNOfFrames, 8);   // number_of_frames
        bs.AddBits(m_uiOffset + 4, 16); // first_access_unit_pointer (4)
        bs.AddBits(0x00, 1);            // emphasis_flag (off)
        bs.AddBits(0x00, 1);            // mute_flag (off)
        bs.AddBits(0x00, 1);            // reserved
        bs.AddBits(m_uiFrameNumber, 5); // number_of_frame
        bs.AddBits(0x00, 2);            // sample_size_code (16bit)
        bs.AddBits(0x00, 2);            // sample_rate_code (48k)
        bs.AddBits(0x09, 4);            // number_of_channels_code (dual_mono)
        bs.AddBits(0x80, 8);            // dynamic_range_control

        // update special header fields
        m_uiFrameNumber = (m_uiFrameNumber + m_uiNOfFrames) % 20;
        m_uiOffset = m_uiNextOffset;
        m_uiNOfFrames = 0;
        m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
    }
} //void MPEG2TSChunkWriter::GenerateSpecialHeader(void)

Status MPEG2TSChunkWriter::WriteChunk(void)
{
    UMC_CALL(PrepareChunk());

    GenerateNonPESHeaders();
    if (m_uiStartIndicator && m_ESType != MPEG2MUX_ES_VBI_DATA)
    {
        GeneratePESHeader();
        if (m_uiSpecialHeaderSize > 0)
            GenerateSpecialHeader();
    }

    // write headers
    Ipp32s iToWrite = (Ipp32s)m_uiHeaderBufSize;
    UMC_CALL(m_pDataWriter->PutData(m_pHeaderBuf, iToWrite));

#ifndef _BIG_ENDIAN_
    if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
        ippsSwapBytes_16u_I((Ipp16u *)payload.pData, payload.uiSize / 2);
#endif

    // write payload data
    iToWrite = (Ipp32s)payload.uiSize;
    UMC_CALL(m_pDataWriter->PutData(payload.pData, iToWrite));

    m_uiStartIndicator = 0;
    return UnLockOutputBuffer(&payload);
} //Status MPEG2TSChunkWriter::WriteChunk(void)


/*
 * PATTableWriter
 */

PATTableWriter::PATTableWriter()
{
    m_iNOfPrograms = 0;
    m_pProgramPID = NULL;
    m_pHeaderBuf = NULL;
    m_uiCounter = 0;
} //PATTableWriter::PATTableWriter()

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

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

    UMC_FREE(m_pHeaderBuf);
    UMC_FREE(m_pProgramPID);

    m_iNOfPrograms = 0;
    m_uiCounter = 0;
    return UMC_OK;
} //Status PATTableWriter::Close(void)

Status PATTableWriter::Init(MediaReceiverParams *pInit)
{
    //DO NOT initialize linear buffer here
    Close();

    PATTableWriterParams *pParams = DynamicCast<PATTableWriterParams>(pInit);
    UMC_CHECK_PTR(pParams);
    UMC_CHECK_PTR(pParams->pDataWriter);
    UMC_CHECK_PTR(pParams->pProgramPID);

    m_pDataWriter = pParams->pDataWriter;
    m_iNOfPrograms = pParams->iNOfPrograms;
    UMC_CHECK(m_iNOfPrograms > 0, UMC_ERR_INVALID_PARAMS);
    UMC_ALLOC_ARR(m_pProgramPID, Ipp16u, m_iNOfPrograms);
    ippsCopy_16s((Ipp16s *)pParams->pProgramPID, (Ipp16s *)m_pProgramPID, m_iNOfPrograms);

    UMC_ALLOC_ARR(m_pHeaderBuf, Ipp8u, MPEG2MUX_TS_PACKET_LENGTH);
    ippsSet_8u(0xFF, m_pHeaderBuf, MPEG2MUX_TS_PACKET_LENGTH);

    AdvancedBitStream bs;
    bs.Reset(m_pHeaderBuf, MPEG2MUX_TS_PACKET_LENGTH);

    // write Program Association Table
    bs.AddBits(0x47, 8);                        // sync_byte
    bs.AddBits(0x00, 1);                        // transport_error_indicator
    bs.AddBits(0x01, 1);                        // payload_unit_start_indicator
    bs.AddBits(0x00, 1);                        // transport_priority
    bs.AddBits(0x00, 13);                       // PID
    bs.AddBits(0x00, 2);                        // transport_scrambling_control
    bs.AddBits(0x01, 2);                        // adaptation_field_control
    bs.AddBits(m_uiCounter, 4);                 // continuity_counter
    bs.AddBits(0x00, 8);                        // pointer_field
    bs.AddBits(0x00, 8);                        // table_id
    bs.AddBits(0x01, 1);                        // section_syntax_indicator
    bs.AddBits(0x00, 1);                        // '0'
    bs.AddBits(0x03, 2);                        // reserved
    bs.AddBits(4 * m_iNOfPrograms + 9, 12);     // section_length
    bs.AddBits(0x00, 16);                       // transport_stream_id
    bs.AddBits(0x03, 2);                        // reserved
    bs.AddBits(0x00, 5);                        // version_number
    bs.AddBits(0x01, 1);                        // current_next_indicator
    bs.AddBits(0x00, 8);                        // section_number
    bs.AddBits(0x00, 8);                        // last_section_number

    Ipp32s i;
    for (i = 0; i < m_iNOfPrograms; i++)
    {
        bs.AddBits(i + 1, 16);                  // program_number
        bs.AddBits(0x07, 3);                    // reserved
        bs.AddBits(m_pProgramPID[i], 13);       // program_map_PID
    }

    Ipp32u uiCRCDataLen = 4 * m_iNOfPrograms + 8;
    Ipp32u uiCRC32 = 0;
    ippsCRC32_BZ2_8u(bs.m_lpb - uiCRCDataLen, uiCRCDataLen, &uiCRC32);
    uiCRC32 ^= 0xFFFFFFFF;
    bs.AddBits(uiCRC32, 32);                    // CRC_32

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

Status PATTableWriter::WriteChunk(void)
{
    Ipp32s iToWrite = MPEG2MUX_TS_PACKET_LENGTH;
    Status umcRes = m_pDataWriter->PutData(m_pHeaderBuf, iToWrite);

    AdvancedBitStream bs;
    bs.Reset(m_pHeaderBuf, MPEG2MUX_TS_PACKET_LENGTH);

    // update continuity_counter
    m_uiCounter = (m_uiCounter + 1) & 0x0f;
    bs.SkipBits(8 + 1 + 1 + 1 + 13 + 2 + 2);
    bs.AddBits(m_uiCounter, 4);
    return umcRes;
} //Status PATTableWriter::WriteChunk(void)

/*
 * PMTTableWriter
 */

PMTTableWriter::PMTTableWriter()
{
    m_pStreamType = NULL;
    m_pPID = NULL;
    m_pHeaderBuf = NULL;
} //PMTTableWriter::PMTTableWriter()

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

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

    UMC_FREE(m_pHeaderBuf);
    UMC_FREE(m_pStreamType);
    UMC_FREE(m_pPID);

    m_uiProgramPID = 0;
    m_uiProgramNumber = 0;
    m_uiNOfStreams = 0;
    m_uiPCRPID = 0;
    m_uiCounter = 0;
    return UMC_OK;
} //Status PMTTableWriter::Close(void)

Status PMTTableWriter::Init(MediaReceiverParams *pInit)
{
    //DO NOT initialize linear buffer here
    Close();

    PMTTableWriterParams *pParams = DynamicCast<PMTTableWriterParams>(pInit);

    UMC_CHECK_PTR(pParams);
    UMC_CHECK_PTR(pParams->pDataWriter);
    UMC_CHECK_PTR(pParams->pStreamType);
    UMC_CHECK_PTR(pParams->pPID);
    UMC_CHECK(pParams->uiNOfStreams > 0, UMC_ERR_INVALID_PARAMS);

    m_pDataWriter = pParams->pDataWriter;
    m_uiNOfStreams = pParams->uiNOfStreams;
    m_uiProgramNumber = pParams->uiProgramNumber;
    m_uiProgramPID = pParams->uiProgramPID;
    m_uiPCRPID = pParams->uiPCRPID;

    UMC_ALLOC_ARR(m_pStreamType, MPEG2MuxerESType, m_uiNOfStreams);
    UMC_ALLOC_ARR(m_pPID, Ipp32u, m_uiNOfStreams);
    UMC_ALLOC_ARR(m_pHeaderBuf, Ipp8u, MPEG2MUX_TS_PACKET_LENGTH);

    ippsCopy_8u((Ipp8u *)pParams->pStreamType, (Ipp8u *)m_pStreamType, m_uiNOfStreams * sizeof(MPEG2MuxerESType));
    ippsCopy_32s((Ipp32s *)pParams->pPID, (Ipp32s *)m_pPID, m_uiNOfStreams);
    ippsSet_8u(0xFF, m_pHeaderBuf, MPEG2MUX_TS_PACKET_LENGTH);

    AdvancedBitStream bs;
    bs.Reset(m_pHeaderBuf, MPEG2MUX_TS_PACKET_LENGTH);

    // write Program Map Table
    bs.AddBits(0x47, 8);                        // sync_byte
    bs.AddBits(0x00, 1);                        // transport_error_indicator
    bs.AddBits(0x01, 1);                        // payload_unit_start_indicator
    bs.AddBits(0x00, 1);                        // transport_priority
    bs.AddBits(m_uiProgramPID, 13);             // PID
    bs.AddBits(0x00, 2);                        // transport_scrambling_control
    bs.AddBits(0x01, 2);                        // adaptation_field_control
    bs.AddBits(m_uiCounter, 4);                 // continuity_counter
    bs.AddBits(0x00, 8);                        // pointer_field
    bs.AddBits(0x02, 8);                        // table_id
    bs.AddBits(0x01, 1);                        // section_syntax_indicator
    bs.AddBits(0x00, 1);                        // '0'
    bs.AddBits(0x03, 2);                        // reserved
    bs.AddBits(13 + 5 * m_uiNOfStreams, 12);    // section_length
    bs.AddBits(m_uiProgramNumber, 16);          // program_number
    bs.AddBits(0x03, 2);                        // reserved
    bs.AddBits(0x00, 5);                        // version_number
    bs.AddBits(0x01, 1);                        // current_next_indicator
    bs.AddBits(0x00, 8);                        // section_number
    bs.AddBits(0x00, 8);                        // last_section_number
    bs.AddBits(0x07, 3);                        // reserved
    bs.AddBits(m_uiPCRPID, 13);                 // PRC_PID
    bs.AddBits(0x0F, 4);                        // reserved
    bs.AddBits(0x00, 12);                       // program_info_length

    Ipp32u uiNum;
    for (uiNum = 0; uiNum < m_uiNOfStreams; uiNum++)
    {
        bs.AddBits(m_pStreamType[uiNum],  8);   // stream_type
        bs.AddBits(0x07,  3);                   // reserved
        bs.AddBits(m_pPID[uiNum], 13);          // elementary_PID
        bs.AddBits(0x0F,  4);                   // reserved
        bs.AddBits(0x00, 12);                   // ES_info_length
    }

    Ipp32u uiCRC32 = 0;
    Ipp32u uiCRCDataLen = 12 + 5 * m_uiNOfStreams;
    ippsCRC32_BZ2_8u(bs.m_lpb - uiCRCDataLen, uiCRCDataLen, &uiCRC32);
    uiCRC32 ^= 0xFFFFFFFF;
    bs.AddBits(uiCRC32, 32);                    // CRC_32

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

Status PMTTableWriter::WriteChunk(void)
{
    Ipp32s iToWrite = MPEG2MUX_TS_PACKET_LENGTH;
    Status umcRes = m_pDataWriter->PutData(m_pHeaderBuf, iToWrite);

    AdvancedBitStream bs;
    bs.Reset(m_pHeaderBuf, MPEG2MUX_TS_PACKET_LENGTH);

    // update continuity_counter
    m_uiCounter = (m_uiCounter + 1) & 0x0f;
    bs.SkipBits(8 + 1 + 1 + 1 + 13 + 2 + 2);
    bs.AddBits(m_uiCounter, 4);
    return umcRes;
} //Status PMTTableWriter::WriteChunk(void)


/*
 * MPEG2TTS
 */

Status MPEG2TTSChunkWriter::WriteChunk(void)
{
    Ipp32s iToWrite = 4;
    Ipp32u uiTimeStamp = LITTLE_ENDIAN_SWAP32((Ipp32u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ));
    m_pDataWriter->PutData(&uiTimeStamp, iToWrite);
    return MPEG2TSChunkWriter::WriteChunk();
} //Status MPEG2TTSChunkWriter::WriteChunk(void)

Status TTSPATTableWriter::WriteChunk(void)
{
    Ipp32s iToWrite = 4;
    Ipp32u uiTimeStamp = LITTLE_ENDIAN_SWAP32((Ipp32u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ));
    m_pDataWriter->PutData(&uiTimeStamp, iToWrite);
    return PATTableWriter::WriteChunk();
} //Status TTSPATTableWriter::WriteChunk(void)

Status TTSPMTTableWriter::WriteChunk(void)
{
    Ipp32s iToWrite = 4;
    Ipp32u uiTimeStamp = LITTLE_ENDIAN_SWAP32((Ipp32u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ));
    m_pDataWriter->PutData(&uiTimeStamp, iToWrite);
    return PMTTableWriter::WriteChunk();
} //Status TTSPMTTableWriter::WriteChunk(void)

⌨️ 快捷键说明

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