//---------------------------------------------------------------------------- //! @brief レンダリング前にコールされる //! //! メディアサンプルにメディアタイムを記録する。 //! メディアタイムは開始フレームに現在のストリーム時間を加算したものになる。 //! もし、フィルタのIMediaSeekingインターフェイスが利用できない場合は、 //! このレンダーフィルタが描画したフレーム数とドロップしたフレーム数を加算する。 //! この場合、より上位のフィルタでドロップしたフレーム数はわからないので、 //! 若干精度が落ちる。 //! @param pMediaSample : メディアサンプル //---------------------------------------------------------------------------- void TBufferRenderer::OnRenderStart( IMediaSample *pMediaSample ) { CBaseVideoRenderer::OnRenderStart(pMediaSample); HRESULT hr; bool bGetTime = false; LONGLONG Current = 0, Stop = 0; IMediaSeeking *mediaSeeking = NULL; if( GetMediaPositionInterface( IID_IMediaSeeking, (void**)&mediaSeeking) == S_OK ) { GUID Format; if( SUCCEEDED(hr = mediaSeeking->GetTimeFormat( &Format ) ) ) { if( SUCCEEDED(hr = mediaSeeking->GetCurrentPosition( &Current )) && SUCCEEDED(hr = mediaSeeking->GetStopPosition( &Stop )) ) { if( IsEqualGUID( TIME_FORMAT_MEDIA_TIME, Format ) ) { double renderTime = Current / 10000000.0; double stopTime = Stop / 10000000.0; REFTIME AvgTimePerFrame; // REFTIME : 秒数を示す小数を表す倍精度浮動小数点数。 if( SUCCEEDED( hr = get_AvgTimePerFrame( &AvgTimePerFrame ) ) ) { Current = (LONGLONG)(renderTime / AvgTimePerFrame + 0.5); Stop = (LONGLONG)(stopTime / AvgTimePerFrame + 0.5); bGetTime = true; } } else if( IsEqualGUID( TIME_FORMAT_FRAME, Format ) ) { bGetTime = true; } } } mediaSeeking->Release(); mediaSeeking = NULL; } LONGLONG TimeStart = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; LONGLONG TimeEnd = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; if( bGetTime == true ) { TimeStart = m_StartFrame + Current; TimeEnd = m_StartFrame + Current; m_StopFrame = m_StartFrame + static_cast<LONG>(Stop); } else { TimeStart = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; TimeEnd = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; m_StopFrame = 0; } pMediaSample->SetMediaTime( &TimeStart, &TimeEnd ); }
long video_get_seek(int id) { get_videor(videoStruct, id, -1); IMediaSeeking* pSeek; HRESULT hr = videoStruct->pGraph->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); DWORD dwCap = 0; hr = pSeek->GetCapabilities(&dwCap); long long position = 0; if (AM_SEEKING_CanSeekAbsolute & dwCap) { hr = pSeek->GetCurrentPosition(&position); } pSeek->Release(); return position; }
int main(int argc, char* argv[]) { ICaptureGraphBuilder2 *pCaptureGraphBuilder = NULL; IGraphBuilder *pGraphBuilder = NULL; IBaseFilter *pSource = NULL; IBaseFilter *pMux = NULL; IBaseFilter *pVideoCompressor = NULL; IBaseFilter *pAudioCompressor = NULL; IAMStreamConfig *pAMStreamConfig = NULL; IAMVideoCompression *pAMVideoCompression = NULL; IMediaControl *pControl = NULL; IMediaSeeking *pSeek = NULL; IMediaEvent *pEvent = NULL; HRESULT hr; DWORD pdwRegister=0; CoInitialize(NULL); // Create the capture graph builder. CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&pCaptureGraphBuilder); // Make the rendering section of the graph. pCaptureGraphBuilder->SetOutputFileName( &MEDIASUBTYPE_Avi, // File type. L"C:\\STDIUE1.avi", // File name. &pMux, // pointer to the multiplexer. NULL); // pointer to the file writer. // Load the source file. pCaptureGraphBuilder->GetFiltergraph(&pGraphBuilder); pGraphBuilder->AddSourceFilter(L"C:\\Program Files\\Microsoft Money\\Media\\STDIUE1.avi", L"Source Filter", &pSource); // Add the compressor filter. CoCreateInstance(CLSID_AVICo, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&pVideoCompressor); pGraphBuilder->AddFilter(pVideoCompressor, L"Video Compressor"); // Render the video stream, through the compressor. pCaptureGraphBuilder->RenderStream( NULL, // Output pin category NULL, // Media type pSource, // Source filter pVideoCompressor, // Compressor filter pMux); // Sink filter (the AVI Mux) /* CoCreateInstance(CLSID_GSM, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&pAudioCompressor); pGraphBuilder->AddFilter(pAudioCompressor, L"Audio Compressor");*/ // Render the audio stream. pCaptureGraphBuilder->RenderStream( NULL, NULL, pSource, pAudioCompressor, pMux); // Compress at 100k/second data rate. AM_MEDIA_TYPE *pmt; pCaptureGraphBuilder->FindInterface(NULL, NULL, pVideoCompressor, IID_IAMStreamConfig, (void **)&pAMStreamConfig); pAMStreamConfig->GetFormat(&pmt); if (pmt->formattype == FORMAT_VideoInfo) { ((VIDEOINFOHEADER *)(pmt->pbFormat))->dwBitRate = 100000; pAMStreamConfig->SetFormat(pmt); } // Request key frames every four frames. pAMStreamConfig->QueryInterface(IID_IAMVideoCompression, (void **)&pAMVideoCompression); pAMVideoCompression->put_KeyFrameRate(4); pAMVideoCompression->Release(); pAMStreamConfig->Release(); // Run the graph. pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pControl); pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pEvent); hr = pMux->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); pControl->Run(); printf("Recompressing... \n"); long evCode; if (SUCCEEDED(hr)) { REFERENCE_TIME rtTotal, rtNow = 0; pSeek->GetDuration(&rtTotal); while ((pEvent->WaitForCompletion(1000, &evCode)) == E_ABORT) { pSeek->GetCurrentPosition(&rtNow); printf("%d%%\n", (rtNow * 100)/rtTotal); } pSeek->Release(); } else // Cannot update the progress. { pEvent->WaitForCompletion(INFINITE, &evCode); } pControl->Stop(); printf("All done\n"); pSource->Release(); pMux->Release(); pVideoCompressor->Release(); pAudioCompressor->Release (); pControl->Release(); pEvent->Release(); pCaptureGraphBuilder->Release(); pGraphBuilder->Release(); CoUninitialize(); return 0; }
STDMETHODIMP CTsReaderFilter::Pause() { //m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO; //m_ShowBufferAudio = INIT_SHOWBUFFERAUDIO; LogDebug("CTsReaderFilter::Pause() - IsTimeShifting = %d - state = %d", IsTimeShifting(), m_State); CAutoLock cObjectLock(m_pLock); if (m_State == State_Running) { m_lastPause = GetTickCount(); m_RandomCompensation = 0; } //pause filter HRESULT hr=CSource::Pause(); if (!m_bPauseOnClockTooFast) { //are we using rtsp? if (m_fileDuration==NULL) { //yes, are we busy seeking? if (!IsSeeking()) { //not seeking, is rtsp streaming at the moment? if (!m_rtspClient.IsRunning()) { //not streaming atm double startTime=m_seekTime.Millisecs(); startTime/=1000.0; long Old_rtspDuration = m_rtspClient.Duration() ; //clear buffers LogDebug(" -- Pause() ->start rtsp from %f", startTime); m_buffer.Clear(); m_demultiplexer.Flush(); //start streaming m_buffer.Run(true); m_rtspClient.Play(startTime,0.0); // m_tickCount = GetTickCount(); LogDebug(" -- Pause() ->rtsp started"); //update the duration of the stream CPcr pcrStart, pcrEnd, pcrMax ; double duration = m_rtspClient.Duration() / 1000.0f ; if (m_bTimeShifting) { // EndPcr is continuously increasing ( until ~26 hours for rollover that will fail ! ) // So, we refer duration to End, and just update start. pcrEnd = m_duration.EndPcr() ; double start = pcrEnd.ToClock() - duration; if (start<0) start=0 ; pcrStart.FromClock(start) ; m_duration.Set( pcrStart, pcrEnd, pcrMax) ; // Pause()-RTSP } else { // It's a record, eventually end can increase if recording is in progress, let the end virtually updated by ThreadProc() //m_bRecording = (Old_rtspDuration != m_rtspClient.Duration()) ; m_bRecording = true; // duration may have not increased in such a short time } LogDebug("Timeshift %d, Recording %d, StartPCR %f, EndPcr %f, Duration %f",m_bTimeShifting,m_bRecording,m_duration.StartPcr().ToClock(),m_duration.EndPcr().ToClock(),(float)m_duration.Duration().Millisecs()/1000.0f) ; } else { //we are streaming at the moment. //query the current position, so it can resume on un-pause at this position //can be required in multiseat with rtsp when changing audio streams IMediaSeeking * ptrMediaPos; if (SUCCEEDED(GetFilterGraph()->QueryInterface(IID_IMediaSeeking, (void**)&ptrMediaPos))) { ptrMediaPos->GetCurrentPosition(&m_seekTime.m_time); ptrMediaPos->Release(); } //pause the streaming LogDebug(" -- Pause() ->pause rtsp at position: %f", (m_seekTime.Millisecs() / 1000.0f)); m_rtspClient.Pause(); } } else //we are seeking { IMediaSeeking * ptrMediaPos; if (SUCCEEDED(GetFilterGraph()->QueryInterface(IID_IMediaSeeking, (void**)&ptrMediaPos))) { LONGLONG currentPos; ptrMediaPos->GetCurrentPosition(¤tPos); ptrMediaPos->Release(); double clock = currentPos;clock /= 10000000.0; float clockEnd = m_duration.EndPcr().ToClock() ; if (clock >= clockEnd && clockEnd > 0 ) { LogDebug("End of rtsp stream..."); m_demultiplexer.SetEndOfFile(true); } } } } m_demultiplexer.m_LastDataFromRtsp = GetTickCount() ; } //is the duration update thread running? if (!IsThreadRunning()) { //nop? then start it //LogDebug(" CTsReaderFilter::Pause()->start duration thread"); StartThread(); } LogDebug("CTsReaderFilter::Pause() - END - state = %d", m_State); return hr; }
void recChannel_t::posReaderThread(void) { __int64 position = 0; __int64 duration = 0; Sleep(1000); while (!fControl) { Sleep(1000); } fControl->slideMoved = true; IMediaSeeking * pSeek = NULL; while(true) { int hr = pGraph->QueryInterface(IID_IMediaSeeking,(void **)&pSeek); //read file pos and put at slicer if (pSeek && hr == S_OK) { if (!fControl->play & fControl->event) { pControl->StopWhenReady(); fControl->event = false; continue; } if (fControl->play & fControl->event) { pControl->Run(); fControl->event = false; } if (fControl->slideMoved) { position = fControl->m_slide.GetPos(); position *=1000000; fControl->slideMoved = false; pSeek->SetPositions(&position, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); }else{ if (!duration) { pSeek->GetDuration(&duration); duration /= 1000000; fControl->m_slide.SetRangeMin(0,true); fControl->m_slide.SetRangeMax(duration,true); } pSeek->GetCurrentPosition(&position); position /= 1000000; fControl->m_slide.SetPos(position); } } pSeek->Release(); Sleep(1000); } }