20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
22 #define _WIN32_WINNT 0x0602
58 #define MF_TIMEBASE (AVRational){1, 10000000}
60 #define MF_INVALID_TIME AV_NOPTS_VALUE
69 while (!(
c->async_need_input ||
c->async_have_output ||
c->draining_done ||
c->async_marker)) {
70 IMFMediaEvent *ev =
NULL;
71 MediaEventType ev_id = 0;
72 HRESULT hr = IMFMediaEventGenerator_GetEvent(
c->async_events, 0, &ev);
78 IMFMediaEvent_GetType(ev, &ev_id);
82 c->async_need_input = 1;
85 c->async_have_output = 1;
95 IMFMediaEvent_Release(ev);
119 IMFSample_SetSampleTime(
sample, stime);
130 HRESULT hr = IMFSample_GetSampleTime(
sample, &
pts);
143 hr = IMFAttributes_GetBlobSize(
type, &MF_MT_USER_DATA, &sz);
144 if (!FAILED(hr) && sz > 0) {
164 if (!
c->out_info.cbSize && !
c->out_stream_provides_samples) {
165 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz);
168 "assuming %d bytes instead.\n", (
int)sz);
169 c->out_info.cbSize = sz;
181 hr = IMFAttributes_GetBlobSize(
type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz);
182 if (!FAILED(hr) && sz > 0) {
186 hr = IMFAttributes_GetBlob(
type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz,
NULL);
206 hr = IMFTransform_GetOutputCurrentType(
c->mft,
c->out_stream_id, &
type);
218 }
else if (
c->is_audio) {
225 IMFMediaType_Release(
type);
240 hr = IMFSample_GetTotalLength(
sample, &
len);
253 IMFMediaBuffer_Release(
buffer);
259 IMFMediaBuffer_Unlock(
buffer);
260 IMFMediaBuffer_Release(
buffer);
264 hr = IMFAttributes_GetUINT32(
sample, &MFSampleExtension_CleanPoint, &t32);
265 if (
c->is_audio || (!FAILED(hr) && t32 != 0))
268 hr = IMFAttributes_GetUINT64(
sample, &MFSampleExtension_DecodeTimestamp, &t);
276 c->reorder_delay = avpkt->
pts - avpkt->
dts;
277 avpkt->
dts -=
c->reorder_delay;
278 avpkt->
pts -=
c->reorder_delay;
320 IMFSample_Release(
sample);
326 IMFMediaBuffer_Release(
buffer);
327 IMFSample_Release(
sample);
333 IMFMediaBuffer_SetCurrentLength(
buffer,
size);
334 IMFMediaBuffer_Unlock(
buffer);
335 IMFMediaBuffer_Release(
buffer);
337 IMFSample_Release(
sample);
370 if (
c->async_events) {
373 if (!
c->async_need_input)
377 IMFSample_SetUINT32(
sample, &MFSampleExtension_Discontinuity, TRUE);
379 hr = IMFTransform_ProcessInput(
c->mft,
c->in_stream_id,
sample, 0);
380 if (hr == MF_E_NOTACCEPTING) {
382 }
else if (FAILED(hr)) {
386 c->async_need_input = 0;
387 }
else if (!
c->draining) {
388 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
394 c->async_need_input = 0;
406 MFT_OUTPUT_DATA_BUFFER out_buffers;
414 if (
c->async_events) {
417 if (!
c->async_have_output ||
c->draining_done) {
423 if (!
c->out_stream_provides_samples) {
429 out_buffers = (MFT_OUTPUT_DATA_BUFFER) {
430 .dwStreamID =
c->out_stream_id,
435 hr = IMFTransform_ProcessOutput(
c->mft, 0, 1, &out_buffers, &st);
437 if (out_buffers.pEvents)
438 IMFCollection_Release(out_buffers.pEvents);
441 *out_sample = out_buffers.pSample;
446 if (out_buffers.pSample)
447 IMFSample_Release(out_buffers.pSample);
449 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
451 c->draining_done = 1;
453 }
else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
461 c->async_have_output = 0;
473 c->async_have_output = 0;
475 if (
ret >= 0 && !*out_sample)
487 if (!
c->frame->buf[0]) {
493 if (
c->frame->buf[0]) {
499 if (
c->is_video &&
c->codec_api) {
501 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame,
FF_VAL_VT_UI4(1));
507 IMFSample_Release(
sample);
518 IMFSample_Release(
sample);
534 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
538 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
539 if (!FAILED(hr) && t == avctx->
channels)
542 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &
tg);
544 if (IsEqualGUID(&
c->main_subtype, &
tg))
549 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t);
553 score |= (1LL << 31) -
diff;
555 score |= (1LL << 30) +
diff;
559 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AAC_PAYLOAD_TYPE, &t);
560 if (!FAILED(hr) && t != 0)
589 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
593 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
594 if (!FAILED(hr) && t == avctx->
channels)
611 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
617 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
618 if (FAILED(hr) || t != avctx->
channels) {
633 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &
tg);
635 if (IsEqualGUID(&
c->main_subtype, &
tg))
648 IMFAttributes_SetUINT32(
type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
670 IMFAttributes_SetUINT32(
type, &MF_MT_MPEG2_PROFILE,
profile);
673 IMFAttributes_SetUINT32(
type, &MF_MT_AVG_BITRATE, avctx->
bit_rate);
680 if (
c->opt_enc_rc >= 0)
681 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode,
FF_VAL_VT_UI4(
c->opt_enc_rc));
683 if (
c->opt_enc_quality >= 0)
684 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonQuality,
FF_VAL_VT_UI4(
c->opt_enc_quality));
695 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable,
FF_VAL_VT_BOOL(1));
697 if (
c->opt_enc_scenario >= 0)
698 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVScenarioInfo,
FF_VAL_VT_UI4(
c->opt_enc_scenario));
731 IMFMediaType *out_type =
NULL;
732 int64_t out_type_score = -1;
733 int out_type_index = -1;
741 hr = IMFTransform_GetOutputAvailableType(
c->mft,
c->out_stream_id, n, &
type);
742 if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
744 if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
760 }
else if (
c->is_audio) {
764 if (score > out_type_score) {
766 IMFMediaType_Release(out_type);
768 out_type_score = score;
770 IMFMediaType_AddRef(out_type);
773 IMFMediaType_Release(
type);
779 hr = MFCreateMediaType(&out_type);
789 }
else if (
c->is_audio) {
797 hr = IMFTransform_SetOutputType(
c->mft,
c->out_stream_id, out_type, 0);
800 }
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
811 IMFMediaType_Release(out_type);
820 IMFMediaType *in_type =
NULL;
821 int64_t in_type_score = -1;
822 int in_type_index = -1;
830 hr = IMFTransform_GetInputAvailableType(
c->mft,
c->in_stream_id, n, &
type);
831 if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
833 if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
849 }
else if (
c->is_audio) {
853 if (score > in_type_score) {
855 IMFMediaType_Release(in_type);
857 in_type_score = score;
859 IMFMediaType_AddRef(in_type);
862 IMFMediaType_Release(
type);
877 }
else if (
c->is_audio) {
885 hr = IMFTransform_SetInputType(
c->mft,
c->in_stream_id, in_type, 0);
888 }
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
899 IMFMediaType_Release(in_type);
911 for (n = 0; n < 2 && (need_input ||
need_output); n++) {
916 need_input =
ret < 1;
936 hr = IMFTransform_GetInputStreamInfo(
c->mft,
c->in_stream_id, &
c->in_info);
940 (
int)
c->in_info.cbSize, (
int)
c->in_info.cbAlignment);
942 hr = IMFTransform_GetOutputStreamInfo(
c->mft,
c->out_stream_id, &
c->out_info);
945 c->out_stream_provides_samples =
946 (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
947 (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
949 (
int)
c->out_info.cbSize, (
int)
c->out_info.cbAlignment,
950 c->out_stream_provides_samples ?
" (provides samples)" :
"");
962 IMFAttributes *attrs;
968 if (!(
c->is_video &&
c->opt_enc_hw))
971 hr = IMFTransform_GetAttributes(
c->mft, &attrs);
977 hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v);
988 hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
994 hr = IMFTransform_QueryInterface(
c->mft, &IID_IMFMediaEventGenerator, (
void **)&
c->async_events);
1003 IMFAttributes_Release(attrs);
1011 MFT_REGISTER_TYPE_INFO reg = {0};
1020 reg.guidSubtype = *subtype;
1023 reg.guidMajorType = MFMediaType_Audio;
1024 category = MFT_CATEGORY_AUDIO_ENCODER;
1026 reg.guidMajorType = MFMediaType_Video;
1027 category = MFT_CATEGORY_VIDEO_ENCODER;
1049 c->is_video = !
c->is_audio;
1052 if (
c->is_video &&
c->opt_enc_hw)
1058 c->main_subtype = *subtype;
1066 hr = IMFTransform_QueryInterface(
c->mft, &IID_ICodecAPI, (
void **)&
c->codec_api);
1071 hr = IMFTransform_GetStreamIDs(
c->mft, 1, &
c->in_stream_id, 1, &
c->out_stream_id);
1072 if (hr == E_NOTIMPL) {
1073 c->in_stream_id =
c->out_stream_id = 0;
1074 }
else if (FAILED(hr)) {
1085 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1091 hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
1099 int sleep = 10000, total = 0;
1101 while (total < 70*1000) {
1118 avctx->
extradata ?
"Got" :
"Didn't get", total / 1000);
1129 ICodecAPI_Release(
c->codec_api);
1131 if (
c->async_events)
1132 IMFMediaEventGenerator_Release(
c->async_events);
1144 #define OFFSET(x) offsetof(MFContext, x)
1146 #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \
1147 static const AVClass ff_ ## NAME ## _mf_encoder_class = { \
1148 .class_name = #NAME "_mf", \
1149 .item_name = av_default_item_name, \
1151 .version = LIBAVUTIL_VERSION_INT, \
1153 const AVCodec ff_ ## NAME ## _mf_encoder = { \
1154 .priv_class = &ff_ ## NAME ## _mf_encoder_class, \
1155 .name = #NAME "_mf", \
1156 .long_name = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"), \
1157 .type = AVMEDIA_TYPE_ ## MEDIATYPE, \
1158 .id = AV_CODEC_ID_ ## ID, \
1159 .priv_data_size = sizeof(MFContext), \
1161 .close = mf_close, \
1162 .receive_packet = mf_receive_packet, \
1164 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \
1166 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | \
1167 FF_CODEC_CAP_INIT_CLEANUP, \
1171 .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, \
1172 AV_SAMPLE_FMT_NONE },
1178 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1180 {
"rate_control",
"Select rate control mode",
OFFSET(opt_enc_rc),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE,
"rate_control"},
1181 {
"default",
"Default mode", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0,
VE,
"rate_control"},
1191 {
"scenario",
"Select usage scenario",
OFFSET(opt_enc_scenario),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE,
"scenario"},
1192 {
"default",
"Default scenario", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0,
VE,
"scenario"},
1206 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \
1207 AV_PIX_FMT_YUV420P, \