Optimizing Playback: MP4 MOV Decoder DirectShow Filter SDK Best Practices

MP4 MOV Decoder DirectShow Filter SDK: API Reference and Examples

This article documents the API for an MP4/MOV Decoder DirectShow Filter SDK and provides concise examples showing how to integrate and use the filter in a Windows DirectShow graph. It assumes a C++ Windows development environment, Visual Studio, and familiarity with COM and DirectShow basics.

Overview

The MP4/MOV Decoder DirectShow Filter SDK exposes a COM-based DirectShow transform filter that decodes MP4/MOV container streams (H.264/HEVC video, AAC/AC-3 audio, and common subtitle tracks) into raw media samples usable by downstream DirectShow renderers or processors. The SDK includes:

  • Filter COM class and registration utilities.
  • Filter-specific interfaces for configuration and diagnostics.
  • Sample code: demuxer+decoder graph and a playback app.
  • Header files, import libraries, and Doxygen-style API docs.

Installation and Registration

  1. Copy the filter DLL (e.g., Mp4MovDecoder.ax) to a system folder or application folder.

  2. Register the filter:

    • From an elevated command prompt:

      Code

      regsvr32 Mp4MovDecoder.ax
    • Or use the provided registration utility: Mp4MovReg.exe /install
  3. Verify registration with GraphEdit/GraphStudioNext — the filter appears under “Filters” as “MP4/MOV Decoder”.

Primary Interfaces

  • IMFMP4MovDecoder (extends IUnknown)

    • Purpose: Configure decoder behavior, query capabilities.
    • IID: {E0A1B2C3-0000-0000-0000-000000000001} (example)
    • Key methods:
      • HRESULT SetDecodingThreads(UINT32 threads);
      • HRESULT GetDecodingThreads(UINT32threads);
      • HRESULT SetHardwareAcceleration(BOOL enable);
      • HRESULT GetHardwareAcceleration(BOOL *enabled);
      • HRESULT SetOutputFormat(GUID mediaSubType); // e.g., MEDIASUBTYPE_RGB24, MEDIASUBTYPE_NV12
      • HRESULT QuerySupportedFormats(IEnumMediaTypes **ppEnum);
  • IMFDecoderStats (extends IUnknown)

    • Purpose: Retrieve runtime statistics.
    • Key methods:
      • HRESULT GetFrameCount(UINT64 *decoded);
      • HRESULT GetDroppedFrameCount(UINT64 *dropped);
      • HRESULT GetAverageDecodeTimeMs(double *avgMs);
  • IFilterPropertyPage (standard DirectShow property page support)

    • Purpose: UI for configuration in GraphEdit/GraphStudioNext.

Registration and CLSID

  • CLSIDMp4MovDecoder: {F1F2F3F4-0000-0000-0000-000000000010}
  • ProgID: Mp4Mov.DecoderFilter

(Use the SDK’s headers for real GUID values.)

Usage Patterns

A. Using the Filter in a Manual DirectShow Graph (C++)

  1. Initialize COM and create the filter graph:

    Code

    CoInitializeEx(NULL, COINIT_MULTITHREADED); IGraphBuilder *pGraph = nullptr; CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPVARGS(&pGraph));
  2. Create instances of source, splitter/demux (if required), and decoder filter:

    Code

    IBaseFilter *pSource = nullptr, *pSplitter = nullptr, *pDecoder = nullptr; // Create source (AsyncReader or custom source) // Create splitter/demux (e.g., LAV Splitter) or use built-in CoCreateInstance(CLSID_Mp4MovDecoder, NULL, CLSCTX_INPROC_SERVER, IID_PPVARGS(&pDecoder)); pGraph->AddFilter(pDecoder, L”MP4/MOV Decoder”);
  3. Connect pins or use RenderFile to let DirectShow auto-build:

    Code

    pGraph->RenderFile(L”C:\videos\sample.mp4”, NULL);
  4. Configure the filter via IMFMP4MovDecoder:

    Code

    IMFMP4MovDecoder *pCfg = nullptr; if (SUCCEEDED(pDecoder->QueryInterface(IID_PPV_ARGS(&pCfg)))) {

    pCfg->SetDecodingThreads(4); pCfg->SetHardwareAcceleration(TRUE); pCfg->SetOutputFormat(MEDIASUBTYPE_NV12); pCfg->Release(); 

    }

  5. Run the graph:

    Code

    IMediaControl *pControl = nullptr; pGraph->QueryInterface(IID_PPV_ARGS(&pControl)); pControl->Run();
  6. Clean up COM objects and uninitialize.

B. Using the Filter with the Sample Playback App

  • The SDK includes a Win32 sample that builds a file-open UI, creates a graph with an AsyncFileSource -> Splitter -> MP4/MOV Decoder -> Video Renderer chain, and exposes a property page for runtime tweaks.

API Reference (Key Methods and Expected Behavior)

Note: HRESULT return values follow COM conventions. Parameters marked [out] must be non-null.

  • IMFMP4MovDecoder::SetDecodingThreads(UINT32 threads)

    • Sets worker threads for parallel frame decode. Allowed range: 1–16. Returns E_INVALIDARG for out-of-range.
  • IMFMP4MovDecoder::GetDecodingThreads(UINT32 *threads)

    • Retrieves current thread count.
  • IMFMP4MovDecoder::SetHardwareAcceleration(BOOL enable)

    • Enables/disables GPU-accelerated decoding (via DXVA2/Media Foundation HW contexts). Returns S_OK or E_FAIL if unsupported.
  • IMFMP4MovDecoder::SetOutputFormat(GUID mediaSubType)

    • Preferred output media subtype; decoder negotiates with downstream filters. If unsupported, the filter falls back to a compatible format and returns S_FALSE.
  • IMFMP4MovDecoder::QuerySupportedFormats(IEnumMediaTypes **ppEnum)

    • Returns enumerator listing supported AM_MEDIATYPE structures.
  • IMFDecoderStats::GetFrameCount(UINT64 *decoded)

    • Returns total decoded frames since filter start/reset.
  • IMFDecoderStats::GetDroppedFrameCount(UINT64 *dropped)

    • Returns dropped frame count.
  • IMFDecoderStats::GetAverageDecodeTimeMs(double *avgMs)

    • Average decode time in milliseconds.

Media Type Notes

  • Video inputs accepted: H.264 (AVC), H.265 (HEVC) in MP4/MOV containers.
  • Audio: AAC, AC-3 — decoder can output raw PCM or pass through to audio decoders.
  • Subtitles: QuickTime text, 3GPP timed text — delivered as separate samples or exposed as sidecar streams.

Example: Querying Capabilities and Enumerating Formats (C++)

Code

IMFMP4MovDecoder *pCfg = nullptr; if (SUCCEEDED(pDecoder->QueryInterface(IID_PPV_ARGS(&pCfg)))) {

IEnumMediaTypes *pEnum = nullptr; if (SUCCEEDED(pCfg->QuerySupportedFormats(&pEnum))) {     AM_MEDIA_TYPE *pmt = nullptr;     while (pEnum->Next(1, &pmt, NULL) == S_OK) {         // Inspect pmt->subtype, pmt->formattype, VIDEOINFOHEADER2, etc.         DeleteMediaType(pmt);     }     pEnum->Release(); } pCfg->Release(); 

}

Example: Reading Runtime Stats (C++)

Code

IMFDecoderStats *pStats = nullptr; if (SUCCEEDED(pDecoder->QueryInterface(IID_PPV_ARGS(&pStats)))) {

UINT64 decoded=0, dropped=0; double avgMs=0.0; pStats->GetFrameCount(&decoded); pStats->GetDroppedFrameCount(&dropped); pStats->GetAverageDecodeTimeMs(&avgMs); // display values pStats->Release(); 

}

Error Handling and Diagnostics

  • Use standard COM HRESULT checking. Common return codes:
    • S_OK, S_FALSE, E_INVALIDARG, E_OUTOFMEMORY, E_FAIL, VFW_E_TYPE_NOT_ACCEPTED.
  • Enable verbose logging via the filter registry key or property page to output decode errors, format negotiations, and DXVA fallbacks.

Performance Tips

  • Prefer MEDIASUBTYPE_NV12 output when using DXVA or hardware renderers.
  • Increase decoding threads for multi-core CPUs, but avoid oversubscription (> core count).
  • Use hardware acceleration when available; fall back gracefully.

Troubleshooting

  • If playback stalls: check downstream pin connections, ensure splitter exposes elementary streams.
  • If wrong colors: verify output media subtype and video renderer color space support.
  • If filter not listed: confirm regsvr32 succeeded and GUIDs match GraphEdit expectations.

Appendix: Sample Build Commands

  • Use Visual Studio solution provided in SDK. Key settings:
    • Platform: x64 (recommended)
    • Runtime: Multi-threaded DLL (/MD)
    • Link against strmiids.lib and quartz.lib

Conclusion

This API provides straightforward methods for configuring decoding threads, hardware acceleration, output format negotiation, and runtime statistics. Use the sample applications and property page to speed integration into DirectShow graphs.

For full reference, consult the SDK headers and the Doxygen-generated docs included in the SDK package.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *