FFmpeg
Loading...
Searching...
No Matches
vf_amf_common.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#include "vf_amf_common.h"
20
21#include "libavutil/avassert.h"
22#include "avfilter.h"
23#include "avfilter_internal.h"
24#include "filters.h"
25#include "formats.h"
26#include "libavutil/mem.h"
27#include "libavutil/imgutils.h"
28#include "libavutil/pixdesc.h"
29#include "libavutil/time.h"
30
31#include "AMF/components/VideoDecoderUVD.h"
34#include "scale_eval.h"
35
36#if CONFIG_DXVA2
37#include <d3d9.h>
38#endif
39
40#if CONFIG_D3D11VA
41#include <d3d11.h>
43#endif
44
46{
47 AMFFilterContext *ctx = avctx->priv;
48
49 if (!strcmp(ctx->format_str, "same")) {
50 ctx->format = AV_PIX_FMT_NONE;
51 } else {
52 ctx->format = av_get_pix_fmt(ctx->format_str);
53 if (ctx->format == AV_PIX_FMT_NONE) {
54 av_log(avctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", ctx->format_str);
55 return AVERROR(EINVAL);
56 }
57 }
58 ctx->format_opt = ctx->format;
59 ctx->shader_input = 1;
60
61 return 0;
62}
63
65{
66 AMFFilterContext *ctx = avctx->priv;
67
68 if (ctx->component) {
69 ctx->component->pVtbl->Terminate(ctx->component);
70 ctx->component->pVtbl->Release(ctx->component);
71 ctx->component = NULL;
72 }
73
74 if (ctx->pre_converter) {
75 ctx->pre_converter->pVtbl->Terminate(ctx->pre_converter);
76 ctx->pre_converter->pVtbl->Release(ctx->pre_converter);
77 ctx->pre_converter = NULL;
78 }
79
80 if (ctx->pending) {
81 AVFrame *props;
82 while (av_fifo_read(ctx->pending, &props, 1) >= 0)
83 av_frame_free(&props);
84 av_fifo_freep2(&ctx->pending);
85 }
86
87 if (ctx->master_display)
88 av_freep(&ctx->master_display);
89
90 if (ctx->light_meta)
91 av_freep(&ctx->light_meta);
92
93 av_buffer_unref(&ctx->amf_device_ref);
94 av_buffer_unref(&ctx->hwdevice_ref);
95 av_buffer_unref(&ctx->hwframes_in_ref);
96 av_buffer_unref(&ctx->hwframes_out_ref);
97}
98
99static int amf_queue_props(AVFilterContext *avctx, const AVFrame *in)
100{
101 AMFFilterContext *ctx = avctx->priv;
102 AVFrame *props = av_frame_alloc();
103 int ret;
104
105 if (!props)
106 return AVERROR(ENOMEM);
107 props->width = in->width;
108 props->height = in->height;
109 ret = av_frame_copy_props(props, in);
110 if (ret >= 0)
111 ret = av_fifo_write(ctx->pending, &props, 1);
112 if (ret < 0)
113 av_frame_free(&props);
114 return ret;
115}
116
117static int amf_receive_surface(AVFilterContext *avctx, AMFComponent *component, AMFSurface **surface)
118{
119 AMFGuid guid = IID_AMFSurface();
120 AMFData *data = NULL;
121 AMF_RESULT res;
122
123 *surface = NULL;
124 res = component->pVtbl->QueryOutput(component, &data);
125 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK || res == AMF_REPEAT || res == AMF_EOF,
126 AVERROR_UNKNOWN, "QueryOutput() failed with error %d\n", res);
127 if (!data)
128 return res == AMF_EOF ? AVERROR_EOF : 0;
129
130 res = data->pVtbl->QueryInterface(data, &guid, (void**)surface);
131 data->pVtbl->Release(data);
132 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface(IID_AMFSurface) failed with error %d\n", res);
133 return 1;
134}
135
137{
138 AMFFilterContext *ctx = avctx->priv;
139 AVFilterLink *outlink = avctx->outputs[0];
140 AMFSurface *surface;
141 AVFrame *props, *out;
142 enum AVColorSpace out_colorspace;
143 enum AVColorRange out_color_range;
144 int64_t pts;
145 int ret, count = 0;
146
147 while ((ret = amf_receive_surface(avctx, ctx->component, &surface)) > 0) {
148 pts = surface->pVtbl->GetPts(surface);
149 out = amf_amfsurface_to_avframe(avctx, surface);
150 if (!out)
151 return AVERROR(ENOMEM);
152
153 if (ctx->outputs_per_input > 1) {
154 while (av_fifo_can_read(ctx->pending) > 1) {
155 av_fifo_peek(ctx->pending, &props, 1, 1);
156 if (props->pts > pts)
157 break;
158 av_fifo_read(ctx->pending, &props, 1);
159 av_frame_free(&props);
160 }
161 props = NULL;
162 if (av_fifo_can_read(ctx->pending))
163 av_fifo_peek(ctx->pending, &props, 1, 0);
164 ret = props ? av_frame_copy_props(out, props) : 0;
165 } else {
166 props = NULL;
167 av_fifo_read(ctx->pending, &props, 1);
168 ret = props ? av_frame_copy_props(out, props) : 0;
169 av_frame_free(&props);
170 }
171 if (ret < 0) {
173 return ret;
174 }
175 out->pts = pts;
176 if (ctx->outputs_per_input > 1)
177 out->duration /= ctx->outputs_per_input;
178
179 out_colorspace = AVCOL_SPC_UNSPECIFIED;
180
181 if (ctx->color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN) {
182 switch(ctx->color_profile) {
183 case AMF_VIDEO_CONVERTER_COLOR_PROFILE_601:
184 out_colorspace = AVCOL_SPC_SMPTE170M;
185 break;
186 case AMF_VIDEO_CONVERTER_COLOR_PROFILE_709:
187 out_colorspace = AVCOL_SPC_BT709;
188 break;
189 case AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020:
190 out_colorspace = AVCOL_SPC_BT2020_NCL;
191 break;
192 case AMF_VIDEO_CONVERTER_COLOR_PROFILE_JPEG:
193 out_colorspace = AVCOL_SPC_RGB;
194 break;
195 default:
196 out_colorspace = AVCOL_SPC_UNSPECIFIED;
197 break;
198 }
199 out->colorspace = out_colorspace;
200 }
201
202 out_color_range = AVCOL_RANGE_UNSPECIFIED;
203 if (ctx->out_color_range == AMF_COLOR_RANGE_FULL)
204 out_color_range = AVCOL_RANGE_JPEG;
205 else if (ctx->out_color_range == AMF_COLOR_RANGE_STUDIO)
206 out_color_range = AVCOL_RANGE_MPEG;
207
208 if (ctx->out_color_range != AMF_COLOR_RANGE_UNDEFINED)
209 out->color_range = out_color_range;
210
211 if (ctx->out_primaries != AMF_COLOR_PRIMARIES_UNDEFINED)
212 out->color_primaries = ctx->out_primaries;
213
214 if (ctx->out_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED)
215 out->color_trc = ctx->out_trc;
216
217 if (ctx->pre_converter)
218 out->colorspace = AVCOL_SPC_RGB;
219
220 ret = ff_filter_frame(outlink, out);
221 if (ret < 0)
222 return ret;
223 count++;
224 }
225
226 return ret < 0 ? ret : count;
227}
228
229static int amf_submit_surface(AVFilterContext *avctx, AMFComponent *component, AMFSurface *surface,
230 int (*deliver)(AVFilterContext *avctx))
231{
232 AMF_RESULT res;
233 int ret = 0;
234
235 while ((res = component->pVtbl->SubmitInput(component, (AMFData*)surface)) == AMF_INPUT_FULL) {
236 ret = deliver(avctx);
237 if (ret < 0)
238 break;
239 if (!ret)
240 av_usleep(100);
241 }
242 surface->pVtbl->Release(surface);
243 if (ret < 0)
244 return ret;
245 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
246 return 0;
247}
248
250{
251 AMFFilterContext *ctx = avctx->priv;
252 AMFSurface *surface;
253 int ret, count = 0;
254
255 while ((ret = amf_receive_surface(avctx, ctx->pre_converter, &surface)) > 0) {
256 ret = amf_submit_surface(avctx, ctx->component, surface, amf_deliver_output);
257 if (ret < 0)
258 return ret;
259 count++;
260 }
261
262 return ret < 0 ? ret : count;
263}
264
265static int amf_drain_component(AVFilterContext *avctx, AMFComponent *component,
266 int (*deliver)(AVFilterContext *avctx))
267{
268 AMF_RESULT res;
269 int ret;
270
271 while ((res = component->pVtbl->Drain(component)) == AMF_INPUT_FULL) {
272 ret = deliver(avctx);
273 if (ret < 0)
274 return ret;
275 if (!ret)
276 av_usleep(100);
277 }
278 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res);
279
280 while ((ret = deliver(avctx)) >= 0)
281 if (!ret)
282 av_usleep(100);
283
284 return ret == AVERROR_EOF ? 0 : ret;
285}
286
288{
289 AVFilterContext *avctx = inlink->dst;
290 AMFFilterContext *ctx = avctx->priv;
291 AMFSurface *surface_in;
292 int ret;
293
294 if (!ctx->component) {
295 av_frame_free(&in);
296 return AVERROR(EINVAL);
297 }
298
299 ret = amf_avframe_to_amfsurface(avctx, in, &surface_in);
300 if (ret < 0)
301 goto fail;
302
303 ret = amf_queue_props(avctx, in);
304 if (ret < 0) {
305 surface_in->pVtbl->Release(surface_in);
306 goto fail;
307 }
308
309 if (ctx->pre_converter) {
310 ret = amf_submit_surface(avctx, ctx->pre_converter, surface_in, amf_forward_converted);
311 if (ret >= 0)
312 ret = amf_forward_converted(avctx);
313 } else
314 ret = amf_submit_surface(avctx, ctx->component, surface_in, amf_deliver_output);
315 if (ret >= 0)
316 ret = amf_deliver_output(avctx);
317fail:
318 av_frame_free(&in);
319 return ret;
320}
321
323{
324 AMFFilterContext *ctx = avctx->priv;
325 int ret = 0;
326
327 if (!av_fifo_can_read(ctx->pending))
328 return 0;
329 if (ctx->pre_converter)
330 ret = amf_forward_converted(avctx);
331 if (ret >= 0)
332 ret = amf_deliver_output(avctx);
333 return ret;
334}
335
337{
338 AMFFilterContext *ctx = avctx->priv;
339 AVFilterLink *inlink = avctx->inputs[0];
340 AVFilterLink *outlink = avctx->outputs[0];
341 AVFrame *in = NULL;
342 int ret;
343
344 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
345
346 if (!ctx->eof) {
347 if (ctx->component) {
348 ret = amf_poll_output(avctx);
349 if (ret < 0)
350 return ret;
351 }
352 ret = ff_inlink_consume_frame(inlink, &in);
353 if (ret < 0)
354 return ret;
355 if (in) {
356 ret = amf_filter_filter_frame(inlink, in);
357 if (ret < 0)
358 return ret;
359 } else if (ff_inlink_acknowledge_status(inlink, &ctx->status, &ctx->status_pts))
360 ctx->eof = 1;
361 }
362
363 if (ctx->eof) {
364 if (ctx->component && !ctx->drained) {
365 ctx->drained = 1;
366 if (ctx->pre_converter) {
367 ret = amf_drain_component(avctx, ctx->pre_converter, amf_forward_converted);
368 if (ret < 0)
369 return ret;
370 }
371 ret = amf_drain_component(avctx, ctx->component, amf_deliver_output);
372 if (ret < 0)
373 return ret;
374 }
375 ff_outlink_set_status(outlink, ctx->status, ctx->status_pts);
376 return 0;
377 }
378
379 FF_FILTER_FORWARD_WANTED(outlink, inlink);
380
381 return FFERROR_NOT_READY;
382}
383
385 const enum AVPixelFormat *input_pix_fmts)
386{
387 int err;
388 AVFilterFormats *input_formats;
389 AVFilterFormats *output_formats;
390 static const enum AVPixelFormat output_pix_fmts[] = {
393 };
394
395 //in case if hw_device_ctx is set to DXVA2 we change order of pixel formats to set DXVA2 be chosen by default
396 //The order is ignored if hw_frames_ctx is not NULL on the config_output stage
397 if (avctx->hw_device_ctx) {
399
400 switch (device_ctx->type) {
401 #if CONFIG_D3D11VA
403 {
404 static const enum AVPixelFormat pix_fmts_d3d11[] = {
407 };
408 input_pix_fmts = pix_fmts_d3d11;
409 }
410 break;
411 #endif
412 #if CONFIG_DXVA2
414 {
415 static const enum AVPixelFormat pix_fmts_dxva2[] = {
418 };
419 input_pix_fmts = pix_fmts_dxva2;
420 }
421 break;
422 #endif
424 break;
425 default:
426 {
427 av_log(avctx, AV_LOG_ERROR, "Unsupported device : %s\n", av_hwdevice_get_type_name(device_ctx->type));
428 return AVERROR(EINVAL);
429 }
430 break;
431 }
432 }
433
434 input_formats = ff_make_pixel_format_list(input_pix_fmts);
435 if (!input_formats) {
436 return AVERROR(ENOMEM);
437 }
438 output_formats = ff_make_pixel_format_list(output_pix_fmts);
439 if (!output_formats) {
440 ff_formats_unref(&input_formats);
441 return AVERROR(ENOMEM);
442 }
443
444 if ((err = ff_formats_ref(input_formats, &avctx->inputs[0]->outcfg.formats)) < 0) {
445 ff_formats_unref(&output_formats);
446 return err;
447 }
448
449 return ff_formats_ref(output_formats, &avctx->outputs[0]->incfg.formats);
450}
451
453 AMFSurface* surface)
454{
455 AMFPlane *plane;
456 uint8_t *dst_data[4];
457 int dst_linesize[4];
458 int planes;
459 int i;
460
461 planes = (int)surface->pVtbl->GetPlanesCount(surface);
462 av_assert0(planes < FF_ARRAY_ELEMS(dst_data));
463
464 for (i = 0; i < planes; i++) {
465 plane = surface->pVtbl->GetPlaneAt(surface, i);
466 dst_data[i] = plane->pVtbl->GetNative(plane);
467 dst_linesize[i] = plane->pVtbl->GetHPitch(plane);
468 }
469 av_image_copy(dst_data, dst_linesize,
470 (const uint8_t**)frame->data, frame->linesize, frame->format,
471 frame->width, frame->height);
472
473 return 0;
474}
475
477{
478 FilterLink *inl = ff_filter_link(inlink);
479
480 if (inl->hw_frames_ctx)
481 return ((AVHWFramesContext*)inl->hw_frames_ctx->data)->sw_format;
482 return inlink->format;
483}
484
486{
487 int err;
488 AMF_RESULT res;
489 AVFilterContext *avctx = outlink->src;
490 AVFilterLink *inlink = avctx->inputs[0];
491 AMFFilterContext *ctx = avctx->priv;
492 AVHWFramesContext *hwframes_out;
493 AVHWDeviceContext *hwdev_ctx;
494 enum AVPixelFormat in_sw_format = inlink->format;
495 enum AVPixelFormat out_sw_format = ctx->format;
496 FilterLink *inl = ff_filter_link(inlink);
497 FilterLink *outl = ff_filter_link(outlink);
498 double w_adj = 1.0;
499
500 if (ctx->w_expr && ctx->h_expr) {
501 if ((err = ff_scale_eval_dimensions(avctx,
502 ctx->w_expr, ctx->h_expr,
503 inlink, outlink,
504 &ctx->width, &ctx->height)) < 0)
505 return err;
506 } else {
507 ctx->width = inlink->w;
508 ctx->height = inlink->h;
509 }
510
511 if (ctx->reset_sar && inlink->sample_aspect_ratio.num)
512 w_adj = (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den;
513
514 err = ff_scale_adjust_dimensions(inlink, &ctx->width, &ctx->height,
515 ctx->force_original_aspect_ratio,
516 ctx->force_divisible_by, w_adj);
517 if (err < 0)
518 return err;
519
520 if (!ctx->pending) {
521 ctx->pending = av_fifo_alloc2(1, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
522 if (!ctx->pending)
523 return AVERROR(ENOMEM);
524 }
525
526 av_buffer_unref(&ctx->amf_device_ref);
527 av_buffer_unref(&ctx->hwframes_in_ref);
528 av_buffer_unref(&ctx->hwframes_out_ref);
529 ctx->local_context = 0;
530 if (inl->hw_frames_ctx) {
532 if (av_av_to_amf_format(frames_ctx->sw_format) == AMF_SURFACE_UNKNOWN) {
533 av_log(avctx, AV_LOG_ERROR, "Format of input frames context (%s) is not supported by AMF.\n",
534 av_get_pix_fmt_name(frames_ctx->sw_format));
535 return AVERROR(EINVAL);
536 }
537
538 err = av_hwdevice_ctx_create_derived(&ctx->amf_device_ref, AV_HWDEVICE_TYPE_AMF, frames_ctx->device_ref, 0);
539 if (err < 0)
540 return err;
541
542 ctx->hwframes_in_ref = av_buffer_ref(inl->hw_frames_ctx);
543 if (!ctx->hwframes_in_ref)
544 return AVERROR(ENOMEM);
545
546 in_sw_format = frames_ctx->sw_format;
547 } else if (avctx->hw_device_ctx) {
548 err = av_hwdevice_ctx_create_derived(&ctx->amf_device_ref, AV_HWDEVICE_TYPE_AMF, avctx->hw_device_ctx, 0);
549 if (err < 0)
550 return err;
551 ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx);
552 if (!ctx->hwdevice_ref)
553 return AVERROR(ENOMEM);
554 } else {
555 res = av_hwdevice_ctx_create(&ctx->amf_device_ref, AV_HWDEVICE_TYPE_AMF, NULL, NULL, 0);
556 AMF_RETURN_IF_FALSE(avctx, res == 0, res, "Failed to create hardware device context (AMF) : %s\n", av_err2str(res));
557
558 }
559 if (out_sw_format == AV_PIX_FMT_NONE) {
561 if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
562 out_sw_format = in_sw_format;
563 else
564 out_sw_format = outlink->format;
565 }
566 ctx->hwframes_out_ref = av_hwframe_ctx_alloc(ctx->amf_device_ref);
567 if (!ctx->hwframes_out_ref)
568 return AVERROR(ENOMEM);
569 hwframes_out = (AVHWFramesContext*)ctx->hwframes_out_ref->data;
570 hwdev_ctx = (AVHWDeviceContext*)ctx->amf_device_ref->data;
571 if (hwdev_ctx->type == AV_HWDEVICE_TYPE_AMF)
572 {
573 ctx->amf_device_ctx = hwdev_ctx->hwctx;
574 }
575 hwframes_out->format = AV_PIX_FMT_AMF_SURFACE;
576 hwframes_out->sw_format = out_sw_format;
577
578 // in_sw_format is inlink->format for software input and the underlying
579 // sw_format for any hw frames input (AMF, D3D11, DXVA2); the component
580 // must always be initialized with a software surface format.
581 *in_format = in_sw_format;
582 outlink->w = ctx->width;
583 outlink->h = ctx->height;
584
585 if (ctx->reset_sar)
586 outlink->sample_aspect_ratio = (AVRational){1, 1};
587 else if (inlink->sample_aspect_ratio.num) {
588 outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio);
589 } else
590 outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
591
592 hwframes_out->width = outlink->w;
593 hwframes_out->height = outlink->h;
594
595 err = av_hwframe_ctx_init(ctx->hwframes_out_ref);
596 if (err < 0)
597 return err;
598
599 outl->hw_frames_ctx = av_buffer_ref(ctx->hwframes_out_ref);
600 if (!outl->hw_frames_ctx) {
601 return AVERROR(ENOMEM);
602 }
603 return 0;
604}
605
606void amf_free_amfsurface(void *opaque, uint8_t *data)
607{
608 AMFSurface *surface = (AMFSurface*)data;
609 surface->pVtbl->Release(surface);
610}
611
613{
615 AMFFilterContext *ctx = avctx->priv;
616
617 if (!frame) {
618 pSurface->pVtbl->Release(pSurface);
619 return NULL;
620 }
621
622 if (ctx->hwframes_out_ref) {
623 AVHWFramesContext *hwframes_out = (AVHWFramesContext *)ctx->hwframes_out_ref->data;
624 if (hwframes_out->format == AV_PIX_FMT_AMF_SURFACE) {
625 int ret = av_hwframe_get_buffer(ctx->hwframes_out_ref, frame, 0);
626 if (ret < 0) {
627 av_log(avctx, AV_LOG_ERROR, "Get hw frame failed.\n");
628 goto fail;
629 }
630 frame->data[0] = (uint8_t *)pSurface;
631 frame->buf[1] = av_buffer_create((uint8_t *)pSurface, sizeof(AMFSurface),
633 (void*)avctx,
635 if (!frame->buf[1])
636 goto fail;
637 } else { // FIXME: add processing of other hw formats
638 av_log(ctx, AV_LOG_ERROR, "Unknown pixel format\n");
639 goto fail;
640 }
641 } else {
642
643 switch (pSurface->pVtbl->GetMemoryType(pSurface))
644 {
645 #if CONFIG_D3D11VA
646 case AMF_MEMORY_DX11:
647 {
648 AMFPlane *plane0 = pSurface->pVtbl->GetPlaneAt(pSurface, 0);
649 frame->data[0] = plane0->pVtbl->GetNative(plane0);
650 frame->data[1] = (uint8_t*)(intptr_t)0;
651
652 frame->buf[0] = av_buffer_create(NULL,
653 0,
655 pSurface,
657 }
658 break;
659 #endif
660 #if CONFIG_DXVA2
661 case AMF_MEMORY_DX9:
662 {
663 AMFPlane *plane0 = pSurface->pVtbl->GetPlaneAt(pSurface, 0);
664 frame->data[3] = plane0->pVtbl->GetNative(plane0);
665
666 frame->buf[0] = av_buffer_create(NULL,
667 0,
669 pSurface,
671 }
672 break;
673 #endif
674 default:
675 {
676 av_log(avctx, AV_LOG_ERROR, "Unsupported memory type : %d\n", pSurface->pVtbl->GetMemoryType(pSurface));
677 goto fail;
678 }
679 }
680 }
681
682
683 return frame;
684fail:
685 pSurface->pVtbl->Release(pSurface);
687 return NULL;
688}
689
690#if CONFIG_D3D11VA
691/* The AMF filter components read their input with a shader, so they reject a
692 * texture created without D3D11_BIND_SHADER_RESOURCE, which is what a D3D11VA
693 * decoder pool gives us. Copy the slice into an AMF allocated surface, which
694 * carries the flags the components need. CopySubresourceRegion() uses the copy
695 * engine, so it can read the decoder texture that a shader cannot. */
696static int amf_copy_d3d11_texture(AVFilterContext *avctx, const AVFrame *frame,
697 int index, AMFSurface **ppSurface)
698{
699 AMFFilterContext *ctx = avctx->priv;
700 AVHWFramesContext *frames = (AVHWFramesContext*)frame->hw_frames_ctx->data;
701 AVD3D11VADeviceContext *hwctx = frames->device_ctx->hwctx;
702 ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0];
703 AMFSurface *surface = NULL;
704 AMFPlane *plane;
705 D3D11_TEXTURE2D_DESC desc;
706 D3D11_BOX box;
707 AMF_RESULT res;
708
709 res = ctx->amf_device_ctx->context->pVtbl->AllocSurface(ctx->amf_device_ctx->context,
710 AMF_MEMORY_DX11, av_av_to_amf_format(frames->sw_format),
711 frame->width, frame->height, &surface);
712 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
713
714 plane = surface->pVtbl->GetPlaneAt(surface, 0);
715 if (!plane) {
716 surface->pVtbl->Release(surface);
717 return AVERROR(ENOMEM);
718 }
719
720 // The decoder pool is allocated with aligned dimensions, so copy the coded
721 // area rather than the whole source subresource. D3D11 wants even bounds
722 // for a planar format, and the source is at least that large.
723 texture->lpVtbl->GetDesc(texture, &desc);
724 box.left = 0;
725 box.top = 0;
726 box.front = 0;
727 box.right = FFMIN(FFALIGN(frame->width, 2), desc.Width);
728 box.bottom = FFMIN(FFALIGN(frame->height, 2), desc.Height);
729 box.back = 1;
730
731 hwctx->lock(hwctx->lock_ctx);
732 hwctx->device_context->lpVtbl->CopySubresourceRegion(hwctx->device_context,
733 (ID3D11Resource*)plane->pVtbl->GetNative(plane), 0, 0, 0, 0,
734 (ID3D11Resource*)texture, index, &box);
735 hwctx->unlock(hwctx->lock_ctx);
736
737 *ppSurface = surface;
738 return 0;
739}
740#endif
741
742#if CONFIG_D3D11VA || CONFIG_DXVA2
743typedef struct AMFFrameHolder {
744 AMFSurfaceObserver observer;
745 AVFrame *frame;
746} AMFFrameHolder;
747
748static void AMF_STD_CALL amf_release_held_frame(AMFSurfaceObserver *observer, AMFSurface *surface)
749{
750 AMFFrameHolder *holder = (AMFFrameHolder*)observer;
751
752 av_frame_free(&holder->frame);
753 av_free(holder);
754}
755
756static const AMFSurfaceObserverVtbl amf_frame_holder_vtbl = { amf_release_held_frame };
757
758static int amf_hold_frame(const AVFrame *frame, AMFSurfaceObserver **observer)
759{
760 AMFFrameHolder *holder = av_mallocz(sizeof(*holder));
761
762 if (!holder)
763 return AVERROR(ENOMEM);
764 holder->frame = av_frame_clone(frame);
765 if (!holder->frame) {
766 av_free(holder);
767 return AVERROR(ENOMEM);
768 }
769 holder->observer.pVtbl = &amf_frame_holder_vtbl;
770 *observer = &holder->observer;
771 return 0;
772}
773#endif
774
775int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface** ppSurface)
776{
777 AMFVariantStruct var = { 0 };
778 AMFFilterContext *ctx = avctx->priv;
779 AMFBuffer *hdrmeta_buffer = NULL;
780 AMFSurface *surface;
781 AMF_RESULT res;
782 int hw_surface = 0;
783#if CONFIG_D3D11VA || CONFIG_DXVA2
784 AMFSurfaceObserver *observer;
785#endif
786
787 switch (frame->format) {
788#if CONFIG_D3D11VA
789 case AV_PIX_FMT_D3D11:
790 {
791 static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
792 ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture
793 int index = (intptr_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use
794 D3D11_TEXTURE2D_DESC desc;
795 int ret;
796
797 texture->lpVtbl->GetDesc(texture, &desc);
798 if (ctx->shader_input && !(desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) && frame->hw_frames_ctx) {
799 ret = amf_copy_d3d11_texture(avctx, frame, index, &surface);
800 if (ret < 0)
801 return ret;
802 hw_surface = 1;
803 break;
804 }
805
806 texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index);
807
808 ret = amf_hold_frame(frame, &observer);
809 if (ret < 0)
810 return ret;
811 res = ctx->amf_device_ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->amf_device_ctx->context, texture, &surface, observer); // wrap to AMF surface
812 if (res != AMF_OK)
813 amf_release_held_frame(observer, NULL);
814 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res);
815 hw_surface = 1;
816 }
817 break;
818#endif
820 {
821 surface = (AMFSurface*)frame->data[0]; // actual surface
822 surface->pVtbl->Acquire(surface); // returned surface has to be to be ref++
823 hw_surface = 1;
824 }
825 break;
826
827#if CONFIG_DXVA2
829 {
830 IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture
831 int ret;
832
833 ret = amf_hold_frame(frame, &observer);
834 if (ret < 0)
835 return ret;
836 res = ctx->amf_device_ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->amf_device_ctx->context, texture, &surface, observer); // wrap to AMF surface
837 if (res != AMF_OK)
838 amf_release_held_frame(observer, NULL);
839 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res);
840 hw_surface = 1;
841 }
842 break;
843#endif
844 default:
845 {
846 AMF_SURFACE_FORMAT amf_fmt = av_av_to_amf_format(frame->format);
847 res = ctx->amf_device_ctx->context->pVtbl->AllocSurface(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, amf_fmt, frame->width, frame->height, &surface);
848 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
849 amf_copy_surface(avctx, frame, surface);
850 }
851 break;
852 }
853
854 // If AMFSurface comes from other AMF components, it may have various
855 // properties already set. These properties can be used by other AMF
856 // components to perform their tasks. In the context of the AMF video
857 // filter, that other component could be an AMFVideoConverter. By default,
858 // AMFVideoConverter will use HDR related properties assigned to a surface
859 // by an AMFDecoder. If frames (surfaces) originated from any other source,
860 // i.e. from hevcdec, assign those properties from avframe; do not
861 // overwrite these properties if they already have a value.
862 res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, &var);
863
864 if (res == AMF_NOT_FOUND && frame->color_trc != AVCOL_TRC_UNSPECIFIED)
865 // Note: as of now(Feb 2026), most AV and AMF enums are interchangeable.
866 // TBD: can enums change their values in the future?
867 // For better future-proofing it's better to have dedicated
868 // enum mapping functions.
869 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, frame->color_trc);
870
871 res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_PRIMARIES, &var);
872 if (res == AMF_NOT_FOUND && frame->color_primaries != AVCOL_PRI_UNSPECIFIED)
873 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_PRIMARIES, frame->color_primaries);
874
875 res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_RANGE, &var);
876 if (res == AMF_NOT_FOUND && frame->color_range != AVCOL_RANGE_UNSPECIFIED)
877 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_RANGE, frame->color_range);
878
879 // Color range for older drivers
880 if (frame->color_range == AVCOL_RANGE_JPEG) {
881 AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 1);
882 } else if (frame->color_range != AVCOL_RANGE_UNSPECIFIED)
883 AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 0);
884
885 // Color profile for newer drivers
886 res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_PROFILE, &var);
887 if (res == AMF_NOT_FOUND && frame->color_range != AVCOL_RANGE_UNSPECIFIED && frame->colorspace != AVCOL_SPC_UNSPECIFIED) {
888 amf_int64 color_profile = color_profile = av_amf_get_color_profile(frame->color_range, frame->colorspace);
889
890 if (color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN)
891 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_PROFILE, color_profile);
892 }
893
894 if (ctx->in_trc == AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084 && (ctx->master_display || ctx->light_meta)) {
895 res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
896 if (res == AMF_OK) {
897 AMFHDRMetadata *hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
898
899 av_amf_display_mastering_meta_to_hdrmeta(ctx->master_display, hdrmeta);
900 av_amf_light_metadata_to_hdrmeta(ctx->light_meta, hdrmeta);
901 AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, AMF_VIDEO_DECODER_HDR_METADATA, hdrmeta_buffer);
902 }
903 } else if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
904 res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_HDR_METADATA, &var);
905 if (res == AMF_NOT_FOUND) {
906 res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
907 if (res == AMF_OK) {
908 AMFHDRMetadata *hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
909
910 if (av_amf_extract_hdr_metadata(frame, hdrmeta) == 0)
911 AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, AMF_VIDEO_DECODER_HDR_METADATA, hdrmeta_buffer);
912 }
913 }
914 }
915
916 if (hdrmeta_buffer) {
917 hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
918 hdrmeta_buffer = NULL;
919 }
920
921 if (frame->crop_left || frame->crop_right || frame->crop_top || frame->crop_bottom) {
922 size_t crop_x = frame->crop_left;
923 size_t crop_y = frame->crop_top;
924 size_t crop_w = frame->width - (frame->crop_left + frame->crop_right);
925 size_t crop_h = frame->height - (frame->crop_top + frame->crop_bottom);
926 AVFilterLink *outlink = avctx->outputs[0];
927 if (crop_x || crop_y) {
928 if (crop_w == outlink->w && crop_h == outlink->h) {
929 AMFData *cropped_buffer = NULL;
930 res = surface->pVtbl->Duplicate(surface, surface->pVtbl->GetMemoryType(surface), &cropped_buffer);
931 AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "Duplicate() failed with error %d\n", res);
932 surface->pVtbl->Release(surface);
933 surface = (AMFSurface*)cropped_buffer;
934 }
935 else
936 surface->pVtbl->SetCrop(surface, (amf_int32)crop_x, (amf_int32)crop_y, (amf_int32)crop_w, (amf_int32)crop_h);
937 }
938 else
939 surface->pVtbl->SetCrop(surface, (amf_int32)crop_x, (amf_int32)crop_y, (amf_int32)crop_w, (amf_int32)crop_h);
940 }
941 else if (hw_surface) {
942 // input HW surfaces can be vertically aligned by 16; tell AMF the real size
943 surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height);
944 }
945
946 surface->pVtbl->SetPts(surface, frame->pts);
947 *ppSurface = surface;
948 return 0;
949}
static void amf_free_amfsurface(void *opaque, uint8_t *data)
Definition amfdec.c:58
#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value,...)
Error handling helper.
Definition amfenc.h:169
static FILE * out
static int frames
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition avfilter.c:1467
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition avfilter.c:1520
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVFrame * frame
static av_unused double box(double x, const double *params)
Definition filters.c:320
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add ref as a new reference to formats.
Definition formats.c:756
void ff_formats_unref(AVFilterFormats **ref)
If *ref is non-NULL, remove *ref as a reference to the format list it currently points to,...
Definition formats.c:795
av_warn_unused_result AVFilterFormats * ff_make_pixel_format_list(const enum AVPixelFormat *fmts)
Create a list of supported pixel formats.
#define fail
Definition test.h:479
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:140
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:104
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition buffer.h:114
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:56
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition fifo.c:47
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition fifo.h:63
size_t av_fifo_can_read(const AVFifo *f)
Definition fifo.c:87
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
Definition fifo.c:255
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition rational.c:80
void av_image_copy(uint8_t *const dst_data[4], const int dst_linesizes[4], const uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Copy image in src_data to dst_data.
Definition imgutils.c:422
int index
Definition gxfenc.c:90
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition hwcontext.c:615
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition hwcontext.c:120
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, int flags)
Create a new device of the specified type from an existing device.
Definition hwcontext.c:718
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:337
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:263
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition hwcontext.c:506
@ AV_HWDEVICE_TYPE_D3D11VA
Definition hwcontext.h:35
@ AV_HWDEVICE_TYPE_AMF
Definition hwcontext.h:41
@ AV_HWDEVICE_TYPE_DXVA2
Definition hwcontext.h:32
int av_amf_display_mastering_meta_to_hdrmeta(const AVMasteringDisplayMetadata *display_meta, AMFHDRMetadata *hdrmeta)
int av_amf_light_metadata_to_hdrmeta(const AVContentLightMetadata *light_meta, AMFHDRMetadata *hdrmeta)
enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
int av_amf_extract_hdr_metadata(const AVFrame *frame, AMFHDRMetadata *hdrmeta)
enum AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM av_amf_get_color_profile(enum AVColorRange color_range, enum AVColorSpace color_space)
An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.
misc image utilities
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition filters.h:694
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition filters.h:629
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
Definition filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition filters.h:639
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
const char * desc
Definition libsvtav1.c:83
static const struct @257111027162314367033347246032313251342043035002 planes[]
#define FFMIN(a, b)
Definition macros.h:49
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
const char data[16]
Definition mxf.c:149
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition pixdesc.c:3392
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition pixdesc.h:128
AVColorRange
Visual content value range.
Definition pixfmt.h:748
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVCOL_RANGE_UNSPECIFIED
Definition pixfmt.h:749
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
Definition pixfmt.h:134
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition pixfmt.h:336
@ AV_PIX_FMT_AMF_SURFACE
HW acceleration through AMF.
Definition pixfmt.h:477
@ AVCOL_PRI_UNSPECIFIED
Definition pixfmt.h:645
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
Definition pixfmt.h:689
@ AVCOL_TRC_UNSPECIFIED
Definition pixfmt.h:675
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition pixfmt.h:708
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition pixfmt.h:707
@ AVCOL_SPC_BT2020_NCL
ITU-R BT2020 non-constant luminance system.
Definition pixfmt.h:717
@ AVCOL_SPC_UNSPECIFIED
Definition pixfmt.h:709
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
Definition pixfmt.h:713
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by, double w_adj)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
Definition scale_eval.c:123
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
Definition scale_eval.c:58
#define FF_ARRAY_ELEMS(a)
uint8_t * data
The data buffer.
Definition buffer.h:90
This struct is allocated as AVHWDeviceContext.hwctx.
An instance of a filter.
Definition avfilter.h:273
AVFilterLink ** inputs
array of pointers to input links
Definition avfilter.h:281
void * priv
private data for use by the filter
Definition avfilter.h:288
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in.
Definition avfilter.h:336
AVFilterLink ** outputs
array of pointers to output links
Definition avfilter.h:285
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition avfilter.h:125
A list of supported formats for one end of a filter link.
Definition formats.h:64
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:574
int width
Definition frame.h:544
int height
Definition frame.h:544
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition hwcontext.h:75
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition hwcontext.h:129
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition time.c:93
static int64_t pts
void amf_free_amfsurface(void *opaque, uint8_t *data)
AVFrame * amf_amfsurface_to_avframe(AVFilterContext *avctx, AMFSurface *pSurface)
static int amf_queue_props(AVFilterContext *avctx, const AVFrame *in)
static int amf_deliver_output(AVFilterContext *avctx)
int amf_copy_surface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface *surface)
int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface **ppSurface)
int amf_setup_input_output_formats(AVFilterContext *avctx, const enum AVPixelFormat *input_pix_fmts)
static int amf_drain_component(AVFilterContext *avctx, AMFComponent *component, int(*deliver)(AVFilterContext *avctx))
int amf_filter_activate(AVFilterContext *avctx)
int amf_filter_init(AVFilterContext *avctx)
int amf_init_filter_config(AVFilterLink *outlink, enum AVPixelFormat *in_format)
enum AVPixelFormat amf_inlink_sw_format(AVFilterLink *inlink)
int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in)
static int amf_poll_output(AVFilterContext *avctx)
static int amf_submit_surface(AVFilterContext *avctx, AMFComponent *component, AMFSurface *surface, int(*deliver)(AVFilterContext *avctx))
static int amf_forward_converted(AVFilterContext *avctx)
static int amf_receive_surface(AVFilterContext *avctx, AMFComponent *component, AMFSurface **surface)
void amf_filter_uninit(AVFilterContext *avctx)