@ -32,6 +32,8 @@
typedef struct MFContext {
AVClass * av_class ;
HMODULE library ;
MFFunctions functions ;
AVFrame * frame ;
int is_video , is_audio ;
GUID main_subtype ;
@ -292,7 +294,8 @@ static IMFSample *mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f
bps = av_get_bytes_per_sample ( avctx - > sample_fmt ) * avctx - > ch_layout . nb_channels ;
len = frame - > nb_samples * bps ;
sample = ff_create_memory_sample ( frame - > data [ 0 ] , len , c - > in_info . cbAlignment ) ;
sample = ff_create_memory_sample ( & c - > functions , frame - > data [ 0 ] , len ,
c - > in_info . cbAlignment ) ;
if ( sample )
IMFSample_SetSampleDuration ( sample , mf_to_mf_time ( avctx , frame - > nb_samples ) ) ;
return sample ;
@ -312,7 +315,8 @@ static IMFSample *mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f
if ( size < 0 )
return NULL ;
sample = ff_create_memory_sample ( NULL , size , c - > in_info . cbAlignment ) ;
sample = ff_create_memory_sample ( & c - > functions , NULL , size ,
c - > in_info . cbAlignment ) ;
if ( ! sample )
return NULL ;
@ -422,7 +426,9 @@ static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample)
}
if ( ! c - > out_stream_provides_samples ) {
sample = ff_create_memory_sample ( NULL , c - > out_info . cbSize , c - > out_info . cbAlignment ) ;
sample = ff_create_memory_sample ( & c - > functions , NULL ,
c - > out_info . cbSize ,
c - > out_info . cbAlignment ) ;
if ( ! sample )
return AVERROR ( ENOMEM ) ;
}
@ -777,7 +783,7 @@ static int mf_choose_output_type(AVCodecContext *avctx)
if ( out_type ) {
av_log ( avctx , AV_LOG_VERBOSE , " picking output type %d. \n " , out_type_index ) ;
} else {
hr = MFCreateMediaType ( & out_type ) ;
hr = c - > functions . MFCreateMediaType ( & out_type ) ;
if ( FAILED ( hr ) ) {
ret = AVERROR ( ENOMEM ) ;
goto done ;
@ -1005,7 +1011,8 @@ err:
return res ;
}
static int mf_create ( void * log , IMFTransform * * mft , const AVCodec * codec , int use_hw )
static int mf_create ( void * log , MFFunctions * f , IMFTransform * * mft ,
const AVCodec * codec , int use_hw )
{
int is_audio = codec - > type = = AVMEDIA_TYPE_AUDIO ;
const CLSID * subtype = ff_codec_to_mf_subtype ( codec - > id ) ;
@ -1028,13 +1035,13 @@ static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int us
category = MFT_CATEGORY_VIDEO_ENCODER ;
}
if ( ( ret = ff_instantiate_mf ( log , category , NULL , & reg , use_hw , mft ) ) < 0 )
if ( ( ret = ff_instantiate_mf ( log , f , category , NULL , & reg , use_hw , mft ) ) < 0 )
return ret ;
return 0 ;
}
static int mf_init ( AVCodecContext * avctx )
static int mf_init_encoder ( AVCodecContext * avctx )
{
MFContext * c = avctx - > priv_data ;
HRESULT hr ;
@ -1058,7 +1065,7 @@ static int mf_init(AVCodecContext *avctx)
c - > main_subtype = * subtype ;
if ( ( ret = mf_create ( avctx , & c - > mft , avctx - > codec , use_hw ) ) < 0 )
if ( ( ret = mf_create ( avctx , & c - > functions , & c - > mft , avctx - > codec , use_hw ) ) < 0 )
return ret ;
if ( ( ret = mf_unlock_async ( avctx ) ) < 0 )
@ -1122,6 +1129,54 @@ static int mf_init(AVCodecContext *avctx)
return 0 ;
}
# if !HAVE_UWP
# define LOAD_MF_FUNCTION(context, func_name) \
context - > functions . func_name = ( void * ) GetProcAddress ( context - > library , # func_name ) ; \
if ( ! context - > functions . func_name ) { \
av_log ( context , AV_LOG_ERROR , " DLL mfplat.dll failed to find function " \
# func_name "\n"); \
return AVERROR_UNKNOWN ; \
}
# else
// In UWP (which lacks LoadLibrary), just link directly against
// the functions - this requires building with new/complete enough
// import libraries.
# define LOAD_MF_FUNCTION(context, func_name) \
context - > functions . func_name = func_name ; \
if ( ! context - > functions . func_name ) { \
av_log ( context , AV_LOG_ERROR , " Failed to find function " # func_name \
" \n " ) ; \
return AVERROR_UNKNOWN ; \
}
# endif
// Windows N editions does not provide MediaFoundation by default.
// So to avoid DLL loading error, MediaFoundation is dynamically loaded except
// on UWP build since LoadLibrary is not available on it.
static int mf_load_library ( AVCodecContext * avctx )
{
MFContext * c = avctx - > priv_data ;
# if !HAVE_UWP
c - > library = LoadLibraryA ( " mfplat.dll " ) ;
if ( ! c - > library ) {
av_log ( c , AV_LOG_ERROR , " DLL mfplat.dll failed to open \n " ) ;
return AVERROR_UNKNOWN ;
}
# endif
LOAD_MF_FUNCTION ( c , MFStartup ) ;
LOAD_MF_FUNCTION ( c , MFShutdown ) ;
LOAD_MF_FUNCTION ( c , MFCreateAlignedMemoryBuffer ) ;
LOAD_MF_FUNCTION ( c , MFCreateSample ) ;
LOAD_MF_FUNCTION ( c , MFCreateMediaType ) ;
// MFTEnumEx is missing in Windows Vista's mfplat.dll.
LOAD_MF_FUNCTION ( c , MFTEnumEx ) ;
return 0 ;
}
static int mf_close ( AVCodecContext * avctx )
{
MFContext * c = avctx - > priv_data ;
@ -1132,7 +1187,15 @@ static int mf_close(AVCodecContext *avctx)
if ( c - > async_events )
IMFMediaEventGenerator_Release ( c - > async_events ) ;
ff_free_mf ( & c - > mft ) ;
# if !HAVE_UWP
if ( c - > library )
ff_free_mf ( & c - > functions , & c - > mft ) ;
FreeLibrary ( c - > library ) ;
c - > library = NULL ;
# else
ff_free_mf ( & c - > functions , & c - > mft ) ;
# endif
av_frame_free ( & c - > frame ) ;
@ -1142,6 +1205,18 @@ static int mf_close(AVCodecContext *avctx)
return 0 ;
}
static int mf_init ( AVCodecContext * avctx )
{
int ret ;
if ( ( ret = mf_load_library ( avctx ) ) = = 0 ) {
if ( ( ret = mf_init_encoder ( avctx ) ) = = 0 ) {
return 0 ;
}
}
mf_close ( avctx ) ;
return ret ;
}
# define OFFSET(x) offsetof(MFContext, x)
# define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \