HRESULT CConvert::SetNoClock(IFilterGraph *graph) { // Keep a useless clock from being instantiated.... IMediaFilter *graphF; HRESULT hr = graph->QueryInterface(IID_IMediaFilter, (void **) &graphF); if(SUCCEEDED(hr)) { hr = graphF->SetSyncSource(NULL); if (FAILED(hr)) printf("SetNoClock: Failed to set sync source! hr=0x%x\n", hr); graphF->Release(); } else { printf("SetNoClock: Failed to QI for media filter! hr=0x%x\n", hr); } return hr; }
void DirectShowFrameGrabber::init() { InitializeDirectX(); HRESULT hr = S_OK; mediaEvent = NULL; mediaControl = NULL; sampleGrabber = NULL; buffer = NULL; bufferLength = 0; width = 640; // just default, will be overriden height = 480; // just default, will be overriden CComPtr<IBaseFilter> captureFilter = NULL; // choose video capture device hr = ChooseDirectXFilter(captureFilter, CLSID_VideoInputDeviceCategory); ASSERT(SUCCEEDED(hr)); //ASSERT(captureFilter != NULL, "no capturing device available!"); CComPtr<IBaseFilter> sampleGrabberFilter = NULL; hr = sampleGrabberFilter.CoCreateInstance(CLSID_SampleGrabber); ASSERT(SUCCEEDED(hr)); CComPtr<IBaseFilter> nullRendererFilter = NULL; hr = nullRendererFilter.CoCreateInstance(CLSID_NullRenderer); ASSERT(SUCCEEDED(hr)); graphBuilder = NULL; hr = graphBuilder.CoCreateInstance(CLSID_FilterGraph); ASSERT(SUCCEEDED(hr)); IMediaFilter *mediaFilter = 0; graphBuilder->QueryInterface(IID_IMediaFilter, (void**)&mediaFilter); mediaFilter->SetSyncSource(NULL); mediaFilter->Release(); hr = graphBuilder->AddFilter(captureFilter, NULL); ASSERT(SUCCEEDED(hr)); // open ui with video capture device properties displayProperties( captureFilter ); hr = graphBuilder->AddFilter(nullRendererFilter, L"NullRenderer"); ASSERT(SUCCEEDED(hr)); hr = graphBuilder->AddFilter(sampleGrabberFilter, L"Grabber"); ASSERT(SUCCEEDED(hr)); hr = sampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&sampleGrabber); ASSERT(SUCCEEDED(hr)); AM_MEDIA_TYPE mediaType; ZeroMemory(&mediaType, sizeof(AM_MEDIA_TYPE)); mediaType.majortype = MEDIATYPE_Video; mediaType.subtype = MEDIASUBTYPE_RGB24; mediaType.formattype = FORMAT_VideoInfo; hr = sampleGrabber->SetMediaType(&mediaType); ASSERT(SUCCEEDED(hr)); CComPtr<IEnumPins> pins = NULL; CComPtr<IPin> cameraOutputPin = NULL; { hr = captureFilter->EnumPins(&pins); ASSERT(SUCCEEDED(hr)); hr = pins->Reset(); ASSERT(SUCCEEDED(hr)); hr = pins->Next(1, &cameraOutputPin, NULL); ASSERT(SUCCEEDED(hr)); pins = NULL; } hr = sampleGrabberFilter->EnumPins(&pins); ASSERT(SUCCEEDED(hr)); hr = pins->Reset(); ASSERT(SUCCEEDED(hr)); CComPtr<IPin> grabberInputPin = NULL; hr = pins->Next(1, &grabberInputPin, NULL); ASSERT(SUCCEEDED(hr)); CComPtr<IPin> grabberOutputPin = NULL; hr = pins->Next(1, &grabberOutputPin, NULL); ASSERT(SUCCEEDED(hr)); pins = NULL; hr = nullRendererFilter->EnumPins(&pins); ASSERT(SUCCEEDED(hr)); hr = pins->Reset(); ASSERT(SUCCEEDED(hr)); CComPtr<IPin> nullRendererInputPin = NULL; hr = pins->Next(1, &nullRendererInputPin, NULL); ASSERT(SUCCEEDED(hr)); // show camera properties CComPtr<ISpecifyPropertyPages> propertyPages; hr = cameraOutputPin->QueryInterface(IID_ISpecifyPropertyPages, (void**)&propertyPages); if (SUCCEEDED(hr)) { PIN_INFO pinInfo; cameraOutputPin->QueryPinInfo(&pinInfo); CAUUID caGUID; propertyPages->GetPages(&caGUID); OleCreatePropertyFrame(NULL, 0, 0, L"Property Sheet", 1, (IUnknown **)&(cameraOutputPin.p), caGUID.cElems, caGUID.pElems, 0, 0, NULL); CoTaskMemFree(caGUID.pElems); pinInfo.pFilter->Release(); } hr = graphBuilder->Connect(cameraOutputPin, grabberInputPin); ASSERT(SUCCEEDED(hr)); hr = graphBuilder->Connect(grabberOutputPin, nullRendererInputPin); ASSERT(SUCCEEDED(hr)); hr = graphBuilder->Render(grabberOutputPin); // ASSERT(SUCCEEDED(hr)); // produces an error: "An invalid field name was used in a query string" hr = sampleGrabber->SetBufferSamples(TRUE); ASSERT(SUCCEEDED(hr)); hr = sampleGrabber->SetOneShot(FALSE); ASSERT(SUCCEEDED(hr)); hr = graphBuilder->QueryInterface(IID_IMediaControl, (void**)&mediaControl); ASSERT(SUCCEEDED(hr)); hr = graphBuilder->QueryInterface(IID_IMediaEvent, (void**)&mediaEvent); ASSERT(SUCCEEDED(hr)); AM_MEDIA_TYPE mt; hr = sampleGrabber->GetConnectedMediaType(&mt); ASSERT(SUCCEEDED(hr)); ASSERT(mt.formattype == FORMAT_VideoInfo); VIDEOINFOHEADER *videoHeader; videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat); width = videoHeader->bmiHeader.biWidth; height = videoHeader->bmiHeader.biHeight; bitmapFormat = 0; CComPtr<IAMVideoControl> videoControl; hr = captureFilter->QueryInterface(IID_IAMVideoControl, (void**)&videoControl); // run the graph! mediaControl->Run(); }
HRESULT videoInputCamera::setupDevice() { comInit(); GUID CAPTURE_MODE = PIN_CATEGORY_CAPTURE; //Don't worry - it ends up being preview (which is faster) //printf("SETUP: Setting up device %i\n",deviceID); // CREATE THE GRAPH BUILDER // // Create the filter graph manager and query for interfaces. HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pCaptureGraphBuilder); if (FAILED(hr)) // FAILED is a macro that tests the return value { printf("ERROR - Could not create the Filter Graph Manager\n"); return hr; } //FITLER GRAPH MANAGER// // Create the Filter Graph Manager. hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&pGraphBuilder); if (FAILED(hr)) { printf("ERROR - Could not add the graph builder!\n"); stopDevice(); return hr; } //SET THE FILTERGRAPH// hr = pCaptureGraphBuilder->SetFiltergraph(pGraphBuilder); if (FAILED(hr)) { printf("ERROR - Could not set filtergraph\n"); stopDevice(); return hr; } //MEDIA CONTROL (START/STOPS STREAM)// // Using QueryInterface on the graph builder, // Get the Media Control object. hr = pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); if (FAILED(hr)) { printf("ERROR - Could not create the Media Control object\n"); stopDevice(); return hr; } char nDeviceName[255]; WCHAR wDeviceName[255]; memset(wDeviceName, 0, sizeof(WCHAR) * 255); memset(nDeviceName, 0, sizeof(char) * 255); //FIND VIDEO DEVICE AND ADD TO GRAPH// //gets the device specified by the second argument. hr = getDevice(&pInputFilter, cfg->device, wDeviceName, nDeviceName); if (SUCCEEDED(hr)){ sprintf(cfg->name,nDeviceName); //printf("SETUP: %s\n", nDeviceName); hr = pGraphBuilder->AddFilter(pInputFilter, wDeviceName); }else{ printf("ERROR - Could not find specified video device\n"); stopDevice(); return hr; } //LOOK FOR PREVIEW PIN IF THERE IS NONE THEN WE USE CAPTURE PIN AND THEN SMART TEE TO PREVIEW IAMStreamConfig *streamConfTest = NULL; hr = pCaptureGraphBuilder->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pInputFilter, IID_IAMStreamConfig, (void **)&streamConfTest); if(FAILED(hr)){ //printf("SETUP: Couldn't find preview pin using SmartTee\n"); }else{ CAPTURE_MODE = PIN_CATEGORY_PREVIEW; streamConfTest->Release(); streamConfTest = NULL; } //CROSSBAR (SELECT PHYSICAL INPUT TYPE)// //my own function that checks to see if the device can support a crossbar and if so it routes it. //webcams tend not to have a crossbar so this function will also detect a webcams and not apply the crossbar /*if(useCrossbar) { //printf("SETUP: Checking crossbar\n"); routeCrossbar(pCaptureGraphBuilder, pInputFilter, connection, CAPTURE_MODE); }*/ //we do this because webcams don't have a preview mode hr = pCaptureGraphBuilder->FindInterface(&CAPTURE_MODE, &MEDIATYPE_Video, pInputFilter, IID_IAMStreamConfig, (void **)&pStreamConfig); if(FAILED(hr)){ printf("ERROR: Couldn't config the stream!\n"); stopDevice(); return hr; } //NOW LETS DEAL WITH GETTING THE RIGHT SIZE hr = pStreamConfig->GetFormat(&pAmMediaType); if(FAILED(hr)){ printf("ERROR: Couldn't getFormat for pAmMediaType!\n"); stopDevice(); return hr; } if (!setSizeAndSubtype()) return false; VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(pAmMediaType->pbFormat); cfg->cam_width = HEADER(pVih)->biWidth; cfg->cam_height = HEADER(pVih)->biHeight; cfg->cam_fps = ((int)floor(100000000.0f/(float)pVih->AvgTimePerFrame + 0.5f))/10.0f; long bufferSize = cfg->cam_width*cfg->cam_height*3; sgCallback->setupBuffer(bufferSize); // Create the Sample Grabber. hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter, (void**)&pGrabberFilter); if (FAILED(hr)){ printf("Could not Create Sample Grabber - CoCreateInstance()\n"); stopDevice(); return hr; } hr = pGraphBuilder->AddFilter(pGrabberFilter, L"Sample Grabber"); if (FAILED(hr)){ printf("Could not add Sample Grabber - AddFilter()\n"); stopDevice(); return hr; } hr = pGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber); if (FAILED(hr)){ printf("ERROR: Could not query SampleGrabber\n"); stopDevice(); return hr; } //Get video properties from the stream's mediatype and apply to the grabber (otherwise we don't get an RGB image) AM_MEDIA_TYPE mt; ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB24; //mt.subtype = MEDIASUBTYPE_YUY2; mt.formattype = FORMAT_VideoInfo; //Set Params - One Shot should be false unless you want to capture just one buffer hr = pSampleGrabber->SetMediaType(&mt); hr = pSampleGrabber->SetOneShot(FALSE); hr = pSampleGrabber->SetBufferSamples(FALSE); //Tell the grabber to use our callback function - 0 is for SampleCB and 1 for BufferCB //We use SampleCB hr = pSampleGrabber->SetCallback(sgCallback, 0); if (FAILED(hr)) { printf("ERROR: problem setting callback\n"); stopDevice(); return hr; } /*else { printf("SETUP: Capture callback set\n"); }*/ //lets try freeing our stream conf here too //this will fail if the device is already running /* if(pStreamConfig) { pStreamConfig->Release(); pStreamConfig = NULL; } else { printf("ERROR: connecting device - prehaps it is already being used?\n"); stopDevice(); return S_FALSE; }*/ //used to give the video stream somewhere to go to. hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)(&pDestFilter)); if (FAILED(hr)){ printf("ERROR: Could not create filter - NullRenderer\n"); stopDevice(); return hr; } hr = pGraphBuilder->AddFilter(pDestFilter, L"NullRenderer"); if (FAILED(hr)){ printf("ERROR: Could not add filter - NullRenderer\n"); stopDevice(); return hr; } //This is where the stream gets put together. hr = pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pInputFilter, pGrabberFilter, pDestFilter); if (FAILED(hr)){ printf("ERROR: Could not connect pins - RenderStream()\n"); stopDevice(); return hr; } //EXP - lets try setting the sync source to null - and make it run as fast as possible { IMediaFilter *pMediaFilter = 0; hr = pGraphBuilder->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); if (FAILED(hr)){ printf("ERROR: Could not get IID_IMediaFilter interface\n"); }else{ pMediaFilter->SetSyncSource(NULL); pMediaFilter->Release(); } } //printf("SETUP: Device is setup and ready to capture.\n\n"); //if we release this then we don't have access to the settings //we release our video input filter but then reconnect with it //each time we need to use it //pInputFilter->Release(); //pInputFilter = NULL; pGrabberFilter->Release(); pGrabberFilter = NULL; pDestFilter->Release(); pDestFilter = NULL; return S_OK; }
const bool CMediaViewer::OpenViewer(HWND hOwnerHwnd, HWND hMessageDrainHwnd, CVideoRenderer::RendererType RendererType, LPCWSTR pszVideoDecoder, LPCWSTR pszAudioDevice) { CTryBlockLock Lock(&m_DecoderLock); if (!Lock.TryLock(LOCK_TIMEOUT)) { SetError(TEXT("タイムアウトエラーです。")); return false; } if (m_bInit) { SetError(TEXT("既にフィルタグラフが構築されています。")); return false; } TRACE(TEXT("CMediaViewer::OpenViewer() フィルタグラフ作成開始\n")); HRESULT hr=S_OK; IPin *pOutput=NULL; IPin *pOutputVideo=NULL; IPin *pOutputAudio=NULL; try { // フィルタグラフマネージャを構築する hr=::CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, IID_IGraphBuilder,pointer_cast<LPVOID*>(&m_pFilterGraph)); if (FAILED(hr)) { throw CBonException(hr,TEXT("フィルタグラフマネージャを作成できません。")); } #ifdef _DEBUG AddToRot(m_pFilterGraph, &m_dwRegister); #endif // IMediaControlインタフェースのクエリー hr=m_pFilterGraph->QueryInterface(IID_IMediaControl, pointer_cast<void**>(&m_pMediaControl)); if (FAILED(hr)) { throw CBonException(hr,TEXT("メディアコントロールを取得できません。")); } Trace(TEXT("ソースフィルタの接続中...")); /* CBonSrcFilter */ { // インスタンス作成 m_pSrcFilter = static_cast<CBonSrcFilter*>(CBonSrcFilter::CreateInstance(NULL, &hr)); if (m_pSrcFilter == NULL || FAILED(hr)) throw CBonException(hr, TEXT("ソースフィルタを作成できません。")); m_pSrcFilter->SetOutputWhenPaused(RendererType == CVideoRenderer::RENDERER_DEFAULT); // フィルタグラフに追加 hr = m_pFilterGraph->AddFilter(m_pSrcFilter, L"BonSrcFilter"); if (FAILED(hr)) throw CBonException(hr, TEXT("ソースフィルタをフィルタグラフに追加できません。")); // 出力ピンを取得 pOutput = DirectShowUtil::GetFilterPin(m_pSrcFilter, PINDIR_OUTPUT); if (pOutput==NULL) throw CBonException(TEXT("ソースフィルタの出力ピンを取得できません。")); m_pSrcFilter->EnableSync(m_bEnablePTSSync); } Trace(TEXT("MPEG-2 Demultiplexerフィルタの接続中...")); /* MPEG-2 Demultiplexer */ { CMediaType MediaTypeVideo; CMediaType MediaTypeAudio; IMpeg2Demultiplexer *pMpeg2Demuxer; hr=::CoCreateInstance(CLSID_MPEG2Demultiplexer,NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter, pointer_cast<LPVOID*>(&m_pMp2DemuxFilter)); if (FAILED(hr)) throw CBonException(hr,TEXT("MPEG-2 Demultiplexerフィルタを作成できません。"), TEXT("MPEG-2 Demultiplexerフィルタがインストールされているか確認してください。")); hr=DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, m_pMp2DemuxFilter,L"Mpeg2Demuxer",&pOutput); if (FAILED(hr)) throw CBonException(hr,TEXT("MPEG-2 Demultiplexerをフィルタグラフに追加できません。")); // この時点でpOutput==NULLのはずだが念のため SAFE_RELEASE(pOutput); // IMpeg2Demultiplexerインタフェースのクエリー hr=m_pMp2DemuxFilter->QueryInterface(IID_IMpeg2Demultiplexer, pointer_cast<void**>(&pMpeg2Demuxer)); if (FAILED(hr)) throw CBonException(hr,TEXT("MPEG-2 Demultiplexerインターフェースを取得できません。"), TEXT("互換性のないスプリッタの優先度がMPEG-2 Demultiplexerより高くなっている可能性があります。")); // 映像メディアフォーマット設定 hr = SetVideoMediaType(&MediaTypeVideo, 1920, 1080); if (FAILED(hr)) throw CBonException(TEXT("メモリが確保できません。")); // 映像出力ピン作成 hr = pMpeg2Demuxer->CreateOutputPin(&MediaTypeVideo, L"Video", &pOutputVideo); if (FAILED(hr)) { pMpeg2Demuxer->Release(); throw CBonException(hr, TEXT("MPEG-2 Demultiplexerの映像出力ピンを作成できません。")); } // 音声メディアフォーマット設定 MediaTypeAudio.InitMediaType(); MediaTypeAudio.SetType(&MEDIATYPE_Audio); MediaTypeAudio.SetSubtype(&MEDIASUBTYPE_NULL); MediaTypeAudio.SetVariableSize(); MediaTypeAudio.SetTemporalCompression(TRUE); MediaTypeAudio.SetSampleSize(0); MediaTypeAudio.SetFormatType(&FORMAT_None); // 音声出力ピン作成 hr=pMpeg2Demuxer->CreateOutputPin(&MediaTypeAudio,L"Audio",&pOutputAudio); pMpeg2Demuxer->Release(); if (FAILED(hr)) throw CBonException(hr,TEXT("MPEG-2 Demultiplexerの音声出力ピンを作成できません。")); // 映像出力ピンのIMPEG2PIDMapインタフェースのクエリー hr=pOutputVideo->QueryInterface(__uuidof(IMPEG2PIDMap),pointer_cast<void**>(&m_pMp2DemuxVideoMap)); if (FAILED(hr)) throw CBonException(hr,TEXT("映像出力ピンのIMPEG2PIDMapを取得できません。")); // 音声出力ピンのIMPEG2PIDMapインタフェースのクエリ hr=pOutputAudio->QueryInterface(__uuidof(IMPEG2PIDMap),pointer_cast<void**>(&m_pMp2DemuxAudioMap)); if (FAILED(hr)) throw CBonException(hr,TEXT("音声出力ピンのIMPEG2PIDMapを取得できません。")); } #ifndef BONTSENGINE_H264_SUPPORT Trace(TEXT("MPEG-2パーサフィルタの接続中...")); /* CMpeg2ParserFilter */ { // インスタンス作成 m_pMpeg2Parser = static_cast<CMpeg2ParserFilter*>(CMpeg2ParserFilter::CreateInstance(NULL, &hr)); if ((!m_pMpeg2Parser) || FAILED(hr)) throw CBonException(hr,TEXT("MPEG-2パーサフィルタを作成できません。")); m_pMpeg2Parser->SetVideoInfoCallback(OnVideoInfo,this); // madVR は映像サイズの変化時に MediaType を設定しないと新しいサイズが適用されない m_pMpeg2Parser->SetAttachMediaType(RendererType==CVideoRenderer::RENDERER_madVR); // フィルタの追加と接続 hr=DirectShowUtil::AppendFilterAndConnect( m_pFilterGraph,m_pMpeg2Parser,L"Mpeg2ParserFilter",&pOutputVideo); if (FAILED(hr)) throw CBonException(hr,TEXT("MPEG-2パーサフィルタをフィルタグラフに追加できません。")); } #else Trace(TEXT("H.264パーサフィルタの接続中...")); /* CH264ParserFilter */ { // インスタンス作成 m_pH264Parser = static_cast<CH264ParserFilter*>(CH264ParserFilter::CreateInstance(NULL, &hr)); if ((!m_pH264Parser) || FAILED(hr)) throw CBonException(TEXT("H.264パーサフィルタを作成できません。")); m_pH264Parser->SetVideoInfoCallback(OnVideoInfo,this); m_pH264Parser->SetAdjustTime(m_bAdjustVideoSampleTime); m_pH264Parser->SetAdjustFrameRate(m_bAdjustFrameRate); // madVR は映像サイズの変化時に MediaType を設定しないと新しいサイズが適用されない m_pH264Parser->SetAttachMediaType(RendererType==CVideoRenderer::RENDERER_madVR); // フィルタの追加と接続 hr=DirectShowUtil::AppendFilterAndConnect( m_pFilterGraph,m_pH264Parser,L"H264ParserFilter",&pOutputVideo); if (FAILED(hr)) throw CBonException(hr,TEXT("H.264パーサフィルタをフィルタグラフに追加できません。")); } #endif // BONTSENGINE_H264_SUPPORT Trace(TEXT("音声デコーダの接続中...")); #if 1 /* CAudioDecFilter */ { // CAudioDecFilterインスタンス作成 m_pAudioDecoder = static_cast<CAudioDecFilter*>(CAudioDecFilter::CreateInstance(NULL, &hr)); if (!m_pAudioDecoder || FAILED(hr)) throw CBonException(hr,TEXT("音声デコーダフィルタを作成できません。")); // フィルタの追加と接続 hr=DirectShowUtil::AppendFilterAndConnect( m_pFilterGraph,m_pAudioDecoder,L"AudioDecFilter",&pOutputAudio); if (FAILED(hr)) throw CBonException(hr,TEXT("音声デコーダフィルタをフィルタグラフに追加できません。")); m_pAudioDecoder->SetJitterCorrection(m_bAdjustAudioStreamTime); if (m_pAudioStreamCallback) m_pAudioDecoder->SetStreamCallback(m_pAudioStreamCallback, m_pAudioStreamCallbackParam); } #else /* 外部AACデコーダを利用すると、チャンネル数が切り替わった際に音が出なくなる、 デュアルモノラルがステレオとして再生される、といった問題が出る */ /* CAacParserFilter */ { CAacParserFilter *m_pAacParser; // CAacParserFilterインスタンス作成 m_pAacParser=static_cast<CAacParserFilter*>(CAacParserFilter::CreateInstance(NULL, &hr)); if (!m_pAacParser || FAILED(hr)) throw CBonException(hr,TEXT("AACパーサフィルタを作成できません。")); // フィルタの追加と接続 hr=DirectShowUtil::AppendFilterAndConnect( m_pFilterGraph,m_pAacParser,L"AacParserFilter",&pOutputAudio); if (FAILED(hr)) throw CBonException(TEXT("AACパーサフィルタをフィルタグラフに追加できません。")); m_pAacParser->Release(); } /* AACデコーダー */ { CDirectShowFilterFinder FilterFinder; // 検索 if(!FilterFinder.FindFilter(&MEDIATYPE_Audio,&MEDIASUBTYPE_AAC)) throw CBonException(TEXT("AACデコーダが見付かりません。"), TEXT("AACデコーダがインストールされているか確認してください。")); WCHAR szAacDecoder[128]; CLSID idAac; bool bConnectSuccess=false; IBaseFilter *pAacDecFilter=NULL; for (int i=0;i<FilterFinder.GetFilterCount();i++){ if (FilterFinder.GetFilterInfo(i,&idAac,szAacDecoder,128)) { if (pszAudioDecoder!=NULL && pszAudioDecoder[0]!='\0' && ::lstrcmpi(szAacDecoder,pszAudioDecoder)!=0) continue; hr=DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, idAac,szAacDecoder,&pAacDecFilter, &pOutputAudio); if (SUCCEEDED(hr)) { TRACE(TEXT("AAC decoder connected : %s\n"),szAacDecoder); bConnectSuccess=true; break; } } } // どれかのフィルタで接続できたか if (bConnectSuccess) { SAFE_RELEASE(pAacDecFilter); //m_pszAacDecoderName=StdUtil::strdup(szAacDecoder); } else { throw CBonException(TEXT("AACデコーダフィルタをフィルタグラフに追加できません。"), TEXT("設定で有効なAACデコーダが選択されているか確認してください。")); } } #endif /* ユーザー指定の音声フィルタの接続 */ if (m_pszAudioFilterName) { Trace(TEXT("音声フィルタの接続中...")); // 検索 bool bConnectSuccess=false; CDirectShowFilterFinder FilterFinder; if (FilterFinder.FindFilter(&MEDIATYPE_Audio,&MEDIASUBTYPE_PCM)) { WCHAR szAudioFilter[128]; CLSID idAudioFilter; for (int i=0;i<FilterFinder.GetFilterCount();i++) { if (FilterFinder.GetFilterInfo(i,&idAudioFilter,szAudioFilter,128)) { if (::lstrcmpi(m_pszAudioFilterName,szAudioFilter)!=0) continue; hr=DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, idAudioFilter,szAudioFilter,&m_pAudioFilter, &pOutputAudio,NULL,true); if (SUCCEEDED(hr)) { TRACE(TEXT("音声フィルタ接続 : %s\n"),szAudioFilter); bConnectSuccess=true; } break; } } } if (!bConnectSuccess) { throw CBonException(hr, TEXT("音声フィルタをフィルタグラフに追加できません。"), TEXT("音声フィルタが利用できないか、音声デバイスに対応していない可能性があります。")); } } #ifndef BONTSENGINE_H264_SUPPORT Trace(TEXT("MPEG-2デコーダの接続中...")); /* Mpeg2デコーダー */ { CDirectShowFilterFinder FilterFinder; // 検索 if(!FilterFinder.FindFilter(&MEDIATYPE_Video,&MEDIASUBTYPE_MPEG2_VIDEO)) throw CBonException(TEXT("MPEG-2デコーダが見付かりません。"), TEXT("MPEG-2デコーダがインストールされているか確認してください。")); WCHAR szMpeg2Decoder[128]; CLSID idMpeg2Vid; bool bConnectSuccess=false; for (int i=0;i<FilterFinder.GetFilterCount();i++){ if (FilterFinder.GetFilterInfo(i,&idMpeg2Vid,szMpeg2Decoder,128)) { if (pszVideoDecoder!=NULL && pszVideoDecoder[0]!='\0' && ::lstrcmpi(szMpeg2Decoder,pszVideoDecoder)!=0) continue; hr=DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, idMpeg2Vid,szMpeg2Decoder,&m_pVideoDecoderFilter, &pOutputVideo,NULL,true); if (SUCCEEDED(hr)) { bConnectSuccess=true; break; } } } // どれかのフィルタで接続できたか if (bConnectSuccess) { m_pszVideoDecoderName=StdUtil::strdup(szMpeg2Decoder); } else { throw CBonException(hr,TEXT("MPEG-2デコーダフィルタをフィルタグラフに追加できません。"), TEXT("設定で有効なMPEG-2デコーダが選択されているか確認してください。\nまた、レンダラを変えてみてください。")); } } #ifndef MPEG2PARSERFILTER_INPLACE /* CyberLinkのデコーダとデフォルトレンダラの組み合わせで 1080x1080(4:3)の映像が正方形に表示される問題に対応 …しようと思ったが変になるので保留 */ if (::StrStrI(m_pszVideoDecoderName, TEXT("CyberLink")) != NULL) m_pMpeg2Parser->SetFixSquareDisplay(true); #endif #else // ndef BONTSENGINE_H264_SUPPORT Trace(TEXT("H.264デコーダの接続中...")); /* H.264デコーダー */ { CDirectShowFilterFinder FilterFinder; // 検索 if(!FilterFinder.FindFilter(&MEDIATYPE_Video,&MEDIASUBTYPE_H264)) throw CBonException(TEXT("H.264デコーダが見付かりません。"), TEXT("H.264デコーダがインストールされているか確認してください。")); WCHAR szH264Decoder[128]; CLSID idH264Decoder; bool bConnectSuccess=false; for (int i=0;i<FilterFinder.GetFilterCount();i++){ if (FilterFinder.GetFilterInfo(i,&idH264Decoder,szH264Decoder,128)) { if (pszVideoDecoder!=NULL && pszVideoDecoder[0]!='\0' && ::lstrcmpi(szH264Decoder,pszVideoDecoder)!=0) continue; hr=DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, idH264Decoder,szH264Decoder,&m_pVideoDecoderFilter, &pOutputVideo,NULL,true); if (SUCCEEDED(hr)) { bConnectSuccess=true; break; } } } // どれかのフィルタで接続できたか if (bConnectSuccess) { m_pszVideoDecoderName=StdUtil::strdup(szH264Decoder); } else { throw CBonException(hr,TEXT("H.264デコーダフィルタをフィルタグラフに追加できません。"), TEXT("設定で有効なH.264デコーダが選択されているか確認してください。\nまた、レンダラを変えてみてください。")); } } #endif // BONTSENGINE_H264_SUPPORT Trace(TEXT("映像レンダラの構築中...")); if (!CVideoRenderer::CreateRenderer(RendererType,&m_pVideoRenderer)) { throw CBonException(TEXT("映像レンダラを作成できません。"), TEXT("設定で有効なレンダラが選択されているか確認してください。")); } if (!m_pVideoRenderer->Initialize(m_pFilterGraph,pOutputVideo, hOwnerHwnd,hMessageDrainHwnd)) { throw CBonException(m_pVideoRenderer->GetLastErrorException()); } m_VideoRendererType=RendererType; Trace(TEXT("音声レンダラの構築中...")); // 音声レンダラ構築 { bool fOK = false; if (pszAudioDevice != NULL && pszAudioDevice[0] != '\0') { CDirectShowDeviceEnumerator DevEnum; if (DevEnum.CreateFilter(CLSID_AudioRendererCategory, pszAudioDevice, &m_pAudioRenderer)) { m_pszAudioRendererName=StdUtil::strdup(pszAudioDevice); fOK = true; } } if (!fOK) { hr = ::CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, pointer_cast<LPVOID*>(&m_pAudioRenderer)); if (SUCCEEDED(hr)) { m_pszAudioRendererName=StdUtil::strdup(TEXT("DirectSound Renderer")); fOK = true; } } if (fOK) { hr = DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, m_pAudioRenderer, L"Audio Renderer", &pOutputAudio); if (SUCCEEDED(hr)) { #ifdef _DEBUG if (pszAudioDevice != NULL && pszAudioDevice[0] != '\0') TRACE(TEXT("音声デバイス %s を接続\n"), pszAudioDevice); #endif if (m_bUseAudioRendererClock) { IMediaFilter *pMediaFilter; if (SUCCEEDED(m_pFilterGraph->QueryInterface(IID_IMediaFilter, pointer_cast<void**>(&pMediaFilter)))) { IReferenceClock *pReferenceClock; if (SUCCEEDED(m_pAudioRenderer->QueryInterface(IID_IReferenceClock, pointer_cast<void**>(&pReferenceClock)))) { pMediaFilter->SetSyncSource(pReferenceClock); pReferenceClock->Release(); TRACE(TEXT("グラフのクロックに音声レンダラを選択\n")); } pMediaFilter->Release(); } } fOK = true; } else { fOK = false; } if (!fOK) { hr = m_pFilterGraph->Render(pOutputAudio); if (FAILED(hr)) throw CBonException(hr, TEXT("音声レンダラを接続できません。"), TEXT("設定で有効な音声デバイスが選択されているか確認してください。")); } } else { // 音声デバイスが無い? // Nullレンダラを繋げておく hr = ::CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, pointer_cast<LPVOID*>(&m_pAudioRenderer)); if (SUCCEEDED(hr)) { hr = DirectShowUtil::AppendFilterAndConnect(m_pFilterGraph, m_pAudioRenderer, L"Null Audio Renderer", &pOutputAudio); if (FAILED(hr)) { throw CBonException(hr, TEXT("Null音声レンダラを接続できません。")); } m_pszAudioRendererName=StdUtil::strdup(TEXT("Null Renderer")); TRACE(TEXT("Nullレンダラを接続\n")); } } } /* デフォルトでMPEG-2 Demultiplexerがグラフのクロックに 設定されるらしいが、一応設定しておく */ if (!m_bUseAudioRendererClock) { IMediaFilter *pMediaFilter; if (SUCCEEDED(m_pFilterGraph->QueryInterface( IID_IMediaFilter,pointer_cast<void**>(&pMediaFilter)))) { IReferenceClock *pReferenceClock; if (SUCCEEDED(m_pMp2DemuxFilter->QueryInterface( IID_IReferenceClock,pointer_cast<void**>(&pReferenceClock)))) { pMediaFilter->SetSyncSource(pReferenceClock); pReferenceClock->Release(); TRACE(TEXT("グラフのクロックにMPEG-2 Demultiplexerを選択\n")); } pMediaFilter->Release(); } } // オーナウィンドウ設定 m_hOwnerWnd = hOwnerHwnd; RECT rc; ::GetClientRect(hOwnerHwnd, &rc); m_wVideoWindowX = (WORD)rc.right; m_wVideoWindowY = (WORD)rc.bottom; m_bInit=true; ULONG PID; if (m_wVideoEsPID != PID_INVALID) { PID = m_wVideoEsPID; if (FAILED(m_pMp2DemuxVideoMap->MapPID(1, &PID, MEDIA_ELEMENTARY_STREAM))) m_wVideoEsPID = PID_INVALID; } if (m_wAudioEsPID != PID_INVALID) { PID = m_wAudioEsPID; if (FAILED(m_pMp2DemuxAudioMap->MapPID(1, &PID, MEDIA_ELEMENTARY_STREAM))) m_wAudioEsPID = PID_INVALID; } } catch (CBonException &Exception) { SetError(Exception); if (Exception.GetErrorCode()!=0) { TCHAR szText[MAX_ERROR_TEXT_LEN+32]; int Length; Length=::AMGetErrorText(Exception.GetErrorCode(),szText,MAX_ERROR_TEXT_LEN); ::wsprintf(szText+Length,TEXT("\nエラーコード(HRESULT) 0x%08X"),Exception.GetErrorCode()); SetErrorSystemMessage(szText); } SAFE_RELEASE(pOutput); SAFE_RELEASE(pOutputVideo); SAFE_RELEASE(pOutputAudio); CloseViewer(); TRACE(TEXT("フィルタグラフ構築失敗 : %s\n"), GetLastErrorText()); return false; } SAFE_RELEASE(pOutputVideo); SAFE_RELEASE(pOutputAudio); ClearError(); TRACE(TEXT("フィルタグラフ構築成功\n")); return true; }