-
-
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 )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.