20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
22 #define _WIN32_WINNT 0x0602
73 #define MF_TIMEBASE (AVRational){1, 10000000}
75 #define MF_INVALID_TIME AV_NOPTS_VALUE
84 while (!(
c->async_need_input ||
c->async_have_output ||
c->draining_done ||
c->async_marker)) {
85 IMFMediaEvent *ev =
NULL;
86 MediaEventType ev_id = 0;
87 HRESULT hr = IMFMediaEventGenerator_GetEvent(
c->async_events, 0, &ev);
93 IMFMediaEvent_GetType(ev, &ev_id);
97 c->async_need_input = 1;
100 c->async_have_output = 1;
103 c->draining_done = 1;
110 IMFMediaEvent_Release(ev);
134 IMFSample_SetSampleTime(
sample, stime);
145 HRESULT hr = IMFSample_GetSampleTime(
sample, &
pts);
167 hr = IMFAttributes_GetBlobSize(
type, &MF_MT_USER_DATA, &sz);
168 if (!FAILED(hr) && sz > 0) {
188 if (!
c->out_info.cbSize && !
c->out_stream_provides_samples) {
189 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz);
192 "assuming %d bytes instead.\n", (
int)sz);
193 c->out_info.cbSize = sz;
205 hr = IMFAttributes_GetBlobSize(
type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz);
206 if (!FAILED(hr) && sz > 0) {
210 hr = IMFAttributes_GetBlob(
type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz,
NULL);
230 hr = IMFTransform_GetOutputCurrentType(
c->mft,
c->out_stream_id, &
type);
242 }
else if (
c->is_audio) {
249 IMFMediaType_Release(
type);
264 hr = IMFSample_GetTotalLength(
sample, &
len);
271 hr = IMFSample_ConvertToContiguousBuffer(
sample, &
buffer);
277 IMFMediaBuffer_Release(
buffer);
283 IMFMediaBuffer_Unlock(
buffer);
284 IMFMediaBuffer_Release(
buffer);
289 hr = IMFAttributes_GetUINT32(
sample, &MFSampleExtension_CleanPoint, &t32);
290 if (
c->is_audio || (!FAILED(hr) && t32 != 0))
293 hr = IMFAttributes_GetUINT64(
sample, &MFSampleExtension_DecodeTimestamp, &t);
301 c->reorder_delay = avpkt->
pts - avpkt->
dts;
302 avpkt->
dts -=
c->reorder_delay;
303 avpkt->
pts -=
c->reorder_delay;
320 c->in_info.cbAlignment);
336 hr =
func->MFCreateDXGIDeviceManager(&
c->resetToken, &
c->dxgiManager);
342 hr = IMFDXGIDeviceManager_ResetDevice(
c->dxgiManager, (IUnknown*)
c->device_hwctx->device,
c->resetToken);
348 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)
c->dxgiManager);
362 ID3D11Texture2D *d3d11_texture =
NULL;
371 if (!
c->dxgiManager) {
378 d3d11_texture = (ID3D11Texture2D*)
frame->data[0];
379 subIdx = (
int)(intptr_t)
frame->data[1];
381 if (!d3d11_texture) {
392 hr =
func->MFCreateDXGISurfaceBuffer(&IID_ID3D11Texture2D, (IUnknown*)d3d11_texture, subIdx, 0, &
buffer);
395 IMFSample_Release(
sample);
402 IMFMediaBuffer_Release(
buffer);
403 IMFSample_Release(
sample);
407 IMFMediaBuffer_Release(
buffer);
427 c->in_info.cbAlignment);
433 IMFSample_Release(
sample);
439 IMFMediaBuffer_Release(
buffer);
440 IMFSample_Release(
sample);
446 IMFMediaBuffer_SetCurrentLength(
buffer,
size);
447 IMFMediaBuffer_Unlock(
buffer);
448 IMFMediaBuffer_Release(
buffer);
450 IMFSample_Release(
sample);
517 if (
c->async_events) {
520 if (!
c->async_need_input)
524 IMFSample_SetUINT32(
sample, &MFSampleExtension_Discontinuity, TRUE);
526 hr = IMFTransform_ProcessInput(
c->mft,
c->in_stream_id,
sample, 0);
527 if (hr == MF_E_NOTACCEPTING) {
529 }
else if (FAILED(hr)) {
533 c->async_need_input = 0;
534 }
else if (!
c->draining) {
535 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
541 c->async_need_input = 0;
553 MFT_OUTPUT_DATA_BUFFER out_buffers;
561 if (
c->async_events) {
564 if (!
c->async_have_output ||
c->draining_done) {
570 if (!
c->out_stream_provides_samples) {
573 c->out_info.cbAlignment);
578 out_buffers = (MFT_OUTPUT_DATA_BUFFER) {
579 .dwStreamID =
c->out_stream_id,
584 hr = IMFTransform_ProcessOutput(
c->mft, 0, 1, &out_buffers, &st);
586 if (out_buffers.pEvents)
587 IMFCollection_Release(out_buffers.pEvents);
590 *out_sample = out_buffers.pSample;
595 if (out_buffers.pSample)
596 IMFSample_Release(out_buffers.pSample);
598 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
600 c->draining_done = 1;
602 }
else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
610 c->async_have_output = 0;
622 c->async_have_output = 0;
624 if (
ret >= 0 && !*out_sample)
636 if (!
c->frame->buf[0]) {
642 if (
c->frame->buf[0]) {
648 if (
c->is_video &&
c->codec_api) {
650 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame,
FF_VAL_VT_UI4(1));
654 if(!
c->stream_started)
656 HRESULT hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
662 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
668 c->stream_started = 1;
673 IMFSample_Release(
sample);
684 IMFSample_Release(
sample);
700 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
704 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
708 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &tg);
710 if (IsEqualGUID(&
c->main_subtype, &tg))
715 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t);
719 score |= (1LL << 31) -
diff;
721 score |= (1LL << 30) +
diff;
725 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AAC_PAYLOAD_TYPE, &t);
726 if (!FAILED(hr) && t != 0)
755 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
759 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
777 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
783 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
799 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &tg);
801 if (IsEqualGUID(&
c->main_subtype, &tg))
814 IMFAttributes_SetUINT32(
type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
835 IMFAttributes_SetUINT32(
type, &MF_MT_MPEG2_PROFILE,
profile);
838 IMFAttributes_SetUINT32(
type, &MF_MT_AVG_BITRATE, avctx->
bit_rate);
845 if (
c->opt_enc_rc >= 0)
846 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode,
FF_VAL_VT_UI4(
c->opt_enc_rc));
848 if (
c->opt_enc_quality >= 0)
849 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonQuality,
FF_VAL_VT_UI4(
c->opt_enc_quality));
875 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable,
FF_VAL_VT_BOOL(1));
877 if (
c->opt_enc_scenario >= 0)
878 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVScenarioInfo,
FF_VAL_VT_UI4(
c->opt_enc_scenario));
926 IMFMediaType *out_type =
NULL;
928 int out_type_index = -1;
936 hr = IMFTransform_GetOutputAvailableType(
c->mft,
c->out_stream_id, n, &
type);
937 if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
939 if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
955 }
else if (
c->is_audio) {
959 if (score > out_type_score) {
961 IMFMediaType_Release(out_type);
963 out_type_score = score;
965 IMFMediaType_AddRef(out_type);
968 IMFMediaType_Release(
type);
974 hr =
c->functions.MFCreateMediaType(&out_type);
984 }
else if (
c->is_audio) {
992 hr = IMFTransform_SetOutputType(
c->mft,
c->out_stream_id, out_type, 0);
995 }
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
1006 IMFMediaType_Release(out_type);
1015 IMFMediaType *in_type =
NULL;
1017 int in_type_index = -1;
1021 for (n = 0; ; n++) {
1025 hr = IMFTransform_GetInputAvailableType(
c->mft,
c->in_stream_id, n, &
type);
1026 if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
1028 if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
1044 }
else if (
c->is_audio) {
1048 if (score > in_type_score) {
1050 IMFMediaType_Release(in_type);
1052 in_type_score = score;
1054 IMFMediaType_AddRef(in_type);
1057 IMFMediaType_Release(
type);
1072 }
else if (
c->is_audio) {
1080 hr = IMFTransform_SetInputType(
c->mft,
c->in_stream_id, in_type, 0);
1083 }
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
1094 IMFMediaType_Release(in_type);
1104 int need_input = 1, need_output = 1;
1106 for (n = 0; n < 2 && (need_input || need_output); n++) {
1111 need_input =
ret < 1;
1115 need_output =
ret < 1;
1117 if (need_input || need_output) {
1119 need_input, need_output);
1131 hr = IMFTransform_GetInputStreamInfo(
c->mft,
c->in_stream_id, &
c->in_info);
1135 (
int)
c->in_info.cbSize, (
int)
c->in_info.cbAlignment);
1137 hr = IMFTransform_GetOutputStreamInfo(
c->mft,
c->out_stream_id, &
c->out_info);
1140 c->out_stream_provides_samples =
1141 (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
1142 (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
1144 (
int)
c->out_info.cbSize, (
int)
c->out_info.cbAlignment,
1145 c->out_stream_provides_samples ?
" (provides samples)" :
"");
1157 IMFAttributes *attrs;
1163 if (!(
c->is_video &&
c->opt_enc_hw))
1166 hr = IMFTransform_GetAttributes(
c->mft, &attrs);
1172 hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v);
1183 hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
1189 hr = IMFTransform_QueryInterface(
c->mft, &IID_IMFMediaEventGenerator, (
void **)&
c->async_events);
1198 IMFAttributes_Release(attrs);
1203 const AVCodec *codec,
int use_hw)
1207 MFT_REGISTER_TYPE_INFO reg = {0};
1216 reg.guidSubtype = *subtype;
1219 reg.guidMajorType = MFMediaType_Audio;
1220 category = MFT_CATEGORY_AUDIO_ENCODER;
1222 reg.guidMajorType = MFMediaType_Video;
1223 category = MFT_CATEGORY_VIDEO_ENCODER;
1245 c->is_video = !
c->is_audio;
1248 if (
c->is_video &&
c->opt_enc_hw)
1254 c->main_subtype = *subtype;
1262 hr = IMFTransform_QueryInterface(
c->mft, &IID_ICodecAPI, (
void **)&
c->codec_api);
1267 hr = IMFTransform_GetStreamIDs(
c->mft, 1, &
c->in_stream_id, 1, &
c->out_stream_id);
1268 if (hr == E_NOTIMPL) {
1269 c->in_stream_id =
c->out_stream_id = 0;
1270 }
else if (FAILED(hr)) {
1283 int sleep = 10000, total = 0;
1285 while (total < 70*1000) {
1302 avctx->
extradata ?
"Got" :
"Didn't get", total / 1000);
1309 #define LOAD_MF_FUNCTION(context, func_name) \
1310 context->functions.func_name = (void *)dlsym(context->library, #func_name); \
1311 if (!context->functions.func_name) { \
1312 av_log(context, AV_LOG_ERROR, "DLL mfplat.dll failed to find function "\
1314 return AVERROR_UNKNOWN; \
1320 #define LOAD_MF_FUNCTION(context, func_name) \
1321 context->functions.func_name = func_name; \
1322 if (!context->functions.func_name) { \
1323 av_log(context, AV_LOG_ERROR, "Failed to find function " #func_name \
1325 return AVERROR_UNKNOWN; \
1337 c->library = dlopen(
"mfplat.dll", 0);
1338 c->d3d_dll = dlopen(
"D3D11.dll", 0);
1364 ICodecAPI_Release(
c->codec_api);
1366 if (
c->async_events)
1367 IMFMediaEventGenerator_Release(
c->async_events);
1373 dlclose(
c->library);
1374 dlclose(
c->d3d_dll);
1399 #define OFFSET(x) offsetof(MFContext, x)
1401 #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, FMTS, CAPS, DEFAULTS) \
1402 static const AVClass ff_ ## NAME ## _mf_encoder_class = { \
1403 .class_name = #NAME "_mf", \
1404 .item_name = av_default_item_name, \
1406 .version = LIBAVUTIL_VERSION_INT, \
1408 const FFCodec ff_ ## NAME ## _mf_encoder = { \
1409 .p.priv_class = &ff_ ## NAME ## _mf_encoder_class, \
1410 .p.name = #NAME "_mf", \
1411 CODEC_LONG_NAME(#ID " via MediaFoundation"), \
1412 .p.type = AVMEDIA_TYPE_ ## MEDIATYPE, \
1413 .p.id = AV_CODEC_ID_ ## ID, \
1414 .priv_data_size = sizeof(MFContext), \
1416 .close = mf_close, \
1417 FF_CODEC_RECEIVE_PACKET_CB(mf_receive_packet), \
1420 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \
1421 .defaults = DEFAULTS, \
1425 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16),
1427 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \
1428 AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
1434 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1436 {
"rate_control",
"Select rate control mode",
OFFSET(opt_enc_rc),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE, .unit =
"rate_control"},
1437 {
"default",
"Default mode", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0,
VE, .unit =
"rate_control"},
1447 {
"scenario",
"Select usage scenario",
OFFSET(opt_enc_scenario),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE, .unit =
"scenario"},
1448 {
"default",
"Default scenario", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0,
VE, .unit =
"scenario"},
1467 CODEC_PIXFMTS(AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_D3D11),
1469 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \