3
votes

I have an MP4 video containing a single H.264 stream and no audio stream. I would like to use DirectShow with C++ to decode the video, but I'm having trouble setting up the DirectShow filters and hoped that someone might be able to help?

Here's my setup code for using DirectShow to decode a WMV3 stream, which I have working well:

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGraph);

if (SUCCEEDED(hr))      hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&m_pFilter);
if (SUCCEEDED(hr))      hr = m_pFilter->QueryInterface(IID_IVMRFilterConfig9, reinterpret_cast<void**>(&filterConfig));
if (SUCCEEDED(hr))      hr = filterConfig->SetRenderingMode( VMR9Mode_Renderless );
if (SUCCEEDED(hr))      hr = filterConfig->SetNumberOfStreams(2);
if (SUCCEEDED(hr))      hr = SetAllocatorPresenter( m_pFilter, g_pMainWindow );
if (SUCCEEDED(hr))      hr = m_pGraph->AddFilter(m_pFilter, L"Video Mixing Renderer 9");
if (SUCCEEDED(hr))      hr = m_pGraph->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&m_pMediaControl));
if (SUCCEEDED(hr))      hr = m_pGraph->QueryInterface(IID_IBasicAudio, reinterpret_cast<void**>(&m_pBasicAudio));
if (SUCCEEDED(hr))      hr = m_pGraph->RenderFile( lpFilename, NULL );

I cannot figure out the right setup to decode an MP4 however. I've already installed 3ivx and ffdshow as discovered in other posts, and now GraphEdit can open my file and display the right graphs (thought - I'm on a 64 bit machine, and when I run the 64 bit version of GraphEdit this DOESN'T work, but the 32 bit one does... could that be something to do with it?). VLC can play my videos fine.

I've search the ENTIRE internet for examples specific to this, and can't find any.

My video file format is as follows (ffmpeg output):

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp42mp41
    creation_time   : 2013-01-16 19:14:52
  Duration: 00:05:25.62, start: 0.033367, bitrate: 3396 kb/s
    Stream #0:0(eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 3393 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc
    Metadata:
      creation_time   : 2013-01-16 19:14:52
      handler_name    : ?Mainconcept Video Media Handler

Any help would be greatly appreciated!

Regards, Graham

1

1 Answers

0
votes

There is no standard/default MP4 demultiplexer in Windows, so you have to have one installed to extended DirectShow to cover MP4s.

  • you need demultiplexer of proper bitness (32 vs. 64 bit) installed to match bitness of your code/app (or GraphEdit)
  • VLC does not matter since it has its own demultiplexer built in
  • you need H.264 decoder as well, and you seem to have one already

Your code is about right but this method of graph building is not quite realiable. First of all you need to see if you are getting any helpful error code (you perhaps have on the RenderFile call).

If GraphEdit Win32 works on this system, all required components (filters) should be available. The difference is that GraphEdit does not build graph the way you do. Instead it uses IGraphBuilder::AddSourceFilter for the given file to add starting filter and then renders its pins. If you take the same approach and on the final step you add your VMR filter for video presentation, this is going to work out well.