ARDeskTop上で動画再生(その2)
OpenCVのcvCaptureFromFile関数では動画の音声トラックは再生されないので、試しにDirectShowでも同時に再生してみた。まあ、あたりまえだが、そのままでは音と映像がズレてしまう。
で、DirectShowのGetPositions関数で現在の再生位置を取得して、それに合わせて動画を再生してみた。
同期成功!
ちなみに、FLV Splitterをインストールするとfpsが30くらいまでのならflvファイルがDirectShowでも再生できるようになる。
http://www.gigafree.net/media/codec/flvsplitter.html
あとは、このままではDirectShowの別ウインドウでも動画が再生されてしまうので、音声のみを再生できるようにすれば終了。
int CCVVideoManager::Animate(void) { if(!capture) return(1); if(!CAnimeManager::Animate()) return(1); int n; if(fps > 40.0f) { if(elapsedTimeMS * fps < counter) return(1); n = elapsedTimeMS * fps - counter + 1; } else { //DirectShowから現在の再生位置を取得して何フレーム進めるか決める LONGLONG pCurrent, pStop; pMediaSeeking->GetPositions(&pCurrent, &pStop); float current = pCurrent * 0.0000001; if(current * fps < counter) return(1); n = current * fps - counter + 1; } IplImage* image; for(int i = 0; i < n; i++) { image = cvQueryFrame(capture); if(!image) { Stop(); return(0); } } counter += n; if(!frame) frame = cvCreateImage(cvSize(image->width / 3, image->height / 3), IPL_DEPTH_8U, 3); cvResize(image, frame, CV_INTER_CUBIC); ((CCVPicture*) component)->SetTexture(image); return(0); } bool CCVVideoManager::OpenVideoFile(wchar_t* pFileName, double size) { char cFileName[256]; setlocale(LC_ALL, "ja"); wcstombs(cFileName, pFileName, 256); //OpenCV capture = cvCaptureFromFile(cFileName); if(!capture) { return(false); } fps = (float) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); //DirectShow if(fps <= 40.0f) { IMediaPosition* pMediaPosition; //DirectShowの初期化は本当はここでやったらダメだろうな。 CoInitialize(NULL); CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (LPVOID*) &pGraphBuilder); pGraphBuilder->QueryInterface(IID_IMediaControl, (LPVOID*) &pMediaControl); pGraphBuilder->QueryInterface(IID_IMediaPosition, (LPVOID*) &pMediaPosition); pGraphBuilder->QueryInterface(IID_IMediaSeeking, (LPVOID*) &pMediaSeeking); pGraphBuilder->RenderFile((BSTR) pFileName, NULL); //再生時間取得 REFTIME length; pMediaPosition->get_Duration(&length); animetionTimeMS = (float) length; pMediaPosition->Release(); pMediaControl->Run(); } else { //DirectShowでは再生不可能 animetionTimeMS = 1000.0f; //適当 } Play(); Animate(); return(true); }
参考サイト:
Geekなぺーじ : DirectShowプログラミング [VC++]
http://www.geekpage.jp/programming/directshow/