Index: DeMultiplexer.cpp =================================================================== --- DeMultiplexer.cpp (revision 28131) +++ 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) @@ -87,7 +85,12 @@ m_iAudioReadCount = 0; m_lastVideoPTS.IsValid = false; m_lastAudioPTS.IsValid = false; + m_bFlushOnPTSJump = false; + m_bFlushOnPESError = false; + m_bHoldFileRead = false; m_mpegParserTriggerFormatChange = false; + m_videoChanged=false; + m_audioChanged=false; SetMediaChanging(false); SetAudioChanging(false); m_DisableDiscontinuitiesFiltering = false; @@ -397,13 +400,16 @@ m_FirstVideoSample = 0x7FFFFFFF00000000LL; m_LastVideoSample = 0; m_lastVideoPTS.IsValid = false; - m_VideoValidPES = true; + m_VideoValidPES = false; m_mVideoValidPES = false; m_WaitHeaderPES=-1 ; m_bVideoAtEof=false; m_MinVideoDelta = 10.0 ; m_filter.m_bRenderingClockTooFast=false ; - + m_bFlushOnPTSJump = false; + m_bFlushOnPESError = false; + m_bSetVideoDiscontinuity=true; + Reset(); // PacketSync reset. } @@ -437,7 +443,10 @@ m_bAudioAtEof = false; m_MinAudioDelta = 10.0; m_filter.m_bRenderingClockTooFast=false; - + m_bFlushOnPTSJump = false; + m_bFlushOnPESError = false; + m_bSetAudioDiscontinuity=true; + Reset(); // PacketSync reset. } @@ -461,6 +470,9 @@ { LogDebug("demux:flushing"); + m_bHoldFileRead = true; //Stop file reads in ReadFromFile() + CAutoLock lock (&m_sectionRead); + m_iAudioReadCount = 0; m_LastDataFromRtsp = GetTickCount(); bool holdAudio = HoldAudio(); @@ -475,6 +487,7 @@ SetHoldAudio(holdAudio); SetHoldVideo(holdVideo); SetHoldSubtitle(holdSubtitle); + m_bHoldFileRead = false; } /// @@ -620,6 +633,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; @@ -633,6 +648,7 @@ { int BytesRead =ReadFromFile(false,false); if (BytesRead==0) Sleep(10); + // LogDebug("demux:Start() BytesRead:%d, BytesProcessed:%d", BytesRead, dwBytesProcessed); if (dwBytesProcessed>INITIAL_READ_SIZE || GetAudioStreamCount()>0) { #ifdef USE_DYNAMIC_PINS @@ -647,6 +663,7 @@ Flush(); m_streamPcr.Reset(); m_bStarting=false; + LogDebug("demux:Start() end1 BytesProcessed:%d", dwBytesProcessed); return; } dwBytesProcessed+=BytesRead; @@ -654,6 +671,7 @@ m_streamPcr.Reset(); m_iAudioReadCount=0; m_bStarting=false; + LogDebug("demux:Start() end2 BytesProcessed:%d", dwBytesProcessed); } void CDeMultiplexer::SetEndOfFile(bool bEndOfFile) @@ -674,7 +692,8 @@ { // if (m_bWeos) return 0 ; // if (IsAudioChanging()) return 0 ; // Do not read any data during stream selection from MP C# - if (m_filter.IsSeeking()) return 0; // Ambass : to check + if (m_filter.IsSeeking() || m_bHoldFileRead) return 0; // Ambass : to check + CAutoLock lock (&m_sectionRead); if (m_reader==NULL) return false; byte buffer[READ_SIZE]; @@ -773,6 +792,7 @@ /// - decode any audio/video packets and put the PES packets in the appropiate buffers void CDeMultiplexer::OnTsPacket(byte* tsPacket) { + //LogDebug("OnTsPacket() start"); CTsHeader header(tsPacket); m_patParser.OnTsPacket(tsPacket); @@ -847,10 +867,16 @@ return; } +// //process the ts packet further +// FillSubtitle(header,tsPacket); +// FillAudio(header,tsPacket); +// FillVideo(header,tsPacket); +// FillTeletext(header,tsPacket); + //process the ts packet further + FillVideo(header,tsPacket); + FillAudio(header,tsPacket); FillSubtitle(header,tsPacket); - FillAudio(header,tsPacket); - FillVideo(header,tsPacket); FillTeletext(header,tsPacket); } @@ -879,7 +905,10 @@ if(!CheckContinuity(m_AudioPrevCC, header)) { LogDebug("Audio Continuity error... %x ( prev %x )", header.ContinuityCounter, m_AudioPrevCC); - if (!m_DisableDiscontinuitiesFiltering) m_AudioValidPES=false; + if (!m_DisableDiscontinuitiesFiltering) + { + m_AudioValidPES=false; + } } m_AudioPrevCC = header.ContinuityCounter; @@ -888,7 +917,26 @@ //does tspacket contain the start of a pes packet? if (header.PayloadUnitStart) { - //yes packet contains start of a pes packet. + //Sanity check PES header + int posn=header.PayLoadStart; + if ( + ((tsPacket[posn+0]!=0) || (tsPacket[posn+1]!=0) || (tsPacket[posn+2]!=1)) //Invalid start code + || ((tsPacket[posn+3] & 0x80)==0) //Invalid stream ID + || ((tsPacket[posn+6] & 0xC0)!=0x80) //Invalid marker bits + || ((tsPacket[posn+6] & 0x20)==0x20) //Payload scrambled + ) + { + //Discard this new/current PES packet + m_AudioValidPES=false; + m_bSetAudioDiscontinuity=true; + LogDebug("PES audio 0-0-1 fail"); + //Flushing is delegated to CTsReaderFilter::ThreadProc() + m_bFlushOnPESError = true; + m_filter.WakeThead(); + return; + } + + //yes, packet contains start of a pes packet. //does current buffer hold any data ? if (m_pCurrentAudioBuffer->Length() > 0) { @@ -896,18 +944,17 @@ m_pCurrentAudioBuffer = new CBuffer(); } - if (m_t_vecAudioBuffers.size()) + if (m_t_vecAudioBuffers.size()) //Process the previous PES packet { CBuffer *Cbuf=*m_t_vecAudioBuffers.begin(); byte *p = Cbuf->Data() ; - if ((p[0]==0) && (p[1]==0) && (p[2]==1) //Valid start code - && ((p[3] & 0x80)!=0) //Valid stream ID - && ((p[6] & 0xC0)==0x80) //Valid marker bits - && ((p[6] & 0x20)!=0x20)) //Payload not scrambled + + if (m_AudioValidPES) { //get pts/dts from pes header CPcr pts; CPcr dts; + if (CPcr::DecodeFromPesHeader(p,0,pts,dts)) { double diff; @@ -917,10 +964,16 @@ diff=m_lastAudioPTS.ToClock()-pts.ToClock(); else diff=pts.ToClock()-m_lastAudioPTS.ToClock(); - if (diff>10.0) + if (diff>2.0) { + //Large PTS jump - flush the world... LogDebug("DeMultiplexer::FillAudio pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastAudioPTS.ToClock()); - m_AudioValidPES=false; + m_lastAudioPTS.IsValid=false; + m_lastVideoPTS.IsValid=false; + m_bSetAudioDiscontinuity=true; + //Flushing is delegated to CTsReaderFilter::ThreadProc() + m_bFlushOnPTSJump = true; + m_filter.WakeThead(); } else { @@ -960,14 +1013,9 @@ else { LogDebug(" No data"); - m_AudioValidPES=false; + m_AudioValidPES=false; //stop further processing } } - else - { - LogDebug("Pes header 0-0-1 fail"); - m_AudioValidPES=false; - } if (m_AudioValidPES) { @@ -1012,7 +1060,7 @@ delete *it; m_t_vecAudioBuffers.erase(it); } - m_bSetAudioDiscontinuity = true; + m_bSetAudioDiscontinuity = true; //Next good packet will be discontinuous } } m_AudioValidPES = true; @@ -1056,7 +1104,10 @@ if (!CheckContinuity(m_VideoPrevCC, header)) { LogDebug("Video Continuity error... %x ( prev %x )", header.ContinuityCounter, m_VideoPrevCC); - if (!m_DisableDiscontinuitiesFiltering) m_VideoValidPES = false; + if (!m_DisableDiscontinuitiesFiltering) + { + m_VideoValidPES = false; + } } m_VideoPrevCC = header.ContinuityCounter; @@ -1072,7 +1123,6 @@ } else { - //ParseVideoH264(header, tsPacket); FillVideoH264(header, tsPacket); } } @@ -1120,13 +1170,23 @@ return; } - if ((start[0]!=0) || (start[1]!=0) || (start[2]!=1) //Invalid start code - || ((start[3] & 0x80)==0)) //Invalid stream ID + if ( + ((start[0]!=0) || (start[1]!=0) || (start[2]!=1)) //Invalid start code + || ((start[3] & 0x80)==0) //Invalid stream ID + || ((start[6] & 0xC0)!=0x80) //Invalid marker bits + || ((start[6] & 0x20)==0x20) //Payload scrambled + ) { - LogDebug("Pes 0-0-1 fail"); + LogDebug("Pes H264 0-0-1 fail"); m_VideoValidPES=false; + m_mVideoValidPES = false; m_p->rtStart = Packet::INVALID_TIME; m_WaitHeaderPES = -1; + m_bSetVideoDiscontinuity=true; + //Flushing is delegated to CTsReaderFilter::ThreadProc() + m_bFlushOnPESError = true; + m_filter.WakeThead(); + return; } else { @@ -1137,11 +1197,6 @@ } else { // full PES header is available. - if ((start[6] & 0xC0)!=0x80 //Invalid marker bits - || (start[6] & 0x20)==0x20) //Payload scrambled - { - return; - } CPcr pts; CPcr dts; @@ -1155,14 +1210,19 @@ diff=m_lastVideoPTS.ToClock()-pts.ToClock(); else diff=pts.ToClock()-m_lastVideoPTS.ToClock(); - if (diff>10.0) + if (diff>2.0) { - LogDebug("DeMultiplexer::FillVideo pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock()); - m_VideoValidPES=false; + //Large PTS jump - flush the world... + LogDebug("DeMultiplexer::FillVideoH264 pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock()); + m_lastAudioPTS.IsValid=false; + m_lastVideoPTS.IsValid=false; + //Flushing is delegated to CTsReaderFilter::ThreadProc() + m_bFlushOnPTSJump = true; + m_filter.WakeThead(); } else { - // LogDebug("DeMultiplexer::FillVideo pts : %f ", (float)pts.ToClock()); + //LogDebug("DeMultiplexer::FillVideoH264 pts diff : %f ", (float)pts.ToClock()); m_lastVideoPTS=pts; } } @@ -1323,26 +1383,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; @@ -1421,13 +1500,23 @@ return; } - if ((start[0]!=0) || (start[1]!=0) || (start[2]!=1) //Invalid start code - || ((start[3] & 0x80)==0)) //Invalid stream ID + if ( + ((start[0]!=0) || (start[1]!=0) || (start[2]!=1)) //Invalid start code + || ((start[3] & 0x80)==0) //Invalid stream ID + || ((start[6] & 0xC0)!=0x80) //Invalid marker bits + || ((start[6] & 0x20)==0x20) //Payload scrambled + ) { - LogDebug("Pes 0-0-1 fail"); - m_VideoValidPES=false; + LogDebug("Pes MPEG2 0-0-1 fail"); + m_VideoValidPES = false; + m_mVideoValidPES = false; m_p->rtStart = Packet::INVALID_TIME; m_WaitHeaderPES = -1; + m_bSetVideoDiscontinuity=true; + //Flushing is delegated to CTsReaderFilter::ThreadProc() + m_bFlushOnPESError = true; + m_filter.WakeThead(); + return; } else { @@ -1438,15 +1527,10 @@ } else { // full PES header is available. - if ((start[6] & 0xC0)!=0x80 //Invalid marker bits - || (start[6] & 0x20)==0x20) //Payload scrambled - { - return; - } CPcr pts; CPcr dts; -// m_VideoValidPES=true ; + m_VideoValidPES=true ; if (CPcr::DecodeFromPesHeader(start,0,pts,dts)) { double diff; @@ -1456,10 +1540,15 @@ diff=m_lastVideoPTS.ToClock()-pts.ToClock(); else diff=pts.ToClock()-m_lastVideoPTS.ToClock(); - if (diff>10.0) + if (diff>2.0) { - LogDebug("DeMultiplexer::FillVideo pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock()); - m_VideoValidPES=false; + //Large PTS jump - flush the world... + LogDebug("DeMultiplexer::FillVideoMPEG2 pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock()); + m_lastAudioPTS.IsValid=false; + m_lastVideoPTS.IsValid=false; + //Flushing is delegated to CTsReaderFilter::ThreadProc() + m_bFlushOnPTSJump = true; + m_filter.WakeThead(); } else { @@ -1536,7 +1625,7 @@ m_pl.AddTail(p2); // LogDebug("DeMultiplexer::FillVideo Frame length : %d %x %x", size, *(DWORD*)start, *(DWORD*)next); - if (m_VideoValidPES) + if (m_mVideoValidPES) { CAutoPtr p(new Packet()); p = m_pl.RemoveHead(); @@ -1635,29 +1724,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 = true; + m_bSetVideoDiscontinuity = !m_mVideoValidPES; } - m_VideoValidPES=true ; // We've just completed a frame, set flag until problem clears it + //m_VideoValidPES=true ; // We've just completed a frame, set flag until problem clears it m_pl.RemoveAll() ; } else // sequence_header_code @@ -1772,6 +1877,8 @@ { //CAutoLock lock (&m_section); CPidTable pids=info.PidTable; + + //LogDebug("OnNewChannel callback, pat version:%d->%d",m_iPatVersion, info.PatVersion); if (info.PatVersion != m_iPatVersion) { @@ -1860,22 +1967,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? 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; @@ -1891,7 +2011,7 @@ if (m_filter.GetAudioPin()->IsConnected()) { changed=true; - audioChanged=true; + m_audioChanged=true; } } @@ -1899,10 +2019,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); @@ -1922,10 +2042,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 28131) +++ DeMultiplexer.h (working copy) @@ -133,6 +133,9 @@ bool m_DisableDiscontinuitiesFiltering; DWORD m_LastDataFromRtsp; bool m_bAudioVideoReady; + bool m_bFlushOnPTSJump; + bool m_bFlushOnPESError; + bool m_bHoldFileRead; private: struct stAudioStream @@ -219,6 +222,8 @@ bool m_bStarting; bool m_mpegParserTriggerFormatChange; + bool m_videoChanged; + bool m_audioChanged; bool m_bSetAudioDiscontinuity; bool m_bSetVideoDiscontinuity; CPcr m_subtitlePcr; Index: TsReader.cpp =================================================================== --- TsReader.cpp (revision 28131) +++ TsReader.cpp (working copy) @@ -170,7 +170,8 @@ TCHAR filename[1024]; GetLogFile(filename); ::DeleteFile(filename); - LogDebug("---------- v0.4.12 -------------------"); + LogDebug("----- Continue after corruption testing ---------"); + LogDebug("---------- v0.4.19 XXX -------------------"); m_fileReader=NULL; m_fileDuration=NULL; @@ -1136,7 +1137,9 @@ /// Every second it will check the stream or local file and determine the total duration of the file/stream /// The duration can/will grow if we are playing a timeshifting buffer/stream // If the duration has changed it will update m_duration and send a EC_LENGTH_CHANGED event -// to the graph +// to the graph. +// Flushing after large video/audio PTS jump and PES '0-0-1 fail' errors +// are also delegated to this thread. void CTsReaderFilter::ThreadProc() { LogDebug("CTsReaderFilter::ThreadProc start()"); @@ -1152,6 +1155,39 @@ //since we're no longer playing if (m_demultiplexer.EndOfFile()) break; + + //Flushing after a PES '0-0-1 fail' error is delegated to this thread + if (m_demultiplexer.m_bFlushOnPESError) + { + LogDebug("CTsReaderFilter::ThreadProc FlushOnPESError start"); + m_demultiplexer.m_bFlushOnPESError = false; + + //Flush the internal data + m_demultiplexer.Flush(); + m_bStreamCompensated=false ; + m_demultiplexer.m_bAudioVideoReady=false ; + + LogDebug("CTsReaderFilter::ThreadProc FlushOnPESError end"); + Sleep(400); + continue; + } + + //Flushing after large video/audio PTS jump is delegated to this thread + if (m_demultiplexer.m_bFlushOnPTSJump) + { + LogDebug("CTsReaderFilter::ThreadProc FlushOnPTSJump start"); + m_demultiplexer.m_bFlushOnPTSJump = false; + + //Flush the internal data + m_demultiplexer.Flush(); + m_bStreamCompensated=false ; + m_demultiplexer.m_bAudioVideoReady=false ; + + LogDebug("CTsReaderFilter::ThreadProc FlushOnPTSJump end"); + Sleep(400); + continue; + } + //are we playing an RTSP stream? if (m_fileDuration!=NULL) { @@ -1251,6 +1287,7 @@ } } } + } while (!ThreadIsStopping(1000)) ; LogDebug("CTsReaderFilter::ThreadProc stopped()"); Index: TSThread.cpp =================================================================== --- TSThread.cpp (revision 28131) +++ TSThread.cpp (working copy) @@ -51,6 +51,7 @@ { m_hStopEvent = CreateEvent(NULL, TRUE, TRUE, NULL); m_hDoneEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + m_hWakeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //Auto-reset m_threadHandle = INVALID_HANDLE_VALUE; m_bThreadRunning=FALSE; } @@ -60,6 +61,7 @@ StopThread(); CloseHandle(m_hStopEvent); CloseHandle(m_hDoneEvent); + CloseHandle(m_hWakeEvent); } @@ -102,10 +104,34 @@ return hr; } +void TSThread::WakeThead() +{ + if (m_bThreadRunning) + { + SetEvent(m_hWakeEvent); + } +} + BOOL TSThread::ThreadIsStopping(DWORD dwTimeoutMilliseconds) { - DWORD result = WaitForSingleObject(m_hStopEvent, dwTimeoutMilliseconds); - return (result != WAIT_TIMEOUT); + HANDLE hEvts[] = {m_hStopEvent, m_hWakeEvent}; + + DWORD result = WaitForMultipleObjects(2, hEvts, FALSE, dwTimeoutMilliseconds); + switch (result) + { + case WAIT_OBJECT_0 : //m_hStopEvent + return true; + break; + case WAIT_OBJECT_0 + 1 : //m_hWakeEvent + ResetEvent(m_hWakeEvent); + return false; + break; + case WAIT_TIMEOUT : //Timeout + return false; + break; + default : //Error conditions + return true; + } } void TSThread::InternalThreadProc() Index: TSThread.h =================================================================== --- TSThread.h (revision 28131) +++ TSThread.h (working copy) @@ -36,6 +36,7 @@ virtual void ThreadProc() = 0; HRESULT StartThread(); HRESULT StopThread(DWORD dwTimeoutMilliseconds = 1000); + void WakeThead(); BOOL ThreadIsStopping(DWORD dwTimeoutMilliseconds = 10); BOOL IsThreadRunning(); @@ -43,6 +44,7 @@ virtual void InternalThreadProc(); HANDLE m_hDoneEvent; HANDLE m_hStopEvent; + HANDLE m_hWakeEvent; private: BOOL m_bThreadRunning;