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);
 
  121         IMFSample_SetSampleTime(
sample, stime);
 
  132     HRESULT hr = IMFSample_GetSampleTime(
sample, &
pts);
 
  145         hr = IMFAttributes_GetBlobSize(
type, &MF_MT_USER_DATA, &sz);
 
  146         if (!FAILED(hr) && sz > 0) {
 
  166     if (!
c->out_info.cbSize && !
c->out_stream_provides_samples) {
 
  167         hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz);
 
  170                    "assuming %d bytes instead.\n", (
int)sz);
 
  171             c->out_info.cbSize = sz;
 
  183     hr = IMFAttributes_GetBlobSize(
type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz);
 
  184     if (!FAILED(hr) && sz > 0) {
 
  188         hr = IMFAttributes_GetBlob(
type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz, 
NULL);
 
  208     hr = IMFTransform_GetOutputCurrentType(
c->mft, 
c->out_stream_id, &
type);
 
  220     } 
else if (
c->is_audio) {
 
  227     IMFMediaType_Release(
type);
 
  242     hr = IMFSample_GetTotalLength(
sample, &
len);
 
  255         IMFMediaBuffer_Release(
buffer);
 
  261     IMFMediaBuffer_Unlock(
buffer);
 
  262     IMFMediaBuffer_Release(
buffer);
 
  266     hr = IMFAttributes_GetUINT32(
sample, &MFSampleExtension_CleanPoint, &t32);
 
  267     if (
c->is_audio || (!FAILED(hr) && t32 != 0))
 
  270     hr = IMFAttributes_GetUINT64(
sample, &MFSampleExtension_DecodeTimestamp, &t);
 
  278             c->reorder_delay = avpkt->
pts - avpkt->
dts;
 
  279         avpkt->
dts -= 
c->reorder_delay;
 
  280         avpkt->
pts -= 
c->reorder_delay;
 
  322         IMFSample_Release(
sample);
 
  328         IMFMediaBuffer_Release(
buffer);
 
  329         IMFSample_Release(
sample);
 
  335     IMFMediaBuffer_SetCurrentLength(
buffer, 
size);
 
  336     IMFMediaBuffer_Unlock(
buffer);
 
  337     IMFMediaBuffer_Release(
buffer);
 
  339         IMFSample_Release(
sample);
 
  372         if (
c->async_events) {
 
  375             if (!
c->async_need_input)
 
  379             IMFSample_SetUINT32(
sample, &MFSampleExtension_Discontinuity, TRUE);
 
  381         hr = IMFTransform_ProcessInput(
c->mft, 
c->in_stream_id, 
sample, 0);
 
  382         if (hr == MF_E_NOTACCEPTING) {
 
  384         } 
else if (FAILED(hr)) {
 
  388         c->async_need_input = 0;
 
  389     } 
else if (!
c->draining) {
 
  390         hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
 
  396         c->async_need_input = 0;
 
  408     MFT_OUTPUT_DATA_BUFFER out_buffers;
 
  416         if (
c->async_events) {
 
  419             if (!
c->async_have_output || 
c->draining_done) {
 
  425         if (!
c->out_stream_provides_samples) {
 
  431         out_buffers = (MFT_OUTPUT_DATA_BUFFER) {
 
  432             .dwStreamID = 
c->out_stream_id,
 
  437         hr = IMFTransform_ProcessOutput(
c->mft, 0, 1, &out_buffers, &st);
 
  439         if (out_buffers.pEvents)
 
  440             IMFCollection_Release(out_buffers.pEvents);
 
  443             *out_sample = out_buffers.pSample;
 
  448         if (out_buffers.pSample)
 
  449             IMFSample_Release(out_buffers.pSample);
 
  451         if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
 
  453                 c->draining_done = 1;
 
  455         } 
else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
 
  463                     c->async_have_output = 0;
 
  475     c->async_have_output = 0;
 
  477     if (
ret >= 0 && !*out_sample)
 
  489     if (!
c->frame->buf[0]) {
 
  495     if (
c->frame->buf[0]) {
 
  501         if (
c->is_video && 
c->codec_api) {
 
  503                 ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame, 
FF_VAL_VT_UI4(1));
 
  509         IMFSample_Release(
sample);
 
  520     IMFSample_Release(
sample);
 
  536     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
 
  540     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
 
  541     if (!FAILED(hr) && t == avctx->
channels)
 
  544     hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &
tg);
 
  546         if (IsEqualGUID(&
c->main_subtype, &
tg))
 
  551     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t);
 
  555             score |= (1LL << 31) - 
diff; 
 
  557             score |= (1LL << 30) + 
diff; 
 
  561     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AAC_PAYLOAD_TYPE, &t);
 
  562     if (!FAILED(hr) && t != 0)
 
  591     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
 
  595     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
 
  596     if (!FAILED(hr) && t == avctx->
channels)
 
  613     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
 
  619     hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
 
  620     if (FAILED(hr) || t != avctx->
channels) {
 
  635     hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &
tg);
 
  637         if (IsEqualGUID(&
c->main_subtype, &
tg))
 
  650     IMFAttributes_SetUINT32(
type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
 
  672         IMFAttributes_SetUINT32(
type, &MF_MT_MPEG2_PROFILE, 
profile);
 
  675     IMFAttributes_SetUINT32(
type, &MF_MT_AVG_BITRATE, avctx->
bit_rate);
 
  682         if (
c->opt_enc_rc >= 0)
 
  683             ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode, 
FF_VAL_VT_UI4(
c->opt_enc_rc));
 
  685         if (
c->opt_enc_quality >= 0)
 
  686             ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncCommonQuality, 
FF_VAL_VT_UI4(
c->opt_enc_quality));
 
  697         ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable, 
FF_VAL_VT_BOOL(1));
 
  699         if (
c->opt_enc_scenario >= 0)
 
  700             ICodecAPI_SetValue(
c->codec_api, &ff_CODECAPI_AVScenarioInfo, 
FF_VAL_VT_UI4(
c->opt_enc_scenario));
 
  733     IMFMediaType *out_type = 
NULL;
 
  734     int64_t out_type_score = -1;
 
  735     int out_type_index = -1;
 
  743         hr = IMFTransform_GetOutputAvailableType(
c->mft, 
c->out_stream_id, n, &
type);
 
  744         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
 
  746         if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
 
  762         } 
else if (
c->is_audio) {
 
  766         if (score > out_type_score) {
 
  768                 IMFMediaType_Release(out_type);
 
  770             out_type_score = score;
 
  772             IMFMediaType_AddRef(out_type);
 
  775         IMFMediaType_Release(
type);
 
  781         hr = MFCreateMediaType(&out_type);
 
  791     } 
else if (
c->is_audio) {
 
  799         hr = IMFTransform_SetOutputType(
c->mft, 
c->out_stream_id, out_type, 0);
 
  802         } 
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
 
  813         IMFMediaType_Release(out_type);
 
  822     IMFMediaType *in_type = 
NULL;
 
  823     int64_t in_type_score = -1;
 
  824     int in_type_index = -1;
 
  832         hr = IMFTransform_GetInputAvailableType(
c->mft, 
c->in_stream_id, n, &
type);
 
  833         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
 
  835         if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
 
  851         } 
else if (
c->is_audio) {
 
  855         if (score > in_type_score) {
 
  857                 IMFMediaType_Release(in_type);
 
  859             in_type_score = score;
 
  861             IMFMediaType_AddRef(in_type);
 
  864         IMFMediaType_Release(
type);
 
  879     } 
else if (
c->is_audio) {
 
  887         hr = IMFTransform_SetInputType(
c->mft, 
c->in_stream_id, in_type, 0);
 
  890         } 
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
 
  901         IMFMediaType_Release(in_type);
 
  913     for (n = 0; n < 2 && (need_input || 
need_output); n++) {
 
  918         need_input = 
ret < 1;
 
  938     hr = IMFTransform_GetInputStreamInfo(
c->mft, 
c->in_stream_id, &
c->in_info);
 
  942            (
int)
c->in_info.cbSize, (
int)
c->in_info.cbAlignment);
 
  944     hr = IMFTransform_GetOutputStreamInfo(
c->mft, 
c->out_stream_id, &
c->out_info);
 
  947     c->out_stream_provides_samples =
 
  948         (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
 
  949         (
c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
 
  951            (
int)
c->out_info.cbSize, (
int)
c->out_info.cbAlignment,
 
  952            c->out_stream_provides_samples ? 
" (provides samples)" : 
"");
 
  964     IMFAttributes *attrs;
 
  970     if (!(
c->is_video && 
c->opt_enc_hw))
 
  973     hr = IMFTransform_GetAttributes(
c->mft, &attrs);
 
  979     hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v);
 
  990     hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
 
  996     hr = IMFTransform_QueryInterface(
c->mft, &IID_IMFMediaEventGenerator, (
void **)&
c->async_events);
 
 1005     IMFAttributes_Release(attrs);
 
 1013     MFT_REGISTER_TYPE_INFO reg = {0};
 
 1022     reg.guidSubtype = *subtype;
 
 1025         reg.guidMajorType = MFMediaType_Audio;
 
 1026         category = MFT_CATEGORY_AUDIO_ENCODER;
 
 1028         reg.guidMajorType = MFMediaType_Video;
 
 1029         category = MFT_CATEGORY_VIDEO_ENCODER;
 
 1051     c->is_video = !
c->is_audio;
 
 1054     if (
c->is_video && 
c->opt_enc_hw)
 
 1060     c->main_subtype = *subtype;
 
 1068     hr = IMFTransform_QueryInterface(
c->mft, &IID_ICodecAPI, (
void **)&
c->codec_api);
 
 1073     hr = IMFTransform_GetStreamIDs(
c->mft, 1, &
c->in_stream_id, 1, &
c->out_stream_id);
 
 1074     if (hr == E_NOTIMPL) {
 
 1075         c->in_stream_id = 
c->out_stream_id = 0;
 
 1076     } 
else if (FAILED(hr)) {
 
 1087     hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
 
 1093     hr = IMFTransform_ProcessMessage(
c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
 
 1101         int sleep = 10000, total = 0;
 
 1103         while (total < 70*1000) {
 
 1120                avctx->
extradata ? 
"Got" : 
"Didn't get", total / 1000);
 
 1131         ICodecAPI_Release(
c->codec_api);
 
 1133     if (
c->async_events)
 
 1134         IMFMediaEventGenerator_Release(
c->async_events);
 
 1146 #define OFFSET(x) offsetof(MFContext, x) 
 1148 #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \ 
 1149     static const AVClass ff_ ## NAME ## _mf_encoder_class = {                  \ 
 1150         .class_name = #NAME "_mf",                                             \ 
 1151         .item_name  = av_default_item_name,                                    \ 
 1153         .version    = LIBAVUTIL_VERSION_INT,                                   \ 
 1155     AVCodec ff_ ## NAME ## _mf_encoder = {                                     \ 
 1156         .priv_class     = &ff_ ## NAME ## _mf_encoder_class,                   \ 
 1157         .name           = #NAME "_mf",                                         \ 
 1158         .long_name      = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"),    \ 
 1159         .type           = AVMEDIA_TYPE_ ## MEDIATYPE,                          \ 
 1160         .id             = AV_CODEC_ID_ ## ID,                                  \ 
 1161         .priv_data_size = sizeof(MFContext),                                   \ 
 1163         .close          = mf_close,                                            \ 
 1164         .receive_packet = mf_receive_packet,                                   \ 
 1166         .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID |           \ 
 1168         .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |                       \ 
 1169                           FF_CODEC_CAP_INIT_CLEANUP,                           \ 
 1173         .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,    \ 
 1174                                                          AV_SAMPLE_FMT_NONE }, 
 1180 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 
 1182     {
"rate_control",  
"Select rate control mode", 
OFFSET(opt_enc_rc), 
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, 
VE, 
"rate_control"},
 
 1183     { 
"default",      
"Default mode", 0, 
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, 
VE, 
"rate_control"},
 
 1193     {
"scenario",          
"Select usage scenario", 
OFFSET(opt_enc_scenario), 
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, 
VE, 
"scenario"},
 
 1194     { 
"default",          
"Default scenario", 0, 
AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, 
VE, 
"scenario"},
 
 1208         .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,       \ 
 1209                                                         AV_PIX_FMT_YUV420P,    \