]> git.sesse.net Git - ffmpeg/blob - libavcodec/mfenc.c
avcodec/options_table: make AVCodecContext->profile search for child constants
[ffmpeg] / libavcodec / mfenc.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #define COBJMACROS
20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
21 #undef _WIN32_WINNT
22 #define _WIN32_WINNT 0x0602
23 #endif
24
25 #include "mf_utils.h"
26 #include "libavutil/imgutils.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/time.h"
29
30 // Include after mf_utils.h due to Windows include mess.
31 #include "mpeg4audio.h"
32
33 typedef struct MFContext {
34     AVClass *av_class;
35     int is_video, is_audio;
36     GUID main_subtype;
37     IMFTransform *mft;
38     IMFMediaEventGenerator *async_events;
39     DWORD in_stream_id, out_stream_id;
40     MFT_INPUT_STREAM_INFO in_info;
41     MFT_OUTPUT_STREAM_INFO out_info;
42     int out_stream_provides_samples;
43     int draining, draining_done;
44     int sample_sent;
45     int async_need_input, async_have_output, async_marker;
46     int64_t reorder_delay;
47     ICodecAPI *codec_api;
48     // set by AVOption
49     int opt_enc_rc;
50     int opt_enc_quality;
51     int opt_enc_scenario;
52     int opt_enc_hw;
53 } MFContext;
54
55 static int mf_choose_output_type(AVCodecContext *avctx);
56 static int mf_setup_context(AVCodecContext *avctx);
57
58 #define MF_TIMEBASE (AVRational){1, 10000000}
59 // Sentinel value only used by us.
60 #define MF_INVALID_TIME AV_NOPTS_VALUE
61
62 static int mf_wait_events(AVCodecContext *avctx)
63 {
64     MFContext *c = avctx->priv_data;
65
66     if (!c->async_events)
67         return 0;
68
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);
73         if (FAILED(hr)) {
74             av_log(avctx, AV_LOG_ERROR, "IMFMediaEventGenerator_GetEvent() failed: %s\n",
75                    ff_hr_str(hr));
76             return AVERROR_EXTERNAL;
77         }
78         IMFMediaEvent_GetType(ev, &ev_id);
79         switch (ev_id) {
80         case ff_METransformNeedInput:
81             if (!c->draining)
82                 c->async_need_input = 1;
83             break;
84         case ff_METransformHaveOutput:
85             c->async_have_output = 1;
86             break;
87         case ff_METransformDrainComplete:
88             c->draining_done = 1;
89             break;
90         case ff_METransformMarker:
91             c->async_marker = 1;
92             break;
93         default: ;
94         }
95         IMFMediaEvent_Release(ev);
96     }
97
98     return 0;
99 }
100
101 static AVRational mf_get_tb(AVCodecContext *avctx)
102 {
103     if (avctx->pkt_timebase.num > 0 && avctx->pkt_timebase.den > 0)
104         return avctx->pkt_timebase;
105     if (avctx->time_base.num > 0 && avctx->time_base.den > 0)
106         return avctx->time_base;
107     return MF_TIMEBASE;
108 }
109
110 static LONGLONG mf_to_mf_time(AVCodecContext *avctx, int64_t av_pts)
111 {
112     if (av_pts == AV_NOPTS_VALUE)
113         return MF_INVALID_TIME;
114     return av_rescale_q(av_pts, mf_get_tb(avctx), MF_TIMEBASE);
115 }
116
117 static void mf_sample_set_pts(AVCodecContext *avctx, IMFSample *sample, int64_t av_pts)
118 {
119     LONGLONG stime = mf_to_mf_time(avctx, av_pts);
120     if (stime != MF_INVALID_TIME)
121         IMFSample_SetSampleTime(sample, stime);
122 }
123
124 static int64_t mf_from_mf_time(AVCodecContext *avctx, LONGLONG stime)
125 {
126     return av_rescale_q(stime, MF_TIMEBASE, mf_get_tb(avctx));
127 }
128
129 static int64_t mf_sample_get_pts(AVCodecContext *avctx, IMFSample *sample)
130 {
131     LONGLONG pts;
132     HRESULT hr = IMFSample_GetSampleTime(sample, &pts);
133     if (FAILED(hr))
134         return AV_NOPTS_VALUE;
135     return mf_from_mf_time(avctx, pts);
136 }
137
138 static int mf_enca_output_type_get(AVCodecContext *avctx, IMFMediaType *type)
139 {
140     MFContext *c = avctx->priv_data;
141     HRESULT hr;
142     UINT32 sz;
143
144     if (avctx->codec_id != AV_CODEC_ID_MP3 && avctx->codec_id != AV_CODEC_ID_AC3) {
145         hr = IMFAttributes_GetBlobSize(type, &MF_MT_USER_DATA, &sz);
146         if (!FAILED(hr) && sz > 0) {
147             avctx->extradata = av_mallocz(sz + AV_INPUT_BUFFER_PADDING_SIZE);
148             if (!avctx->extradata)
149                 return AVERROR(ENOMEM);
150             avctx->extradata_size = sz;
151             hr = IMFAttributes_GetBlob(type, &MF_MT_USER_DATA, avctx->extradata, sz, NULL);
152             if (FAILED(hr))
153                 return AVERROR_EXTERNAL;
154
155             if (avctx->codec_id == AV_CODEC_ID_AAC && avctx->extradata_size >= 12) {
156                 // Get rid of HEAACWAVEINFO (after wfx field, 12 bytes).
157                 avctx->extradata_size = avctx->extradata_size - 12;
158                 memmove(avctx->extradata, avctx->extradata + 12, avctx->extradata_size);
159             }
160         }
161     }
162
163     // I don't know where it's documented that we need this. It happens with the
164     // MS mp3 encoder MFT. The idea for the workaround is taken from NAudio.
165     // (Certainly any lossy codec will have frames much smaller than 1 second.)
166     if (!c->out_info.cbSize && !c->out_stream_provides_samples) {
167         hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz);
168         if (!FAILED(hr)) {
169             av_log(avctx, AV_LOG_VERBOSE, "MFT_OUTPUT_STREAM_INFO.cbSize set to 0, "
170                    "assuming %d bytes instead.\n", (int)sz);
171             c->out_info.cbSize = sz;
172         }
173     }
174
175     return 0;
176 }
177
178 static int mf_encv_output_type_get(AVCodecContext *avctx, IMFMediaType *type)
179 {
180     HRESULT hr;
181     UINT32 sz;
182
183     hr = IMFAttributes_GetBlobSize(type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz);
184     if (!FAILED(hr) && sz > 0) {
185         uint8_t *extradata = av_mallocz(sz + AV_INPUT_BUFFER_PADDING_SIZE);
186         if (!extradata)
187             return AVERROR(ENOMEM);
188         hr = IMFAttributes_GetBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz, NULL);
189         if (FAILED(hr)) {
190             av_free(extradata);
191             return AVERROR_EXTERNAL;
192         }
193         av_freep(&avctx->extradata);
194         avctx->extradata = extradata;
195         avctx->extradata_size = sz;
196     }
197
198     return 0;
199 }
200
201 static int mf_output_type_get(AVCodecContext *avctx)
202 {
203     MFContext *c = avctx->priv_data;
204     HRESULT hr;
205     IMFMediaType *type;
206     int ret;
207
208     hr = IMFTransform_GetOutputCurrentType(c->mft, c->out_stream_id, &type);
209     if (FAILED(hr)) {
210         av_log(avctx, AV_LOG_ERROR, "could not get output type\n");
211         return AVERROR_EXTERNAL;
212     }
213
214     av_log(avctx, AV_LOG_VERBOSE, "final output type:\n");
215     ff_media_type_dump(avctx, type);
216
217     ret = 0;
218     if (c->is_video) {
219         ret = mf_encv_output_type_get(avctx, type);
220     } else if (c->is_audio) {
221         ret = mf_enca_output_type_get(avctx, type);
222     }
223
224     if (ret < 0)
225         av_log(avctx, AV_LOG_ERROR, "output type not supported\n");
226
227     IMFMediaType_Release(type);
228     return ret;
229 }
230
231 static int mf_sample_to_avpacket(AVCodecContext *avctx, IMFSample *sample, AVPacket *avpkt)
232 {
233     MFContext *c = avctx->priv_data;
234     HRESULT hr;
235     int ret;
236     DWORD len;
237     IMFMediaBuffer *buffer;
238     BYTE *data;
239     UINT64 t;
240     UINT32 t32;
241
242     hr = IMFSample_GetTotalLength(sample, &len);
243     if (FAILED(hr))
244         return AVERROR_EXTERNAL;
245
246     if ((ret = av_new_packet(avpkt, len)) < 0)
247         return ret;
248
249     IMFSample_ConvertToContiguousBuffer(sample, &buffer);
250     if (FAILED(hr))
251         return AVERROR_EXTERNAL;
252
253     hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
254     if (FAILED(hr)) {
255         IMFMediaBuffer_Release(buffer);
256         return AVERROR_EXTERNAL;
257     }
258
259     memcpy(avpkt->data, data, len);
260
261     IMFMediaBuffer_Unlock(buffer);
262     IMFMediaBuffer_Release(buffer);
263
264     avpkt->pts = avpkt->dts = mf_sample_get_pts(avctx, sample);
265
266     hr = IMFAttributes_GetUINT32(sample, &MFSampleExtension_CleanPoint, &t32);
267     if (c->is_audio || (!FAILED(hr) && t32 != 0))
268         avpkt->flags |= AV_PKT_FLAG_KEY;
269
270     hr = IMFAttributes_GetUINT64(sample, &MFSampleExtension_DecodeTimestamp, &t);
271     if (!FAILED(hr)) {
272         avpkt->dts = mf_from_mf_time(avctx, t);
273         // At least on Qualcomm's HEVC encoder on SD 835, the output dts
274         // starts from the input pts of the first frame, while the output pts
275         // is shifted forward. Therefore, shift the output values back so that
276         // the output pts matches the input.
277         if (c->reorder_delay == AV_NOPTS_VALUE)
278             c->reorder_delay = avpkt->pts - avpkt->dts;
279         avpkt->dts -= c->reorder_delay;
280         avpkt->pts -= c->reorder_delay;
281     }
282
283     return 0;
284 }
285
286 static IMFSample *mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame)
287 {
288     MFContext *c = avctx->priv_data;
289     size_t len;
290     size_t bps;
291     IMFSample *sample;
292
293     bps = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels;
294     len = frame->nb_samples * bps;
295
296     sample = ff_create_memory_sample(frame->data[0], len, c->in_info.cbAlignment);
297     if (sample)
298         IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->nb_samples));
299     return sample;
300 }
301
302 static IMFSample *mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame)
303 {
304     MFContext *c = avctx->priv_data;
305     IMFSample *sample;
306     IMFMediaBuffer *buffer;
307     BYTE *data;
308     HRESULT hr;
309     int ret;
310     int size;
311
312     size = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
313     if (size < 0)
314         return NULL;
315
316     sample = ff_create_memory_sample(NULL, size, c->in_info.cbAlignment);
317     if (!sample)
318         return NULL;
319
320     hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
321     if (FAILED(hr)) {
322         IMFSample_Release(sample);
323         return NULL;
324     }
325
326     hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
327     if (FAILED(hr)) {
328         IMFMediaBuffer_Release(buffer);
329         IMFSample_Release(sample);
330         return NULL;
331     }
332
333     ret = av_image_copy_to_buffer((uint8_t *)data, size, (void *)frame->data, frame->linesize,
334                                   avctx->pix_fmt, avctx->width, avctx->height, 1);
335     IMFMediaBuffer_SetCurrentLength(buffer, size);
336     IMFMediaBuffer_Unlock(buffer);
337     IMFMediaBuffer_Release(buffer);
338     if (ret < 0) {
339         IMFSample_Release(sample);
340         return NULL;
341     }
342
343     IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->pkt_duration));
344
345     return sample;
346 }
347
348 static IMFSample *mf_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame)
349 {
350     MFContext *c = avctx->priv_data;
351     IMFSample *sample;
352
353     if (c->is_audio) {
354         sample = mf_a_avframe_to_sample(avctx, frame);
355     } else {
356         sample = mf_v_avframe_to_sample(avctx, frame);
357     }
358
359     if (sample)
360         mf_sample_set_pts(avctx, sample, frame->pts);
361
362     return sample;
363 }
364
365 static int mf_send_sample(AVCodecContext *avctx, IMFSample *sample)
366 {
367     MFContext *c = avctx->priv_data;
368     HRESULT hr;
369     int ret;
370
371     if (sample) {
372         if (c->async_events) {
373             if ((ret = mf_wait_events(avctx)) < 0)
374                 return ret;
375             if (!c->async_need_input)
376                 return AVERROR(EAGAIN);
377         }
378         if (!c->sample_sent)
379             IMFSample_SetUINT32(sample, &MFSampleExtension_Discontinuity, TRUE);
380         c->sample_sent = 1;
381         hr = IMFTransform_ProcessInput(c->mft, c->in_stream_id, sample, 0);
382         if (hr == MF_E_NOTACCEPTING) {
383             return AVERROR(EAGAIN);
384         } else if (FAILED(hr)) {
385             av_log(avctx, AV_LOG_ERROR, "failed processing input: %s\n", ff_hr_str(hr));
386             return AVERROR_EXTERNAL;
387         }
388         c->async_need_input = 0;
389     } else if (!c->draining) {
390         hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
391         if (FAILED(hr))
392             av_log(avctx, AV_LOG_ERROR, "failed draining: %s\n", ff_hr_str(hr));
393         // Some MFTs (AC3) will send a frame after each drain command (???), so
394         // this is required to make draining actually terminate.
395         c->draining = 1;
396         c->async_need_input = 0;
397     } else {
398         return AVERROR_EOF;
399     }
400     return 0;
401 }
402
403 static int mf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
404 {
405     MFContext *c = avctx->priv_data;
406     int ret;
407     IMFSample *sample = NULL;
408     if (frame) {
409         sample = mf_avframe_to_sample(avctx, frame);
410         if (!sample)
411             return AVERROR(ENOMEM);
412         if (c->is_video && c->codec_api) {
413             if (frame->pict_type == AV_PICTURE_TYPE_I || !c->sample_sent)
414                 ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame, FF_VAL_VT_UI4(1));
415         }
416     }
417     ret = mf_send_sample(avctx, sample);
418     if (sample)
419         IMFSample_Release(sample);
420     return ret;
421 }
422
423 static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample)
424 {
425     MFContext *c = avctx->priv_data;
426     HRESULT hr;
427     DWORD st;
428     MFT_OUTPUT_DATA_BUFFER out_buffers;
429     IMFSample *sample;
430     int ret = 0;
431
432     while (1) {
433         *out_sample = NULL;
434         sample = NULL;
435
436         if (c->async_events) {
437             if ((ret = mf_wait_events(avctx)) < 0)
438                 return ret;
439             if (!c->async_have_output || c->draining_done) {
440                 ret = 0;
441                 break;
442             }
443         }
444
445         if (!c->out_stream_provides_samples) {
446             sample = ff_create_memory_sample(NULL, c->out_info.cbSize, c->out_info.cbAlignment);
447             if (!sample)
448                 return AVERROR(ENOMEM);
449         }
450
451         out_buffers = (MFT_OUTPUT_DATA_BUFFER) {
452             .dwStreamID = c->out_stream_id,
453             .pSample = sample,
454         };
455
456         st = 0;
457         hr = IMFTransform_ProcessOutput(c->mft, 0, 1, &out_buffers, &st);
458
459         if (out_buffers.pEvents)
460             IMFCollection_Release(out_buffers.pEvents);
461
462         if (!FAILED(hr)) {
463             *out_sample = out_buffers.pSample;
464             ret = 0;
465             break;
466         }
467
468         if (out_buffers.pSample)
469             IMFSample_Release(out_buffers.pSample);
470
471         if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
472             if (c->draining)
473                 c->draining_done = 1;
474             ret = 0;
475         } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
476             av_log(avctx, AV_LOG_WARNING, "stream format change\n");
477             ret = mf_choose_output_type(avctx);
478             if (ret == 0) // we don't expect renegotiating the input type
479                 ret = AVERROR_EXTERNAL;
480             if (ret > 0) {
481                 ret = mf_setup_context(avctx);
482                 if (ret >= 0) {
483                     c->async_have_output = 0;
484                     continue;
485                 }
486             }
487         } else {
488             av_log(avctx, AV_LOG_ERROR, "failed processing output: %s\n", ff_hr_str(hr));
489             ret = AVERROR_EXTERNAL;
490         }
491
492         break;
493     }
494
495     c->async_have_output = 0;
496
497     if (ret >= 0 && !*out_sample)
498         ret = c->draining_done ? AVERROR_EOF : AVERROR(EAGAIN);
499
500     return ret;
501 }
502
503 static int mf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
504 {
505     IMFSample *sample;
506     int ret;
507
508     ret = mf_receive_sample(avctx, &sample);
509     if (ret < 0)
510         return ret;
511
512     ret = mf_sample_to_avpacket(avctx, sample, avpkt);
513     IMFSample_Release(sample);
514
515     return ret;
516 }
517
518 // Most encoders seem to enumerate supported audio formats on the output types,
519 // at least as far as channel configuration and sample rate is concerned. Pick
520 // the one which seems to match best.
521 static int64_t mf_enca_output_score(AVCodecContext *avctx, IMFMediaType *type)
522 {
523     MFContext *c = avctx->priv_data;
524     HRESULT hr;
525     UINT32 t;
526     GUID tg;
527     int64_t score = 0;
528
529     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
530     if (!FAILED(hr) && t == avctx->sample_rate)
531         score |= 1LL << 32;
532
533     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
534     if (!FAILED(hr) && t == avctx->channels)
535         score |= 2LL << 32;
536
537     hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg);
538     if (!FAILED(hr)) {
539         if (IsEqualGUID(&c->main_subtype, &tg))
540             score |= 4LL << 32;
541     }
542
543     // Select the bitrate (lowest priority).
544     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t);
545     if (!FAILED(hr)) {
546         int diff = (int)t - avctx->bit_rate / 8;
547         if (diff >= 0) {
548             score |= (1LL << 31) - diff; // prefer lower bitrate
549         } else {
550             score |= (1LL << 30) + diff; // prefer higher bitrate
551         }
552     }
553
554     hr = IMFAttributes_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &t);
555     if (!FAILED(hr) && t != 0)
556         return -1;
557
558     return score;
559 }
560
561 static int mf_enca_output_adjust(AVCodecContext *avctx, IMFMediaType *type)
562 {
563     // (some decoders allow adjusting this freely, but it can also cause failure
564     //  to set the output type - so it's commented for being too fragile)
565     //IMFAttributes_SetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, avctx->bit_rate / 8);
566     //IMFAttributes_SetUINT32(type, &MF_MT_AVG_BITRATE, avctx->bit_rate);
567
568     return 0;
569 }
570
571 static int64_t mf_enca_input_score(AVCodecContext *avctx, IMFMediaType *type)
572 {
573     HRESULT hr;
574     UINT32 t;
575     int64_t score = 0;
576
577     enum AVSampleFormat sformat = ff_media_type_to_sample_fmt((IMFAttributes *)type);
578     if (sformat == AV_SAMPLE_FMT_NONE)
579         return -1; // can not use
580
581     if (sformat == avctx->sample_fmt)
582         score |= 1;
583
584     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
585     if (!FAILED(hr) && t == avctx->sample_rate)
586         score |= 2;
587
588     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
589     if (!FAILED(hr) && t == avctx->channels)
590         score |= 4;
591
592     return score;
593 }
594
595 static int mf_enca_input_adjust(AVCodecContext *avctx, IMFMediaType *type)
596 {
597     HRESULT hr;
598     UINT32 t;
599
600     enum AVSampleFormat sformat = ff_media_type_to_sample_fmt((IMFAttributes *)type);
601     if (sformat != avctx->sample_fmt) {
602         av_log(avctx, AV_LOG_ERROR, "unsupported input sample format set\n");
603         return AVERROR(EINVAL);
604     }
605
606     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
607     if (FAILED(hr) || t != avctx->sample_rate) {
608         av_log(avctx, AV_LOG_ERROR, "unsupported input sample rate set\n");
609         return AVERROR(EINVAL);
610     }
611
612     hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
613     if (FAILED(hr) || t != avctx->channels) {
614         av_log(avctx, AV_LOG_ERROR, "unsupported input channel number set\n");
615         return AVERROR(EINVAL);
616     }
617
618     return 0;
619 }
620
621 static int64_t mf_encv_output_score(AVCodecContext *avctx, IMFMediaType *type)
622 {
623     MFContext *c = avctx->priv_data;
624     GUID tg;
625     HRESULT hr;
626     int score = -1;
627
628     hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg);
629     if (!FAILED(hr)) {
630         if (IsEqualGUID(&c->main_subtype, &tg))
631             score = 1;
632     }
633
634     return score;
635 }
636
637 static int mf_encv_output_adjust(AVCodecContext *avctx, IMFMediaType *type)
638 {
639     MFContext *c = avctx->priv_data;
640     AVRational framerate;
641
642     ff_MFSetAttributeSize((IMFAttributes *)type, &MF_MT_FRAME_SIZE, avctx->width, avctx->height);
643     IMFAttributes_SetUINT32(type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
644
645     if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
646         framerate = avctx->framerate;
647     } else {
648         framerate = av_inv_q(avctx->time_base);
649         framerate.den *= avctx->ticks_per_frame;
650     }
651
652     ff_MFSetAttributeRatio((IMFAttributes *)type, &MF_MT_FRAME_RATE, framerate.num, framerate.den);
653
654     // (MS HEVC supports eAVEncH265VProfile_Main_420_8 only.)
655     if (avctx->codec_id == AV_CODEC_ID_H264) {
656         UINT32 profile = eAVEncH264VProfile_Base;
657         switch (avctx->profile) {
658         case FF_PROFILE_H264_MAIN:
659             profile = eAVEncH264VProfile_Main;
660             break;
661         case FF_PROFILE_H264_HIGH:
662             profile = eAVEncH264VProfile_High;
663             break;
664         }
665         IMFAttributes_SetUINT32(type, &MF_MT_MPEG2_PROFILE, profile);
666     }
667
668     IMFAttributes_SetUINT32(type, &MF_MT_AVG_BITRATE, avctx->bit_rate);
669
670     // Note that some of the ICodecAPI options must be set before SetOutputType.
671     if (c->codec_api) {
672         if (avctx->bit_rate)
673             ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonMeanBitRate, FF_VAL_VT_UI4(avctx->bit_rate));
674
675         if (c->opt_enc_rc >= 0)
676             ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode, FF_VAL_VT_UI4(c->opt_enc_rc));
677
678         if (c->opt_enc_quality >= 0)
679             ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonQuality, FF_VAL_VT_UI4(c->opt_enc_quality));
680
681         // Always set the number of b-frames. Qualcomm's HEVC encoder on SD835
682         // defaults this to 1, and that setting is buggy with many of the
683         // rate control modes. (0 or 2 b-frames works fine with most rate
684         // control modes, but 2 seems buggy with the u_vbr mode.) Setting
685         // "scenario" to "camera_record" sets it in CFR mode (where the default
686         // is VFR), which makes the encoder avoid dropping frames.
687         ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncMPVDefaultBPictureCount, FF_VAL_VT_UI4(avctx->max_b_frames));
688         avctx->has_b_frames = avctx->max_b_frames > 0;
689
690         ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable, FF_VAL_VT_BOOL(1));
691
692         if (c->opt_enc_scenario >= 0)
693             ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVScenarioInfo, FF_VAL_VT_UI4(c->opt_enc_scenario));
694     }
695
696     return 0;
697 }
698
699 static int64_t mf_encv_input_score(AVCodecContext *avctx, IMFMediaType *type)
700 {
701     enum AVPixelFormat pix_fmt = ff_media_type_to_pix_fmt((IMFAttributes *)type);
702     if (pix_fmt != avctx->pix_fmt)
703         return -1; // can not use
704
705     return 0;
706 }
707
708 static int mf_encv_input_adjust(AVCodecContext *avctx, IMFMediaType *type)
709 {
710     enum AVPixelFormat pix_fmt = ff_media_type_to_pix_fmt((IMFAttributes *)type);
711     if (pix_fmt != avctx->pix_fmt) {
712         av_log(avctx, AV_LOG_ERROR, "unsupported input pixel format set\n");
713         return AVERROR(EINVAL);
714     }
715
716     //ff_MFSetAttributeSize((IMFAttributes *)type, &MF_MT_FRAME_SIZE, avctx->width, avctx->height);
717
718     return 0;
719 }
720
721 static int mf_choose_output_type(AVCodecContext *avctx)
722 {
723     MFContext *c = avctx->priv_data;
724     HRESULT hr;
725     int ret;
726     IMFMediaType *out_type = NULL;
727     int64_t out_type_score = -1;
728     int out_type_index = -1;
729     int n;
730
731     av_log(avctx, AV_LOG_VERBOSE, "output types:\n");
732     for (n = 0; ; n++) {
733         IMFMediaType *type;
734         int64_t score = -1;
735
736         hr = IMFTransform_GetOutputAvailableType(c->mft, c->out_stream_id, n, &type);
737         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
738             break;
739         if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
740             av_log(avctx, AV_LOG_VERBOSE, "(need to set input type)\n");
741             ret = 0;
742             goto done;
743         }
744         if (FAILED(hr)) {
745             av_log(avctx, AV_LOG_ERROR, "error getting output type: %s\n", ff_hr_str(hr));
746             ret = AVERROR_EXTERNAL;
747             goto done;
748         }
749
750         av_log(avctx, AV_LOG_VERBOSE, "output type %d:\n", n);
751         ff_media_type_dump(avctx, type);
752
753         if (c->is_video) {
754             score = mf_encv_output_score(avctx, type);
755         } else if (c->is_audio) {
756             score = mf_enca_output_score(avctx, type);
757         }
758
759         if (score > out_type_score) {
760             if (out_type)
761                 IMFMediaType_Release(out_type);
762             out_type = type;
763             out_type_score = score;
764             out_type_index = n;
765             IMFMediaType_AddRef(out_type);
766         }
767
768         IMFMediaType_Release(type);
769     }
770
771     if (out_type) {
772         av_log(avctx, AV_LOG_VERBOSE, "picking output type %d.\n", out_type_index);
773     } else {
774         hr = MFCreateMediaType(&out_type);
775         if (FAILED(hr)) {
776             ret = AVERROR(ENOMEM);
777             goto done;
778         }
779     }
780
781     ret = 0;
782     if (c->is_video) {
783         ret = mf_encv_output_adjust(avctx, out_type);
784     } else if (c->is_audio) {
785         ret = mf_enca_output_adjust(avctx, out_type);
786     }
787
788     if (ret >= 0) {
789         av_log(avctx, AV_LOG_VERBOSE, "setting output type:\n");
790         ff_media_type_dump(avctx, out_type);
791
792         hr = IMFTransform_SetOutputType(c->mft, c->out_stream_id, out_type, 0);
793         if (!FAILED(hr)) {
794             ret = 1;
795         } else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
796             av_log(avctx, AV_LOG_VERBOSE, "rejected - need to set input type\n");
797             ret = 0;
798         } else {
799             av_log(avctx, AV_LOG_ERROR, "could not set output type (%s)\n", ff_hr_str(hr));
800             ret = AVERROR_EXTERNAL;
801         }
802     }
803
804 done:
805     if (out_type)
806         IMFMediaType_Release(out_type);
807     return ret;
808 }
809
810 static int mf_choose_input_type(AVCodecContext *avctx)
811 {
812     MFContext *c = avctx->priv_data;
813     HRESULT hr;
814     int ret;
815     IMFMediaType *in_type = NULL;
816     int64_t in_type_score = -1;
817     int in_type_index = -1;
818     int n;
819
820     av_log(avctx, AV_LOG_VERBOSE, "input types:\n");
821     for (n = 0; ; n++) {
822         IMFMediaType *type = NULL;
823         int64_t score = -1;
824
825         hr = IMFTransform_GetInputAvailableType(c->mft, c->in_stream_id, n, &type);
826         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
827             break;
828         if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
829             av_log(avctx, AV_LOG_VERBOSE, "(need to set output type 1)\n");
830             ret = 0;
831             goto done;
832         }
833         if (FAILED(hr)) {
834             av_log(avctx, AV_LOG_ERROR, "error getting input type: %s\n", ff_hr_str(hr));
835             ret = AVERROR_EXTERNAL;
836             goto done;
837         }
838
839         av_log(avctx, AV_LOG_VERBOSE, "input type %d:\n", n);
840         ff_media_type_dump(avctx, type);
841
842         if (c->is_video) {
843             score = mf_encv_input_score(avctx, type);
844         } else if (c->is_audio) {
845             score = mf_enca_input_score(avctx, type);
846         }
847
848         if (score > in_type_score) {
849             if (in_type)
850                 IMFMediaType_Release(in_type);
851             in_type = type;
852             in_type_score = score;
853             in_type_index = n;
854             IMFMediaType_AddRef(in_type);
855         }
856
857         IMFMediaType_Release(type);
858     }
859
860     if (in_type) {
861         av_log(avctx, AV_LOG_VERBOSE, "picking input type %d.\n", in_type_index);
862     } else {
863         // Some buggy MFTs (WMA encoder) fail to return MF_E_TRANSFORM_TYPE_NOT_SET.
864         av_log(avctx, AV_LOG_VERBOSE, "(need to set output type 2)\n");
865         ret = 0;
866         goto done;
867     }
868
869     ret = 0;
870     if (c->is_video) {
871         ret = mf_encv_input_adjust(avctx, in_type);
872     } else if (c->is_audio) {
873         ret = mf_enca_input_adjust(avctx, in_type);
874     }
875
876     if (ret >= 0) {
877         av_log(avctx, AV_LOG_VERBOSE, "setting input type:\n");
878         ff_media_type_dump(avctx, in_type);
879
880         hr = IMFTransform_SetInputType(c->mft, c->in_stream_id, in_type, 0);
881         if (!FAILED(hr)) {
882             ret = 1;
883         } else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
884             av_log(avctx, AV_LOG_VERBOSE, "rejected - need to set output type\n");
885             ret = 0;
886         } else {
887             av_log(avctx, AV_LOG_ERROR, "could not set input type (%s)\n", ff_hr_str(hr));
888             ret = AVERROR_EXTERNAL;
889         }
890     }
891
892 done:
893     if (in_type)
894         IMFMediaType_Release(in_type);
895     return ret;
896 }
897
898 static int mf_negotiate_types(AVCodecContext *avctx)
899 {
900     // This follows steps 1-5 on:
901     //  https://msdn.microsoft.com/en-us/library/windows/desktop/aa965264(v=vs.85).aspx
902     // If every MFT implementer does this correctly, this loop should at worst
903     // be repeated once.
904     int need_input = 1, need_output = 1;
905     int n;
906     for (n = 0; n < 2 && (need_input || need_output); n++) {
907         int ret;
908         ret = mf_choose_input_type(avctx);
909         if (ret < 0)
910             return ret;
911         need_input = ret < 1;
912         ret = mf_choose_output_type(avctx);
913         if (ret < 0)
914             return ret;
915         need_output = ret < 1;
916     }
917     if (need_input || need_output) {
918         av_log(avctx, AV_LOG_ERROR, "format negotiation failed (%d/%d)\n",
919                need_input, need_output);
920         return AVERROR_EXTERNAL;
921     }
922     return 0;
923 }
924
925 static int mf_setup_context(AVCodecContext *avctx)
926 {
927     MFContext *c = avctx->priv_data;
928     HRESULT hr;
929     int ret;
930
931     hr = IMFTransform_GetInputStreamInfo(c->mft, c->in_stream_id, &c->in_info);
932     if (FAILED(hr))
933         return AVERROR_EXTERNAL;
934     av_log(avctx, AV_LOG_VERBOSE, "in_info: size=%d, align=%d\n",
935            (int)c->in_info.cbSize, (int)c->in_info.cbAlignment);
936
937     hr = IMFTransform_GetOutputStreamInfo(c->mft, c->out_stream_id, &c->out_info);
938     if (FAILED(hr))
939         return AVERROR_EXTERNAL;
940     c->out_stream_provides_samples =
941         (c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
942         (c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
943     av_log(avctx, AV_LOG_VERBOSE, "out_info: size=%d, align=%d%s\n",
944            (int)c->out_info.cbSize, (int)c->out_info.cbAlignment,
945            c->out_stream_provides_samples ? " (provides samples)" : "");
946
947     if ((ret = mf_output_type_get(avctx)) < 0)
948         return ret;
949
950     return 0;
951 }
952
953 static int mf_unlock_async(AVCodecContext *avctx)
954 {
955     MFContext *c = avctx->priv_data;
956     HRESULT hr;
957     IMFAttributes *attrs;
958     UINT32 v;
959     int res = AVERROR_EXTERNAL;
960
961     // For hw encoding we unfortunately need to use async mode, otherwise
962     // play it safe and avoid it.
963     if (!(c->is_video && c->opt_enc_hw))
964         return 0;
965
966     hr = IMFTransform_GetAttributes(c->mft, &attrs);
967     if (FAILED(hr)) {
968         av_log(avctx, AV_LOG_ERROR, "error retrieving MFT attributes: %s\n", ff_hr_str(hr));
969         goto err;
970     }
971
972     hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v);
973     if (FAILED(hr)) {
974         av_log(avctx, AV_LOG_ERROR, "error querying async: %s\n", ff_hr_str(hr));
975         goto err;
976     }
977
978     if (!v) {
979         av_log(avctx, AV_LOG_ERROR, "hardware MFT is not async\n");
980         goto err;
981     }
982
983     hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
984     if (FAILED(hr)) {
985         av_log(avctx, AV_LOG_ERROR, "could not set async unlock: %s\n", ff_hr_str(hr));
986         goto err;
987     }
988
989     hr = IMFTransform_QueryInterface(c->mft, &IID_IMFMediaEventGenerator, (void **)&c->async_events);
990     if (FAILED(hr)) {
991         av_log(avctx, AV_LOG_ERROR, "could not get async interface\n");
992         goto err;
993     }
994
995     res = 0;
996
997 err:
998     IMFAttributes_Release(attrs);
999     return res;
1000 }
1001
1002 static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int use_hw)
1003 {
1004     int is_audio = codec->type == AVMEDIA_TYPE_AUDIO;
1005     const CLSID *subtype = ff_codec_to_mf_subtype(codec->id);
1006     MFT_REGISTER_TYPE_INFO reg = {0};
1007     GUID category;
1008     int ret;
1009
1010     *mft = NULL;
1011
1012     if (!subtype)
1013         return AVERROR(ENOSYS);
1014
1015     reg.guidSubtype = *subtype;
1016
1017     if (is_audio) {
1018         reg.guidMajorType = MFMediaType_Audio;
1019         category = MFT_CATEGORY_AUDIO_ENCODER;
1020     } else {
1021         reg.guidMajorType = MFMediaType_Video;
1022         category = MFT_CATEGORY_VIDEO_ENCODER;
1023     }
1024
1025     if ((ret = ff_instantiate_mf(log, category, NULL, &reg, use_hw, mft)) < 0)
1026         return ret;
1027
1028     return 0;
1029 }
1030
1031 static int mf_init(AVCodecContext *avctx)
1032 {
1033     MFContext *c = avctx->priv_data;
1034     HRESULT hr;
1035     int ret;
1036     const CLSID *subtype = ff_codec_to_mf_subtype(avctx->codec_id);
1037     int use_hw = 0;
1038
1039     c->is_audio = avctx->codec_type == AVMEDIA_TYPE_AUDIO;
1040     c->is_video = !c->is_audio;
1041     c->reorder_delay = AV_NOPTS_VALUE;
1042
1043     if (c->is_video && c->opt_enc_hw)
1044         use_hw = 1;
1045
1046     if (!subtype)
1047         return AVERROR(ENOSYS);
1048
1049     c->main_subtype = *subtype;
1050
1051     if ((ret = mf_create(avctx, &c->mft, avctx->codec, use_hw)) < 0)
1052         return ret;
1053
1054     if ((ret = mf_unlock_async(avctx)) < 0)
1055         return ret;
1056
1057     hr = IMFTransform_QueryInterface(c->mft, &IID_ICodecAPI, (void **)&c->codec_api);
1058     if (!FAILED(hr))
1059         av_log(avctx, AV_LOG_VERBOSE, "MFT supports ICodecAPI.\n");
1060
1061
1062     hr = IMFTransform_GetStreamIDs(c->mft, 1, &c->in_stream_id, 1, &c->out_stream_id);
1063     if (hr == E_NOTIMPL) {
1064         c->in_stream_id = c->out_stream_id = 0;
1065     } else if (FAILED(hr)) {
1066         av_log(avctx, AV_LOG_ERROR, "could not get stream IDs (%s)\n", ff_hr_str(hr));
1067         return AVERROR_EXTERNAL;
1068     }
1069
1070     if ((ret = mf_negotiate_types(avctx)) < 0)
1071         return ret;
1072
1073     if ((ret = mf_setup_context(avctx)) < 0)
1074         return ret;
1075
1076     hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1077     if (FAILED(hr)) {
1078         av_log(avctx, AV_LOG_ERROR, "could not start streaming (%s)\n", ff_hr_str(hr));
1079         return AVERROR_EXTERNAL;
1080     }
1081
1082     hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
1083     if (FAILED(hr)) {
1084         av_log(avctx, AV_LOG_ERROR, "could not start stream (%s)\n", ff_hr_str(hr));
1085         return AVERROR_EXTERNAL;
1086     }
1087
1088     if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER && c->async_events &&
1089         c->is_video && !avctx->extradata) {
1090         int sleep = 10000, total = 0;
1091         av_log(avctx, AV_LOG_VERBOSE, "Awaiting extradata\n");
1092         while (total < 70*1000) {
1093             // The Qualcomm H264 encoder on SD835 doesn't provide extradata
1094             // immediately, but it becomes available soon after init (without
1095             // any waitable event). In practice, it's available after less
1096             // than 10 ms, but wait for up to 70 ms before giving up.
1097             // Some encoders (Qualcomm's HEVC encoder on SD835, some versions
1098             // of the QSV H264 encoder at least) don't provide extradata this
1099             // way at all, not even after encoding a frame - it's only
1100             // available prepended to frames.
1101             av_usleep(sleep);
1102             total += sleep;
1103             mf_output_type_get(avctx);
1104             if (avctx->extradata)
1105                 break;
1106             sleep *= 2;
1107         }
1108         av_log(avctx, AV_LOG_VERBOSE, "%s extradata in %d ms\n",
1109                avctx->extradata ? "Got" : "Didn't get", total / 1000);
1110     }
1111
1112     return 0;
1113 }
1114
1115 static int mf_close(AVCodecContext *avctx)
1116 {
1117     MFContext *c = avctx->priv_data;
1118
1119     if (c->codec_api)
1120         ICodecAPI_Release(c->codec_api);
1121
1122     if (c->async_events)
1123         IMFMediaEventGenerator_Release(c->async_events);
1124
1125     ff_free_mf(&c->mft);
1126
1127     av_freep(&avctx->extradata);
1128     avctx->extradata_size = 0;
1129
1130     return 0;
1131 }
1132
1133 #define OFFSET(x) offsetof(MFContext, x)
1134
1135 #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \
1136     static const AVClass ff_ ## NAME ## _mf_encoder_class = {                  \
1137         .class_name = #NAME "_mf",                                             \
1138         .item_name  = av_default_item_name,                                    \
1139         .option     = OPTS,                                                    \
1140         .version    = LIBAVUTIL_VERSION_INT,                                   \
1141     };                                                                         \
1142     AVCodec ff_ ## NAME ## _mf_encoder = {                                     \
1143         .priv_class     = &ff_ ## NAME ## _mf_encoder_class,                   \
1144         .name           = #NAME "_mf",                                         \
1145         .long_name      = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"),    \
1146         .type           = AVMEDIA_TYPE_ ## MEDIATYPE,                          \
1147         .id             = AV_CODEC_ID_ ## ID,                                  \
1148         .priv_data_size = sizeof(MFContext),                                   \
1149         .init           = mf_init,                                             \
1150         .close          = mf_close,                                            \
1151         .send_frame     = mf_send_frame,                                       \
1152         .receive_packet = mf_receive_packet,                                   \
1153         EXTRA                                                                  \
1154         .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID,            \
1155         .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |                       \
1156                           FF_CODEC_CAP_INIT_CLEANUP,                           \
1157     };
1158
1159 #define AFMTS \
1160         .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,    \
1161                                                          AV_SAMPLE_FMT_NONE },
1162
1163 MF_ENCODER(AUDIO, aac,         AAC, NULL, AFMTS);
1164 MF_ENCODER(AUDIO, ac3,         AC3, NULL, AFMTS);
1165 MF_ENCODER(AUDIO, mp3,         MP3, NULL, AFMTS);
1166
1167 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1168 static const AVOption venc_opts[] = {
1169     {"rate_control",  "Select rate control mode", OFFSET(opt_enc_rc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "rate_control"},
1170     { "default",      "Default mode", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "rate_control"},
1171     { "cbr",          "CBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_CBR}, 0, 0, VE, "rate_control"},
1172     { "pc_vbr",       "Peak constrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_PeakConstrainedVBR}, 0, 0, VE, "rate_control"},
1173     { "u_vbr",        "Unconstrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_UnconstrainedVBR}, 0, 0, VE, "rate_control"},
1174     { "quality",      "Quality mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_Quality}, 0, 0, VE, "rate_control" },
1175     // The following rate_control modes require Windows 8.
1176     { "ld_vbr",       "Low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_LowDelayVBR}, 0, 0, VE, "rate_control"},
1177     { "g_vbr",        "Global VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalVBR}, 0, 0, VE, "rate_control" },
1178     { "gld_vbr",      "Global low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR}, 0, 0, VE, "rate_control"},
1179
1180     {"scenario",          "Select usage scenario", OFFSET(opt_enc_scenario), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "scenario"},
1181     { "default",          "Default scenario", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "scenario"},
1182     { "display_remoting", "Display remoting", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_DisplayRemoting}, 0, 0, VE, "scenario"},
1183     { "video_conference", "Video conference", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_VideoConference}, 0, 0, VE, "scenario"},
1184     { "archive",          "Archive", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_Archive}, 0, 0, VE, "scenario"},
1185     { "live_streaming",   "Live streaming", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_LiveStreaming}, 0, 0, VE, "scenario"},
1186     { "camera_record",    "Camera record", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_CameraRecord}, 0, 0, VE, "scenario"},
1187     { "display_remoting_with_feature_map", "Display remoting with feature map", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap}, 0, 0, VE, "scenario"},
1188
1189     {"quality",       "Quality", OFFSET(opt_enc_quality), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE},
1190     {"hw_encoding",   "Force hardware encoding", OFFSET(opt_enc_hw), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE},
1191     {NULL}
1192 };
1193
1194 #define VFMTS \
1195         .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,       \
1196                                                         AV_PIX_FMT_YUV420P,    \
1197                                                         AV_PIX_FMT_NONE },
1198
1199 MF_ENCODER(VIDEO, h264,        H264, venc_opts, VFMTS);
1200 MF_ENCODER(VIDEO, hevc,        HEVC, venc_opts, VFMTS);