Multiple MFT ProcessOutput calls for single MF MediaEngine SetCurrentTime

Vytautas 1 Reputation point
2021-04-29T09:30:44.433+00:00

Hi,
I try to use Grayscale Transform (mft_grayscale example from Windows SDK 7.1) -based MFT to grab and save frame of opened MP4 video.
MFT is added as video effect to MediaEngine-besed player.
f I seek to frame using MF MediaEngine SetCurrentTime, then ProcessOutput of transform is called 4 times:

  1. At ProcessOutput m_pSample == NULL (MF_E_TRANSFORM_NEED_MORE_INPUT);
  2. At ProcessOutput m_pSample is not NULL, can get data.
  3. At ProcessOutput m_pSample == NULL (MF_E_TRANSFORM_NEED_MORE_INPUT);
  4. At ProcessOutput m_pSample is not NULL, can get data.
    And at last call of ProcessOutput, input sample contains not data of seeked and by renderer displayed frame, but frame after(?) it.
    How in ProcessOutput get single frame that will be shown by renderer?
    Below is mftrace of single SetCurrentTime call.

9756,3750 08:25:58.85157 TraceOSVersion @ OS version (BuildLabEx): 19041.1.amd64fre.vb_release.191206-1406
9756,3750 08:25:58.85157 TraceMFDetoursVersion @ MFDetours version 1.0.0.1
9756,3750 08:25:58.85161 TraceEnabledKeywords @ Keywords and levels: Default 4, Detours 4, Kernel32Export 4, MFExport 4, MFPlatExport 4, MFPlayExport 4, MFReadWriteExport 4, Ole32Export 4, wmvCoreExport 4, MFPublic 4, IMFActivate 4, IMFAttributes 4, IMFClock 4, IMFMediaEventGenerator 4, IMFMediaSession 4, IMFMediaSink 4, IMFMediaSource 4, IMFMediaStream 4, IMFPMediaPlayer 4, IMFPMediaItem 4, IMFPMediaPlayerCallback 4, IMFPresentationClock 4
9756,3750 08:25:58.85164 TraceEnabledKeywords @ Keywords and levels: IMFQualityAdvise 4, IMFQualityAdvise2 4, IMFQualityManager 4, IMFSample 4, IMFSinkWriter 4, IMFSourceReader 4, IMFSourceReaderCallback 4, IMFSourceResolver 4, IMFStreamSink 4, IMFTopology 4, IMFTopologyNode 4, IMFTopoLoader 4, IMFTransform 4, IMediaObject 4, IMFSchemeHandler 4, IMFByteStream 4, IMFByteStreamHandler 4, IMFReadWriteClassFactory 4, IFilterGraph 4, IGraphBuilder 4
9756,3750 08:25:58.85164 TraceEnabledKeywords @ Keywords and levels: IMediaControl 4, IMemInputPin 4, IWMReader 4, IWMReaderCallback 4
9756,3750 08:25:58.85217 CMFMediaSessionDetours::Attach @16557DF8 Presentation clock @07AC0EE0
9756,2394 08:25:58.90048 CMFPresentationClockDetours::GetTime @20C98E40 Time 8389024hns
9756,2394 08:25:58.90180 CMFPresentationClockDetours::GetTime @20C98E40 Time 8389024hns
9756,2394 08:26:09.20358 CMFPresentationClockDetours::GetTime @20C98E40 Time 8389024hns
...
9756,2394 08:26:09.20362 CKernel32ExportDetours::OutputDebugStringA @ -----; CPlayer2; OnMediaEngineEvent; MF_MEDIA_ENGINE_EVENT_SEEKING
9756,2394 08:26:09.20367 CKernel32ExportDetours::OutputDebugStringA @ -----; CPlayer2; OnMediaEngineEvent; MF_MEDIA_ENGINE_EVENT_TIMEUPDATE
9756,37B0 08:26:09.20384 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=108 MESessionRateChanged, value 0.000000,
9756,1DBC 08:26:09.20411 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessMessage; ++
9756,1DBC 08:26:09.20413 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessMessage; --
9756,1DBC 08:26:09.20453 CKernel32ExportDetours::OutputDebugStringA @ -----; GetStreamCount; ++
9756,1DBC 08:26:09.20456 CKernel32ExportDetours::OutputDebugStringA @ -----; GetStreamCount; --
9756,1DBC 08:26:09.20457 CKernel32ExportDetours::OutputDebugStringA @ -----; GetStreamCount; ++
9756,1DBC 08:26:09.20458 CKernel32ExportDetours::OutputDebugStringA @ -----; GetStreamCount; --
9756,1DBC 08:26:09.20460 CKernel32ExportDetours::OutputDebugStringA @ -----; GetInputCurrentType; ++
9756,1DBC 08:26:09.20461 CKernel32ExportDetours::OutputDebugStringA @ -----; GetInputCurrentType; --
9756,1DBC 08:26:09.20462 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputCurrentType; ++
9756,1DBC 08:26:09.20463 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputCurrentType; --
9756,1DBC 08:26:09.20470 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessMessage; ++
9756,1DBC 08:26:09.20471 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessMessage; --
9756,1DBC 08:26:09.20489 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; ++
9756,1DBC 08:26:09.20490 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; --
9756,1DBC 08:26:09.20492 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessOutput; ++ MF_E_TRANSFORM_NEED_MORE_INPUT
9756,1DBC 08:26:09.23066 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessInput; ++
9756,1DBC 08:26:09.23068 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessInput; --
9756,1DBC 08:26:09.23070 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; ++
9756,1DBC 08:26:09.23071 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; --
9756,1DBC 08:26:09.23073 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessOutput; ++
9756,1DBC 08:26:09.23353 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessOutput; --
9756,1DBC 08:26:09.23390 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; ++
9756,1DBC 08:26:09.23392 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; --
9756,1DBC 08:26:09.23393 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessOutput; ++ MF_E_TRANSFORM_NEED_MORE_INPUT
9756,1DBC 08:26:09.23407 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessInput; ++
9756,1DBC 08:26:09.23408 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessInput; --
9756,1DBC 08:26:09.23410 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; ++
9756,1DBC 08:26:09.23411 CKernel32ExportDetours::OutputDebugStringA @ -----; GetOutputStreamInfo; --
9756,1DBC 08:26:09.23412 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessOutput; ++
9756,1DBC 08:26:09.23648 CKernel32ExportDetours::OutputDebugStringA @ -----; ProcessOutput; --
9756,C34 08:26:09.23657 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=110 MESessionCapabilitiesChanged, value (empty), MF_EVENT_SESSIONCAPS=119;MF_EVENT_SESSIONCAPS_DELTA=4
9756,C34 08:26:09.23662 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=103 MESessionStarted, value (empty), MF_EVENT_PRESENTATION_TIME_OFFSET=0 (0,0)
9756,C34 08:26:09.23668 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=109 MESessionScrubSampleComplete, value (empty),
9756,1DBC 08:26:09.23670 CMFStreamSinkDetours::EndGetEvent @07AC2100 Met=303 MEStreamSinkPaused, value (empty),
9756,37B0 08:26:09.23674 CMFMediaSourceDetours::EndGetEvent @01C664C8 Met=209 MESourcePaused, value (empty),
9756,37B0 08:26:09.23677 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=110 MESessionCapabilitiesChanged, value (empty), MF_EVENT_SESSIONCAPS=115;MF_EVENT_SESSIONCAPS_DELTA=4
9756,37B0 08:26:09.23678 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=104 MESessionPaused, value (empty),
9756,37B0 08:26:09.23680 CMFMediaSourceDetours::EndGetEvent @01C664C8 Met=217 MESourceRateChanged, value 1.000000,
9756,C34 08:26:09.23690 CMFMediaSessionDetours::EndGetEvent @20C93C00 Met=108 MESessionRateChanged, value 1.000000,
9756,C34 08:26:09.23691 CMFPresentationClockDetours::GetTime @20C98E40 Time 7689938hns
9756,C34 08:26:09.23693 CKernel32ExportDetours::OutputDebugStringA @ -----; CPlayer2; OnMediaEngineEvent; MF_MEDIA_ENGINE_EVENT_TIMEUPDATE
9756,C34 08:26:09.23695 CKernel32ExportDetours::OutputDebugStringA @ -----; CPlayer2; OnMediaEngineEvent; MF_MEDIA_ENGINE_EVENT_SEEKED
9756,2394 08:26:09.23746 CMFPresentationClockDetours::GetTime @20C98E40 Time 7689938hns
9756,2394 08:26:09.23751 CMFPresentationClockDetours::GetTime @20C98E40 Time 7689938hns
...

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,428 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Klaus Weitzekker 1 Reputation point
    2021-10-19T12:51:03.78+00:00

    Here is some code for you to prove tha tMP4 video resamper is capable to process large video files at once. It is good, efficient processing style:

    winrt::com_ptr<IMFTransform> Transform;
    winrt::check_hresult(CoCreateInstance(CLSID_CResamplerMediaObject, nullptr, CLSCTX_ALL, IID_PPV_ARGS(Transform.put())));
    
    WAVEFORMATEX InputWaveFormatEx { WAVE_FORMAT_PCM, 1, 44100, 44100 * 2, 2, 16 };
    WAVEFORMATEX OutputWaveFormatEx { WAVE_FORMAT_PCM, 1, 48000, 48000 * 2, 2, 16 };
    
    winrt::com_ptr<IMFMediaType> InputMediaType;
    winrt::check_hresult(MFCreateMediaType(InputMediaType.put()));
    winrt::check_hresult(MFInitMediaTypeFromWaveFormatEx(InputMediaType.get(), &InputWaveFormatEx, sizeof InputWaveFormatEx));
    winrt::com_ptr<IMFMediaType> OutputMediaType;
    winrt::check_hresult(MFCreateMediaType(OutputMediaType.put()));
    winrt::check_hresult(MFInitMediaTypeFromWaveFormatEx(OutputMediaType.get(), &OutputWaveFormatEx, sizeof OutputWaveFormatEx));
    
    winrt::check_hresult(Transform->SetInputType(0, InputMediaType.get(), 0));
    winrt::check_hresult(Transform->SetOutputType(0, OutputMediaType.get(), 0));
    
    MFT_OUTPUT_STREAM_INFO OutputStreamInfo { };
    winrt::check_hresult(Transform->GetOutputStreamInfo(0, &OutputStreamInfo));
    _A(!(OutputStreamInfo.dwFlags & MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER));
    
    DWORD const InputMediaBufferSize = InputWaveFormatEx.nAvgBytesPerSec;
    winrt::com_ptr<IMFMediaBuffer> InputMediaBuffer;
    winrt::check_hresult(MFCreateMemoryBuffer(InputMediaBufferSize, InputMediaBuffer.put()));
    winrt::check_hresult(InputMediaBuffer->SetCurrentLength(InputMediaBufferSize));
    winrt::com_ptr<IMFSample> InputSample;
    winrt::check_hresult(MFCreateSample(InputSample.put()));
    winrt::check_hresult(InputSample->AddBuffer(InputMediaBuffer.get()));
    winrt::check_hresult(Transform->ProcessInput(0, InputSample.get(), 0));
    
    DWORD const OutputMediaBufferCapacity = OutputWaveFormatEx.nAvgBytesPerSec;
    winrt::com_ptr<IMFMediaBuffer> OutputMediaBuffer;
    winrt::check_hresult(MFCreateMemoryBuffer(OutputMediaBufferCapacity, OutputMediaBuffer.put()));
    winrt::check_hresult(OutputMediaBuffer->SetCurrentLength(0));
    winrt::com_ptr<IMFSample> OutputSample;
    winrt::check_hresult(MFCreateSample(OutputSample.put()));
    winrt::check_hresult(OutputSample->AddBuffer(OutputMediaBuffer.get()));
    MFT_OUTPUT_DATA_BUFFER OutputDataBuffer { 0, OutputSample.get() };
    DWORD Status;
    winrt::check_hresult(Transform->ProcessOutput(0, 1, &OutputDataBuffer, &Status));
    
    DWORD OutputMediaBufferSize = 0;
    winrt::check_hresult(OutputMediaBuffer->GetCurrentLength(&OutputMediaBufferSize));
    

    Also I'm not sure if Javascript getTime function works correctly in this case...

    0 comments No comments