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

📄 umc_demuxer.cpp

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

    if (m_dDuration < 0.0 || IsPure())
    {
        // if parser isn't able to provide duration, try to estimate it
        if (m_uiSourceSize > 0)
        {
            if (-1 != m_iRefTrack && m_pFC[m_iRefTrack])
            {
                // estimation for pure streams
                Ipp32u bitrate = 0;
                Ipp64f frame_rate = 0.0;
                if (m_pFC[m_iRefTrack]->GetInfo()->m_Type & TRACK_ANY_VIDEO)
                {
                    bitrate = ((VideoStreamInfo *)m_pFC[m_iRefTrack]->GetInfo()->m_pStreamInfo)->bitrate;
                    frame_rate = ((VideoStreamInfo *)m_pFC[m_iRefTrack]->GetInfo()->m_pStreamInfo)->framerate;
                    if (frame_rate > 0.0)
                        bitrate = 0; // do not use bitrate for video if framerate is valid
                    else if (0 == bitrate)
                        frame_rate = 30.0; // if both framerate and bitrate are invalid assume 30fps
                }
                else if (m_pFC[m_iRefTrack]->GetInfo()->m_Type & TRACK_ANY_AUDIO)
                    bitrate = ((AudioStreamInfo *)m_pFC[m_iRefTrack]->GetInfo()->m_pStreamInfo)->bitrate;

                if (bitrate > 0)
                    m_dDuration = (Ipp64f)(Ipp64s)m_uiSourceSize / (bitrate / 8);
                else if (frame_rate > 0.0 && m_uiTotalSize > 0 && m_uiNOfFrames > 0 && (m_uiNOfFrames > 30 || m_bEndOfStream || m_bBufFilled))
                    m_dDuration = ((((Ipp64f)(Ipp64s)m_uiSourceSize) / (Ipp64s)m_uiTotalSize) * m_uiNOfFrames) / frame_rate;
            }
        }
    }

    return m_dDuration;
}

void Demuxer::TerminateInit(StreamParserParams *pPtr)
{
    if (m_pParser)
    {
        delete m_pParser;
        m_pParser = NULL;
    }
    if (m_bInnerMemAllocator && m_pMemoryAllocator)
    {
        delete m_pMemoryAllocator;
        m_pMemoryAllocator = NULL;
        m_bInnerMemAllocator = false;
    }
    if (pPtr)
    {
        delete pPtr;
        pPtr = NULL;
    }
}

static const Ipp32u IS_LINEAR = 1;
static const Ipp32u NUM_OF_INTERVALS = 10;
Ipp64f Demuxer::GetExactDuration(void)
{
    Status umcRes = UMC_OK;
    CheckPoint prevPoint;
    CheckPoint curPoint;
    Ipp64u uiInitStep;
    Ipp64u uiStepAtTheEnd;
    Ipp64u uiStep;
    Ipp64u uiSavedPos;

    if (m_dDuration >= 0.0)
        return m_dDuration;

    m_dBytesPerSec = 0;
    m_dDuration = -1.0;

    uiSavedPos = m_pParser->GetPosition();
    if (0 == m_uiSourceSize)
        return -1.0;

    uiInitStep = uiStep = (IS_LINEAR) ? (m_uiSourceSize / NUM_OF_INTERVALS) : (m_uiSourceSize >> (NUM_OF_INTERVALS - 1));
    if (0 == uiStep)
        return -1.0;

    // get first check point
    m_pParser->SetPosition(0);
    m_Corrector.ResetAfterReposition();
    umcRes = m_Corrector.GetSystemTime(m_Start);
    if (UMC_OK != umcRes)
    {
        m_pParser->SetPosition(uiSavedPos);
        return -1.0;
    }

    uiStepAtTheEnd = 100000;
    if (MPEG1_PROGRAMM_STREAM == m_SplInfo.m_SystemType || MPEG2_PROGRAMM_STREAM == m_SplInfo.m_SystemType)
        uiStepAtTheEnd = 10000;

    // get last point without discontinuity detection
    // after loop m_End will contain position of latest time
    Ipp64u start = m_uiSourceSize;
    Ipp64u end = m_uiSourceSize;
    CheckPoint tmpEnd(-1.0, 0);
    m_End.dTime = -1.0;
    while (m_End.dTime < 0.0)
    {
        start = (start > uiStepAtTheEnd) ? start - uiStepAtTheEnd : 0;
        m_pParser->SetPosition(start);
        m_Corrector.ResetAfterReposition();
        tmpEnd.uiPos = start;

        // find latest time at the interval [start; end]
        umcRes = UMC_OK;
        while (UMC_OK == umcRes && m_End.uiPos < end)
            umcRes = m_Corrector.GetSystemTimeUpTo(m_End, end);

        end = start;
        uiStepAtTheEnd *= 2;
    }

    // do additional jumps between m_Start and m_End with discontinuity detection
    Ipp64u uiLastGapPos = 0;
    Ipp64f dCurBps, dPrevBps = -1.0;
    prevPoint = curPoint = m_Start;
    while (curPoint.uiPos < m_End.uiPos)
    {
        curPoint.uiPos += uiStep;
        if (curPoint.uiPos > m_End.uiPos)
            curPoint.uiPos = m_End.uiPos;

        m_pParser->SetPosition(curPoint.uiPos);
        m_Corrector.ResetAfterReposition();

        umcRes = m_Corrector.GetSystemTime(curPoint);
        if (UMC_OK != umcRes)
            break;

        uiStep = (IS_LINEAR) ? uiStep : (curPoint.uiPos - uiLastGapPos);
        dCurBps = prevPoint.GetBPS(curPoint);

        // here is criteria of discontinuity
        if ((curPoint.dTime < prevPoint.dTime) || // negative time-stamp delta
            (dCurBps > 0.0 && (dPrevBps / dCurBps) > 100.) || // too large positive time-stamp delta
            (dPrevBps < 0.0 && dCurBps < 1000.0)) // very small bitrate for at step is very suspisious
        {
            if (TryToDetectDiscontinuity(prevPoint, curPoint, 3))
            {
                uiStep = uiInitStep;
                uiLastGapPos = curPoint.uiPos;
                dCurBps = prevPoint.GetBPS(curPoint);
            }
        }

        dPrevBps = dCurBps;
        prevPoint = curPoint;
    }

    m_End = prevPoint;
    if (m_End.dTime > m_Start.dTime)
    {
        m_dDuration = m_End.dTime - m_Start.dTime;
        m_dBytesPerSec = m_Start.GetBPS(m_End);
    }

    m_pParser->SetPosition(uiSavedPos);
    m_Corrector.ResetAfterReposition();
    return m_dDuration;
}

bool Demuxer::IsPure(void)
{
    if (AVI_STREAM == m_SplInfo.m_SystemType ||
        MP4_ATOM_STREAM == m_SplInfo.m_SystemType ||
        ASF_STREAM == m_SplInfo.m_SystemType ||
        MPEG1_PES_PACKETS_STREAM == m_SplInfo.m_SystemType ||
        MPEG1_PROGRAMM_STREAM == m_SplInfo.m_SystemType ||
        MPEG2_PES_PACKETS_STREAM == m_SplInfo.m_SystemType ||
        MPEG2_PROGRAMM_STREAM == m_SplInfo.m_SystemType ||
        MPEG2_TRANSPORT_STREAM == m_SplInfo.m_SystemType ||
        MPEG2_TRANSPORT_STREAM_TTS == m_SplInfo.m_SystemType)
        return false;
    else
        return true;
}

bool Demuxer::IsSeekable(void)
{
    if (m_iRefTrack < 0 ||
       (m_iRefTrack >= 0 && !m_pFC[m_iRefTrack]) ||
       (m_iRefTrack >= 0 && m_pFC[m_iRefTrack] && !(m_pFC[m_iRefTrack]->GetInfo()->m_Type & TRACK_ANY_VIDEO)))
       return false;
    else
        return true;
}

bool Demuxer::TryToDetectDiscontinuity(CheckPoint start, CheckPoint &rEnd, Ipp32s nOfTries)
{
    if (0 == m_uiSourceSize)
        return false;

    Status umcRes = UMC_OK;
    CheckPoint end = rEnd;
    CheckPoint middle;
    Ipp64f dBpsAt1stHalf, dBpsAt2ndHalf, dCurBPS = 0;
    Ipp32s attempt = 0;

    // this loop is trying to localize discontinuity in the 2 seconds interval
    bool isDetected = false;
    while (attempt < nOfTries || isDetected)
    {
        m_Corrector.ResetAfterReposition();
        umcRes = m_pParser->SetPosition((end.uiPos + start.uiPos) / 2);
        if (UMC_OK != umcRes)
            return false;

        //find next valid time stamp
        umcRes = m_Corrector.GetSystemTime(middle);
        if (UMC_OK != umcRes)
            return false;

        dBpsAt1stHalf = start.GetBPS(middle);
        dBpsAt2ndHalf = middle.GetBPS(end);

        if (dBpsAt1stHalf < 0)
        { // negative jump at 1st half
            isDetected = true;
            end = middle;
            dCurBPS = dBpsAt2ndHalf;
        }
        else if (dBpsAt2ndHalf < 0)
        { // negative jump at 2nd half
            isDetected = true;
            start = middle;
            dCurBPS = dBpsAt1stHalf;
        }
        else if (dBpsAt2ndHalf / dBpsAt1stHalf > 100.0)
        { // can't detect negative jump, assume positive jump at 1st half
            isDetected = true;
            end = middle;
            dCurBPS = dBpsAt2ndHalf;
        }
        else if (dBpsAt1stHalf / dBpsAt2ndHalf > 100.0)
        { // can't detect negative jump, assume positive jump at 2nd half
            isDetected = true;
            start = middle;
            dCurBPS = dBpsAt1stHalf;
        }
        else if (!isDetected)
            break;

        if (dCurBPS <= 0.0)
            dCurBPS = 500000.0;

        attempt++;
        if (isDetected && ((Ipp64s)(end.uiPos - start.uiPos) / dCurBPS) < 2.0)
            break;
    }

    if (isDetected)
    { // scan small fragment (2 seconds) for discontinuity
        isDetected = false;
        middle.uiPos = start.uiPos;
        m_pParser->SetPosition(middle.uiPos);
        m_Corrector.ResetAfterReposition();
        while (UMC_OK == umcRes && middle.uiPos < end.uiPos)
        {
            umcRes = m_Corrector.GetSystemTime(middle, &isDetected);
            if (UMC_OK != umcRes)
                return isDetected;

            if (isDetected)
                break;
        }

        // move end check point to point at the gap detected
        if (isDetected)
            rEnd = middle;
    }

    return isDetected;
}

void Demuxer::AssignRefTrack(void)
{
    Ipp32u i;
    Ipp32s iATrack = -1;
    Ipp32s iVTrack = -1;
    Ipp32s iOTrack = -1;
    for (i = 0; i < m_uiTracks; i++)
    {
        if (m_pFC[i] && m_pFC[i]->GetInfo()->m_isSelected)
        {
            if (iATrack < 0 && m_pFC[i]->GetInfo()->m_Type & TRACK_ANY_AUDIO)
                iATrack = i;
            else if (iVTrack < 0 && m_pFC[i]->GetInfo()->m_Type & TRACK_ANY_VIDEO)
                iVTrack = i;
            else if (iOTrack < 0 && m_pFC[i]->GetInfo()->m_Type & TRACK_ANY_SPECIAL)
                iOTrack = i;
        }
    }
    m_iRefTrack = (iVTrack >= 0) ? iVTrack : ((iATrack >= 0) ? iATrack : iOTrack);
}

#ifdef DUMP_SOMETHING
void Demuxer::DumpSample(Ipp32u uiTrack)
{
    char binFileName[256] = {0};
    char txtFileName[256] = {0};

    if (m_pFC[uiTrack]->GetInfo()->m_Type & TRACK_ANY_AUDIO)
    {
#ifdef DUMP_AUDIO_BIN
        strcpy(&binFileName[0], "C:/zzz_audio.mpg");
#endif //DUMP_AUDIO_BIN
#ifdef DUMP_AUDIO_TXT
        strcpy(&txtFileName[0], "C:/zzz_audio.txt");
#endif //DUMP_AUDIO_TXT
    }

    if (m_pFC[uiTrack]->GetInfo()->m_Type & TRACK_ANY_VIDEO)
    {
        if (m_dRate > 1.0)
        {
#ifdef DUMP_VIDEO_FF_BIN
            strcpy(&binFileName[0], "C:/zzz_video_ff.mpg");
#endif //DUMP_VIDEO_FF_BIN
#ifdef DUMP_VIDEO_FF_TXT
            strcpy(&txtFileName[0], "C:/zzz_video_ff.txt");
#endif //DUMP_VIDEO_FF_TXT
        }
        else if (m_dRate < 0.0)
        {
#ifdef DUMP_VIDEO_BF_BIN
            strcpy(&binFileName[0], "C:/zzz_video_bf.mpg");
#endif //DUMP_VIDEO_BF_BIN
#ifdef DUMP_VIDEO_BF_TXT
            strcpy(&txtFileName[0], "C:/zzz_video_bf.txt");
#endif //DUMP_VIDEO_BF_TXT
        }
        else
        {
#ifdef DUMP_VIDEO_1X_BIN
            strcpy(&binFileName[0], "C:/zzz_video_1x.mpg");
#endif //DUMP_VIDEO_1X_BIN
#ifdef DUMP_VIDEO_1X_TXT
            strcpy(&txtFileName[0], "C:/zzz_video_1x.txt");
#endif //DUMP_VIDEO_1X_TXT
        }
    }

    if (binFileName[0] || txtFileName[0])
    {
        SplMediaData sampleData;
        m_pFC[uiTrack]->LockOutputBuffer(&sampleData);

        if (txtFileName[0])
        {
            FILE *fd_txt = fopen(txtFileName, "a");
            if (fd_txt)
            {
                fprintf(fd_txt, "size = %6d, absPos = %8x, pts = %2.3f, type = %d\n", sampleData.GetDataSize(), (int)sampleData.GetAbsPos(), sampleData.GetTime(), sampleData.GetFrameType());
                fclose(fd_txt);
            }
        }

        if (binFileName[0])
        {
            FILE *fd = fopen(binFileName, "ab");
            if (fd)
            {
                fwrite(sampleData.GetDataPointer(), sampleData.GetDataSize(), 1, fd);
                fclose(fd);
            }
        }
    }
}
#endif //DUMP_SOMETHING

void TimeStampCorrector::AttachParser(Mpeg2PesParser *pParser)
{
    m_pParser = pParser;
    m_dPrevValidSystemTime = -1.0;
}

void TimeStampCorrector::ResetAfterReposition(void)
{
    m_dPrevValidSystemTime = -1.0;
}

bool TimeStampCorrector::CorrectTime(CheckPoint &rCheckPoint)
{
    CheckPoint gap;
    Status err = UMC_OK;
    bool isNewGapDetected = false;

    // make corrections using known gaps
    err = m_ListOfGaps.First(gap);
    while (UMC_OK == err)

⌨️ 快捷键说明

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