Skip to content

Instantly share code, notes, and snippets.

@adammarks
Last active June 15, 2016 13:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adammarks/667f87a019928661d82a1ffcac28870c to your computer and use it in GitHub Desktop.
Save adammarks/667f87a019928661d82a1ffcac28870c to your computer and use it in GitHub Desktop.
This code tries to use the Intel QuickSync Encoder MFT and it causes a crash on Win7 when we try to get a event ( Intel HD3000 graphics )
#include "stdafx.h"
#include <assert.h>
#include <mfapi.h>
#include <mfidl.h>
#include <Mfreadwrite.h>
#include <mferror.h>
#include <initguid.h>
#pragma comment(lib, "mfreadwrite")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfuuid")
#pragma comment(lib, "mf")
// {4BE8D3C0-0515-4A37-AD55-E4BAE19AF471}
DEFINE_GUID( CLSID_MF_INTEL_H264EncFilter, // Intel Quick Sync Encoder
0x4be8d3c0, 0x0515, 0x4a37, 0xad, 0x55, 0xe4, 0xba, 0xe1, 0x9a, 0xf4, 0x71 );
#define CHECK_HR(_hr) { if ( FAILED(hr) ) goto done; hr = (_hr); assert(SUCCEEDED(hr)); if ( FAILED(hr) ) goto done; }
// Format constants
const UINT32 VIDEO_WIDTH = 640;
const UINT32 VIDEO_HEIGHT = 480;
const UINT32 HEIGHT_X_WIDTH = VIDEO_WIDTH * VIDEO_HEIGHT;
const UINT32 VIDEO_FPS = 30;
const UINT64 VIDEO_FRAME_DURATION = 10 * 1000 * 1000 / VIDEO_FPS;
const UINT32 VIDEO_BIT_RATE = 800000;
const GUID VIDEO_ENCODING_FORMAT = MFVideoFormat_H264;
const GUID VIDEO_INPUT_FORMAT = MFVideoFormat_NV12;
const UINT32 VIDEO_PELS = HEIGHT_X_WIDTH + HEIGHT_X_WIDTH / 2;
BYTE videoFrameBuffer[VIDEO_PELS * 2];
const UINT32 VIDEO_FRAME_COUNT = 120 * VIDEO_FPS;
int main()
{
HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
CHECK_HR( MFStartup( MF_VERSION ) );
IMFMediaType *pMediaTypeOut = NULL;
IMFMediaType *pMediaTypeIn = NULL;
IMFMediaEventGenerator *m_pEventGenerator;
IMFTransform* m_pEncoder;
// Set the output media type.
CHECK_HR( MFCreateMediaType( &pMediaTypeOut ) );
CHECK_HR( pMediaTypeOut->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Video ) );
CHECK_HR( pMediaTypeOut->SetGUID( MF_MT_SUBTYPE, VIDEO_ENCODING_FORMAT ) );
CHECK_HR( pMediaTypeOut->SetUINT32( MF_MT_AVG_BITRATE, VIDEO_BIT_RATE ) );
CHECK_HR( pMediaTypeOut->SetUINT32( MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive ) );
CHECK_HR( MFSetAttributeSize( pMediaTypeOut, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT ) );
CHECK_HR( MFSetAttributeRatio( pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1 ) );
CHECK_HR( MFSetAttributeRatio( pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1 ) );
// Set the input media type.
CHECK_HR( MFCreateMediaType( &pMediaTypeIn ) );
CHECK_HR( pMediaTypeIn->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Video ) );
CHECK_HR( pMediaTypeIn->SetGUID( MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT ) );
CHECK_HR( pMediaTypeIn->SetUINT32( MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive ) );
CHECK_HR( MFSetAttributeSize( pMediaTypeIn, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT ) );
CHECK_HR( MFSetAttributeRatio( pMediaTypeIn, MF_MT_FRAME_RATE, VIDEO_FPS, 1 ) );
CHECK_HR( MFSetAttributeRatio( pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1 ) );
// First Create The Intel Codec
CHECK_HR( CoCreateInstance( CLSID_MF_INTEL_H264EncFilter, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &m_pEncoder ) ) );
// Is the Encoder async
IMFAttributes *pAttributes = NULL;
UINT32 nIsAsync = 0;
hr = m_pEncoder->GetAttributes( &pAttributes );
if ( SUCCEEDED( hr ) )
{
hr = pAttributes->GetUINT32( MF_TRANSFORM_ASYNC, &nIsAsync );
}
if ( nIsAsync )
{
CHECK_HR( pAttributes->SetUINT32( MF_TRANSFORM_ASYNC_UNLOCK, TRUE ) );
}
CHECK_HR( m_pEncoder->SetOutputType( 0, pMediaTypeOut, 0 ) );
CHECK_HR( m_pEncoder->SetInputType( 0, pMediaTypeIn, 0 ) );
CHECK_HR( m_pEncoder->ProcessMessage( MFT_MESSAGE_COMMAND_FLUSH, NULL ) );
CHECK_HR( m_pEncoder->ProcessMessage( MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL ) );
CHECK_HR( m_pEncoder->ProcessMessage( MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL ) );
CHECK_HR( m_pEncoder->QueryInterface( IID_PPV_ARGS( &m_pEventGenerator ) ) );
IMFMediaEvent* event;
// On Win7, this crashes with a access violation
CHECK_HR( m_pEventGenerator->GetEvent( 0, &event ) );
MFShutdown();
done:
CoUninitialize();
return 0;
}
// Call Stack of Crash
// mfplat.dll!MFTRACE_MEDIA_EVENT_IMPL( unsigned long, unsigned long, struct IMFMediaEvent * ) <---- Access Violation Here
// mfplat.dll!CMFMediaEventGenerator::GetEvent( unsigned long, struct IMFMediaEvent * * )
// mfplat.dll!CMFMediaEventQueue::GetEvent( unsigned long, struct IMFMediaEvent * * )
// mfx_mft_h264ve_w7_32.dll!0f4fb3b0()
// > EventCrash.exe!main() Line 92
@adammarks
Copy link
Author

I did end up getting past this crash by using BeginGetEvent() instead of GetEvent(), for whatever reason the Intel Encoder MFT on this machine likes the BeginGetEvent()/EndGetEvent()/IMFAsyncCallback pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment