Search code examples
ms-media-foundation

Efficiently connecting an asynchronous IMFSourceReader to a synchronous IMFTransform


Given an asynchronous IMFSourceReader connected to a synchronous only IMFTransform.

Then for the IMFSourceReaderCallback::OnReadSample() callback is it a good idea not to call IMFTransform::ProcessInput directly within OnReadSample, but instead push the produced sample onto another queue for another thread to call the transforms ProcessInput on?

Or would I just be replicating identical work source readers typically do internally? Or put another way does work within OnReadSample run the risk of blocking any further decoding work within the source reader that could have otherwise happened more asynchronously?

So I am suggesting something like:

WorkQueue transformInputs;
...

//  Called back async
HRESULT OnReadSampleCallback(... IMFSample* sample)
{
    // Push sample and return immediately
    Push(transformInputs, sample); 
}

//  Different worker thread awoken for transformInputs queue samples
void OnTransformInputWork()
{
    //  Transform object is not async capable
    transform->TransformInput(0, Pop(transformInputs), 0);
    ...
}

This is touched on, but not elaborated on here 'Implementing the Callback Interface': https://learn.microsoft.com/en-us/windows/win32/medfound/using-the-source-reader-in-asynchronous-mode

Or is it completely dependent on whatever the source reader sets up internally and not easily determined?


Solution

  • It is not a good idea to perform a long blocking operation in IMFSourceReaderCallback::OnReadSample. Nothing is going to be fatal or serious but this is not the intended usage.

    Taking into consideration your previous question about audio format conversion though, audio sample data conversion is fast enough to happen on such callback.

    Also, it is not clear or documented (depends on actual implementation), ProcessInput is often instant and only references input data. ProcessOutput would be computationally expensive in this case. If you don't do ProcessOutput right there in the same callback you might run into situation where MFT is no longer accepting input, and so you'd have to implement a queue anyway.

    With all this in mind you would just do the processing in the callback neglecting performance impact assuming your processing is not too heavy, or otherwise you would just start doing the queue otherwise.