MSDNのヘルプページから、ビデオエンコードとビデオ入力形式がWMV3/RGB32の場合、InitializeSinkWriterは正常に動作しますが、WMV1、MPEG2などに変更するとSetInputMediaTypeは失敗します。なぜMediaFoundation InitializeSinkWriter(SetInputMediaType)はWMV3形式のみを受け入れますか?
AFAIK私は、Sherlock the Codec Detectiveプログラムに従って、WMV1をコーデックとしてインストールしています。 (ソースのコメントに「問題」を検索し、問題のコードを見つけるために、無関係であるボイラープレートコードがたくさんある)
// Format constants
const UINT32 VIDEO_WIDTH = 640;
const UINT32 VIDEO_HEIGHT = 480;
const UINT32 VIDEO_FPS = 30;
const UINT64 VIDEO_FRAME_DURATION = 10 * 1000 * 1000/VIDEO_FPS;
const UINT32 VIDEO_BIT_RATE = 800000;
const GUID VIDEO_ENCODING_FORMAT = MFVideoFormat_WMV1 ; // problem here, must be WMV3
const GUID VIDEO_INPUT_FORMAT = MFVideoFormat_WMV3 ; // problem here if not wmv3 too
const UINT32 VIDEO_PELS = VIDEO_WIDTH * VIDEO_HEIGHT;
const UINT32 VIDEO_FRAME_COUNT = 20 * VIDEO_FPS;
HRESULT InitializeSinkWriter(IMFSinkWriter **ppWriter, DWORD *pStreamIndex)
{
*ppWriter = NULL;
*pStreamIndex = NULL;
IMFSinkWriter *pSinkWriter = NULL;
IMFMediaType *pMediaTypeOut = NULL;
IMFMediaType *pMediaTypeIn = NULL;
DWORD streamIndex;
HRESULT hr = MFCreateSinkWriterFromURL(L"output.wmv", NULL, NULL, &pSinkWriter);
// Set the output media type.
if (SUCCEEDED(hr))
{
hr = MFCreateMediaType(&pMediaTypeOut);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, VIDEO_ENCODING_FORMAT);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, VIDEO_BIT_RATE);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
}
if (SUCCEEDED(hr))
{
hr = pSinkWriter->AddStream(pMediaTypeOut, &streamIndex);
}
// Set the input media type.
if (SUCCEEDED(hr))
{
hr = MFCreateMediaType(&pMediaTypeIn);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, VIDEO_FPS, 1);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
}
if (SUCCEEDED(hr))
{
// Problem here! Codec issue with wmv1, mpeg, etc.
hr = pSinkWriter->SetInputMediaType(streamIndex, pMediaTypeIn, NULL);
}
else {
puts("setattributeratio failed");
}
// Tell the sink writer to start accepting data.
if (SUCCEEDED(hr))
{
hr = pSinkWriter->BeginWriting();
}
else {
puts("setinputmediatype failed"); // <-- HR result problem here
}
// Return the pointer to the caller.
if (SUCCEEDED(hr))
{
*ppWriter = pSinkWriter;
(*ppWriter)->AddRef();
*pStreamIndex = streamIndex;
}
else {
puts("beginwriting failed");
}
SafeRelease(&pSinkWriter);
SafeRelease(&pMediaTypeOut);
SafeRelease(&pMediaTypeIn);
return hr;
}
初期化:ここで
は、問題の原因コードですシンクライターは、このコードで呼び出されます。
void main()
{
DWORD streamidx = 0;
const WCHAR *SAMPLE_FILE = L"sample.wmv";
IMFSourceReader *pReader = NULL;
IMFSinkWriter *pWriter = NULL;
puts("Initializing...");
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
if (SUCCEEDED(hr))
{
// problem here !
hr = InitializeSinkWriter(&pWriter, &streamidx);
if (SUCCEEDED(hr))
{
// more code would go here...
}
else {
puts("InitializeSinkWriter failed"); // this is called
}
SafeRelease(&pWriter);
MFShutdown();
}
CoUninitialize();
}
puts("Finished...");
}
これは、私はコーデックをインストールする必要がどういう意味、それが唯一のエンコーダや入力タイプとしてWMV3を受け入れた場合、私が使用しています標準のWindows 7コンピュータであり、そう?これは、WMV1やMPEGのような一般的なフォーマットが既にインストールされているはずで、Sherlockコーデックの探偵はそれがそうだと言っているので不合理に思えます
面白いので、技術的にはWindowsの(VFW)の古いビデオもののVFWを使用してビデオを圧縮するために、ほとんどのコーデックを使用できるため、技術的に優れています。 VFWの代替品ですか、古くて、おそらく別のツールですか?おそらく –
のDirectShowでも、使用できない場合、APIにWMV1のこれらの定数があるのはなぜですか?つまり、MFVideoFormat_WMV1は利用可能な孤立定数ですが、許容できません。どうして?廃止されましたか? Vistaの日に戻って使用されましたか?あるいは、将来の使用のためにこれらの定数をここに入れますか? APIにはMFVideoFormat_がプレフィックスされた数多くの定数があり、実際に使用できるのはほんのわずかです。 –
はい、それはMedia Foundationの弱点の1つです。新しいAPIに古いユースケースのレシピがあり、移行する方法があると一般的に想定されています。実際、Media Foundationでは、MicrosoftはDirectShowと比較して柔軟性を大幅に取り戻し、移行には十分なツールを提供していませんでした。 DirectShowは最もフレキシブルで開発者にとって使いやすいものです。 –