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

📄 umc_mpeg2_muxer_chunk.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    bs.AddBits(0x00, 2);                    // PES_scrambling_control
    bs.AddBits(0x00, 1);                    // PES_priority
    bs.AddBits(0x00, 1);                    // data_alignment_indicator
    bs.AddBits(0x00, 1);                    // copyright
    bs.AddBits(0x00, 1);                    // original_or_copy
    bs.AddBits(m_uiPTSDTSFlags, 2);         // PTS_DTS_flags
    bs.AddBits(0x00, 1);                    // ESCR_flag
    bs.AddBits(0x00, 1);                    // ES_rate_flag
    bs.AddBits(0x00, 1);                    // DSM_trick_mode_flag
    bs.AddBits(0x00, 1);                    // additional_copy_info_flag
    bs.AddBits(0x00, 1);                    // PES_CRC_flag
    bs.AddBits(0x00, 1);                    // PES_extension_flag
    bs.AddBits(m_uiPESHeaderDataLength, 8); // PES_header_data_length

    if (m_uiPTSDTSFlags & 0x02)
    {
        Ipp64u pts = (Ipp64u)(payload.dPTS * 90000.0 + 0.5);
        bs.AddBits(m_uiPTSDTSFlags & 3, 4);             // '0010' or '0011'
        bs.AddBits((Ipp32s)((pts >> 30) & 0x07), 3);    // PTS [32..30]
        bs.AddBits(0x01, 1);                            // marker_bit
        bs.AddBits((Ipp32s)((pts >> 15) & 0x7fff), 15); // PTS [29..15]
        bs.AddBits(0x01, 1);                            // marker_bit
        bs.AddBits((Ipp32s)(pts & 0x7fff), 15);         // PTS [14..0]
        bs.AddBits(0x01, 1);                            // marker_bit
    }
    if (0x03 == m_uiPTSDTSFlags)
    {
        Ipp64u dts = (Ipp64u)(payload.dDTS * 90000.0 + 0.5);
        bs.AddBits(0x01, 4);                            // '0001'
        bs.AddBits((Ipp32s)((dts >> 30) & 0x07), 3);    // DTS [32..30]
        bs.AddBits(0x01, 1);                            // marker_bit
        bs.AddBits((Ipp32s)((dts >> 15) & 0x7fff), 15); // DTS [29..15]
        bs.AddBits(0x01, 1);                            // marker_bit
        bs.AddBits((Ipp32s)(dts & 0x7fff), 15);         // DTS [14..0]
        bs.AddBits(0x01, 1);                            // marker_bit
    }

    Ipp32u i;
    for (i = 0; i < m_uiNOfStuffingBytes; i++)
        bs.AddBits(0xff, 8); // stuffing_byte

    m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
} //void MPEG2PSChunkWriter::GeneratePESHeader(void)

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

    if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
    {
        bs.AddBits(m_uiSubStreamID, 8); // LPCM_ID (0xA0...0xA7)
        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;
    }
    else if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
    {
        bs.AddBits(m_uiSubStreamID, 8); // AC3_ID (0x80...0x87)
        bs.AddBits(0x00, 1);            // emphasis_flag (off)
        bs.AddBits(0x00, 1);            // mute_flag (off)
        bs.AddBits(0x00, 1);            // reserved
        bs.AddBits(m_uiNOfFrames, 5);   // number_of_frames
        bs.AddBits(m_uiOffset, 16);     // offset of first access unit

        // update special header fields
        m_uiNOfFrames = 0;
        m_uiOffset = m_uiNextOffset;
    }

    m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
} //void MPEG2PSChunkWriter::GenerateSpecialHeader(void)

Status MPEG2PSChunkWriter::PrepareChunk(void)
{
    m_uiPESPacketLength = 0;
    m_uiPESHeaderDataLength = 0;
    m_uiNOfStuffingBytes = 0;
    m_uiNOfPaddingBytes = 0;
    m_uiPayloadSize = 0;
    m_uiPTSDTSFlags = 0x00;

    // calculate PES_packet_length of PES packet
    m_uiPESPacketLength = m_uiPacketSize;
    m_uiPESPacketLength -= m_uiPackHeaderSize; // pack header if exist
    m_uiPESPacketLength -= m_uiSystemHeaderSize; // system header if exist
    m_uiPESPacketLength -= 6; // PES_start_code and PES_header_length

    // calculate maximum space available for payload
    m_uiPayloadSize = m_uiPESPacketLength;
    m_uiPayloadSize -= 3; // PES_flags and PES_header_data_length field
    m_uiPayloadSize -= m_uiSpecialHeaderSize; // special header (AC3 or LPCM)

    // try to get payload
    payload.uiSize = m_uiPayloadSize;
    if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
        payload.uiSize += 4; // it is to be sure that whole AC3 header will be available

    UMC_CALL(LockOutputBuffer(&payload));

    // analize time stamps
    if (payload.dPTS > 0.0)
    {
        m_uiPESHeaderDataLength += 5;
        m_uiPayloadSize -= 5;
        m_uiPTSDTSFlags = 0x02;
        if (payload.dDTS > 0.0)
        {
            m_uiPESHeaderDataLength += 5;
            m_uiPayloadSize -= 5;
            m_uiPTSDTSFlags = 0x03;
        }
    }

    //analize size of payload
    if (payload.uiSize < m_uiPayloadSize)
    {
        if (m_uiPayloadSize - payload.uiSize > 6)
        { // size of payload is much smaller, padding packet is needed
            m_uiNOfPaddingBytes = m_uiPayloadSize - payload.uiSize;
            m_uiPESPacketLength -= m_uiNOfPaddingBytes;
        }
        else
        { // size of payload is not much smaller, add stuffing bytes right to PES header
            m_uiNOfStuffingBytes = m_uiPayloadSize - payload.uiSize;
            m_uiPESHeaderDataLength += m_uiNOfStuffingBytes;
        }

        m_uiPayloadSize = payload.uiSize;
    }
    else
    {
        payload.uiSize = m_uiPayloadSize;
        if (payload.uiTSOffset >= m_uiPayloadSize)
        { // time stamps is proved to be out of this packet
            if (m_uiPTSDTSFlags & 0x02)
            { // add stuffing bytes intead of time stamps
                m_uiNOfStuffingBytes += 5;
                if (m_uiPTSDTSFlags == 0x03)
                    m_uiNOfStuffingBytes += 5;
            }

            m_uiPTSDTSFlags = 0x00;
        }
    }

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

        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;
    }
    else if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
    {
        Ipp8u *pBuf = payload.pData;
        Ipp32u uiPos = 0;
        m_uiFrameNumber = 0;

        if (m_uiOffset >= m_uiPayloadSize)
        { // AC3 syncword is out of this packet, update offset
            m_uiOffset -= m_uiPayloadSize;
            return UMC_OK;
        }

        if (pBuf[uiPos + m_uiOffset] != 0x0b || pBuf[uiPos + m_uiOffset + 1] != 0x77)
        { // wrong offset, look for AC3 syncword
            for (; uiPos < m_uiPayloadSize; uiPos++)
                if (pBuf[uiPos] == 0x0b && pBuf[uiPos + 1] == 0x77)
                    break;

            // offset is not found in this packet
            if (uiPos >= m_uiPayloadSize)
                return UMC_OK;

            m_uiOffset = uiPos; // correct offset is found
        }
        else
        { // correct offset, go to it
            uiPos = m_uiOffset;
        }

        m_uiFrameNumber++; // one AC3 syncword is found

        // evaluate next offset
        Ipp8u fscod = pBuf[uiPos + 4] >> 6;
        Ipp8u frmsizecod = pBuf[uiPos + 4] & 0x3F;
        m_uiNextOffset = 2 * AC3FrameSize[3 * frmsizecod + fscod];

        // count AC3 frames
        while (uiPos + m_uiNextOffset < m_uiPayloadSize)
        {
            if (pBuf[uiPos + m_uiNextOffset] != 0x0b || pBuf[uiPos + m_uiNextOffset + 1] != 0x77)
            { // wrong offset, look for AC3 syncword
                m_uiNextOffset = 0;
                for (; uiPos < m_uiPayloadSize; uiPos++)
                    if (pBuf[uiPos] == 0x0b && pBuf[uiPos + 1] == 0x77)
                        break;

                // no more AC3 syncwords in this packet
                if (uiPos >= m_uiPayloadSize)
                    break;

                m_uiNextOffset = uiPos; // correct offset is found
            }
            else
                uiPos += m_uiNextOffset;

            m_uiFrameNumber++;
            fscod = pBuf[uiPos + 4] >> 6;
            frmsizecod = pBuf[uiPos + 4] & 0x3F;
            m_uiNextOffset = 2 * AC3FrameSize[3 * frmsizecod + fscod];
        }

        m_uiNextOffset -= m_uiPayloadSize - uiPos;
    }

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

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

    GenerateNonPESHeaders();
    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));

    // check if packet is had to be padded
    if (m_uiNOfPaddingBytes > 0)
    {
        UMC_CALL(WritePadding(m_uiNOfPaddingBytes));
    }

    return UnLockOutputBuffer(&payload);
} //Status MPEG2PSChunkWriter::WriteChunk(void)

static const Ipp8u paddingArray[2048] = {0x00};
Status MPEG2PSChunkWriter::WritePadding(Ipp32s iNOfPaddingBytes)
{
    Ipp32s iToWrite, i;
    Ipp32s size = iNOfPaddingBytes - 6;
    if (size < 0)
        size += m_uiPacketSize;

    Ipp8u pPaddingHeader[6];
    pPaddingHeader[0] = 0x00;
    pPaddingHeader[1] = 0x00;
    pPaddingHeader[2] = 0x01;
    pPaddingHeader[3] = MPEG2MUX_PES_ID_PADDING;
    pPaddingHeader[4] = (Ipp8u)(size >> 8);
    pPaddingHeader[5] = (Ipp8u)(size & 0xFF);

    iToWrite = 6;
    UMC_CALL(m_pDataWriter->PutData(pPaddingHeader, iToWrite));

    iToWrite = 2048;
    for (i = 0; i < size / 2048; i++)
        UMC_CALL(m_pDataWriter->PutData((void *)paddingArray, iToWrite));

    iToWrite = size % 2048;
    UMC_CALL(m_pDataWriter->PutData((void *)paddingArray, iToWrite));

    return UMC_OK;
} //Status MPEG2PSChunkWriter::WritePadding(Ipp32s iNOfPaddingBytes)


/*
 * MPEG2TSChunkWriter
 */

MPEG2TSChunkWriter::MPEG2TSChunkWriter()
{
} //MPEG2TSChunkWriter::MPEG2TSChunkWriter()

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

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

    m_uiPID = 0;
    m_bIsPCRPID = false;

    m_dPCR = 0.0;
    m_uiPCRFlag = 0;
    m_uiStartIndicator = 0;
    m_uiCounter = 0;
    m_uiAdaptFieldCtrl = 0;
    m_uiAdaptFieldLen = 0;
    m_uiNOfTSStuffingBytes = 0;
    return UMC_OK;
} //Status MPEG2TSChunkWriter::Close(void)

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

    MPEG2TSChunkWriterParams *pParams = DynamicCast<MPEG2TSChunkWriterParams>(pInit);
    if (!pParams)
        return UMC_ERR_NULL_PTR;

    m_uiPID = pParams->uiPID;
    m_bIsPCRPID = pParams->bIsPCRPID;

    m_uiStartIndicator = 1;
    m_uiPackHeaderSize = 0;
    m_uiSystemHeaderSize = 0;
    m_uiSpecialHeaderSize = 0;
    if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
        m_uiSpecialHeaderSize = 6;

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

Status MPEG2TSChunkWriter::UnLockOutputBuffer(MPEG2MuxerSample *pData)
{
    if (pData->uiSize == m_pFirstUsedSample->uiSize)
        m_uiStartIndicator = 1;

    return MPEG2MuxerLinearBuffer::UnLockOutputBuffer(pData);
} //Status MPEG2TSChunkWriter::UnLockOutputBuffer(MPEG2MuxerSample *pData)

Status MPEG2TSChunkWriter::PrepareChunk(void)
{
    // PES section
    m_uiPESPacketLength = 0;
    m_uiPTSDTSFlags = 0x00;
    m_uiPESHeaderDataLength = 0;
    m_uiNOfStuffingBytes = 0;
    m_uiPayloadSize = 0;
    m_uiNOfPaddingBytes = 0;

    // TS section
    Ipp32u uiMaxPayloadSize = MPEG2MUX_TS_PACKET_LENGTH;
    m_uiAdaptFieldCtrl = 0x01;
    m_uiAdaptFieldLen = 0;
    m_uiPCRFlag = 0;
    m_uiNOfTSStuffingBytes = 0;

    uiMaxPayloadSize -= 4; // obligatory TS packet fields

    payload = *m_pFirstUsedSample;
    if (m_uiStartIndicator && m_ESType != MPEG2MUX_ES_VBI_DATA)
    {
        if (m_bIsPCRPID)
        {
            m_uiPCRFlag = 1;
            m_uiAdaptFieldCtrl = 0x03;
            m_uiAdaptFieldLen = 7;
            uiMaxPayloadSize -= 8;

            if (m_dPCR < payload.dExactDTS - 0.3)
                m_dPCR = payload.dExactDTS - 0.3;
            else
                m_dPCR += 1.0 / MPEG2MUX_SYS_CLOCK_FREQ;

        }

        if (payload.dPTS > 0.0)
        {
            m_uiPTSDTSFlags = 0x02;
            m_uiPESHeaderDataLength += 5;
            if (payload.dDTS > 0.0)
            {
                m_uiPTSDTSFlags = 0x03;
                m_uiPESHeaderDataLength += 5;
            }
        }

        m_uiPESPacketLength = payload.uiSize;
        m_uiPESPacketLength += m_uiSpecialHeaderSize; // special header is needed for LPCM
        m_uiPESPacketLength += m_uiPESHeaderDataLength; // PTS/DTS
        m_uiPESPacketLength += 3; // PES flags and PES_header_data_length field

⌨️ 快捷键说明

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