📄 umc_demuxer.cpp
字号:
}
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 + -