FFmpeg
mfenc.c
Go to the documentation of this file.
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 "encode.h"
26 #include "mf_utils.h"
27 #include "libavutil/imgutils.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/time.h"
31 #include "codec_internal.h"
32 #include "internal.h"
33 #include "compat/w32dlfcn.h"
34 #if CONFIG_D3D11VA
36 #endif
37 
38 typedef struct MFContext {
40  HMODULE library;
41  HMODULE d3d_dll;
42  ID3D11DeviceContext* d3d_context;
43  IMFDXGIDeviceManager *dxgiManager;
45 
50  IMFTransform *mft;
51  IMFMediaEventGenerator *async_events;
53  MFT_INPUT_STREAM_INFO in_info;
54  MFT_OUTPUT_STREAM_INFO out_info;
61  ICodecAPI *codec_api;
62  // set by AVOption
68 } MFContext;
69 
70 static int mf_choose_output_type(AVCodecContext *avctx);
71 static int mf_setup_context(AVCodecContext *avctx);
72 
73 #define MF_TIMEBASE (AVRational){1, 10000000}
74 // Sentinel value only used by us.
75 #define MF_INVALID_TIME AV_NOPTS_VALUE
76 
77 static int mf_wait_events(AVCodecContext *avctx)
78 {
79  MFContext *c = avctx->priv_data;
80 
81  if (!c->async_events)
82  return 0;
83 
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);
88  if (FAILED(hr)) {
89  av_log(avctx, AV_LOG_ERROR, "IMFMediaEventGenerator_GetEvent() failed: %s\n",
90  ff_hr_str(hr));
91  return AVERROR_EXTERNAL;
92  }
93  IMFMediaEvent_GetType(ev, &ev_id);
94  switch (ev_id) {
96  if (!c->draining)
97  c->async_need_input = 1;
98  break;
100  c->async_have_output = 1;
101  break;
103  c->draining_done = 1;
104  break;
106  c->async_marker = 1;
107  break;
108  default: ;
109  }
110  IMFMediaEvent_Release(ev);
111  }
112 
113  return 0;
114 }
115 
117 {
118  if (avctx->time_base.num > 0 && avctx->time_base.den > 0)
119  return avctx->time_base;
120  return MF_TIMEBASE;
121 }
122 
123 static LONGLONG mf_to_mf_time(AVCodecContext *avctx, int64_t av_pts)
124 {
125  if (av_pts == AV_NOPTS_VALUE)
126  return MF_INVALID_TIME;
127  return av_rescale_q(av_pts, mf_get_tb(avctx), MF_TIMEBASE);
128 }
129 
130 static void mf_sample_set_pts(AVCodecContext *avctx, IMFSample *sample, int64_t av_pts)
131 {
132  LONGLONG stime = mf_to_mf_time(avctx, av_pts);
133  if (stime != MF_INVALID_TIME)
134  IMFSample_SetSampleTime(sample, stime);
135 }
136 
137 static int64_t mf_from_mf_time(AVCodecContext *avctx, LONGLONG stime)
138 {
139  return av_rescale_q(stime, MF_TIMEBASE, mf_get_tb(avctx));
140 }
141 
142 static int64_t mf_sample_get_pts(AVCodecContext *avctx, IMFSample *sample)
143 {
144  LONGLONG pts;
145  HRESULT hr = IMFSample_GetSampleTime(sample, &pts);
146  if (FAILED(hr))
147  return AV_NOPTS_VALUE;
148  return mf_from_mf_time(avctx, pts);
149 }
150 
152 {
153  LONGLONG duration;
154  HRESULT hr = IMFSample_GetSampleDuration(sample, &duration);
155  if (FAILED(hr))
156  return 0;
157  return mf_from_mf_time(avctx, duration);
158 }
159 
160 static int mf_enca_output_type_get(AVCodecContext *avctx, IMFMediaType *type)
161 {
162  MFContext *c = avctx->priv_data;
163  HRESULT hr;
164  UINT32 sz;
165 
166  if (avctx->codec_id != AV_CODEC_ID_MP3 && avctx->codec_id != AV_CODEC_ID_AC3) {
167  hr = IMFAttributes_GetBlobSize(type, &MF_MT_USER_DATA, &sz);
168  if (!FAILED(hr) && sz > 0) {
170  if (!avctx->extradata)
171  return AVERROR(ENOMEM);
172  avctx->extradata_size = sz;
173  hr = IMFAttributes_GetBlob(type, &MF_MT_USER_DATA, avctx->extradata, sz, NULL);
174  if (FAILED(hr))
175  return AVERROR_EXTERNAL;
176 
177  if (avctx->codec_id == AV_CODEC_ID_AAC && avctx->extradata_size >= 12) {
178  // Get rid of HEAACWAVEINFO (after wfx field, 12 bytes).
179  avctx->extradata_size = avctx->extradata_size - 12;
180  memmove(avctx->extradata, avctx->extradata + 12, avctx->extradata_size);
181  }
182  }
183  }
184 
185  // I don't know where it's documented that we need this. It happens with the
186  // MS mp3 encoder MFT. The idea for the workaround is taken from NAudio.
187  // (Certainly any lossy codec will have frames much smaller than 1 second.)
188  if (!c->out_info.cbSize && !c->out_stream_provides_samples) {
189  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz);
190  if (!FAILED(hr)) {
191  av_log(avctx, AV_LOG_VERBOSE, "MFT_OUTPUT_STREAM_INFO.cbSize set to 0, "
192  "assuming %d bytes instead.\n", (int)sz);
193  c->out_info.cbSize = sz;
194  }
195  }
196 
197  return 0;
198 }
199 
200 static int mf_encv_output_type_get(AVCodecContext *avctx, IMFMediaType *type)
201 {
202  HRESULT hr;
203  UINT32 sz;
204 
205  hr = IMFAttributes_GetBlobSize(type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz);
206  if (!FAILED(hr) && sz > 0) {
207  uint8_t *extradata = av_mallocz(sz + AV_INPUT_BUFFER_PADDING_SIZE);
208  if (!extradata)
209  return AVERROR(ENOMEM);
210  hr = IMFAttributes_GetBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz, NULL);
211  if (FAILED(hr)) {
212  av_free(extradata);
213  return AVERROR_EXTERNAL;
214  }
215  av_freep(&avctx->extradata);
216  avctx->extradata = extradata;
217  avctx->extradata_size = sz;
218  }
219 
220  return 0;
221 }
222 
224 {
225  MFContext *c = avctx->priv_data;
226  HRESULT hr;
227  IMFMediaType *type;
228  int ret;
229 
230  hr = IMFTransform_GetOutputCurrentType(c->mft, c->out_stream_id, &type);
231  if (FAILED(hr)) {
232  av_log(avctx, AV_LOG_ERROR, "could not get output type\n");
233  return AVERROR_EXTERNAL;
234  }
235 
236  av_log(avctx, AV_LOG_VERBOSE, "final output type:\n");
237  ff_media_type_dump(avctx, type);
238 
239  ret = 0;
240  if (c->is_video) {
241  ret = mf_encv_output_type_get(avctx, type);
242  } else if (c->is_audio) {
243  ret = mf_enca_output_type_get(avctx, type);
244  }
245 
246  if (ret < 0)
247  av_log(avctx, AV_LOG_ERROR, "output type not supported\n");
248 
249  IMFMediaType_Release(type);
250  return ret;
251 }
252 
253 static int mf_sample_to_avpacket(AVCodecContext *avctx, IMFSample *sample, AVPacket *avpkt)
254 {
255  MFContext *c = avctx->priv_data;
256  HRESULT hr;
257  int ret;
258  DWORD len;
259  IMFMediaBuffer *buffer;
260  BYTE *data;
261  UINT64 t;
262  UINT32 t32;
263 
264  hr = IMFSample_GetTotalLength(sample, &len);
265  if (FAILED(hr))
266  return AVERROR_EXTERNAL;
267 
268  if ((ret = ff_get_encode_buffer(avctx, avpkt, len, 0)) < 0)
269  return ret;
270 
271  hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer);
272  if (FAILED(hr))
273  return AVERROR_EXTERNAL;
274 
275  hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
276  if (FAILED(hr)) {
277  IMFMediaBuffer_Release(buffer);
278  return AVERROR_EXTERNAL;
279  }
280 
281  memcpy(avpkt->data, data, len);
282 
283  IMFMediaBuffer_Unlock(buffer);
284  IMFMediaBuffer_Release(buffer);
285 
286  avpkt->pts = avpkt->dts = mf_sample_get_pts(avctx, sample);
287  avpkt->duration = mf_sample_get_duration(avctx, sample);
288 
289  hr = IMFAttributes_GetUINT32(sample, &MFSampleExtension_CleanPoint, &t32);
290  if (c->is_audio || (!FAILED(hr) && t32 != 0))
291  avpkt->flags |= AV_PKT_FLAG_KEY;
292 
293  hr = IMFAttributes_GetUINT64(sample, &MFSampleExtension_DecodeTimestamp, &t);
294  if (!FAILED(hr)) {
295  avpkt->dts = mf_from_mf_time(avctx, t);
296  // At least on Qualcomm's HEVC encoder on SD 835, the output dts
297  // starts from the input pts of the first frame, while the output pts
298  // is shifted forward. Therefore, shift the output values back so that
299  // the output pts matches the input.
300  if (c->reorder_delay == AV_NOPTS_VALUE)
301  c->reorder_delay = avpkt->pts - avpkt->dts;
302  avpkt->dts -= c->reorder_delay;
303  avpkt->pts -= c->reorder_delay;
304  }
305 
306  return 0;
307 }
308 
309 static int mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
310 {
311  MFContext *c = avctx->priv_data;
312  size_t len;
313  size_t bps;
314  IMFSample *sample;
315 
317  len = frame->nb_samples * bps;
318 
319  sample = ff_create_memory_sample(&c->functions, frame->data[0], len,
320  c->in_info.cbAlignment);
321  if (!sample)
322  return AVERROR(ENOMEM);
323 
324  IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->nb_samples));
325 
326  *out_sample = sample;
327  return 0;
328 }
329 
331 {
332  MFContext *c = avctx->priv_data;
333  MFFunctions *func = &c->functions;
334  HRESULT hr;
335 
336  hr = func->MFCreateDXGIDeviceManager(&c->resetToken, &c->dxgiManager);
337  if (FAILED(hr)) {
338  av_log(avctx, AV_LOG_ERROR, "Failed to create DXGI device manager: %s\n", ff_hr_str(hr));
339  return AVERROR_EXTERNAL;
340  }
341 
342  hr = IMFDXGIDeviceManager_ResetDevice(c->dxgiManager, (IUnknown*)c->device_hwctx->device, c->resetToken);
343  if (FAILED(hr)) {
344  av_log(avctx, AV_LOG_ERROR, "Failed to reset device: %s\n", ff_hr_str(hr));
345  return AVERROR_EXTERNAL;
346  }
347 
348  hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)c->dxgiManager);
349  if (FAILED(hr)) {
350  av_log(avctx, AV_LOG_ERROR, "Failed to set D3D manager: %s\n", ff_hr_str(hr));
351  return AVERROR_EXTERNAL;
352  }
353 
354  return 0;
355 }
356 
357 static int process_d3d11_frame(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
358 {
359  MFContext *c = avctx->priv_data;
360  MFFunctions *func = &c->functions;
361  AVHWFramesContext *frames_ctx = NULL;
362  ID3D11Texture2D *d3d11_texture = NULL;
363  IMFSample *sample = NULL;
364  IMFMediaBuffer *buffer = NULL;
365  int subIdx = 0;
366  HRESULT hr;
367 
368  frames_ctx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
369  c->device_hwctx = (AVD3D11VADeviceContext*)frames_ctx->device_ctx->hwctx;
370 
371  if (!c->dxgiManager) {
372  hr = initialize_dxgi_manager(avctx);
373  if (FAILED(hr)) {
374  return AVERROR_EXTERNAL;
375  }
376  }
377 
378  d3d11_texture = (ID3D11Texture2D*)frame->data[0];
379  subIdx = (int)(intptr_t)frame->data[1];
380 
381  if (!d3d11_texture) {
382  av_log(avctx, AV_LOG_ERROR, "D3D11 texture not found\n");
383  return AVERROR(EINVAL);
384  }
385 
386  hr = func->MFCreateSample(&sample);
387  if (FAILED(hr)) {
388  av_log(avctx, AV_LOG_ERROR, "Failed to create MF sample: %s\n", ff_hr_str(hr));
389  return AVERROR_EXTERNAL;
390  }
391 
392  hr = func->MFCreateDXGISurfaceBuffer(&IID_ID3D11Texture2D, (IUnknown*)d3d11_texture, subIdx, 0, &buffer);
393  if (FAILED(hr)) {
394  av_log(avctx, AV_LOG_ERROR, "Failed to create DXGI surface buffer: %s\n", ff_hr_str(hr));
395  IMFSample_Release(sample);
396  return AVERROR_EXTERNAL;
397  }
398 
399  hr = IMFSample_AddBuffer(sample, buffer);
400  if (FAILED(hr)) {
401  av_log(avctx, AV_LOG_ERROR, "Failed to add buffer to sample: %s\n", ff_hr_str(hr));
402  IMFMediaBuffer_Release(buffer);
403  IMFSample_Release(sample);
404  return AVERROR_EXTERNAL;
405  }
406 
407  IMFMediaBuffer_Release(buffer);
408 
409  *out_sample = sample;
410  return 0;
411 }
412 
413 static int process_software_frame(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
414 {
415  MFContext *c = avctx->priv_data;
416  IMFSample *sample = NULL;
417  IMFMediaBuffer *buffer = NULL;
418  BYTE *data = NULL;
419  HRESULT hr;
420  int size, ret;
421 
422  size = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
423  if (size < 0)
424  return size;
425 
426  sample = ff_create_memory_sample(&c->functions, NULL, size,
427  c->in_info.cbAlignment);
428  if (!sample)
429  return AVERROR_EXTERNAL;
430 
431  hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
432  if (FAILED(hr)) {
433  IMFSample_Release(sample);
434  return AVERROR_EXTERNAL;
435  }
436 
437  hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
438  if (FAILED(hr)) {
439  IMFMediaBuffer_Release(buffer);
440  IMFSample_Release(sample);
441  return AVERROR_EXTERNAL;
442  }
443 
444  ret = av_image_copy_to_buffer((uint8_t *)data, size, (void *)frame->data, frame->linesize,
445  avctx->pix_fmt, avctx->width, avctx->height, 1);
446  IMFMediaBuffer_SetCurrentLength(buffer, size);
447  IMFMediaBuffer_Unlock(buffer);
448  IMFMediaBuffer_Release(buffer);
449  if (ret < 0) {
450  IMFSample_Release(sample);
451  return ret;
452  }
453 
454  IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->duration));
455  *out_sample = sample;
456 
457  return 0;
458 }
459 
460 static int mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
461 {
462  IMFSample *sample = NULL;
463  HRESULT hr;
464  int ret;
465 
466  if (frame->format == AV_PIX_FMT_D3D11) {
467  // Handle D3D11 hardware frames
468  ret = process_d3d11_frame(avctx, frame, &sample);
469  if (ret < 0) {
470  return ret;
471  }
472  } else {
473  // Handle software frames
475  if (ret < 0) {
476  return ret;
477  }
478  }
479 
480  // Set sample duration
481  hr = IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->duration));
482  if (FAILED(hr)) {
483  av_log(avctx, AV_LOG_WARNING, "Failed to set sample duration: %s\n", ff_hr_str(hr));
484  }
485 
486  *out_sample = sample;
487  return 0;
488 }
489 
490 static int mf_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
491 {
492  MFContext *c = avctx->priv_data;
493  IMFSample *sample;
494  int ret;
495 
496  if (c->is_audio) {
498  } else {
500  }
501 
502  if (ret < 0)
503  return ret;
504 
505  mf_sample_set_pts(avctx, sample, frame->pts);
506  *out_sample = sample;
507  return 0;
508 }
509 
510 static int mf_send_sample(AVCodecContext *avctx, IMFSample *sample)
511 {
512  MFContext *c = avctx->priv_data;
513  HRESULT hr;
514  int ret;
515 
516  if (sample) {
517  if (c->async_events) {
518  if ((ret = mf_wait_events(avctx)) < 0)
519  return ret;
520  if (!c->async_need_input)
521  return AVERROR(EAGAIN);
522  }
523  if (!c->sample_sent)
524  IMFSample_SetUINT32(sample, &MFSampleExtension_Discontinuity, TRUE);
525  c->sample_sent = 1;
526  hr = IMFTransform_ProcessInput(c->mft, c->in_stream_id, sample, 0);
527  if (hr == MF_E_NOTACCEPTING) {
528  return AVERROR(EAGAIN);
529  } else if (FAILED(hr)) {
530  av_log(avctx, AV_LOG_ERROR, "failed processing input: %s\n", ff_hr_str(hr));
531  return AVERROR_EXTERNAL;
532  }
533  c->async_need_input = 0;
534  } else if (!c->draining) {
535  hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
536  if (FAILED(hr))
537  av_log(avctx, AV_LOG_ERROR, "failed draining: %s\n", ff_hr_str(hr));
538  // Some MFTs (AC3) will send a frame after each drain command (???), so
539  // this is required to make draining actually terminate.
540  c->draining = 1;
541  c->async_need_input = 0;
542  } else {
543  return AVERROR_EOF;
544  }
545  return 0;
546 }
547 
548 static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample)
549 {
550  MFContext *c = avctx->priv_data;
551  HRESULT hr;
552  DWORD st;
553  MFT_OUTPUT_DATA_BUFFER out_buffers;
554  IMFSample *sample;
555  int ret = 0;
556 
557  while (1) {
558  *out_sample = NULL;
559  sample = NULL;
560 
561  if (c->async_events) {
562  if ((ret = mf_wait_events(avctx)) < 0)
563  return ret;
564  if (!c->async_have_output || c->draining_done) {
565  ret = 0;
566  break;
567  }
568  }
569 
570  if (!c->out_stream_provides_samples) {
571  sample = ff_create_memory_sample(&c->functions, NULL,
572  c->out_info.cbSize,
573  c->out_info.cbAlignment);
574  if (!sample)
575  return AVERROR(ENOMEM);
576  }
577 
578  out_buffers = (MFT_OUTPUT_DATA_BUFFER) {
579  .dwStreamID = c->out_stream_id,
580  .pSample = sample,
581  };
582 
583  st = 0;
584  hr = IMFTransform_ProcessOutput(c->mft, 0, 1, &out_buffers, &st);
585 
586  if (out_buffers.pEvents)
587  IMFCollection_Release(out_buffers.pEvents);
588 
589  if (!FAILED(hr)) {
590  *out_sample = out_buffers.pSample;
591  ret = 0;
592  break;
593  }
594 
595  if (out_buffers.pSample)
596  IMFSample_Release(out_buffers.pSample);
597 
598  if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
599  if (c->draining)
600  c->draining_done = 1;
601  ret = 0;
602  } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
603  av_log(avctx, AV_LOG_WARNING, "stream format change\n");
604  ret = mf_choose_output_type(avctx);
605  if (ret == 0) // we don't expect renegotiating the input type
607  if (ret > 0) {
608  ret = mf_setup_context(avctx);
609  if (ret >= 0) {
610  c->async_have_output = 0;
611  continue;
612  }
613  }
614  } else {
615  av_log(avctx, AV_LOG_ERROR, "failed processing output: %s\n", ff_hr_str(hr));
617  }
618 
619  break;
620  }
621 
622  c->async_have_output = 0;
623 
624  if (ret >= 0 && !*out_sample)
625  ret = c->draining_done ? AVERROR_EOF : AVERROR(EAGAIN);
626 
627  return ret;
628 }
629 
630 static int mf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
631 {
632  MFContext *c = avctx->priv_data;
633  IMFSample *sample = NULL;
634  int ret;
635 
636  if (!c->frame->buf[0]) {
637  ret = ff_encode_get_frame(avctx, c->frame);
638  if (ret < 0 && ret != AVERROR_EOF)
639  return ret;
640  }
641 
642  if (c->frame->buf[0]) {
643  ret = mf_avframe_to_sample(avctx, c->frame, &sample);
644  if (ret < 0) {
645  av_frame_unref(c->frame);
646  return ret;
647  }
648  if (c->is_video && c->codec_api) {
649  if (c->frame->pict_type == AV_PICTURE_TYPE_I || !c->sample_sent)
650  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame, FF_VAL_VT_UI4(1));
651  }
652  }
653 
654  if(!c->stream_started)
655  {
656  HRESULT hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
657  if (FAILED(hr)) {
658  av_log(avctx, AV_LOG_ERROR, "could not start streaming (%s)\n", ff_hr_str(hr));
659  return AVERROR(EBADMSG);
660  }
661 
662  hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
663  if (FAILED(hr)) {
664  av_log(avctx, AV_LOG_ERROR, "could not start stream (%s)\n", ff_hr_str(hr));
665  return AVERROR(EBADMSG);
666  }
667 
668  c->stream_started = 1;
669  }
670 
671  ret = mf_send_sample(avctx, sample);
672  if (sample)
673  IMFSample_Release(sample);
674  if (ret != AVERROR(EAGAIN))
675  av_frame_unref(c->frame);
676  if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
677  return ret;
678 
679  ret = mf_receive_sample(avctx, &sample);
680  if (ret < 0)
681  return ret;
682 
683  ret = mf_sample_to_avpacket(avctx, sample, avpkt);
684  IMFSample_Release(sample);
685 
686  return ret;
687 }
688 
689 // Most encoders seem to enumerate supported audio formats on the output types,
690 // at least as far as channel configuration and sample rate is concerned. Pick
691 // the one which seems to match best.
692 static int64_t mf_enca_output_score(AVCodecContext *avctx, IMFMediaType *type)
693 {
694  MFContext *c = avctx->priv_data;
695  HRESULT hr;
696  UINT32 t;
697  GUID tg;
698  int64_t score = 0;
699 
700  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
701  if (!FAILED(hr) && t == avctx->sample_rate)
702  score |= 1LL << 32;
703 
704  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
705  if (!FAILED(hr) && t == avctx->ch_layout.nb_channels)
706  score |= 2LL << 32;
707 
708  hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg);
709  if (!FAILED(hr)) {
710  if (IsEqualGUID(&c->main_subtype, &tg))
711  score |= 4LL << 32;
712  }
713 
714  // Select the bitrate (lowest priority).
715  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t);
716  if (!FAILED(hr)) {
717  int diff = (int)t - avctx->bit_rate / 8;
718  if (diff >= 0) {
719  score |= (1LL << 31) - diff; // prefer lower bitrate
720  } else {
721  score |= (1LL << 30) + diff; // prefer higher bitrate
722  }
723  }
724 
725  hr = IMFAttributes_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &t);
726  if (!FAILED(hr) && t != 0)
727  return -1;
728 
729  return score;
730 }
731 
732 static int mf_enca_output_adjust(AVCodecContext *avctx, IMFMediaType *type)
733 {
734  // (some decoders allow adjusting this freely, but it can also cause failure
735  // to set the output type - so it's commented for being too fragile)
736  //IMFAttributes_SetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, avctx->bit_rate / 8);
737  //IMFAttributes_SetUINT32(type, &MF_MT_AVG_BITRATE, avctx->bit_rate);
738 
739  return 0;
740 }
741 
742 static int64_t mf_enca_input_score(AVCodecContext *avctx, IMFMediaType *type)
743 {
744  HRESULT hr;
745  UINT32 t;
746  int64_t score = 0;
747 
748  enum AVSampleFormat sformat = ff_media_type_to_sample_fmt((IMFAttributes *)type);
749  if (sformat == AV_SAMPLE_FMT_NONE)
750  return -1; // can not use
751 
752  if (sformat == avctx->sample_fmt)
753  score |= 1;
754 
755  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
756  if (!FAILED(hr) && t == avctx->sample_rate)
757  score |= 2;
758 
759  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
760  if (!FAILED(hr) && t == avctx->ch_layout.nb_channels)
761  score |= 4;
762 
763  return score;
764 }
765 
766 static int mf_enca_input_adjust(AVCodecContext *avctx, IMFMediaType *type)
767 {
768  HRESULT hr;
769  UINT32 t;
770 
771  enum AVSampleFormat sformat = ff_media_type_to_sample_fmt((IMFAttributes *)type);
772  if (sformat != avctx->sample_fmt) {
773  av_log(avctx, AV_LOG_ERROR, "unsupported input sample format set\n");
774  return AVERROR(EINVAL);
775  }
776 
777  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t);
778  if (FAILED(hr) || t != avctx->sample_rate) {
779  av_log(avctx, AV_LOG_ERROR, "unsupported input sample rate set\n");
780  return AVERROR(EINVAL);
781  }
782 
783  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t);
784  if (FAILED(hr) || t != avctx->ch_layout.nb_channels) {
785  av_log(avctx, AV_LOG_ERROR, "unsupported input channel number set\n");
786  return AVERROR(EINVAL);
787  }
788 
789  return 0;
790 }
791 
792 static int64_t mf_encv_output_score(AVCodecContext *avctx, IMFMediaType *type)
793 {
794  MFContext *c = avctx->priv_data;
795  GUID tg;
796  HRESULT hr;
797  int score = -1;
798 
799  hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg);
800  if (!FAILED(hr)) {
801  if (IsEqualGUID(&c->main_subtype, &tg))
802  score = 1;
803  }
804 
805  return score;
806 }
807 
808 static int mf_encv_output_adjust(AVCodecContext *avctx, IMFMediaType *type)
809 {
810  MFContext *c = avctx->priv_data;
812 
813  ff_MFSetAttributeSize((IMFAttributes *)type, &MF_MT_FRAME_SIZE, avctx->width, avctx->height);
814  IMFAttributes_SetUINT32(type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
815 
816  if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
817  framerate = avctx->framerate;
818  } else {
819  framerate = av_inv_q(avctx->time_base);
820  }
821 
822  ff_MFSetAttributeRatio((IMFAttributes *)type, &MF_MT_FRAME_RATE, framerate.num, framerate.den);
823 
824  // (MS HEVC supports eAVEncH265VProfile_Main_420_8 only.)
825  if (avctx->codec_id == AV_CODEC_ID_H264) {
827  switch (avctx->profile) {
830  break;
833  break;
834  }
835  IMFAttributes_SetUINT32(type, &MF_MT_MPEG2_PROFILE, profile);
836  }
837 
838  IMFAttributes_SetUINT32(type, &MF_MT_AVG_BITRATE, avctx->bit_rate);
839 
840  // Note that some of the ICodecAPI options must be set before SetOutputType.
841  if (c->codec_api) {
842  if (avctx->bit_rate)
843  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonMeanBitRate, FF_VAL_VT_UI4(avctx->bit_rate));
844 
845  if (c->opt_enc_rc >= 0)
846  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode, FF_VAL_VT_UI4(c->opt_enc_rc));
847 
848  if (c->opt_enc_quality >= 0)
849  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonQuality, FF_VAL_VT_UI4(c->opt_enc_quality));
850 
851  if (avctx->rc_max_rate > 0)
852  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonMaxBitRate, FF_VAL_VT_UI4(avctx->rc_max_rate));
853 
854  if (avctx->gop_size > 0)
855  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncMPVGOPSize, FF_VAL_VT_UI4(avctx->gop_size));
856 
857  if(avctx->rc_buffer_size > 0)
858  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonBufferSize, FF_VAL_VT_UI4(avctx->rc_buffer_size));
859 
860  if(avctx->compression_level >= 0)
861  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonQualityVsSpeed, FF_VAL_VT_UI4(avctx->compression_level));
862 
863  if(avctx->global_quality > 0)
864  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncVideoEncodeQP, FF_VAL_VT_UI4(avctx->global_quality ));
865 
866  // Always set the number of b-frames. Qualcomm's HEVC encoder on SD835
867  // defaults this to 1, and that setting is buggy with many of the
868  // rate control modes. (0 or 2 b-frames works fine with most rate
869  // control modes, but 2 seems buggy with the u_vbr mode.) Setting
870  // "scenario" to "camera_record" sets it in CFR mode (where the default
871  // is VFR), which makes the encoder avoid dropping frames.
872  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncMPVDefaultBPictureCount, FF_VAL_VT_UI4(avctx->max_b_frames));
873  avctx->has_b_frames = avctx->max_b_frames > 0;
874 
875  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable, FF_VAL_VT_BOOL(1));
876 
877  if (c->opt_enc_scenario >= 0)
878  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVScenarioInfo, FF_VAL_VT_UI4(c->opt_enc_scenario));
879 
880  if (avctx->flags & AV_CODEC_FLAG_LOW_DELAY)
881  ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVLowLatencyMode, FF_VAL_VT_UI4(1));
882  }
883 
884  return 0;
885 }
886 
887 static int64_t mf_encv_input_score(AVCodecContext *avctx, IMFMediaType *type)
888 {
889  enum AVPixelFormat pix_fmt = ff_media_type_to_pix_fmt((IMFAttributes *)type);
890 
891  if (avctx->pix_fmt == AV_PIX_FMT_D3D11) {
892  if (pix_fmt != AV_PIX_FMT_NV12) {
893  return -1; // can not use
894  }
895  }
896  else {
897  if (pix_fmt != avctx->pix_fmt)
898  return -1; // can not use
899  }
900 
901  return 0;
902 }
903 
904 static int mf_encv_input_adjust(AVCodecContext *avctx, IMFMediaType *type)
905 {
906  enum AVPixelFormat pix_fmt = ff_media_type_to_pix_fmt((IMFAttributes *)type);
907  if (avctx->pix_fmt == AV_PIX_FMT_D3D11) {
909  av_log(avctx, AV_LOG_ERROR, "unsupported input pixel format set\n");
910  return AVERROR(EINVAL);
911  }
912  } else {
913  if (pix_fmt != avctx->pix_fmt) {
914  av_log(avctx, AV_LOG_ERROR, "unsupported input pixel format set\n");
915  return AVERROR(EINVAL);
916  }
917  }
918 
919  //ff_MFSetAttributeSize((IMFAttributes *)type, &MF_MT_FRAME_SIZE, avctx->width, avctx->height);
920 
921  return 0;
922 }
923 
925 {
926  MFContext *c = avctx->priv_data;
927  HRESULT hr;
928  int ret;
929  IMFMediaType *out_type = NULL;
930  int64_t out_type_score = -1;
931  int out_type_index = -1;
932  int n;
933 
934  av_log(avctx, AV_LOG_VERBOSE, "output types:\n");
935  for (n = 0; ; n++) {
936  IMFMediaType *type;
937  int64_t score = -1;
938 
939  hr = IMFTransform_GetOutputAvailableType(c->mft, c->out_stream_id, n, &type);
940  if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
941  break;
942  if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
943  av_log(avctx, AV_LOG_VERBOSE, "(need to set input type)\n");
944  ret = 0;
945  goto done;
946  }
947  if (FAILED(hr)) {
948  av_log(avctx, AV_LOG_ERROR, "error getting output type: %s\n", ff_hr_str(hr));
950  goto done;
951  }
952 
953  av_log(avctx, AV_LOG_VERBOSE, "output type %d:\n", n);
954  ff_media_type_dump(avctx, type);
955 
956  if (c->is_video) {
957  score = mf_encv_output_score(avctx, type);
958  } else if (c->is_audio) {
959  score = mf_enca_output_score(avctx, type);
960  }
961 
962  if (score > out_type_score) {
963  if (out_type)
964  IMFMediaType_Release(out_type);
965  out_type = type;
966  out_type_score = score;
967  out_type_index = n;
968  IMFMediaType_AddRef(out_type);
969  }
970 
971  IMFMediaType_Release(type);
972  }
973 
974  if (out_type) {
975  av_log(avctx, AV_LOG_VERBOSE, "picking output type %d.\n", out_type_index);
976  } else {
977  hr = c->functions.MFCreateMediaType(&out_type);
978  if (FAILED(hr)) {
979  ret = AVERROR(ENOMEM);
980  goto done;
981  }
982  }
983 
984  ret = 0;
985  if (c->is_video) {
986  ret = mf_encv_output_adjust(avctx, out_type);
987  } else if (c->is_audio) {
988  ret = mf_enca_output_adjust(avctx, out_type);
989  }
990 
991  if (ret >= 0) {
992  av_log(avctx, AV_LOG_VERBOSE, "setting output type:\n");
993  ff_media_type_dump(avctx, out_type);
994 
995  hr = IMFTransform_SetOutputType(c->mft, c->out_stream_id, out_type, 0);
996  if (!FAILED(hr)) {
997  ret = 1;
998  } else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
999  av_log(avctx, AV_LOG_VERBOSE, "rejected - need to set input type\n");
1000  ret = 0;
1001  } else {
1002  av_log(avctx, AV_LOG_ERROR, "could not set output type (%s)\n", ff_hr_str(hr));
1004  }
1005  }
1006 
1007 done:
1008  if (out_type)
1009  IMFMediaType_Release(out_type);
1010  return ret;
1011 }
1012 
1014 {
1015  MFContext *c = avctx->priv_data;
1016  HRESULT hr;
1017  int ret;
1018  IMFMediaType *in_type = NULL;
1019  int64_t in_type_score = -1;
1020  int in_type_index = -1;
1021  int n;
1022 
1023  av_log(avctx, AV_LOG_VERBOSE, "input types:\n");
1024  for (n = 0; ; n++) {
1025  IMFMediaType *type = NULL;
1026  int64_t score = -1;
1027 
1028  hr = IMFTransform_GetInputAvailableType(c->mft, c->in_stream_id, n, &type);
1029  if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL)
1030  break;
1031  if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
1032  av_log(avctx, AV_LOG_VERBOSE, "(need to set output type 1)\n");
1033  ret = 0;
1034  goto done;
1035  }
1036  if (FAILED(hr)) {
1037  av_log(avctx, AV_LOG_ERROR, "error getting input type: %s\n", ff_hr_str(hr));
1039  goto done;
1040  }
1041 
1042  av_log(avctx, AV_LOG_VERBOSE, "input type %d:\n", n);
1043  ff_media_type_dump(avctx, type);
1044 
1045  if (c->is_video) {
1046  score = mf_encv_input_score(avctx, type);
1047  } else if (c->is_audio) {
1048  score = mf_enca_input_score(avctx, type);
1049  }
1050 
1051  if (score > in_type_score) {
1052  if (in_type)
1053  IMFMediaType_Release(in_type);
1054  in_type = type;
1055  in_type_score = score;
1056  in_type_index = n;
1057  IMFMediaType_AddRef(in_type);
1058  }
1059 
1060  IMFMediaType_Release(type);
1061  }
1062 
1063  if (in_type) {
1064  av_log(avctx, AV_LOG_VERBOSE, "picking input type %d.\n", in_type_index);
1065  } else {
1066  // Some buggy MFTs (WMA encoder) fail to return MF_E_TRANSFORM_TYPE_NOT_SET.
1067  av_log(avctx, AV_LOG_VERBOSE, "(need to set output type 2)\n");
1068  ret = 0;
1069  goto done;
1070  }
1071 
1072  ret = 0;
1073  if (c->is_video) {
1074  ret = mf_encv_input_adjust(avctx, in_type);
1075  } else if (c->is_audio) {
1076  ret = mf_enca_input_adjust(avctx, in_type);
1077  }
1078 
1079  if (ret >= 0) {
1080  av_log(avctx, AV_LOG_VERBOSE, "setting input type:\n");
1081  ff_media_type_dump(avctx, in_type);
1082 
1083  hr = IMFTransform_SetInputType(c->mft, c->in_stream_id, in_type, 0);
1084  if (!FAILED(hr)) {
1085  ret = 1;
1086  } else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
1087  av_log(avctx, AV_LOG_VERBOSE, "rejected - need to set output type\n");
1088  ret = 0;
1089  } else {
1090  av_log(avctx, AV_LOG_ERROR, "could not set input type (%s)\n", ff_hr_str(hr));
1092  }
1093  }
1094 
1095 done:
1096  if (in_type)
1097  IMFMediaType_Release(in_type);
1098  return ret;
1099 }
1100 
1102 {
1103  // This follows steps 1-5 on:
1104  // https://msdn.microsoft.com/en-us/library/windows/desktop/aa965264(v=vs.85).aspx
1105  // If every MFT implementer does this correctly, this loop should at worst
1106  // be repeated once.
1107  int need_input = 1, need_output = 1;
1108  int n;
1109  for (n = 0; n < 2 && (need_input || need_output); n++) {
1110  int ret;
1111  ret = mf_choose_input_type(avctx);
1112  if (ret < 0)
1113  return ret;
1114  need_input = ret < 1;
1115  ret = mf_choose_output_type(avctx);
1116  if (ret < 0)
1117  return ret;
1118  need_output = ret < 1;
1119  }
1120  if (need_input || need_output) {
1121  av_log(avctx, AV_LOG_ERROR, "format negotiation failed (%d/%d)\n",
1122  need_input, need_output);
1123  return AVERROR_EXTERNAL;
1124  }
1125  return 0;
1126 }
1127 
1129 {
1130  MFContext *c = avctx->priv_data;
1131  HRESULT hr;
1132  int ret;
1133 
1134  hr = IMFTransform_GetInputStreamInfo(c->mft, c->in_stream_id, &c->in_info);
1135  if (FAILED(hr))
1136  return AVERROR_EXTERNAL;
1137  av_log(avctx, AV_LOG_VERBOSE, "in_info: size=%d, align=%d\n",
1138  (int)c->in_info.cbSize, (int)c->in_info.cbAlignment);
1139 
1140  hr = IMFTransform_GetOutputStreamInfo(c->mft, c->out_stream_id, &c->out_info);
1141  if (FAILED(hr))
1142  return AVERROR_EXTERNAL;
1143  c->out_stream_provides_samples =
1144  (c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
1145  (c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
1146  av_log(avctx, AV_LOG_VERBOSE, "out_info: size=%d, align=%d%s\n",
1147  (int)c->out_info.cbSize, (int)c->out_info.cbAlignment,
1148  c->out_stream_provides_samples ? " (provides samples)" : "");
1149 
1150  if ((ret = mf_output_type_get(avctx)) < 0)
1151  return ret;
1152 
1153  return 0;
1154 }
1155 
1157 {
1158  MFContext *c = avctx->priv_data;
1159  HRESULT hr;
1160  IMFAttributes *attrs;
1161  UINT32 v;
1162  int res = AVERROR_EXTERNAL;
1163 
1164  // For hw encoding we unfortunately need to use async mode, otherwise
1165  // play it safe and avoid it.
1166  if (!(c->is_video && c->opt_enc_hw))
1167  return 0;
1168 
1169  hr = IMFTransform_GetAttributes(c->mft, &attrs);
1170  if (FAILED(hr)) {
1171  av_log(avctx, AV_LOG_ERROR, "error retrieving MFT attributes: %s\n", ff_hr_str(hr));
1172  goto err;
1173  }
1174 
1175  hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v);
1176  if (FAILED(hr)) {
1177  av_log(avctx, AV_LOG_ERROR, "error querying async: %s\n", ff_hr_str(hr));
1178  goto err;
1179  }
1180 
1181  if (!v) {
1182  av_log(avctx, AV_LOG_ERROR, "hardware MFT is not async\n");
1183  goto err;
1184  }
1185 
1186  hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
1187  if (FAILED(hr)) {
1188  av_log(avctx, AV_LOG_ERROR, "could not set async unlock: %s\n", ff_hr_str(hr));
1189  goto err;
1190  }
1191 
1192  hr = IMFTransform_QueryInterface(c->mft, &IID_IMFMediaEventGenerator, (void **)&c->async_events);
1193  if (FAILED(hr)) {
1194  av_log(avctx, AV_LOG_ERROR, "could not get async interface\n");
1195  goto err;
1196  }
1197 
1198  res = 0;
1199 
1200 err:
1201  IMFAttributes_Release(attrs);
1202  return res;
1203 }
1204 
1205 static int mf_create(void *log, MFFunctions *f, IMFTransform **mft,
1206  const AVCodec *codec, int use_hw)
1207 {
1208  int is_audio = codec->type == AVMEDIA_TYPE_AUDIO;
1209  const CLSID *subtype = ff_codec_to_mf_subtype(codec->id);
1210  MFT_REGISTER_TYPE_INFO reg = {0};
1211  GUID category;
1212  int ret;
1213 
1214  *mft = NULL;
1215 
1216  if (!subtype)
1217  return AVERROR(ENOSYS);
1218 
1219  reg.guidSubtype = *subtype;
1220 
1221  if (is_audio) {
1222  reg.guidMajorType = MFMediaType_Audio;
1223  category = MFT_CATEGORY_AUDIO_ENCODER;
1224  } else {
1225  reg.guidMajorType = MFMediaType_Video;
1226  category = MFT_CATEGORY_VIDEO_ENCODER;
1227  }
1228 
1229  if ((ret = ff_instantiate_mf(log, f, category, NULL, &reg, use_hw, mft)) < 0)
1230  return ret;
1231 
1232  return 0;
1233 }
1234 
1236 {
1237  MFContext *c = avctx->priv_data;
1238  HRESULT hr;
1239  int ret;
1240  const CLSID *subtype = ff_codec_to_mf_subtype(avctx->codec_id);
1241  int use_hw = 0;
1242 
1243  c->frame = av_frame_alloc();
1244  if (!c->frame)
1245  return AVERROR(ENOMEM);
1246 
1247  c->is_audio = avctx->codec_type == AVMEDIA_TYPE_AUDIO;
1248  c->is_video = !c->is_audio;
1249  c->reorder_delay = AV_NOPTS_VALUE;
1250 
1251  if (c->is_video && c->opt_enc_hw)
1252  use_hw = 1;
1253 
1254  if (!subtype)
1255  return AVERROR(ENOSYS);
1256 
1257  c->main_subtype = *subtype;
1258 
1259  if ((ret = mf_create(avctx, &c->functions, &c->mft, avctx->codec, use_hw)) < 0)
1260  return ret;
1261 
1262  if ((ret = mf_unlock_async(avctx)) < 0)
1263  return ret;
1264 
1265  hr = IMFTransform_QueryInterface(c->mft, &IID_ICodecAPI, (void **)&c->codec_api);
1266  if (!FAILED(hr))
1267  av_log(avctx, AV_LOG_VERBOSE, "MFT supports ICodecAPI.\n");
1268 
1269 
1270  hr = IMFTransform_GetStreamIDs(c->mft, 1, &c->in_stream_id, 1, &c->out_stream_id);
1271  if (hr == E_NOTIMPL) {
1272  c->in_stream_id = c->out_stream_id = 0;
1273  } else if (FAILED(hr)) {
1274  av_log(avctx, AV_LOG_ERROR, "could not get stream IDs (%s)\n", ff_hr_str(hr));
1275  return AVERROR_EXTERNAL;
1276  }
1277 
1278  if ((ret = mf_negotiate_types(avctx)) < 0)
1279  return ret;
1280 
1281  if ((ret = mf_setup_context(avctx)) < 0)
1282  return ret;
1283 
1284  if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER && c->async_events &&
1285  c->is_video && !avctx->extradata) {
1286  int sleep = 10000, total = 0;
1287  av_log(avctx, AV_LOG_VERBOSE, "Awaiting extradata\n");
1288  while (total < 70*1000) {
1289  // The Qualcomm H264 encoder on SD835 doesn't provide extradata
1290  // immediately, but it becomes available soon after init (without
1291  // any waitable event). In practice, it's available after less
1292  // than 10 ms, but wait for up to 70 ms before giving up.
1293  // Some encoders (Qualcomm's HEVC encoder on SD835, some versions
1294  // of the QSV H264 encoder at least) don't provide extradata this
1295  // way at all, not even after encoding a frame - it's only
1296  // available prepended to frames.
1297  av_usleep(sleep);
1298  total += sleep;
1299  mf_output_type_get(avctx);
1300  if (avctx->extradata)
1301  break;
1302  sleep *= 2;
1303  }
1304  av_log(avctx, AV_LOG_VERBOSE, "%s extradata in %d ms\n",
1305  avctx->extradata ? "Got" : "Didn't get", total / 1000);
1306  }
1307 
1308  return 0;
1309 }
1310 
1311 #if !HAVE_UWP
1312 #define LOAD_MF_FUNCTION(context, func_name) \
1313  context->functions.func_name = (void *)dlsym(context->library, #func_name); \
1314  if (!context->functions.func_name) { \
1315  av_log(context, AV_LOG_ERROR, "DLL mfplat.dll failed to find function "\
1316  #func_name "\n"); \
1317  return AVERROR_UNKNOWN; \
1318  }
1319 #else
1320 // In UWP (which lacks LoadLibrary), just link directly against
1321 // the functions - this requires building with new/complete enough
1322 // import libraries.
1323 #define LOAD_MF_FUNCTION(context, func_name) \
1324  context->functions.func_name = func_name; \
1325  if (!context->functions.func_name) { \
1326  av_log(context, AV_LOG_ERROR, "Failed to find function " #func_name \
1327  "\n"); \
1328  return AVERROR_UNKNOWN; \
1329  }
1330 #endif
1331 
1332 // Windows N editions does not provide MediaFoundation by default.
1333 // So to avoid DLL loading error, MediaFoundation is dynamically loaded except
1334 // on UWP build since LoadLibrary is not available on it.
1336 {
1337  MFContext *c = avctx->priv_data;
1338 
1339 #if !HAVE_UWP
1340  c->library = dlopen("mfplat.dll", 0);
1341  c->d3d_dll = dlopen("D3D11.dll", 0);
1342 
1343  if (!c->library) {
1344  av_log(c, AV_LOG_ERROR, "DLL mfplat.dll failed to open\n");
1345  return AVERROR_UNKNOWN;
1346  }
1347 #endif
1348 
1349  LOAD_MF_FUNCTION(c, MFStartup);
1350  LOAD_MF_FUNCTION(c, MFShutdown);
1351  LOAD_MF_FUNCTION(c, MFCreateAlignedMemoryBuffer);
1352  LOAD_MF_FUNCTION(c, MFCreateSample);
1353  LOAD_MF_FUNCTION(c, MFCreateMediaType);
1354  LOAD_MF_FUNCTION(c, MFCreateDXGISurfaceBuffer);
1355  LOAD_MF_FUNCTION(c, MFCreateDXGIDeviceManager);
1356  // MFTEnumEx is missing in Windows Vista's mfplat.dll.
1357  LOAD_MF_FUNCTION(c, MFTEnumEx);
1358 
1359  return 0;
1360 }
1361 
1362 static int mf_close(AVCodecContext *avctx)
1363 {
1364  MFContext *c = avctx->priv_data;
1365 
1366  if (c->codec_api)
1367  ICodecAPI_Release(c->codec_api);
1368 
1369  if (c->async_events)
1370  IMFMediaEventGenerator_Release(c->async_events);
1371 
1372  if (c->dxgiManager)
1373  IMFDXGIDeviceManager_Release(c->dxgiManager);
1374 
1375 #if !HAVE_UWP
1376  if (c->library)
1377  ff_free_mf(&c->functions, &c->mft);
1378 
1379  dlclose(c->library);
1380  dlclose(c->d3d_dll);
1381  c->library = NULL;
1382 #else
1383  ff_free_mf(&c->functions, &c->mft);
1384 #endif
1385 
1386  av_frame_free(&c->frame);
1387 
1388  av_freep(&avctx->extradata);
1389  avctx->extradata_size = 0;
1390 
1391  return 0;
1392 }
1393 
1394 static av_cold int mf_init(AVCodecContext *avctx)
1395 {
1396  int ret;
1397  if ((ret = mf_load_library(avctx)) == 0) {
1398  if ((ret = mf_init_encoder(avctx)) == 0) {
1399  return 0;
1400  }
1401  }
1402  return ret;
1403 }
1404 
1405 #define OFFSET(x) offsetof(MFContext, x)
1406 
1407 #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, FMTS, CAPS, DEFAULTS) \
1408  static const AVClass ff_ ## NAME ## _mf_encoder_class = { \
1409  .class_name = #NAME "_mf", \
1410  .item_name = av_default_item_name, \
1411  .option = OPTS, \
1412  .version = LIBAVUTIL_VERSION_INT, \
1413  }; \
1414  const FFCodec ff_ ## NAME ## _mf_encoder = { \
1415  .p.priv_class = &ff_ ## NAME ## _mf_encoder_class, \
1416  .p.name = #NAME "_mf", \
1417  CODEC_LONG_NAME(#ID " via MediaFoundation"), \
1418  .p.type = AVMEDIA_TYPE_ ## MEDIATYPE, \
1419  .p.id = AV_CODEC_ID_ ## ID, \
1420  .priv_data_size = sizeof(MFContext), \
1421  .init = mf_init, \
1422  .close = mf_close, \
1423  FF_CODEC_RECEIVE_PACKET_CB(mf_receive_packet), \
1424  FMTS \
1425  CAPS \
1426  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \
1427  .defaults = DEFAULTS, \
1428  };
1429 
1430 #define AFMTS \
1431  CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16),
1432 #define ACAPS \
1433  .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \
1434  AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
1435 
1436 MF_ENCODER(AUDIO, aac, AAC, NULL, AFMTS, ACAPS, NULL);
1437 MF_ENCODER(AUDIO, ac3, AC3, NULL, AFMTS, ACAPS, NULL);
1438 MF_ENCODER(AUDIO, mp3, MP3, NULL, AFMTS, ACAPS, NULL);
1439 
1440 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1441 static const AVOption venc_opts[] = {
1442  {"rate_control", "Select rate control mode", OFFSET(opt_enc_rc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, .unit = "rate_control"},
1443  { "default", "Default mode", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, .unit = "rate_control"},
1444  { "cbr", "CBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_CBR}, 0, 0, VE, .unit = "rate_control"},
1445  { "pc_vbr", "Peak constrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_PeakConstrainedVBR}, 0, 0, VE, .unit = "rate_control"},
1446  { "u_vbr", "Unconstrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_UnconstrainedVBR}, 0, 0, VE, .unit = "rate_control"},
1447  { "quality", "Quality mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_Quality}, 0, 0, VE, .unit = "rate_control" },
1448  // The following rate_control modes require Windows 8.
1449  { "ld_vbr", "Low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_LowDelayVBR}, 0, 0, VE, .unit = "rate_control"},
1450  { "g_vbr", "Global VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalVBR}, 0, 0, VE, .unit = "rate_control" },
1451  { "gld_vbr", "Global low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR}, 0, 0, VE, .unit = "rate_control"},
1452 
1453  {"scenario", "Select usage scenario", OFFSET(opt_enc_scenario), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, .unit = "scenario"},
1454  { "default", "Default scenario", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, .unit = "scenario"},
1455  { "display_remoting", "Display remoting", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_DisplayRemoting}, 0, 0, VE, .unit = "scenario"},
1456  { "video_conference", "Video conference", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_VideoConference}, 0, 0, VE, .unit = "scenario"},
1457  { "archive", "Archive", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_Archive}, 0, 0, VE, .unit = "scenario"},
1458  { "live_streaming", "Live streaming", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_LiveStreaming}, 0, 0, VE, .unit = "scenario"},
1459  { "camera_record", "Camera record", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_CameraRecord}, 0, 0, VE, .unit = "scenario"},
1460  { "display_remoting_with_feature_map", "Display remoting with feature map", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap}, 0, 0, VE, .unit = "scenario"},
1461 
1462  {"quality", "Quality", OFFSET(opt_enc_quality), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE},
1463  {"hw_encoding", "Force hardware encoding", OFFSET(opt_enc_hw), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE},
1464  {NULL}
1465 };
1466 
1467 static const FFCodecDefault defaults[] = {
1468  { "g", "0" },
1469  { NULL },
1470 };
1471 
1472 #define VFMTS \
1473  CODEC_PIXFMTS(AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_D3D11),
1474 #define VCAPS \
1475  .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \
1476  AV_CODEC_CAP_DR1,
1477 
1478 MF_ENCODER(VIDEO, h264, H264, venc_opts, VFMTS, VCAPS, defaults);
1479 MF_ENCODER(VIDEO, hevc, HEVC, venc_opts, VFMTS, VCAPS, defaults);
1480 MF_ENCODER(VIDEO, av1, AV1, venc_opts, VFMTS, VCAPS, defaults);
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:68
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
MFContext::resetToken
int resetToken
Definition: mfenc.c:44
AVCodec
AVCodec.
Definition: codec.h:172
process_d3d11_frame
static int process_d3d11_frame(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
Definition: mfenc.c:357
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
ff_hr_str
#define ff_hr_str(hr)
Definition: mf_utils.h:169
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
VCAPS
#define VCAPS
Definition: mfenc.c:1474
AV_CODEC_ID_AC3
@ AV_CODEC_ID_AC3
Definition: codec_id.h:462
FF_VAL_VT_UI4
#define FF_VAL_VT_UI4(v)
Definition: mf_utils.h:174
AVERROR
Filter the word โ€œframeโ€ indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
AVCodecContext::sample_rate
int sample_rate
samples per second
Definition: avcodec.h:1024
venc_opts
static const AVOption venc_opts[]
Definition: mfenc.c:1441
mf_choose_input_type
static int mf_choose_input_type(AVCodecContext *avctx)
Definition: mfenc.c:1013
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
LOAD_MF_FUNCTION
#define LOAD_MF_FUNCTION(context, func_name)
Definition: mfenc.c:1312
AV_PROFILE_H264_MAIN
#define AV_PROFILE_H264_MAIN
Definition: defs.h:112
int64_t
long long int64_t
Definition: coverity.c:34
normalize.log
log
Definition: normalize.py:21
ff_codec_to_mf_subtype
const CLSID * ff_codec_to_mf_subtype(enum AVCodecID codec)
Definition: mf_utils.c:508
mf_enca_output_score
static int64_t mf_enca_output_score(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:692
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
MFContext::opt_enc_hw
int opt_enc_hw
Definition: mfenc.c:66
MFContext::av_class
AVClass * av_class
Definition: mfenc.c:39
mf_receive_sample
static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample)
Definition: mfenc.c:548
MF_ENCODER
#define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, FMTS, CAPS, DEFAULTS)
Definition: mfenc.c:1407
mf_enca_output_type_get
static int mf_enca_output_type_get(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:160
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:558
MFContext::sample_sent
int sample_sent
Definition: mfenc.c:57
ff_eAVEncCommonRateControlMode_Quality
@ ff_eAVEncCommonRateControlMode_Quality
Definition: mf_utils.h:131
ff_eAVEncCommonRateControlMode_CBR
@ ff_eAVEncCommonRateControlMode_CBR
Definition: mf_utils.h:128
AVOption
AVOption.
Definition: opt.h:429
encode.h
data
const char data[16]
Definition: mxf.c:149
mf_encv_output_score
static int64_t mf_encv_output_score(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:792
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
category
category
Definition: openal-dec.c:249
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:576
MFContext::draining_done
int draining_done
Definition: mfenc.c:56
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:329
ff_MFSetAttributeSize
HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 uw, UINT32 uh)
Definition: mf_utils.c:40
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:613
MFContext::functions
MFFunctions functions
Definition: mfenc.c:46
ff_eAVEncH264VProfile_High
@ ff_eAVEncH264VProfile_High
Definition: mf_utils.h:165
AV_CODEC_FLAG_GLOBAL_HEADER
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: avcodec.h:318
AVCodecContext::framerate
AVRational framerate
Definition: avcodec.h:551
MFContext::out_stream_id
DWORD out_stream_id
Definition: mfenc.c:52
MFContext::async_marker
int async_marker
Definition: mfenc.c:59
FFCodecDefault
Definition: codec_internal.h:96
AVCodecContext::codec
const struct AVCodec * codec
Definition: avcodec.h:440
AVCodecContext::ch_layout
AVChannelLayout ch_layout
Audio channel layout.
Definition: avcodec.h:1039
ff_media_type_to_sample_fmt
enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type)
Definition: mf_utils.c:114
MFContext::async_need_input
int async_need_input
Definition: mfenc.c:59
OFFSET
#define OFFSET(x)
Definition: mfenc.c:1405
mf_receive_packet
static int mf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Definition: mfenc.c:630
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:488
MFContext::is_audio
int is_audio
Definition: mfenc.c:48
mf_utils.h
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
AV_CODEC_FLAG_LOW_DELAY
#define AV_CODEC_FLAG_LOW_DELAY
Force low delay.
Definition: avcodec.h:314
VFMTS
#define VFMTS
Definition: mfenc.c:1472
pts
static int64_t pts
Definition: transcode_aac.c:644
AV_CODEC_ID_MP3
@ AV_CODEC_ID_MP3
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:460
ff_eAVEncCommonRateControlMode_GlobalVBR
@ ff_eAVEncCommonRateControlMode_GlobalVBR
Definition: mf_utils.h:133
AVRational::num
int num
Numerator.
Definition: rational.h:59
ff_instantiate_mf
int ff_instantiate_mf(void *log, MFFunctions *f, GUID category, MFT_REGISTER_TYPE_INFO *in_type, MFT_REGISTER_TYPE_INFO *out_type, int use_hw, IMFTransform **res)
Definition: mf_utils.c:552
ff_free_mf
void ff_free_mf(MFFunctions *f, IMFTransform **mft)
Definition: mf_utils.c:645
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
mf_setup_context
static int mf_setup_context(AVCodecContext *avctx)
Definition: mfenc.c:1128
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:100
duration
int64_t duration
Definition: movenc.c:65
mf_avframe_to_sample
static int mf_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
Definition: mfenc.c:490
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:515
AVCodecContext::has_b_frames
int has_b_frames
Size of the frame reordering buffer in the decoder.
Definition: avcodec.h:697
MFContext::opt_enc_rc
int opt_enc_rc
Definition: mfenc.c:63
AVCodecContext::global_quality
int global_quality
Global quality for codecs which cannot change it per frame.
Definition: avcodec.h:1217
MFContext::reorder_delay
int64_t reorder_delay
Definition: mfenc.c:60
mf_encv_output_adjust
static int mf_encv_output_adjust(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:808
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:201
MFContext::opt_enc_scenario
int opt_enc_scenario
Definition: mfenc.c:65
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
MFContext::codec_api
ICodecAPI * codec_api
Definition: mfenc.c:61
MFContext::in_info
MFT_INPUT_STREAM_INFO in_info
Definition: mfenc.c:53
MFContext::out_stream_provides_samples
int out_stream_provides_samples
Definition: mfenc.c:55
AVCodecContext::rc_max_rate
int64_t rc_max_rate
maximum bitrate
Definition: avcodec.h:1270
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:441
MFContext::library
HMODULE library
Definition: mfenc.c:40
MFContext::frame
AVFrame * frame
Definition: mfenc.c:47
if
if(ret)
Definition: filter_design.txt:179
ff_eAVScenarioInfo_LiveStreaming
@ ff_eAVScenarioInfo_LiveStreaming
Definition: mf_utils.h:142
AVCodecContext::rc_buffer_size
int rc_buffer_size
decoder bitstream buffer size
Definition: avcodec.h:1255
ff_METransformMarker
@ ff_METransformMarker
Definition: mf_utils.h:155
ff_MFSetAttributeRatio
#define ff_MFSetAttributeRatio
Definition: mf_utils.c:47
framerate
float framerate
Definition: av1_levels.c:29
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
NULL
#define NULL
Definition: coverity.c:32
ff_eAVEncCommonRateControlMode_PeakConstrainedVBR
@ ff_eAVEncCommonRateControlMode_PeakConstrainedVBR
Definition: mf_utils.h:129
AVCodec::type
enum AVMediaType type
Definition: codec.h:185
mf_enca_input_score
static int64_t mf_enca_input_score(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:742
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
MF_INVALID_TIME
#define MF_INVALID_TIME
Definition: mfenc.c:75
AVCodecContext::bit_rate
int64_t bit_rate
the average bitrate
Definition: avcodec.h:481
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:278
mf_enca_input_adjust
static int mf_enca_input_adjust(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:766
time.h
MFContext::dxgiManager
IMFDXGIDeviceManager * dxgiManager
Definition: mfenc.c:43
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
initialize_dxgi_manager
static int initialize_dxgi_manager(AVCodecContext *avctx)
Definition: mfenc.c:330
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:461
ff_METransformDrainComplete
@ ff_METransformDrainComplete
Definition: mf_utils.h:154
AVCodecContext::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avcodec.h:535
ff_media_type_to_pix_fmt
enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type)
Definition: mf_utils.c:158
MFFunctions
Definition: mf_utils.h:48
f
f
Definition: af_crystalizer.c:122
ff_eAVScenarioInfo_Archive
@ ff_eAVScenarioInfo_Archive
Definition: mf_utils.h:141
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1005
codec_internal.h
bps
unsigned bps
Definition: movenc.c:1958
AVCodecContext::sample_fmt
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1031
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
sample
#define sample
Definition: flacdsp_template.c:44
MFContext::is_video
int is_video
Definition: mfenc.c:48
size
int size
Definition: twinvq_data.h:10344
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:247
MFContext::stream_started
int stream_started
Definition: mfenc.c:58
ff_eAVEncH264VProfile_Base
@ ff_eAVEncH264VProfile_Base
Definition: mf_utils.h:163
ff_eAVScenarioInfo_DisplayRemoting
@ ff_eAVScenarioInfo_DisplayRemoting
Definition: mf_utils.h:139
ACAPS
#define ACAPS
Definition: mfenc.c:1432
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:166
MFContext::d3d_context
ID3D11DeviceContext * d3d_context
Definition: mfenc.c:42
MFContext::opt_enc_quality
int opt_enc_quality
Definition: mfenc.c:64
MFContext::async_events
IMFMediaEventGenerator * async_events
Definition: mfenc.c:51
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:557
ff_eAVEncCommonRateControlMode_UnconstrainedVBR
@ ff_eAVEncCommonRateControlMode_UnconstrainedVBR
Definition: mf_utils.h:130
MF_TIMEBASE
#define MF_TIMEBASE
Definition: mfenc.c:73
av_image_get_buffer_size
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
Return the size in bytes of the amount of data required to store an image with the given parameters.
Definition: imgutils.c:466
ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap
@ ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap
Definition: mf_utils.h:144
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:564
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:336
process_software_frame
static int process_software_frame(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
Definition: mfenc.c:413
AVCodec::id
enum AVCodecID id
Definition: codec.h:186
mf_get_tb
static AVRational mf_get_tb(AVCodecContext *avctx)
Definition: mfenc.c:116
mf_load_library
static int mf_load_library(AVCodecContext *avctx)
Definition: mfenc.c:1335
MFContext::d3d_dll
HMODULE d3d_dll
Definition: mfenc.c:41
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:551
mf_send_sample
static int mf_send_sample(AVCodecContext *avctx, IMFSample *sample)
Definition: mfenc.c:510
MFContext::in_stream_id
DWORD in_stream_id
Definition: mfenc.c:52
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:108
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:514
MFContext::async_have_output
int async_have_output
Definition: mfenc.c:59
AVD3D11VADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_d3d11va.h:45
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
VE
#define VE
Definition: mfenc.c:1440
MFContext::out_info
MFT_OUTPUT_STREAM_INFO out_info
Definition: mfenc.c:54
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:496
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
len
int len
Definition: vorbis_enc_data.h:426
profile
int profile
Definition: mxfenc.c:2278
MFContext
Definition: mfenc.c:38
AVCodecContext::height
int height
Definition: avcodec.h:592
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:631
mf_negotiate_types
static int mf_negotiate_types(AVCodecContext *avctx)
Definition: mfenc.c:1101
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
ff_METransformNeedInput
@ ff_METransformNeedInput
Definition: mf_utils.h:152
ff_METransformHaveOutput
@ ff_METransformHaveOutput
Definition: mf_utils.h:153
mf_enca_output_adjust
static int mf_enca_output_adjust(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:732
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:137
mf_sample_set_pts
static void mf_sample_set_pts(AVCodecContext *avctx, IMFSample *sample, int64_t av_pts)
Definition: mfenc.c:130
mf_to_mf_time
static LONGLONG mf_to_mf_time(AVCodecContext *avctx, int64_t av_pts)
Definition: mfenc.c:123
mf_create
static int mf_create(void *log, MFFunctions *f, IMFTransform **mft, const AVCodec *codec, int use_hw)
Definition: mfenc.c:1205
mf_from_mf_time
static int64_t mf_from_mf_time(AVCodecContext *avctx, LONGLONG stime)
Definition: mfenc.c:137
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
mf_v_avframe_to_sample
static int mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
Definition: mfenc.c:460
AVCodecContext
main external API structure.
Definition: avcodec.h:431
AV_PROFILE_H264_HIGH
#define AV_PROFILE_H264_HIGH
Definition: defs.h:114
mf_init
static av_cold int mf_init(AVCodecContext *avctx)
Definition: mfenc.c:1394
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ff_get_encode_buffer
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition: encode.c:104
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1618
mf_init_encoder
static int mf_init_encoder(AVCodecContext *avctx)
Definition: mfenc.c:1235
mf_close
static int mf_close(AVCodecContext *avctx)
Definition: mfenc.c:1362
mf_encv_input_adjust
static int mf_encv_input_adjust(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:904
MFContext::device_hwctx
AVD3D11VADeviceContext * device_hwctx
Definition: mfenc.c:67
MFContext::draining
int draining
Definition: mfenc.c:56
ff_eAVScenarioInfo_CameraRecord
@ ff_eAVScenarioInfo_CameraRecord
Definition: mf_utils.h:143
AVCodecContext::codec_type
enum AVMediaType codec_type
Definition: avcodec.h:439
FF_VAL_VT_BOOL
#define FF_VAL_VT_BOOL(v)
Definition: mf_utils.h:175
mem.h
AVCodecContext::max_b_frames
int max_b_frames
maximum number of B-frames between non-B-frames Note: The output will be delayed by max_b_frames+1 re...
Definition: avcodec.h:769
ff_encode_get_frame
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
Definition: encode.c:203
mf_choose_output_type
static int mf_choose_output_type(AVCodecContext *avctx)
Definition: mfenc.c:924
ff_eAVScenarioInfo_VideoConference
@ ff_eAVScenarioInfo_VideoConference
Definition: mf_utils.h:140
AFMTS
#define AFMTS
Definition: mfenc.c:1430
ff_media_type_dump
void ff_media_type_dump(void *log, IMFMediaType *type)
Definition: mf_utils.c:503
defaults
static const FFCodecDefault defaults[]
Definition: mfenc.c:1467
mf_encv_input_score
static int64_t mf_encv_input_score(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:887
mf_output_type_get
static int mf_output_type_get(AVCodecContext *avctx)
Definition: mfenc.c:223
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
av_image_copy_to_buffer
int av_image_copy_to_buffer(uint8_t *dst, int dst_size, const uint8_t *const src_data[4], const int src_linesize[4], enum AVPixelFormat pix_fmt, int width, int height, int align)
Copy image data from an image into a buffer.
Definition: imgutils.c:501
AVPacket
This structure stores compressed data.
Definition: packet.h:535
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:458
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
mf_sample_to_avpacket
static int mf_sample_to_avpacket(AVCodecContext *avctx, IMFSample *sample, AVPacket *avpkt)
Definition: mfenc.c:253
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:592
imgutils.h
MFContext::mft
IMFTransform * mft
Definition: mfenc.c:50
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
mf_unlock_async
static int mf_unlock_async(AVCodecContext *avctx)
Definition: mfenc.c:1156
mf_a_avframe_to_sample
static int mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame, IMFSample **out_sample)
Definition: mfenc.c:309
mf_sample_get_duration
static int64_t mf_sample_get_duration(AVCodecContext *avctx, IMFSample *sample)
Definition: mfenc.c:151
ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR
@ ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR
Definition: mf_utils.h:134
mf_wait_events
static int mf_wait_events(AVCodecContext *avctx)
Definition: mfenc.c:77
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
hwcontext_d3d11va.h
ff_eAVEncH264VProfile_Main
@ ff_eAVEncH264VProfile_Main
Definition: mf_utils.h:164
mf_sample_get_pts
static int64_t mf_sample_get_pts(AVCodecContext *avctx, IMFSample *sample)
Definition: mfenc.c:142
MFContext::main_subtype
GUID main_subtype
Definition: mfenc.c:49
ff_eAVEncCommonRateControlMode_LowDelayVBR
@ ff_eAVEncCommonRateControlMode_LowDelayVBR
Definition: mf_utils.h:132
w32dlfcn.h
mf_encv_output_type_get
static int mf_encv_output_type_get(AVCodecContext *avctx, IMFMediaType *type)
Definition: mfenc.c:200
AVCodecContext::compression_level
int compression_level
Definition: avcodec.h:1223
ff_create_memory_sample
IMFSample * ff_create_memory_sample(MFFunctions *f, void *fill_data, size_t size, size_t align)
Definition: mf_utils.c:76