A zero-length sample is valid only if that successful ProcessOutput call also returned a non-empty in-band event collection; if it returned neither H.264 data nor events, the Qualcomm MFT is not following the documented IMFTransform::ProcessOutput contract.
Handle the result by payload, events, and status
For every METransformHaveOutput, call ProcessOutput exactly once. An asynchronous MFT requires this one-to-one event/call relationship and should not return MF_E_TRANSFORM_NEED_MORE_INPUT; calling at another time can return E_UNEXPECTED.^1^
On S_OK:
- Process
output.pEventsbefore the sample. - Inspect
output.dwStatusandoutputStatus. - Consume the sample only when its total/current length is nonzero.
- If
MFT_OUTPUT_DATA_BUFFER_INCOMPLETEis set, more output remains, but for an asynchronous MFT wait for the correspondingMETransformHaveOutputrather than adding an unprompted synchronous-style call. - Log an anomaly when both payload and the event collection are empty.
Media Foundation explicitly permits S_OK with zero output samples when in-band events were returned. If no stream has data and no events exist, the normal synchronous result is MF_E_TRANSFORM_NEED_MORE_INPUT.^2^
Your current code releases pEvents without examining its contents. Record the collection count first:
DWORD eventCount = 0;
if (output.pEvents)
output.pEvents->GetElementCount(&eventCount);
DWORD totalLength = 0;
if (output.pSample)
output.pSample->GetTotalLength(&totalLength);
printf("hr=%08X bytes=%lu events=%lu stream=%08lX global=%08lX\n",
static_cast<unsigned>(hr),
static_cast<unsigned long>(totalLength),
static_cast<unsigned long>(eventCount),
static_cast<unsigned long>(output.dwStatus),
static_cast<unsigned long>(outputStatus));
if (SUCCEEDED(hr) && totalLength == 0 && eventCount == 0)
LogEncoderContractViolation();
Also decode dwStatus, particularly NO_SAMPLE, INCOMPLETE, FORMAT_CHANGE, and STREAM_END. NO_SAMPLE means that stream has no sample ready; INCOMPLETE means more output can be generated.^3^
It does not, by itself, prove a dropped frame
A zero-byte result alone does not distinguish:
- an intentional duplicate-frame suppression;
- a frame dropped because of encoder or buffer constraints;
- an event-only output;
- an implementation/driver defect.
The documented output attributes MFSampleExtension_VideoEncodePictureType and MFSampleExtension_VideoEncodeQP describe the picture type and QP of an encoded sample.^4^^5^ They are useful on non-empty samples but are not documented as drop-reason indicators. MFSampleExtension_Discontinuity identifies the first sample after a stream gap, not why an encoder omitted data.^6^
Microsoft documents zero-byte and dropped-frame statistics for codecs exposing the corresponding legacy property interfaces. Querying them is useful only if this Qualcomm MFT actually exposes those properties:
-
MFPKEY_ZEROBYTEFRAMES: duplicate frames skipped. -
MFPKEY_CODEDFRAMESversusMFPKEY_TOTALFRAMES: difference indicates dropped frames.^7^
Do not assume those Windows Media codec properties or MFPKEY_PRODUCEDUMMYFRAMES are implemented by this Qualcomm H.264 MFT; no supplied Qualcomm documentation establishes that support.
Configuration and recovery
There is no documented Media Foundation operation that reconstructs the missing H.264 access unit after the MFT has emitted an empty result. Continue processing, but preserve the input/output timestamps in the diagnostic log.
If the MFT reports CODECAPI_AVLowLatencyMode as supported through ICodecAPI::IsSupported, test enabling it before streaming. Low-latency mode expects one input sample to produce one output sample without reordering delay, although it can reduce encoding quality.^8^ This is a diagnostic/configuration option, not evidence that empty outputs are expected or a guaranteed recovery mechanism.
Also compare the requested workload against the MFT’s read-only MF_VIDEO_MAX_MB_PER_SEC attribute, if present. It reports the hardware encoder’s maximum macroblock processing rate and is affected by level, quality-versus-speed, and B-frame settings.^9^ If the requested rate exceeds that capability, reduce frame rate/resolution or select faster supported settings before treating the result as a driver defect.
Capture evidence for the OEM
Run MFTrace around the process:
mftrace.exe -a YourEncoderApp.exe -o mftrace.txt
Search for:
-
CMFTransformDetours::ProcessInput -
CMFTransformDetours::ProcessOutput -
METransformNeedInput -
ProcessOutputs available -
0xc00d
MFTrace can attach to an existing process and records Media Foundation calls; ETW/WPP provider tracing requires a configuration file.^10^
If a trace shows one ProcessOutput per METransformHaveOutput, S_OK, zero bytes, zero in-band events, no format/stream status, and later normal output, collect the device model, Windows build, Qualcomm display/media driver version, negotiated media types, timestamps, and a minimal reproduction for the device OEM or Qualcomm. That evidence identifies a Qualcomm MFT/driver contract violation rather than an application-side empty-sample handling issue.
References
- Asynchronous MFTs
- IMFTransform::ProcessOutput (mftransform.h) - Win32 apps
- _MFT_OUTPUT_DATA_BUFFER_FLAGS enumeration (mftransform.h)
- MFSampleExtension_VideoEncodePictureType attribute
- MFSampleExtension_VideoEncodeQP attribute
- MFSampleExtension_Discontinuity attribute
- Getting Encoding Statistics (Microsoft Media Foundation)
- CODECAPI_AVLowLatencyMode property
- MF_VIDEO_MAX_MB_PER_SEC attribute
- Using MFTrace