2017-06-30 29 views
0

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コーデックの探偵はそれがそうだと言っているので不合理に思えます

答えて

2

Windows Media Foundationで試しているコーデックはサポートしていません他のAPIのための他のコーデック)。

参照:

+0

面白いので、技術的にはWindowsの(VFW)の古いビデオもののVFWを使用してビデオを圧縮するために、ほとんどのコーデックを使用できるため、技術的に優れています。 VFWの代替品ですか、古くて、おそらく別のツールですか?おそらく –

+0

のDirectShowでも、使用できない場合、APIにWMV1のこれらの定数があるのはなぜですか?つまり、MFVideoFormat_WMV1は利用可能な孤立定数ですが、許容できません。どうして?廃止されましたか? Vistaの日に戻って使用されましたか?あるいは、将来の使用のためにこれらの定数をここに入れますか? APIにはMFVideoFormat_がプレフィックスされた数多くの定数があり、実際に使用できるのはほんのわずかです。 –

+0

はい、それはMedia Foundationの弱点の1つです。新しいAPIに古いユースケースのレシピがあり、移行する方法があると一般的に想定されています。実際、Media Foundationでは、MicrosoftはDirectShowと比較して柔軟性を大幅に取り戻し、移行には十分なツールを提供していませんでした。 DirectShowは最もフレキシブルで開発者にとって使いやすいものです。 –

関連する問題