// // Run // STDMETHODIMP CDVBSub::Run( REFERENCE_TIME tStart ) { CAutoLock cObjectLock( m_pLock ); LogDebug( "CDVBSub::Run" ); m_startTimestamp = tStart; HRESULT hr = CBaseFilter::Run( tStart ); if( hr != S_OK ) { LogDebug( "CDVBSub::Run - BaseFilter returned %i", hr ); return hr; } // Get media seeking interface if missing if( !m_pIMediaSeeking ) { IFilterGraph *pGraph = GetFilterGraph(); if( pGraph ) { pGraph->QueryInterface( &m_pIMediaSeeking ); pGraph->Release(); } } LogDebug( "CDVBSub::Run - done" ); return hr; }
// // OnConnect // // Called when the property page connects to a filter // HRESULT CProgramProperties::OnConnect(IUnknown *pUnknown) { ASSERT(m_pProgram == NULL); CheckPointer(pUnknown,E_POINTER); HRESULT hr = pUnknown->QueryInterface(IID_IMpeg2PsiParser, (void **) &m_pProgram); if(FAILED(hr)) { return E_NOINTERFACE; } ASSERT(m_pProgram); IBaseFilter * pParserFilter ; hr = m_pProgram->QueryInterface(IID_IBaseFilter, (void **) &pParserFilter); RETURN_FALSE_IF_FAILED(TEXT("CProgramProperties::OnUpdate() QueryInterface() failed."), hr); FILTER_INFO Info; IFilterGraph * pGraph; hr = pParserFilter->QueryFilterInfo(&Info); RETURN_FALSE_IF_FAILED(TEXT("CProgramProperties::OnUpdate() QueryFilterInfo() failed."), hr); pGraph = Info.pGraph; pParserFilter->Release(); hr = pGraph->QueryInterface(IID_IGraphBuilder, (void **) & m_pGraphBuilder); RETURN_FALSE_IF_FAILED(TEXT("CProgramProperties::OnUpdate() QueryInterface() failed."), hr); // get demux filter hr = GetDemuxFilter(pGraph, &m_pDemux); RETURN_FALSE_IF_FAILED(TEXT("CProgramProperties::OnUpdate() GetDemuxFilter() failed."), hr); pGraph->Release(); // if there is no streaming, the following variables will not be initialized. if(m_pDemux != NULL && m_pGraphBuilder != NULL){ hr = m_pGraphBuilder->QueryInterface(IID_IMediaControl, (void **) & m_pMediaControl); RETURN_FALSE_IF_FAILED( TEXT(" CProgramProperties::OnUpdate():Failed to QI IMediaControl."), hr); // Get the initial Program value m_pProgram->GetTransportStreamId( &m_stream_id); m_pProgram->GetPatVersionNumber( &m_pat_version); m_pProgram->GetCountOfPrograms( &m_number_of_programs ); } if(!OnUpdate()) return FALSE; return NOERROR; }
void CSubtitlePin::LogCurrentPosition() { IFilterGraph* pGraph = m_pTsReaderFilter->GetFilterGraph(); IMediaSeeking* pMediaSeeking( NULL ); if( pGraph ) { pGraph->QueryInterface( &pMediaSeeking ); pGraph->Release(); } LONGLONG pos( 0 ); pMediaSeeking->GetCurrentPosition( &pos ); //pMediaSeeking->Release(); float fPos = (float)pos; fPos = ( ( fPos / 10000000 ) ); LogDebug("sub current position %f", fPos ); }
DWORD WINAPI PushDataThread(PVOID param) { PushParam* pushParam = (PushParam*)param; HANDLE PushSemaphore = pushParam->PushSemaphore; HANDLE PushDataMutex = pushParam->PushDataMutex; NetReceiveFilter* filter = pushParam->filter; std::map<REFERENCE_TIME, IMediaSample*>& SampleList = *pushParam->SampleList; delete pushParam; REFERENCE_TIME startTime,endTime; CRefTime streamTime(LONG(0)),lastStreamTime(LONG(0)); bool first = true; AM_MEDIA_TYPE mediaType; IMediaSample* sample ; while (SampleList.size() == 0) //等待足够多的数据 { WaitForSingleObject(PushSemaphore,INFINITE); } CBasePin* pin = filter->GetPin(0); pin->ConnectionMediaType(&mediaType); IFilterGraph* filterGraph = filter->GetFilterGraph(); ComReleaser filterGraphReleaser(filterGraph); HRESULT hr; IMediaControl* mediaControl; hr = filterGraph->QueryInterface(IID_IMediaControl, (void**)&mediaControl); if(FAILED(hr)) { ErrorPrint("Get media control error", hr); return false; } ComReleaser mediaControlReleaser(mediaControl); while (true) { WaitForSingleObject(PushDataMutex, INFINITE); if (filter->getPlayMode() == 0) // 如果只是尽快播放,则不考虑时间戳,而且一次一sample的往下传 { if (SampleList.size() == 0) { ReleaseMutex(PushDataMutex); while (SampleList.size() == 0) { WaitForSingleObject(PushSemaphore,INFINITE); } WaitForSingleObject(PushDataMutex, INFINITE); } sample = SampleList.begin()->second; } else if (filter->getPlayMode() == 1) //需要考虑时间戳 { NetReceiveFilter::State state = filter->getState(); if (SampleList.size() == 0) { g_ReferenceTimeFilter->pauseTime(); //暂停时钟 ReleaseMutex(PushDataMutex); while (SampleList.size() == 0) //等待足够多的数据 { WaitForSingleObject(PushSemaphore,INFINITE); } WaitForSingleObject(PushDataMutex, INFINITE); g_ReferenceTimeFilter->startTime(); //启动时钟 } if (state == NetReceiveFilter::Stopped) { ReleaseMutex(PushDataMutex); Sleep(50); continue; } if(g_ReferenceTimeFilter->isStop()) { ReleaseMutex(PushDataMutex); Sleep(50); continue; } sample = SampleList.begin()->second; sample->GetTime(&startTime,&endTime); filter->StreamTime(streamTime); //得到当前的流时间 g_ReferenceTimeFilter->GetTime(&startTime); g_ReferenceTimeFilter->GetTime(&endTime); if (mediaType.majortype == MEDIATYPE_Video) { int a = 0; } else { int b = 0; } if(state != NetReceiveFilter::Paused) //pause时不修正 { if(startTime - 10000000 > streamTime ) { ReleaseMutex(PushDataMutex); Sleep(50); continue; } sample->SetTime(&startTime, &endTime); } if (mediaType.majortype == MEDIATYPE_Video) { int a = 0; } else { int b = 0; } } // if (mediaType.majortype == MEDIATYPE_Video) // { // std::cout<<"Push video data."<<std::endl; // } SampleList.erase(SampleList.begin()); ReleaseMutex(PushDataMutex); if(!filter->PushData(sample)) { ErrorPrint("Push data error"); sample->Release(); continue; } sample->Release(); } return 0; }
DWORD WINAPI CBDReaderFilter::CommandThread() { SetThreadName(-1, "BDReader_COMMAND"); IFilterGraph* pGraph = NULL; pGraph = GetFilterGraph(); if (pGraph) { pGraph->QueryInterface(&m_pMediaSeeking); pGraph->Release(); } HANDLE handles[2]; handles[0] = m_hStopCommandThreadEvent; handles[1] = m_hCommandEvent; if (m_pMediaSeeking) { while(1) { //DWORD result = WaitForMultipleObjects(2, handles, false, 40); DWORD result = WaitForMultipleObjects(2, handles, false, INFINITE); if (result == WAIT_OBJECT_0) // exit event { LogDebug("CBDReaderFilter::Command thread: closing down"); return 0; } /* else if (result == WAIT_TIMEOUT) { LONGLONG pos = 0; HRESULT hr = m_pMediaSeeking->GetCurrentPosition(&pos); if (SUCCEEDED(hr)) { lib.ProvideUserInput(CONVERT_DS_90KHz(pos), BD_VK_NONE); } } */ else if (result == WAIT_OBJECT_0 + 1) // command in queue { LONGLONG posEnd = 0; LONGLONG zeroPos = 0; m_pMediaSeeking->GetDuration(&posEnd); ivecCommandQueue it; DS_CMD cmd; { // just fetch the command and release the lock CAutoLock lock(&m_csCommandQueue); it = m_commandQueue.begin(); cmd = (*it); m_commandQueue.erase(it); if (m_commandQueue.empty()) { ResetEvent(m_hCommandEvent); } } switch (cmd.id) { case REBUILD: { LogDebug("CBDReaderFilter::Command thread: issue rebuild!"); LONGLONG pos = 0; if (cmd.refTime.m_time < 0) { CAutoLock lock(&m_csClock); pos = m_rtCurrentTime; } else pos = cmd.refTime.m_time; m_eRebuild.Reset(); TriggerOnMediaChanged(); m_eRebuild.Wait(); if (m_bRebuildOngoing) { LogDebug("CBDReaderFilter::Command thread: graph rebuild has failed?"); return 0; } m_bUpdateStreamPositionOnly = true; LogDebug("CBDReaderFilter::Command thread: seek - pos: %06.3f (rebuild)", cmd.refTime.Millisecs() / 1000.0); m_pMediaSeeking->SetPositions(&pos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_FakeSeek, &posEnd, AM_SEEKING_NoPositioning); m_eSeekDone.Wait(); m_eSeekDone.Reset(); m_demultiplexer.SetMediaChanging(false); m_demultiplexer.m_bRebuildOngoing = false; break; } case SEEK: m_bUpdateStreamPositionOnly = true; LogDebug("CBDReaderFilter::Command thread: seek requested - pos: %06.3f", cmd.refTime.Millisecs() / 1000.0); HRESULT hr = m_pMediaSeeking->SetPositions((LONGLONG*)&cmd.refTime.m_time, AM_SEEKING_AbsolutePositioning | AM_SEEKING_FakeSeek, &posEnd, AM_SEEKING_NoPositioning); m_eSeekDone.Wait(); m_eSeekDone.Reset(); break; } } else { DWORD error = GetLastError(); LogDebug("CBDReaderFilter::Command thread: WaitForMultipleObjects failed: %d", error); } } } return 0; }
HRESULT TffdshowVideoInputPin::CheckMediaType(const CMediaType* mt) { if (mt->majortype != MEDIATYPE_Video && !(mt->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && supdvddec)) { return VFW_E_TYPE_NOT_ACCEPTED; } if (mt->subtype == MEDIASUBTYPE_DVD_SUBPICTURE) { return VFW_E_TYPE_NOT_ACCEPTED; } BITMAPINFOHEADER *hdr = NULL, hdr0; if (mt->formattype == FORMAT_VideoInfo) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt->pbFormat; hdr = &vih->bmiHeader; fixMPEGinAVI(hdr->biCompression); } else if (mt->formattype == FORMAT_VideoInfo2) { VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)mt->pbFormat; hdr = &vih2->bmiHeader; fixMPEGinAVI(hdr->biCompression); } else if (mt->formattype == FORMAT_MPEGVideo) { MPEG1VIDEOINFO *mpeg1info = (MPEG1VIDEOINFO*)mt->pbFormat; hdr = &(hdr0 = mpeg1info->hdr.bmiHeader); hdr->biCompression = FOURCC_MPG1; } else if (mt->formattype == FORMAT_MPEG2Video) { MPEG2VIDEOINFO *mpeg2info = (MPEG2VIDEOINFO*)mt->pbFormat; hdr = &(hdr0 = mpeg2info->hdr.bmiHeader); if (hdr->biCompression == 0 || hdr->biCompression == 0x0038002d) { if (mt->subtype == MEDIASUBTYPE_H264_TRANSPORT) { hdr->biCompression = FOURCC_H264; } else if (mt->subtype == MEDIASUBTYPE_AVC1 || mt->subtype == MEDIASUBTYPE_avc1 || mt->subtype == MEDIASUBTYPE_H264 || mt->subtype == MEDIASUBTYPE_h264 || mt->subtype == MEDIASUBTYPE_CCV1) { hdr->biCompression = FOURCC_H264; } else { hdr->biCompression = FOURCC_MPG2; } } } else if (mt->formattype == FORMAT_TheoraIll) { sTheoraFormatBlock *oggFormat = (sTheoraFormatBlock*)mt->pbFormat; hdr = &hdr0; hdr->biWidth = oggFormat->width; hdr->biHeight = oggFormat->height; hdr->biCompression = FOURCC_THEO; } else if (mt->formattype == FORMAT_RLTheora) { hdr = &hdr0; hdr->biCompression = FOURCC_THEO; } else { return VFW_E_TYPE_NOT_ACCEPTED; } char_t pomS[60]; DPRINTF(_l("TffdshowVideoInputPin::CheckMediaType: %s, %i, %i"), fourcc2str(hdr2fourcc(hdr, &mt->subtype), pomS, 60), hdr->biWidth, hdr->biHeight); /* Information : WMP 11 and Media Center under Vista do not check for uncompressed format anymore, so no way to get ffdshow raw video decoder for postprocessing on uncompressed. So instead of saying "Media Type not supported", we says it is but only if there is an existing filter that can take this format in charge, and then ffdshow will be plugged after this codec (plug is done by TffdshowDecVideo::ConnectCompatibleFilter). */ int res = getVideoCodecId(hdr, &mt->subtype, NULL); OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); ffstring exeFilename(fv->getExefilename()); exeFilename.ConvertToLowerCase(); if (res == 0 && pCompatibleFilter == NULL && fv->deci->getParam2(IDFF_alternateUncompressed) == 1 && // Enable WMP11 postprocessing fv->deci->getParam2(IDFF_rawv) != 0 && // Raw video not on disabled (exeFilename == _l("wmplayer.exe") || exeFilename == _l("ehshell.exe"))) { // Only WMP and Media Center are concerned bool doPostProcessing = false; if (osvi.dwMajorVersion > 5) { // OS >= VISTA doPostProcessing = true; } else if (osvi.dwMajorVersion == 5 // If OS=XP, check version of WMP && exeFilename == _l("ehshell.exe")) { // But only for Media Center // Read WMP version from the aRegistry HKEY hKey = NULL; LONG regErr; // Read WMP version from the following registry key regErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _l("SOFTWARE\\Microsoft\\MediaPlayer\\Setup\\Installed Versions"), 0, KEY_READ, &hKey); if (regErr != ERROR_SUCCESS) { return res == AV_CODEC_ID_NONE ? VFW_E_TYPE_NOT_ACCEPTED : S_OK; } DWORD dwType; BYTE buf[4096] = { '\0' }; // make it big enough for any kind of values DWORD dwSize = sizeof(buf); regErr = RegQueryValueEx(hKey, _T("wmplayer.exe"), 0, &dwType, buf, &dwSize); if (hKey) { RegCloseKey(hKey); } if (regErr != ERROR_SUCCESS || dwType != REG_BINARY) { return res == AV_CODEC_ID_NONE ? VFW_E_TYPE_NOT_ACCEPTED : S_OK; } if (buf[2] >= 0x0b) { // Third byte is the major version number doPostProcessing = true; } } if (doPostProcessing) { DPRINTF(_l("TffdshowVideoInputPin::CheckMediaType: input format disabled or not supported. Trying to maintain in the graph...")); IFilterMapper2 *pMapper = NULL; IEnumMoniker *pEnum = NULL; HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC, IID_IFilterMapper2, (void **) &pMapper); if (FAILED(hr)) { // Error handling omitted for clarity. } GUID arrayInTypes[2]; arrayInTypes[0] = mt->majortype;//MEDIATYPE_Video; arrayInTypes[1] = mt->subtype;//MEDIASUBTYPE_dvsd; hr = pMapper->EnumMatchingFilters( &pEnum, 0, // Reserved. TRUE, // Use exact match? MERIT_DO_NOT_USE + 1, // Minimum merit. TRUE, // At least one input pin? 1, // Number of major type/subtype pairs for input. arrayInTypes, // Array of major type/subtype pairs for input. NULL, // Input medium. NULL, // Input pin category. FALSE, // Must be a renderer? TRUE, // At least one output pin? 0, // Number of major type/subtype pairs for output. NULL, // Array of major type/subtype pairs for output. NULL, // Output medium. NULL); // Output pin category. // Enumerate the monikers. IMoniker *pMoniker; ULONG cFetched; while (pEnum->Next(1, &pMoniker, &cFetched) == S_OK) { IPropertyBag *pPropBag = NULL; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); if (SUCCEEDED(hr)) { // To retrieve the friendly name of the filter, do the following: VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (SUCCEEDED(hr)) { if (varName.pbstrVal == NULL || _strnicmp(FFDSHOW_NAME_L, varName.bstrVal, 22) != 0) { // Display the name in your UI somehow. DPRINTF(_l("TffdshowVideoInputPin::CheckMediaType: compatible filter found (%s)"), varName.pbstrVal); hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pCompatibleFilter); } } // Now add the filter to the graph. Remember to release pFilter later. IFilterGraph *pGraph = NULL; fv->deci->getGraph(&pGraph); IGraphBuilder *pGraphBuilder = NULL; hr = pGraph->QueryInterface(IID_IGraphBuilder, (void **)&pGraphBuilder); if (hr == S_OK) { pGraphBuilder->AddFilter(pCompatibleFilter, varName.bstrVal); } else { pCompatibleFilter->Release(); pCompatibleFilter = NULL; } // Clean up. VariantClear(&varName); pGraphBuilder->Release(); pPropBag->Release(); } pMoniker->Release(); if (pCompatibleFilter != NULL) { break; } } // Clean up. pMapper->Release(); pEnum->Release(); } } if (pCompatibleFilter != NULL) { return S_OK; } return res == AV_CODEC_ID_NONE ? VFW_E_TYPE_NOT_ACCEPTED : S_OK; }