DirectShowにてビデオキャプチャデバイスから
ファイルに保存する(プレビューウィンドウ付き)で
普通にAVIファイルには保存できますがフィルターのMicrosoft Video 1を追加して圧縮をして保存するようにしたいと思います。
(上記フィルタは本当に圧縮かどうかはわかりませんが。。。
GraphEditで確認したところ圧縮(保存ファイルサイズが激減)したようでしたので。。)
現在のフィルターグラフにMicrosoft Video 1を追加する方法をご教示願えればと思います。
初心者なのでMSDNなど見てもいまいち理解できません。
簡単なサンプルなどあれば助かります。
よろしくお願い致します。
No.1ベストアンサー
- 回答日時:
こんばんは。
以下のURLが参考になります。http://msdn.microsoft.com/ja-jp/library/cc973418 …
http://msdn.microsoft.com/ja-jp/library/cc353106 …
http://www.codeguru.com/forum/showthread.php?t=3 …
圧縮コーデックの一覧から、Microsoft Video 1を探し出して見つかればフィルタを作成して、SplitterとMuxの間に挟み込めばOK見たいです。
大分乱暴なコードですが、以下で圧縮が出来ました。参考程度に。
#include <stdio.h>
#include <dshow.h>
#include <qedit.h>
#pragma comment(lib, "strmiids.lib")
//コーデックを探す
static IBaseFilter* FindCodec(BSTR bstrDesire)
{
ICreateDevEnum *pSysDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;
IBaseFilter *pFilter = NULL;
HRESULT hr = ::CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum);
if(FAILED(hr))
return pFilter;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnum, 0);
if(hr != S_OK)
return pFilter;
while (S_OK == pEnum->Next(1, &pMoniker, NULL))
{
IPropertyBag *pPropBag = NULL;
pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
VARIANT var;
::VariantInit(&var);
hr = pPropBag->Read(L"FriendlyName", &var, 0);
if(SUCCEEDED(hr))
{
::wprintf(L"[codec %s]\n", var.bstrVal);
//見つかったのでフィルタを作成する
if(::lstrcmp(var.bstrVal, bstrDesire) == 0)
{
pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
}
}
::VariantClear(&var);
pPropBag->Release();
pMoniker->Release();
//見つかっているのでループから抜ける
if(pFilter)break;
}
//最後の後始末
pSysDevEnum->Release();
pEnum->Release();
return pFilter;
}
int main()
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
::CoInitialize(NULL);
//グラフの作成
::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
//コントロールとイベントの作成
pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
//グラフビルダーの作成
ICaptureGraphBuilder2* pBuilder = NULL;
::CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder);
//フィルタの作成
IBaseFilter *pFileSource;
pGraph->AddSourceFilter( L"test.avi", L"Source", &pFileSource);
IBaseFilter *pAviSplit;
::CoCreateInstance(CLSID_AviSplitter, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviSplit);
IBaseFilter *pAviMux;
::CoCreateInstance(CLSID_AviDest, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviMux);
IBaseFilter *pWriter;
::CoCreateInstance(CLSID_FileWriter, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pWriter);
IBaseFilter *pMSVideo1 = ::FindCodec(L"Microsoft Video 1");
//出力先の設定
IFileSinkFilter *pSink= NULL;
pWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pSink);
pSink->SetFileName(L"testresult.avi", NULL);
pSink->Release();
//フィルタを追加
pGraph->AddFilter(pFileSource, L"AVI Source");
pGraph->AddFilter(pAviSplit, L"AVI Splitter");
pGraph->AddFilter(pAviMux, L"AVI MUX");
pGraph->AddFilter(pWriter, L"AVI Writer");
pGraph->AddFilter(pMSVideo1, L"Microsoft Video 1");
//フィルタ同士の接続
pBuilder->SetFiltergraph(pGraph);
pBuilder->RenderStream(0, 0, pFileSource, 0, pAviSplit);
pBuilder->RenderStream(0, &MEDIATYPE_Video, pAviSplit, pMSVideo1, pAviMux);//split⇔mux間にMS Video1を挟み込む
pBuilder->RenderStream(0, &MEDIATYPE_Audio, pAviSplit, 0, pAviMux);
pBuilder->RenderStream(0, 0, pAviMux, 0, pWriter);
//書き込みスタート
pControl->Run();
//達成まで待つ
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
//停止 此れがないと駄目
pControl->Stop();
//始末
pControl->Release();
pEvent->Release();
pGraph->Release();
pFileSource->Release();
pAviSplit->Release();
pAviMux->Release();
pWriter->Release();
pMSVideo1->Release();
pBuilder->Release();
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PDF PDFファイルの圧縮 1 2022/10/04 13:48
- ノートパソコン パソコンのファイル追加履歴について 1 2022/05/07 15:35
- Visual Basic(VBA) エクセルのマクロについて教えてください。 1 2023/02/21 11:19
- Google Drive Google Drive (G:)の容量を、購入した容量と一致させるにはどうすればよいでしょうか? 1 2022/04/10 22:32
- ホームページ作成・プログラミング 保存したホームページのファイルは何をしている推測できますでしょうか。 1 2023/08/18 15:50
- ネットワーク syslog保存サーバーに蓄積するログファイル容量について 3 2023/01/09 20:13
- Visual Basic(VBA) エクセルのマクロコードの一部分を変更する方法について教えてください。 2 2023/02/17 08:40
- Google Drive USB内の圧縮フォルダが開けません。教えて下さい! 1 2022/07/26 18:44
- Excel(エクセル) EXCELのグラフを画像(JPG形式)で保存、通常実行がうまく行かない。ステップインはうまく行く 3 2022/08/30 12:06
- iPhone(アイフォーン) iPhoneからpicsartにフォントの追加をしたいのですがiPhoneに無料のフォントを保存する 1 2023/02/19 07:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
静的でないメンバ関数の呼び出...
-
C++にてtemplateで受け取った任...
-
int main()、void main()、void...
-
【gcc・cygwin】multiple defin...
-
多重定義が起きている?--lnk20...
-
戻り値を返す関数の前に(void)...
-
const_castのつかいどころを教...
-
ArduinoでMouse関数を使用して...
-
c言語。5枚のカードの中に2枚同...
-
Notepad++の関数リスト表示の変...
-
C言語 プロトタイプ宣言
-
C++別のオブジェクトからメンバ...
-
コントロールへのイベント定義...
-
ウインドウの移動禁止
-
VC++でGetKeyboardStateがうま...
-
メッセージマップ(ON_CONTROL_...
-
プログラムを教えてください。...
-
コールバックって・・・
-
AKI-h8 3069f C言語 HEW マイ...
-
stddef.hって何?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Notepad++の関数リスト表示の変...
-
ArduinoでMouse関数を使用して...
-
【gcc・cygwin】multiple defin...
-
戻り値を返す関数の前に(void)...
-
多重定義が起きている?--lnk20...
-
C++にてtemplateで受け取った任...
-
既定のコンストラクタがありま...
-
静的でないメンバ関数の呼び出...
-
gcc: incompatible pointer type
-
C# Controls.Addで動的に配置し...
-
int main()、void main()、void...
-
(void)0 はどんな意味ですか
-
VC++でGetKeyboardStateがうま...
-
void*型の配列について
-
C# KeyDownイベントでショート...
-
const_castのつかいどころを教...
-
H8マイコンのシリアル通信につ...
-
コールバックって・・・
-
関数ポインタについて
-
void main()って誰が最初?:AN...
おすすめ情報