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

📄 umc_mpeg2ts_parser.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    {
        Ipp16u program_number = GET_16U(&tsHeader[iPos + 0]);
        Ipp16u program_PID = GET_16U(&tsHeader[iPos + 2]) & 0x1fff;
        if (0 == program_number)
            continue;

        if (!pat.uiSecLen)
        { // fill program params
            pat.pProgs[i].uiProgInd = (Ipp16s)i;
            pat.pProgs[i].uiProgNum = program_number;
            pat.pProgs[i].uiProgPid = program_PID;
        }
        else if (m_bDetectPSIChanges)
        { // check changes in programs's numbers/PIDs
            if (pat.pProgs[i].uiProgNum != program_number || pat.pProgs[i].uiProgPid != program_PID)
            {
                m_bPatWasChanged = true;
                return UMC_WRN_INVALID_STREAM;
            }
        }
        i++;
    }

    if (!pat.uiSecLen)
    { // fill PAT fields only once
        pat.uiSecLen = (Ipp16u)section_length;
        pat.uiTsId = transport_stream_id;
        pat.uiVer = version_number;
        pat.uiProgs = uiPrograms;
    }

    return UMC_OK;
}

Status Mpeg2TsParser::ParseTsPmt(Mpeg2TsPmt &pmt, Ipp32s iPos, bool bDetectChanges)
{
    if (pmt.uiSecLen > 0 && !bDetectChanges)
        return UMC_OK;

    // read rest of packet
    Ipp8u tsHeader[TTS_PACKET_SIZE];
    CACHE_N_BYTES(&tsHeader[iPos], TTS_PACKET_SIZE - iPos, iPos);

    Ipp32u pointer_field = tsHeader[iPos];
    iPos += 1 + pointer_field;
    if (iPos + 3 >= m_iPacketSize)
        return UMC_ERR_INVALID_STREAM;

    Ipp32u table_id = tsHeader[iPos++];
    if (2 != table_id)
        return UMC_ERR_INVALID_STREAM;

    Ipp32s section_length = GET_16U(&tsHeader[iPos]) & 0xfff;
    Ipp32s section_end = (Ipp16u)(iPos + 2 + section_length);
    if (section_end > m_iPacketSize)
        return UMC_ERR_INVALID_STREAM;

    Ipp8u version_number = (tsHeader[iPos + 4] >> 1) & 0x1f;
    Ipp32u section_number = tsHeader[iPos + 5];
    Ipp32u last_section_number = tsHeader[iPos + 6];
    if (0 != section_number || 0 != last_section_number)
        return UMC_ERR_INVALID_STREAM; // multi-section tables are not supported

    Ipp16u PCR_PID = GET_16U(&tsHeader[iPos + 7]) & 0x1fff;
    Ipp32s program_info_length = GET_16U(&tsHeader[iPos + 9]) & 0x0fff;
    if (iPos + 11 + program_info_length + 4 > section_end)
        return UMC_ERR_INVALID_STREAM;

    iPos += 11; // points program info
    Ipp8u *pProgInfo = &tsHeader[iPos];
    iPos += program_info_length;

    //first count ESs
    Ipp32u uiESs = 0;
    Ipp32s iTmpPos = iPos;
    Ipp32s iBytesLeft = section_length - 13 - program_info_length;
    for (uiESs = 0; iTmpPos + 5 < section_end; uiESs++)
    {
        Ipp32u ES_info_length = GET_16U(&tsHeader[iTmpPos + 3]) & 0x0fff;
        if (ES_info_length >= 1023) return UMC_ERR_INVALID_STREAM;
        iTmpPos += 5 + ES_info_length;
        iBytesLeft -= 5 + ES_info_length;
    }

    if (!pmt.uiSecLen && uiESs > 0)
    { // allocate Mpeg2TsPmts only ones
        pmt.pESs = new Mpeg2Es[uiESs];
        if (!pmt.pESs)
        {
            pmt.Release();
            return UMC_ERR_ALLOC;
        }
        pmt.uiProgInfoLen = (Ipp16u)program_info_length;
        if (program_info_length > 0)
            pmt.SetInfo(pProgInfo, (Ipp16u)program_info_length);
    }
    else if (bDetectChanges)
    { // check some PMT fields for changes
        if (pmt.uiSecLen != section_length || pmt.uiVer != version_number ||
            pmt.uiProgInfoLen != program_info_length || pmt.uiESs != uiESs)
        {
            m_bPmtWasChanged = true;
            return UMC_WRN_INVALID_STREAM;
        }
    }

    // parse ESs PIDs/types checking changes
    Ipp32u i;
    Ipp32s ES_info_length = 0;
    iBytesLeft = section_length - 13 - program_info_length;
    for (i = 0; i < uiESs; i++, iPos += 5 + ES_info_length)
    {
        Ipp8u stream_type = tsHeader[iPos];
        Ipp16u elementary_PID = GET_16U(&tsHeader[iPos + 1]) & 0x1fff;
        ES_info_length = GET_16U(&tsHeader[iPos + 3]) & 0x0fff;

        if (!pmt.uiSecLen)
        { // first PMT
            pmt.pESs[i].uiType = stream_type;
            pmt.pESs[i].uiPid = elementary_PID;
            pmt.pESs[i].uiEsInfoLen = ES_info_length;
            if (ES_info_length > 0)
                pmt.pESs[i].SetInfo(&tsHeader[iPos + 5], (Ipp16u)ES_info_length);
            pmt.uiESs++;
        }
        else if (bDetectChanges)
        { // check ES description
            if (pmt.pESs[i].uiPid != elementary_PID || pmt.pESs[i].uiType != stream_type ||
                pmt.pESs[i].uiEsInfoLen != (Ipp16u)ES_info_length)
            {
                m_bPmtWasChanged = true;
                return UMC_WRN_INVALID_STREAM;
            }
        }
    }

    if (!pmt.uiSecLen)
    { // firsr PMT, fill fields
        pmt.uiPcrPid = PCR_PID;
        pmt.uiSecLen = (Ipp16u)section_length;
        pmt.uiVer = version_number;
    }

    iPos += 4;
    return UMC_OK;
}

Status Mpeg2TsParser::ReSync(void)
{
    if (m_iOrig < 0)
    {
        for (m_iOrig = 0; m_iOrig < m_iPacketSize; m_iOrig++)
        {
            Status umcRes;
            Ipp8u byte1, byte2, byte3;
            umcRes = m_pDataReader->Check8u(&byte1, m_iOrig + 1 * m_iPacketSize - TS_PACKET_SIZE);
            umcRes = m_pDataReader->Check8u(&byte2, m_iOrig + 2 * m_iPacketSize - TS_PACKET_SIZE);
            umcRes = m_pDataReader->Check8u(&byte3, m_iOrig + 3 * m_iPacketSize - TS_PACKET_SIZE);
            if (UMC_OK != umcRes)
                return UMC_ERR_FAILED;
            if (ID_TS_SYNC == byte1 && ID_TS_SYNC == byte2 && ID_TS_SYNC == byte3)
                break;
        }
        if (m_iOrig >= m_iPacketSize)
        {
            m_iOrig = -1;
            return UMC_ERR_FAILED;
        }
    }

    Ipp64u uiCurPos = m_pDataReader->GetPosition();
    Ipp64u uiPos = IPP_MAX(uiCurPos, m_iOrig);
    uiPos = ((uiPos - m_iOrig + m_iPacketSize - 1) / m_iPacketSize) * m_iPacketSize + m_iOrig;
    return uiPos > uiCurPos ? m_pDataReader->MovePosition(uiPos - uiCurPos) : UMC_OK;
}

// convert stream type from mpeg2ts pmt into internal TrackType
TrackType PmtStreamTypeToTrackType(Ipp8u uiStreamType)
{
    switch (uiStreamType)
    {
    case 0x01: return TRACK_MPEG1V;
    case 0x02: return TRACK_MPEG2V;
    case 0x03: return TRACK_MPEGA;
    case 0x04: return TRACK_MPEGA;
    case 0x0F: return TRACK_AAC;
    case 0x10: return TRACK_MPEG4V;
    case 0x11: return TRACK_AAC;
    case 0x1A: return TRACK_H264;
    case 0x1B: return TRACK_H264;
    case 0x81: return TRACK_AC3;
    case 0x83: return TRACK_LPCM;
    default:   return TRACK_UNKNOWN;
    }
}

Status Mpeg2TsParser::GetSystemTime(CheckPoint &rCheckPoint, Ipp64u upToPos)
{
    Status umcRes = UMC_OK;
    Packet packet;

    // if pid is unspecified find out it from PAT/PMT
    for (; m_iSysTimePid < 0;)
    {
        // find PAT table
        Mpeg2TsPat pat;
        packet.iPid = ID_TS_PAT;
        for (umcRes = UMC_OK; !pat.uiProgs && UMC_OK == umcRes; umcRes = SKIP_TS_PACKET())
        {
            Ipp32s iPos = 0;
            packet.uiAbsPos = upToPos;
            umcRes = DispatchPacketWithPid(packet, iPos, false);
            if (UMC_ERR_INVALID_STREAM == umcRes)
                continue;
            if (UMC_OK == umcRes)
                umcRes = ParseTsPat(pat, iPos, false);
        }
        if (UMC_OK != umcRes)
            return umcRes;

        // find any PMT table with valid PCR_PID
        Ipp32s prog = 0;
        Ipp32u uiProgsChecked = 0;
        for (; packet.uiAbsPos < upToPos && UMC_OK == umcRes; umcRes = SKIP_TS_PACKET())
        {
            Ipp32s iPos = 0;
            umcRes = DispatchPacket(packet, iPos, false);
            if (UMC_OK == umcRes && (prog = pat.GetProgIdx(packet.iPid)) >= 0)
            {
                if (!pat.pProgs[prog].uiSecLen)
                    uiProgsChecked++;
                umcRes = ParseTsPmt(pat.pProgs[prog], iPos, false);
                if (UMC_OK != umcRes)
                    uiProgsChecked--;
                else if (pat.pProgs[prog].uiPcrPid != ID_TS_NULL || uiProgsChecked >= pat.uiProgs)
                    break; // exit if 'good' pcr_pid is found or if all programs are checked
            }
        }
        if (packet.uiAbsPos >= upToPos)
            return UMC_ERR_FAILED;
        else if (UMC_OK != umcRes)
            return umcRes;

        if (ID_TS_NULL == pat.pProgs[prog].uiPcrPid)
        { // PCR is absent in the stream, try to use PTS/DTS of one of tracks
            m_bPcrPresent = false;
            Ipp32s iVideoPid = -1;
            for (prog = 0; prog < (Ipp32s)pat.uiProgs && m_iSysTimePid < 0; prog++)
            {
                Ipp32u es;
                for (es = 0; es < pat.pProgs[prog].uiESs && m_iSysTimePid < 0; es++)
                {
                    if (PmtStreamTypeToTrackType(pat.pProgs[prog].pESs[es].uiType) & TRACK_ANY_AUDIO)
                        m_iSysTimePid = (Ipp32s)pat.pProgs[prog].pESs[es].uiPid;
                    else if (PmtStreamTypeToTrackType(pat.pProgs[prog].pESs[es].uiType) & TRACK_ANY_VIDEO)
                        iVideoPid = iVideoPid < 0 ? (Ipp32s)pat.pProgs[prog].pESs[es].uiPid : iVideoPid;
                }
            }
            if (m_iSysTimePid < 0)
                m_iSysTimePid = iVideoPid;
            if (m_iSysTimePid < 0) // critical situation, stream with nor audio neither video
                return UMC_ERR_FAILED;
        }
        else
        { // PCR presents in the stream
            m_bPcrPresent = true;
            m_iSysTimePid = pat.pProgs[prog].uiPcrPid;
        }
    }

    packet.iPid = m_iSysTimePid;
    for (; UMC_OK == umcRes; umcRes = SKIP_TS_PACKET())
    {
        Ipp32s iPos = 0;
        packet.uiAbsPos = upToPos;
        packet.dPTS = packet.dDTS = -1.0;
        umcRes = DispatchPacketWithPid(packet, iPos, m_bPcrPresent);
        if (UMC_OK != umcRes)
            return umcRes;

        if (!m_bPcrPresent)
        { // if pcr isn't present in the stream, we have to get pes packet timestamps
            if (!packet.GetFlag(FCSample::PES_START))
                continue;
            umcRes = ParsePesHeader(packet, iPos, true);
            if (UMC_ERR_INVALID_STREAM == umcRes)
                continue;
        }

        if (packet.dPTS < 0.0)
            continue;
        rCheckPoint.uiPos = packet.uiAbsPos;
        rCheckPoint.dTime = packet.dDTS < 0.0 ? packet.dPTS : packet.dDTS;
        umcRes = SKIP_TS_PACKET();
        break;
    }

    return umcRes;
}

Status Mpeg2TsParser::MoveToNextHeader(void)
{
    PARSER_CHECK_INIT;
    if (END_OF_STREAM == m_ParserState)
        return UMC_ERR_END_OF_STREAM;
    else if (HEADER == m_ParserState)
        return UMC_OK;
    m_ParserState = HEADER;
    Status umcRes = m_pDataReader->MovePosition(m_iPacketSize);
    Reset();
    return umcRes;
}

⌨️ 快捷键说明

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