Index: DeMultiplexer.cpp =================================================================== --- DeMultiplexer.cpp (revision 28016) +++ DeMultiplexer.cpp (working copy) @@ -52,9 +52,7 @@ // *** UNCOMMENT THE NEXT LINE TO ENABLE DYNAMIC VIDEO PIN HANDLING!!!! ****** #define USE_DYNAMIC_PINS -extern int ShowBuffer; - CDeMultiplexer::CDeMultiplexer(CTsDuration& duration,CTsReaderFilter& filter) :m_duration(duration) ,m_filter(filter) @@ -88,6 +86,8 @@ m_lastVideoPTS.IsValid = false; m_lastAudioPTS.IsValid = false; m_mpegParserTriggerFormatChange = false; + m_videoChanged=false; + m_audioChanged=false; SetMediaChanging(false); SetAudioChanging(false); m_DisableDiscontinuitiesFiltering = false; @@ -620,6 +620,8 @@ m_bStarting=true ; m_receivedPackets=0; m_mpegParserTriggerFormatChange=false; + m_videoChanged=false; + m_audioChanged=false; m_bEndOfFile=false; m_bHoldAudio=false; m_bHoldVideo=false; @@ -1324,26 +1326,45 @@ LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced); if (m_mpegParserTriggerFormatChange) { - LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser"); + LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser, aud %d, vid 1", m_audioChanged); SetMediaChanging(true); - m_filter.OnMediaTypeChanged(3); + if (m_audioChanged) + m_filter.OnMediaTypeChanged(3); //Video and audio + else + m_filter.OnMediaTypeChanged(2); //Video only m_mpegParserTriggerFormatChange=false; } LogDebug("DeMultiplexer: triggering OnVideoFormatChanged"); m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced); } - else + else //video resolution is the unchanged, but there may be other format changes { if (m_mpegParserTriggerFormatChange && Gop) { - LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now."); - m_filter.OnMediaTypeChanged(3); + if (m_audioChanged || m_videoChanged) + { + SetMediaChanging(true); + LogDebug("DeMultiplexer: Got GOP after channel change detected, trigger format change, aud %d, vid %d", m_audioChanged, m_videoChanged); + if (m_audioChanged && m_videoChanged) + m_filter.OnMediaTypeChanged(3); + else if (m_audioChanged) + m_filter.OnMediaTypeChanged(1); + else + m_filter.OnMediaTypeChanged(2); + } + else + { + SetMediaChanging(false); + } m_mpegParserTriggerFormatChange=false; } } } else + { m_bSetVideoDiscontinuity = !m_mVideoValidPES; + } + m_pl.RemoveAll(); p2->bDiscontinuity = m_p->bDiscontinuity; m_p->bDiscontinuity = FALSE; @@ -1638,20 +1659,36 @@ LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced); if (m_mpegParserTriggerFormatChange) { - LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser"); + LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser, aud %d, vid 1", m_audioChanged); SetMediaChanging(true); - m_filter.OnMediaTypeChanged(3); + if (m_audioChanged) + m_filter.OnMediaTypeChanged(3); //Video and audio + else + m_filter.OnMediaTypeChanged(2); //Video only m_mpegParserTriggerFormatChange=false; } LogDebug("DeMultiplexer: triggering OnVideoFormatChanged"); m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced); } - else + else //video resolution is the unchanged, but there may be other format changes { if (m_mpegParserTriggerFormatChange && Gop) { - LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now."); - m_filter.OnMediaTypeChanged(3); + if (m_audioChanged || m_videoChanged) + { + SetMediaChanging(true); + LogDebug("DeMultiplexer: Got GOP after channel change detected, trigger format change, aud %d, vid %d", m_audioChanged, m_videoChanged); + if (m_audioChanged && m_videoChanged) + m_filter.OnMediaTypeChanged(3); + else if (m_audioChanged) + m_filter.OnMediaTypeChanged(1); + else + m_filter.OnMediaTypeChanged(2); + } + else + { + SetMediaChanging(false); + } m_mpegParserTriggerFormatChange=false; } } @@ -1863,22 +1900,35 @@ } bool changed=false; - bool videoChanged=false; + m_videoChanged=false; + m_audioChanged=false; + + #ifdef USE_DYNAMIC_PINS + //Is the video pin connected? + if ((m_filter.GetVideoPin()->IsConnected()) && (m_pids.videoPids.size() > 0)) + { + changed=true; //force a check in the mpeg parser + if (oldVideoServiceType != m_pids.videoPids[0].VideoServiceType) + { + m_videoChanged=true; + } + } + #else //did the video format change? - if (m_pids.videoPids.size() > 0 && oldVideoServiceType != m_pids.videoPids[0].VideoServiceType ) + if (m_pids.videoPids.size() > 0 && oldVideoServiceType != m_pids.videoPids[0].VideoServiceType) { - //yes, is the video pin connected? + //yes, is the audio pin connected? if (m_filter.GetVideoPin()->IsConnected()) { changed=true; - videoChanged=true; + m_videoChanged=true; } } - + #endif + m_iAudioStream = 0; LogDebug ("Setting initial audio index to : %i", m_iAudioStream); - bool audioChanged=false; //get the new audio format int newAudioStreamType=SERVICE_TYPE_AUDIO_MPEG2; @@ -1894,7 +1944,7 @@ if (m_filter.GetAudioPin()->IsConnected()) { changed=true; - audioChanged=true; + m_audioChanged=true; } } @@ -1902,10 +1952,10 @@ if (changed) { #ifdef USE_DYNAMIC_PINS - // if we have a video stream and it's format changed, let the mpeg parser trigger the OnMediaTypeChanged - if (m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid>0x1 && videoChanged) + // if we have a video stream, let the mpeg parser trigger the OnMediaTypeChanged + if (m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid>0x1) { - LogDebug("DeMultiplexer: We detected a new media type change which has a video stream, so we let the mpegParser trigger the event"); + LogDebug("DeMultiplexer: We have a video stream, so we let the mpegParser check/trigger format changes"); m_receivedPackets=0; m_mpegParserTriggerFormatChange=true; SetMediaChanging(true); @@ -1925,10 +1975,10 @@ } } #else - if (audioChanged && videoChanged) + if (m_audioChanged && m_videoChanged) m_filter.OnMediaTypeChanged(3); else - if (audioChanged) + if (m_audioChanged) m_filter.OnMediaTypeChanged(1); else m_filter.OnMediaTypeChanged(2); Index: DeMultiplexer.h =================================================================== --- DeMultiplexer.h (revision 28016) +++ DeMultiplexer.h (working copy) @@ -219,6 +219,8 @@ bool m_bStarting; bool m_mpegParserTriggerFormatChange; + bool m_videoChanged; + bool m_audioChanged; bool m_bSetAudioDiscontinuity; bool m_bSetVideoDiscontinuity; CPcr m_subtitlePcr; Index: TsDuration.cpp =================================================================== --- TsDuration.cpp (revision 28016) +++ TsDuration.cpp (working copy) @@ -80,7 +80,6 @@ { m_bSearchStart=true; m_bSearchEnd=false; - m_bSearchMax=false; m_startPcr.Reset(); m_maxPcr.Reset(); m_reader->SetFilePointer(0,FILE_BEGIN); @@ -160,26 +159,9 @@ //and fill maxPcr if (m_endPcr.PcrReferenceBase < m_startPcr.PcrReferenceBase) { - //PCR rollover - m_bSearchMax=true; - m_bSearchEnd=false; - __int64 offset=sizeof(buffer); - while (!m_maxPcr.IsValid) - { - DWORD dwBytesRead; - m_reader->SetFilePointer(-offset,FILE_END); - if (!SUCCEEDED(m_reader->Read(buffer,sizeof(buffer),&dwBytesRead))) - { - break; - } - if (dwBytesRead==0) - { - break; - } - Reset() ; // Reset internal "PacketSync" buffer - OnRawData(buffer,dwBytesRead); - offset+=sizeof(buffer); - } + m_maxPcr.PcrReferenceBase = 0x1ffffffffULL; + m_maxPcr.PcrReferenceExtension = 0x1ffULL; + m_maxPcr.IsValid = true; } //park filepointer at end of file @@ -211,13 +193,6 @@ { m_endPcr=field.Pcr; } - if (m_bSearchMax && m_pid==header.Pid) - { - if (field.Pcr.ToClock() > m_startPcr.ToClock()) - { - m_maxPcr=field.Pcr; - } - } } } Index: TsDuration.h =================================================================== --- TsDuration.h (revision 28016) +++ TsDuration.h (working copy) @@ -41,5 +41,4 @@ CPcr m_firstStartPcr; bool m_bSearchStart; bool m_bSearchEnd; - bool m_bSearchMax; }; Index: TsFileSeek.cpp =================================================================== --- TsFileSeek.cpp (revision 28016) +++ TsFileSeek.cpp (working copy) @@ -38,7 +38,6 @@ CTsFileSeek::CTsFileSeek( CTsDuration& duration) :m_duration(duration) { - m_useBinarySearch = true; } CTsFileSeek::~CTsFileSeek(void) @@ -73,49 +72,35 @@ filePos/=188; filePos*=188; - if( m_duration.FirstStartPcr() > m_duration.EndPcr() ) - { - // no PCR rollover is allowed when using binary search with seeking - m_useBinarySearch = false; - } - else - { - m_useBinarySearch = true; - } - seekTimeStamp /= 1000.0f; // convert to seconds. m_seekPid=m_duration.GetPid(); LogDebug("seek to %f filepos:%x pid:%x", seekTimeStamp,(DWORD)filePos, m_seekPid); byte buffer[188*10]; - if (filePos<=0) - { - //no need to seek for timestamp 0, - //simply set the pointer at the beginning of the file - m_reader->SetFilePointer(0,FILE_BEGIN); - return; - } - if (filePos+sizeof(buffer) > m_reader->GetFileSize()) - { - //no need to seek when we want to seek to end of file - //simply set the pointer at the end of the file - m_reader->SetFilePointer(0,FILE_END); - return; - } - __int64 prevfilePos=filePos; __int64 binaryMax=m_reader->GetFileSize(); __int64 binaryMin=0; __int64 lastFilePos=0; int seekingIteration=0; - SeekState state=FindPcr; Reset() ; // Reset "PacketSync" while (true) { //sanity checks - if (filePos<0) return; - if (filePos+sizeof(buffer) > m_reader->GetFileSize()) return; + if (filePos<=0) + { + //no need to seek for timestamp 0, + //simply set the pointer at the beginning of the file + m_reader->SetFilePointer(0,FILE_BEGIN); + return; + } + if (filePos+sizeof(buffer) > m_reader->GetFileSize()) + { + //no need to seek when we want to seek to end of file + //simply set the pointer at the end of the file + m_reader->SetFilePointer(0,FILE_END); + return; + } //set filepointer to filePos m_reader->SetFilePointer(filePos,FILE_BEGIN); @@ -139,131 +124,56 @@ { //yes. pcr found double clockFound=m_pcrFound.ToClock(); - if( m_useBinarySearch ) + double diff = clockFound - seekTimeStamp; + //LogDebug(" got %f at filepos %x diff %f ( %I64x, %I64x )", clockFound, (DWORD)filePos, diff, binaryMin, binaryMax); + + // Make sure that seeking position is at least the target one + if (0 <= diff && diff <= SEEKING_ACCURACY) { - double diff = clockFound - seekTimeStamp; - //LogDebug(" got %f at filepos %x diff %f ( %I64x, %I64x )", clockFound, (DWORD)filePos, diff, binaryMin, binaryMax); - - // Make sure that seeking position is at least the target one - if (0 <= diff && diff <= SEEKING_ACCURACY) - { - LogDebug(" stop seek: %f at %x - target: %f, diff: %f", - clockFound, (DWORD)filePos, seekTimeStamp, diff); - m_reader->SetFilePointer(filePos,FILE_BEGIN); - return; - } + LogDebug(" stop seek: %f at %x - target: %f, diff: %f", + clockFound, (DWORD)filePos, seekTimeStamp, diff); + m_reader->SetFilePointer(filePos,FILE_BEGIN); + return; + } - seekingIteration++; - if( seekingIteration > MAX_SEEKING_ITERATIONS ) - { - LogDebug(" stop seek max iterations reached (%d): %f at %x - target: %f, diff: %f", - MAX_SEEKING_ITERATIONS, clockFound, (DWORD)filePos, seekTimeStamp, diff); - m_reader->SetFilePointer(filePos,FILE_BEGIN); - return; - } + seekingIteration++; + if( seekingIteration > MAX_SEEKING_ITERATIONS ) + { + LogDebug(" stop seek max iterations reached (%d): %f at %x - target: %f, diff: %f", + MAX_SEEKING_ITERATIONS, clockFound, (DWORD)filePos, seekTimeStamp, diff); + m_reader->SetFilePointer(filePos,FILE_BEGIN); + return; + } - // lower bound becomes valid - if( clockFound > seekTimeStamp ) - { - if (filePos < binaryMax) binaryMax = filePos-1; - } - else - { - if (filePos > binaryMin) binaryMin = filePos+1; - } - - if (lastFilePos==filePos) - { - LogDebug(" stop seek closer target found : %f at %x - target: %f, diff: %f", - clockFound, (DWORD)filePos, seekTimeStamp, diff); - m_reader->SetFilePointer(filePos,FILE_BEGIN); - return; - } - - lastFilePos=filePos; - filePos = binaryMin + ( binaryMax - binaryMin ) / 2; - Reset() ; // Random jump, Reset "PacketSync" + // lower bound becomes valid + if( clockFound > seekTimeStamp ) + { + if (filePos < binaryMax) binaryMax = filePos-1; } else { - if (state==FindPcr) - { - prevfilePos=filePos; - //we found the pcr. - //compare it with the timestamp we want to seek to - if (clockFound < seekTimeStamp) - { - // pcr found is too low, move forward in file and seek next pcr - state=FindNextPcr; - - //LogDebug(" got %f at filepos %x ->find next", clockFound, (DWORD)filePos); - filePos += sizeof(buffer); - } - else if (clockFound > seekTimeStamp) - { - // pcr found is too high, move backward in file and seek previous pcr - //LogDebug(" got %f at filepos %x ->find prev", clockFound, (DWORD)filePos); - state=FindPreviousPcr; - filePos -= sizeof(buffer); - Reset() ; // Backward jump, Reset "PacketSync" - } - else - { - //pcr is correct, just return - //LogDebug(" got %f", clockFound); - m_reader->SetFilePointer(filePos,FILE_BEGIN); - return; - } - } - else - { - //pcr found, check state - if (state==FindNextPcr) - { - //LogDebug(" got %f at filepos %x", clockFound, (DWORD)filePos); - //looking for a pcr > seektime - if (clockFound > seekTimeStamp) - { - //found it.. - //LogDebug(" stop seek too big: %f at %x", clockFound, (DWORD)filePos); - m_reader->SetFilePointer(prevfilePos,FILE_BEGIN); - return; - } - prevfilePos=filePos; - filePos+=sizeof(buffer); - } - else if (state==FindPreviousPcr) - { - //LogDebug(" got %f at filepos %x", clockFound, (DWORD)filePos); - //looking for a pcr < seektime - if (clockFound < seekTimeStamp) - { - //found it... - //LogDebug(" stop seek too small: %f at %x", clockFound, (DWORD)filePos); - m_reader->SetFilePointer(filePos,FILE_BEGIN); - return; - } - prevfilePos=filePos; - filePos-=sizeof(buffer); - Reset() ; // Backward jump, Reset "PacketSync" - } - } + if (filePos > binaryMin) binaryMin = filePos+1; } + + lastFilePos=filePos; + filePos = binaryMin + ( binaryMax - binaryMin ) / 2; + filePos/=188; + filePos*=188; + + if (lastFilePos==filePos) + { + LogDebug(" stop seek closer target found : %f at %x - target: %f, diff: %f", + clockFound, (DWORD)filePos, seekTimeStamp, diff); + m_reader->SetFilePointer(filePos,FILE_BEGIN); + return; + } + + Reset() ; // Random jump, Reset "PacketSync" } else // no first PCR { - //no pcr found. - if (state == FindPreviousPcr) - { - //move filepointer back and continue searching for a PCR - filePos -=sizeof(buffer); - Reset() ; // Backward jump, Reset "PacketSync" - } - else - { - //move filepointer forward and continue searching for a PCR - filePos += sizeof(buffer); - } + //move filepointer forward and continue searching for a PCR + filePos += sizeof(buffer); } } } @@ -290,7 +200,7 @@ { // pid is valid // did we have a pcr rollover ?? - if (m_duration.MaxPcr().IsValid) + if (m_duration.FirstStartPcr() > m_duration.EndPcr()) { //pcr rollover occured. //next we need to convert the pcr into filestamp @@ -298,23 +208,28 @@ //but the file can start with any pcr timestamp if (field.Pcr.ToClock() <=m_duration.EndPcr().ToClock()) { - // pcr < endpcr - // pcrFound= (pcr-startpcr) + // pcr < endpcr (second half of the file) + // pcrFound= pcr+(MAXIMUM_PCR - startpcr) + // StartPcr------>(0x1ffffffff;0x1ff), (0x0,0x0)--------->EndPcr m_pcrFound=field.Pcr; double d1=m_pcrFound.ToClock(); - double start=m_duration.StartPcr().ToClock();//earliest pcr available in the file - d1-=start; + CPcr pcr2; + pcr2.PcrReferenceBase = 0x1ffffffffULL; + pcr2.PcrReferenceExtension = 0x1ffULL; + double start=pcr2.ToClock()- m_duration.StartPcr().ToClock(); + d1+=start; m_pcrFound.FromClock(d1); } else { - //PCR > endpcr - // pcrFound- pcr+(maxPcr-startpcr) - // StartPcr------>MaxPcr--->0--------->EndPcr + //PCR > endpcr (first half of the file) + // pcrFound= (pcr-startpcr) m_pcrFound=field.Pcr; double d1=m_pcrFound.ToClock(); - double start=m_duration.MaxPcr().ToClock()- m_duration.StartPcr().ToClock(); - d1+=start; + double start=m_duration.StartPcr().ToClock();//earliest pcr available in the file + LogDebug(" found clock %f earliest is %f", d1, start); + d1-=start; + LogDebug(" after sub %f", d1); m_pcrFound.FromClock(d1); } } Index: TsFileSeek.h =================================================================== --- TsFileSeek.h (revision 28016) +++ TsFileSeek.h (working copy) @@ -8,12 +8,6 @@ class CTsFileSeek: public CPacketSync { public: - enum SeekState - { - FindPreviousPcr=-1, - FindPcr=0, - FindNextPcr=1 - }; CTsFileSeek( CTsDuration& duration ); virtual ~CTsFileSeek(void); void OnTsPacket(byte* tsPacket); @@ -25,5 +19,4 @@ CTsDuration& m_duration; CPcr m_pcrFound; int m_seekPid; - bool m_useBinarySearch; }; Index: TsReader.cpp =================================================================== --- TsReader.cpp (revision 28016) +++ TsReader.cpp (working copy) @@ -170,7 +170,8 @@ TCHAR filename[1024]; GetLogFile(filename); ::DeleteFile(filename); - LogDebug("---------- v0.4.12 -------------------"); + LogDebug("----- Graph rebuild testing ---------"); + LogDebug("---------- v0.4.14 XXX -------------------"); m_fileReader=NULL; m_fileDuration=NULL;