20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
22 #define _WIN32_WINNT 0x0602
62 #define MF_TIMEBASE (AVRational){1, 10000000}
64 #define MF_INVALID_TIME AV_NOPTS_VALUE
73 while (!(
c->async_need_input ||
c->async_have_output ||
c->draining_done ||
c->async_marker)) {
74 IMFMediaEvent *ev =
NULL;
75 MediaEventType ev_id = 0;
76 HRESULT hr = IMFMediaEventGenerator_GetEvent(
c->async_events, 0, &ev);
82 IMFMediaEvent_GetType(ev, &ev_id);
86 c->async_need_input = 1;
89 c->async_have_output = 1;
99 IMFMediaEvent_Release(ev);
123 IMFSample_SetSampleTime(
sample, stime);
134 HRESULT hr = IMFSample_GetSampleTime(
sample, &
pts);
147 hr = IMFAttributes_GetBlobSize(
type, &MF_MT_USER_DATA, &sz);
148 if (!FAILED(hr) && sz > 0) {
168 if (!
c->out_info.cbSize && !
c->out_stream_provides_samples) {
169 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz);
172 "assuming %d bytes instead.\n", (
int)sz);
173 c->out_info.cbSize = sz;
185 hr = IMFAttributes_GetBlobSize(
type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz);
186 if (!FAILED(hr) && sz > 0) {
190 hr = IMFAttributes_GetBlob(
type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz,
NULL);
210 hr = IMFTransform_GetOutputCurrentType(
c->mft,
c->out_stream_id, &
type);
222 }
else if (
c->is_audio) {
229 IMFMediaType_Release(
type);
244 hr = IMFSample_GetTotalLength(
sample, &
len);
257 IMFMediaBuffer_Release(
buffer);
263 IMFMediaBuffer_Unlock(
buffer);
264 IMFMediaBuffer_Release(
buffer);
268 hr = IMFAttributes_GetUINT32(
sample, &MFSampleExtension_CleanPoint, &t32);
269 if (
c->is_audio || (!FAILED(hr) && t32 != 0))
272 hr = IMFAttributes_GetUINT64(
sample, &MFSampleExtension_DecodeTimestamp, &t);
280 c->reorder_delay = avpkt->
pts - avpkt->
dts;
281 avpkt->
dts -=
c->reorder_delay;
282 avpkt->
pts -=
c->reorder_delay;
299 c->in_info.cbAlignment);
320 c->in_info.cbAlignment);
326 IMFSample_Release(
sample);
332 IMFMediaBuffer_Release(
buffer);
333 IMFSample_Release(
sample);
339 IMFMediaBuffer_SetCurrentLength(
buffer,
size);
340 IMFMediaBuffer_Unlock(
buffer);
341 IMFMediaBuffer_Release(
buffer);
343 IMFSample_Release(
sample);
376 if (
c->async_events) {
379 if (!
c->async_need_input)
383 IMFSample_SetUINT32(
sample, &MFSampleExtension_Discontinuity, TRUE);
385 hr = IMFTransform_ProcessInput(
c->mft,
c->in_stream_id,
sample, 0);
386 if (hr == MF_E_NOTACCEPTING) {
388 }
else if (FAILED(hr)) {
392 c->async_need_input = 0;
393 }
else if (!
c->draining) {
394 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
400 c->async_need_input = 0;
412 MFT_OUTPUT_DATA_BUFFER out_buffers;
420 if (
c->async_events) {
423 if (!
c->async_have_output ||
c->draining_done) {
429 if (!
c->out_stream_provides_samples) {
432 c->out_info.cbAlignment);
437 out_buffers = (MFT_OUTPUT_DATA_BUFFER) {
438 .dwStreamID =
c->out_stream_id,
443 hr = IMFTransform_ProcessOutput(
c->mft, 0, 1, &out_buffers, &st);
445 if (out_buffers.pEvents)
446 IMFCollection_Release(out_buffers.pEvents);
449 *out_sample = out_buffers.pSample;
454 if (out_buffers.pSample)
455 IMFSample_Release(out_buffers.pSample);
457 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
459 c->draining_done = 1;
461 }
else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
469 c->async_have_output = 0;
481 c->async_have_output = 0;
483 if (
ret >= 0 && !*out_sample)
495 if (!
c->frame->buf[0]) {
501 if (
c->frame->buf[0]) {
507 if (
c->is_video &&
c->codec_api) {
509 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame,
FF_VAL_VT_UI4(1));
515 IMFSample_Release(
sample);
526 IMFSample_Release(
sample);
542 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
546 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
550 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &
tg);
552 if (IsEqualGUID(&
c->main_subtype, &
tg))
557 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t);
561 score |= (1LL << 31) -
diff;
563 score |= (1LL << 30) +
diff;
567 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AAC_PAYLOAD_TYPE, &t);
568 if (!FAILED(hr) && t != 0)
597 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
601 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
619 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
625 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
641 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &
tg);
643 if (IsEqualGUID(&
c->main_subtype, &
tg))
656 IMFAttributes_SetUINT32(
type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
662 #if FF_API_TICKS_PER_FRAME
682 IMFAttributes_SetUINT32(
type, &MF_MT_MPEG2_PROFILE,
profile);
685 IMFAttributes_SetUINT32(
type, &MF_MT_AVG_BITRATE, avctx->
bit_rate);
692 if (
c->opt_enc_rc >= 0)
693 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode,
FF_VAL_VT_UI4(
c->opt_enc_rc));
695 if (
c->opt_enc_quality >= 0)
696 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonQuality,
FF_VAL_VT_UI4(
c->opt_enc_quality));
707 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable,
FF_VAL_VT_BOOL(1));
709 if (
c->opt_enc_scenario >= 0)
710 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVScenarioInfo,
FF_VAL_VT_UI4(
c->opt_enc_scenario));
743 IMFMediaType *out_type =
NULL;
744 int64_t out_type_score = -1;
745 int out_type_index = -1;
753 hr = IMFTransform_GetOutputAvailableType(
c->mft,
c->out_stream_id, n, &
type);
754 if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
756 if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
772 }
else if (
c->is_audio) {
776 if (score > out_type_score) {
778 IMFMediaType_Release(out_type);
780 out_type_score = score;
782 IMFMediaType_AddRef(out_type);
785 IMFMediaType_Release(
type);
791 hr =
c->functions.MFCreateMediaType(&out_type);
801 }
else if (
c->is_audio) {
809 hr = IMFTransform_SetOutputType(
c->mft,
c->out_stream_id, out_type, 0);
812 }
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
823 IMFMediaType_Release(out_type);
832 IMFMediaType *in_type =
NULL;
833 int64_t in_type_score = -1;
834 int in_type_index = -1;
842 hr = IMFTransform_GetInputAvailableType(
c->mft,
c->in_stream_id, n, &
type);
843 if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
845 if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
861 }
else if (
c->is_audio) {
865 if (score > in_type_score) {
867 IMFMediaType_Release(in_type);
869 in_type_score = score;
871 IMFMediaType_AddRef(in_type);
874 IMFMediaType_Release(
type);
889 }
else if (
c->is_audio) {
897 hr = IMFTransform_SetInputType(
c->mft,
c->in_stream_id, in_type, 0);
900 }
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
911 IMFMediaType_Release(in_type);
921 int need_input = 1, need_output = 1;
923 for (n = 0; n < 2 && (need_input || need_output); n++) {
928 need_input =
ret < 1;
932 need_output =
ret < 1;
934 if (need_input || need_output) {
936 need_input, need_output);
948 hr = IMFTransform_GetInputStreamInfo(
c->mft,
c->in_stream_id, &
c->in_info);
952 (
int)
c->in_info.cbSize, (
int)
c->in_info.cbAlignment);
954 hr = IMFTransform_GetOutputStreamInfo(
c->mft,
c->out_stream_id, &
c->out_info);
957 c->out_stream_provides_samples =
958 (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
959 (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
961 (
int)
c->out_info.cbSize, (
int)
c->out_info.cbAlignment,
962 c->out_stream_provides_samples ?
" (provides samples)" :
"");
974 IMFAttributes *attrs;
980 if (!(
c->is_video &&
c->opt_enc_hw))
983 hr = IMFTransform_GetAttributes(
c->mft, &attrs);
989 hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v);
1000 hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
1006 hr = IMFTransform_QueryInterface(
c->mft, &IID_IMFMediaEventGenerator, (
void **)&
c->async_events);
1015 IMFAttributes_Release(attrs);
1020 const AVCodec *codec,
int use_hw)
1024 MFT_REGISTER_TYPE_INFO reg = {0};
1033 reg.guidSubtype = *subtype;
1036 reg.guidMajorType = MFMediaType_Audio;
1037 category = MFT_CATEGORY_AUDIO_ENCODER;
1039 reg.guidMajorType = MFMediaType_Video;
1040 category = MFT_CATEGORY_VIDEO_ENCODER;
1062 c->is_video = !
c->is_audio;
1065 if (
c->is_video &&
c->opt_enc_hw)
1071 c->main_subtype = *subtype;
1079 hr = IMFTransform_QueryInterface(
c->mft, &IID_ICodecAPI, (
void **)&
c->codec_api);
1084 hr = IMFTransform_GetStreamIDs(
c->mft, 1, &
c->in_stream_id, 1, &
c->out_stream_id);
1085 if (hr == E_NOTIMPL) {
1086 c->in_stream_id =
c->out_stream_id = 0;
1087 }
else if (FAILED(hr)) {
1098 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1104 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
1112 int sleep = 10000, total = 0;
1114 while (total < 70*1000) {
1131 avctx->
extradata ?
"Got" :
"Didn't get", total / 1000);
1138 #define LOAD_MF_FUNCTION(context, func_name) \
1139 context->functions.func_name = (void *)dlsym(context->library, #func_name); \
1140 if (!context->functions.func_name) { \
1141 av_log(context, AV_LOG_ERROR, "DLL mfplat.dll failed to find function "\
1143 return AVERROR_UNKNOWN; \
1149 #define LOAD_MF_FUNCTION(context, func_name) \
1150 context->functions.func_name = func_name; \
1151 if (!context->functions.func_name) { \
1152 av_log(context, AV_LOG_ERROR, "Failed to find function " #func_name \
1154 return AVERROR_UNKNOWN; \
1166 c->library = dlopen(
"mfplat.dll", 0);
1190 ICodecAPI_Release(
c->codec_api);
1192 if (
c->async_events)
1193 IMFMediaEventGenerator_Release(
c->async_events);
1199 dlclose(
c->library);
1224 #define OFFSET(x) offsetof(MFContext, x)
1226 #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, FMTS, CAPS) \
1227 static const AVClass ff_ ## NAME ## _mf_encoder_class = { \
1228 .class_name = #NAME "_mf", \
1229 .item_name = av_default_item_name, \
1231 .version = LIBAVUTIL_VERSION_INT, \
1233 const FFCodec ff_ ## NAME ## _mf_encoder = { \
1234 .p.priv_class = &ff_ ## NAME ## _mf_encoder_class, \
1235 .p.name = #NAME "_mf", \
1236 CODEC_LONG_NAME(#ID " via MediaFoundation"), \
1237 .p.type = AVMEDIA_TYPE_ ## MEDIATYPE, \
1238 .p.id = AV_CODEC_ID_ ## ID, \
1239 .priv_data_size = sizeof(MFContext), \
1241 .close = mf_close, \
1242 FF_CODEC_RECEIVE_PACKET_CB(mf_receive_packet), \
1245 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \
1249 .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, \
1250 AV_SAMPLE_FMT_NONE },
1252 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \
1253 AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
1259 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1261 {
"rate_control",
"Select rate control mode",
OFFSET(opt_enc_rc),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE,
"rate_control"},
1262 {
"default",
"Default mode", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0,
VE,
"rate_control"},
1272 {
"scenario",
"Select usage scenario",
OFFSET(opt_enc_scenario),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE,
"scenario"},
1273 {
"default",
"Default scenario", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0,
VE,
"scenario"},
1287 .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \
1288 AV_PIX_FMT_YUV420P, \
1291 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \