FFmpeg
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 "formats.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/imgutils.h"
27 #include "libavutil/pixdesc.h"
28 
29 #include "AMF/components/VideoDecoderUVD.h"
32 #include "scale_eval.h"
33 
34 #if CONFIG_DXVA2
35 #include <d3d9.h>
36 #endif
37 
38 #if CONFIG_D3D11VA
39 #include <d3d11.h>
40 #endif
41 
43 {
44  AMFFilterContext *ctx = avctx->priv;
45 
46  if (!strcmp(ctx->format_str, "same")) {
47  ctx->format = AV_PIX_FMT_NONE;
48  } else {
49  ctx->format = av_get_pix_fmt(ctx->format_str);
50  if (ctx->format == AV_PIX_FMT_NONE) {
51  av_log(avctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", ctx->format_str);
52  return AVERROR(EINVAL);
53  }
54  }
55 
56  return 0;
57 }
58 
60 {
61  AMFFilterContext *ctx = avctx->priv;
62 
63  if (ctx->component) {
64  ctx->component->pVtbl->Terminate(ctx->component);
65  ctx->component->pVtbl->Release(ctx->component);
66  ctx->component = NULL;
67  }
68 
69  if (ctx->master_display)
70  av_freep(&ctx->master_display);
71 
72  if (ctx->light_meta)
73  av_freep(&ctx->light_meta);
74 
75  av_buffer_unref(&ctx->amf_device_ref);
76  av_buffer_unref(&ctx->hwdevice_ref);
77  av_buffer_unref(&ctx->hwframes_in_ref);
78  av_buffer_unref(&ctx->hwframes_out_ref);
79 }
80 
82 {
83  AVFilterContext *avctx = inlink->dst;
84  AMFFilterContext *ctx = avctx->priv;
85  AVFilterLink *outlink = avctx->outputs[0];
86  AMF_RESULT res;
87  AMFSurface *surface_in;
88  AMFSurface *surface_out;
89  AMFData *data_out = NULL;
90  enum AVColorSpace out_colorspace;
91  enum AVColorRange out_color_range;
92 
93  AVFrame *out = NULL;
94  int ret = 0;
95 
96  if (!ctx->component)
97  return AVERROR(EINVAL);
98 
99  ret = amf_avframe_to_amfsurface(avctx, in, &surface_in);
100  if (ret < 0)
101  goto fail;
102 
103  res = ctx->component->pVtbl->SubmitInput(ctx->component, (AMFData*)surface_in);
104  surface_in->pVtbl->Release(surface_in); // release surface after use
105  AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
106  res = ctx->component->pVtbl->QueryOutput(ctx->component, &data_out);
107  AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryOutput() failed with error %d\n", res);
108 
109  if (data_out) {
110  AMFGuid guid = IID_AMFSurface();
111  res = data_out->pVtbl->QueryInterface(data_out, &guid, (void**)&surface_out); // query for buffer interface
112  data_out->pVtbl->Release(data_out);
113  AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface(IID_AMFSurface) failed with error %d\n", res);
114  } else {
115  return AVERROR(EAGAIN);
116  }
117 
118  out = amf_amfsurface_to_avframe(avctx, surface_out);
119 
120  ret = av_frame_copy_props(out, in);
121  av_frame_unref(in);
122 
123  out_colorspace = AVCOL_SPC_UNSPECIFIED;
124 
125  if (ctx->color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN) {
126  switch(ctx->color_profile) {
127  case AMF_VIDEO_CONVERTER_COLOR_PROFILE_601:
128  out_colorspace = AVCOL_SPC_SMPTE170M;
129  break;
130  case AMF_VIDEO_CONVERTER_COLOR_PROFILE_709:
131  out_colorspace = AVCOL_SPC_BT709;
132  break;
133  case AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020:
134  out_colorspace = AVCOL_SPC_BT2020_NCL;
135  break;
136  case AMF_VIDEO_CONVERTER_COLOR_PROFILE_JPEG:
137  out_colorspace = AVCOL_SPC_RGB;
138  break;
139  default:
140  out_colorspace = AVCOL_SPC_UNSPECIFIED;
141  break;
142  }
143  out->colorspace = out_colorspace;
144  }
145 
146  out_color_range = AVCOL_RANGE_UNSPECIFIED;
147  if (ctx->out_color_range == AMF_COLOR_RANGE_FULL)
148  out_color_range = AVCOL_RANGE_JPEG;
149  else if (ctx->out_color_range == AMF_COLOR_RANGE_STUDIO)
150  out_color_range = AVCOL_RANGE_MPEG;
151 
152  if (ctx->out_color_range != AMF_COLOR_RANGE_UNDEFINED)
153  out->color_range = out_color_range;
154 
155  if (ctx->out_primaries != AMF_COLOR_PRIMARIES_UNDEFINED)
156  out->color_primaries = ctx->out_primaries;
157 
158  if (ctx->out_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED)
159  out->color_trc = ctx->out_trc;
160 
161 
162  if (ret < 0)
163  goto fail;
164 
165  out->hw_frames_ctx = av_buffer_ref(ctx->hwframes_out_ref);
166  if (!out->hw_frames_ctx) {
167  ret = AVERROR(ENOMEM);
168  goto fail;
169  }
170 
171  av_frame_free(&in);
172  return ff_filter_frame(outlink, out);
173 fail:
174  av_frame_free(&in);
175  av_frame_free(&out);
176  return ret;
177 }
178 
179 
180 
182  const enum AVPixelFormat *input_pix_fmts,
183  const enum AVPixelFormat *output_pix_fmts)
184 {
185  int err;
186  AVFilterFormats *input_formats;
187  AVFilterFormats *output_formats;
188 
189  //in case if hw_device_ctx is set to DXVA2 we change order of pixel formats to set DXVA2 be chosen by default
190  //The order is ignored if hw_frames_ctx is not NULL on the config_output stage
191  if (avctx->hw_device_ctx) {
192  AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data;
193 
194  switch (device_ctx->type) {
195  #if CONFIG_D3D11VA
197  {
198  static const enum AVPixelFormat output_pix_fmts_d3d11[] = {
201  };
202  output_pix_fmts = output_pix_fmts_d3d11;
203  }
204  break;
205  #endif
206  #if CONFIG_DXVA2
208  {
209  static const enum AVPixelFormat output_pix_fmts_dxva2[] = {
212  };
213  output_pix_fmts = output_pix_fmts_dxva2;
214  }
215  break;
216  #endif
218  break;
219  default:
220  {
221  av_log(avctx, AV_LOG_ERROR, "Unsupported device : %s\n", av_hwdevice_get_type_name(device_ctx->type));
222  return AVERROR(EINVAL);
223  }
224  break;
225  }
226  }
227 
228  input_formats = ff_make_pixel_format_list(output_pix_fmts);
229  if (!input_formats) {
230  return AVERROR(ENOMEM);
231  }
232  output_formats = ff_make_pixel_format_list(output_pix_fmts);
233  if (!output_formats) {
234  return AVERROR(ENOMEM);
235  }
236 
237  if ((err = ff_formats_ref(input_formats, &avctx->inputs[0]->outcfg.formats)) < 0)
238  return err;
239 
240  if ((err = ff_formats_ref(output_formats, &avctx->outputs[0]->incfg.formats)) < 0)
241  return err;
242  return 0;
243 }
244 
246  AMFSurface* surface)
247 {
248  AMFPlane *plane;
249  uint8_t *dst_data[4];
250  int dst_linesize[4];
251  int planes;
252  int i;
253 
254  planes = (int)surface->pVtbl->GetPlanesCount(surface);
255  av_assert0(planes < FF_ARRAY_ELEMS(dst_data));
256 
257  for (i = 0; i < planes; i++) {
258  plane = surface->pVtbl->GetPlaneAt(surface, i);
259  dst_data[i] = plane->pVtbl->GetNative(plane);
260  dst_linesize[i] = plane->pVtbl->GetHPitch(plane);
261  }
262  av_image_copy(dst_data, dst_linesize,
263  (const uint8_t**)frame->data, frame->linesize, frame->format,
264  frame->width, frame->height);
265 
266  return 0;
267 }
268 
269 int amf_init_filter_config(AVFilterLink *outlink, enum AVPixelFormat *in_format)
270 {
271  int err;
272  AMF_RESULT res;
273  AVFilterContext *avctx = outlink->src;
274  AVFilterLink *inlink = avctx->inputs[0];
275  AMFFilterContext *ctx = avctx->priv;
276  AVHWFramesContext *hwframes_out;
277  AVHWDeviceContext *hwdev_ctx;
278  enum AVPixelFormat in_sw_format = inlink->format;
279  enum AVPixelFormat out_sw_format = ctx->format;
281  FilterLink *outl = ff_filter_link(outlink);
282  double w_adj = 1.0;
283 
284  if (ctx->w_expr && ctx->h_expr) {
285  if ((err = ff_scale_eval_dimensions(avctx,
286  ctx->w_expr, ctx->h_expr,
287  inlink, outlink,
288  &ctx->width, &ctx->height)) < 0)
289  return err;
290  } else {
291  ctx->width = inlink->w;
292  ctx->height = inlink->h;
293  }
294 
295  if (ctx->reset_sar && inlink->sample_aspect_ratio.num)
296  w_adj = (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den;
297 
298  err = ff_scale_adjust_dimensions(inlink, &ctx->width, &ctx->height,
299  ctx->force_original_aspect_ratio,
300  ctx->force_divisible_by, w_adj);
301  if (err < 0)
302  return err;
303 
304  av_buffer_unref(&ctx->amf_device_ref);
305  av_buffer_unref(&ctx->hwframes_in_ref);
306  av_buffer_unref(&ctx->hwframes_out_ref);
307  ctx->local_context = 0;
308  if (inl->hw_frames_ctx) {
310  if (av_av_to_amf_format(frames_ctx->sw_format) == AMF_SURFACE_UNKNOWN) {
311  av_log(avctx, AV_LOG_ERROR, "Format of input frames context (%s) is not supported by AMF.\n",
312  av_get_pix_fmt_name(frames_ctx->sw_format));
313  return AVERROR(EINVAL);
314  }
315 
316  err = av_hwdevice_ctx_create_derived(&ctx->amf_device_ref, AV_HWDEVICE_TYPE_AMF, frames_ctx->device_ref, 0);
317  if (err < 0)
318  return err;
319 
320  ctx->hwframes_in_ref = av_buffer_ref(inl->hw_frames_ctx);
321  if (!ctx->hwframes_in_ref)
322  return AVERROR(ENOMEM);
323 
324  in_sw_format = frames_ctx->sw_format;
325  } else if (avctx->hw_device_ctx) {
326  err = av_hwdevice_ctx_create_derived(&ctx->amf_device_ref, AV_HWDEVICE_TYPE_AMF, avctx->hw_device_ctx, 0);
327  if (err < 0)
328  return err;
329  ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx);
330  if (!ctx->hwdevice_ref)
331  return AVERROR(ENOMEM);
332  } else {
333  res = av_hwdevice_ctx_create(&ctx->amf_device_ref, AV_HWDEVICE_TYPE_AMF, NULL, NULL, 0);
334  AMF_RETURN_IF_FALSE(avctx, res == 0, res, "Failed to create hardware device context (AMF) : %s\n", av_err2str(res));
335 
336  }
337  if (out_sw_format == AV_PIX_FMT_NONE) {
339  if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
340  out_sw_format = in_sw_format;
341  else
342  out_sw_format = outlink->format;
343  }
344  ctx->hwframes_out_ref = av_hwframe_ctx_alloc(ctx->amf_device_ref);
345  if (!ctx->hwframes_out_ref)
346  return AVERROR(ENOMEM);
347  hwframes_out = (AVHWFramesContext*)ctx->hwframes_out_ref->data;
348  hwdev_ctx = (AVHWDeviceContext*)ctx->amf_device_ref->data;
349  if (hwdev_ctx->type == AV_HWDEVICE_TYPE_AMF)
350  {
351  ctx->amf_device_ctx = hwdev_ctx->hwctx;
352  }
353  hwframes_out->format = AV_PIX_FMT_AMF_SURFACE;
354  hwframes_out->sw_format = out_sw_format;
355 
356  // in_sw_format is inlink->format for software input and the underlying
357  // sw_format for any hw frames input (AMF, D3D11, DXVA2); the component
358  // must always be initialized with a software surface format.
359  *in_format = in_sw_format;
360  outlink->w = ctx->width;
361  outlink->h = ctx->height;
362 
363  if (ctx->reset_sar)
364  outlink->sample_aspect_ratio = (AVRational){1, 1};
365  else if (inlink->sample_aspect_ratio.num) {
366  outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio);
367  } else
368  outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
369 
370  hwframes_out->width = outlink->w;
371  hwframes_out->height = outlink->h;
372 
373  err = av_hwframe_ctx_init(ctx->hwframes_out_ref);
374  if (err < 0)
375  return err;
376 
377  outl->hw_frames_ctx = av_buffer_ref(ctx->hwframes_out_ref);
378  if (!outl->hw_frames_ctx) {
379  return AVERROR(ENOMEM);
380  }
381  return 0;
382 }
383 
384 void amf_free_amfsurface(void *opaque, uint8_t *data)
385 {
386  AMFSurface *surface = (AMFSurface*)data;
387  surface->pVtbl->Release(surface);
388 }
389 
390 AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, AMFSurface* pSurface)
391 {
393  AMFFilterContext *ctx = avctx->priv;
394 
395  if (!frame)
396  return NULL;
397 
398  if (ctx->hwframes_out_ref) {
399  AVHWFramesContext *hwframes_out = (AVHWFramesContext *)ctx->hwframes_out_ref->data;
400  if (hwframes_out->format == AV_PIX_FMT_AMF_SURFACE) {
401  int ret = av_hwframe_get_buffer(ctx->hwframes_out_ref, frame, 0);
402  if (ret < 0) {
403  av_log(avctx, AV_LOG_ERROR, "Get hw frame failed.\n");
404  goto fail;
405  }
406  frame->data[0] = (uint8_t *)pSurface;
407  frame->buf[1] = av_buffer_create((uint8_t *)pSurface, sizeof(AMFSurface),
409  (void*)avctx,
411  } else { // FIXME: add processing of other hw formats
412  av_log(ctx, AV_LOG_ERROR, "Unknown pixel format\n");
413  goto fail;
414  }
415  } else {
416 
417  switch (pSurface->pVtbl->GetMemoryType(pSurface))
418  {
419  #if CONFIG_D3D11VA
420  case AMF_MEMORY_DX11:
421  {
422  AMFPlane *plane0 = pSurface->pVtbl->GetPlaneAt(pSurface, 0);
423  frame->data[0] = plane0->pVtbl->GetNative(plane0);
424  frame->data[1] = (uint8_t*)(intptr_t)0;
425 
426  frame->buf[0] = av_buffer_create(NULL,
427  0,
429  pSurface,
431  }
432  break;
433  #endif
434  #if CONFIG_DXVA2
435  case AMF_MEMORY_DX9:
436  {
437  AMFPlane *plane0 = pSurface->pVtbl->GetPlaneAt(pSurface, 0);
438  frame->data[3] = plane0->pVtbl->GetNative(plane0);
439 
440  frame->buf[0] = av_buffer_create(NULL,
441  0,
443  pSurface,
445  }
446  break;
447  #endif
448  default:
449  {
450  av_log(avctx, AV_LOG_ERROR, "Unsupported memory type : %d\n", pSurface->pVtbl->GetMemoryType(pSurface));
451  goto fail;
452  }
453  }
454  }
455 
456 
457  return frame;
458 fail:
460  return NULL;
461 }
462 
463 int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface** ppSurface)
464 {
465  AMFVariantStruct var = { 0 };
466  AMFFilterContext *ctx = avctx->priv;
467  AMFBuffer *hdrmeta_buffer = NULL;
468  AMFSurface *surface;
469  AMF_RESULT res;
470  int hw_surface = 0;
471 
472  switch (frame->format) {
473 #if CONFIG_D3D11VA
474  case AV_PIX_FMT_D3D11:
475  {
476  static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
477  ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture
478  int index = (intptr_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use
479  texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index);
480 
481  res = ctx->amf_device_ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->amf_device_ctx->context, texture, &surface, NULL); // wrap to AMF surface
482  AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res);
483  hw_surface = 1;
484  }
485  break;
486 #endif
488  {
489  surface = (AMFSurface*)frame->data[0]; // actual surface
490  surface->pVtbl->Acquire(surface); // returned surface has to be to be ref++
491  hw_surface = 1;
492  }
493  break;
494 
495 #if CONFIG_DXVA2
497  {
498  IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture
499 
500  res = ctx->amf_device_ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->amf_device_ctx->context, texture, &surface, NULL); // wrap to AMF surface
501  AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res);
502  hw_surface = 1;
503  }
504  break;
505 #endif
506  default:
507  {
508  AMF_SURFACE_FORMAT amf_fmt = av_av_to_amf_format(frame->format);
509  res = ctx->amf_device_ctx->context->pVtbl->AllocSurface(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, amf_fmt, frame->width, frame->height, &surface);
510  AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
511  amf_copy_surface(avctx, frame, surface);
512  }
513  break;
514  }
515 
516  // If AMFSurface comes from other AMF components, it may have various
517  // properties already set. These properties can be used by other AMF
518  // components to perform their tasks. In the context of the AMF video
519  // filter, that other component could be an AMFVideoConverter. By default,
520  // AMFVideoConverter will use HDR related properties assigned to a surface
521  // by an AMFDecoder. If frames (surfaces) originated from any other source,
522  // i.e. from hevcdec, assign those properties from avframe; do not
523  // overwrite these properties if they already have a value.
524  res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, &var);
525 
526  if (res == AMF_NOT_FOUND && frame->color_trc != AVCOL_TRC_UNSPECIFIED)
527  // Note: as of now(Feb 2026), most AV and AMF enums are interchangeable.
528  // TBD: can enums change their values in the future?
529  // For better future-proofing it's better to have dedicated
530  // enum mapping functions.
531  AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, frame->color_trc);
532 
533  res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_PRIMARIES, &var);
534  if (res == AMF_NOT_FOUND && frame->color_primaries != AVCOL_PRI_UNSPECIFIED)
535  AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_PRIMARIES, frame->color_primaries);
536 
537  res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_RANGE, &var);
538  if (res == AMF_NOT_FOUND && frame->color_range != AVCOL_RANGE_UNSPECIFIED)
539  AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_RANGE, frame->color_range);
540 
541  // Color range for older drivers
542  if (frame->color_range == AVCOL_RANGE_JPEG) {
543  AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 1);
544  } else if (frame->color_range != AVCOL_RANGE_UNSPECIFIED)
545  AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 0);
546 
547  // Color profile for newer drivers
548  res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_PROFILE, &var);
549  if (res == AMF_NOT_FOUND && frame->color_range != AVCOL_RANGE_UNSPECIFIED && frame->colorspace != AVCOL_SPC_UNSPECIFIED) {
550  amf_int64 color_profile = color_profile = av_amf_get_color_profile(frame->color_range, frame->colorspace);
551 
552  if (color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN)
553  AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_PROFILE, color_profile);
554  }
555 
556  if (ctx->in_trc == AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084 && (ctx->master_display || ctx->light_meta)) {
557  res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
558  if (res == AMF_OK) {
559  AMFHDRMetadata *hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
560 
561  av_amf_display_mastering_meta_to_hdrmeta(ctx->master_display, hdrmeta);
562  av_amf_light_metadata_to_hdrmeta(ctx->light_meta, hdrmeta);
563  AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, AMF_VIDEO_DECODER_HDR_METADATA, hdrmeta_buffer);
564  }
565  } else if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
566  res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_HDR_METADATA, &var);
567  if (res == AMF_NOT_FOUND) {
568  res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
569  if (res == AMF_OK) {
570  AMFHDRMetadata *hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
571 
572  if (av_amf_extract_hdr_metadata(frame, hdrmeta) == 0)
573  AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, AMF_VIDEO_DECODER_HDR_METADATA, hdrmeta_buffer);
574  }
575  }
576  }
577 
578  if (hdrmeta_buffer) {
579  hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
580  hdrmeta_buffer = NULL;
581  }
582 
583  if (frame->crop_left || frame->crop_right || frame->crop_top || frame->crop_bottom) {
584  size_t crop_x = frame->crop_left;
585  size_t crop_y = frame->crop_top;
586  size_t crop_w = frame->width - (frame->crop_left + frame->crop_right);
587  size_t crop_h = frame->height - (frame->crop_top + frame->crop_bottom);
588  AVFilterLink *outlink = avctx->outputs[0];
589  if (crop_x || crop_y) {
590  if (crop_w == outlink->w && crop_h == outlink->h) {
591  AMFData *cropped_buffer = NULL;
592  res = surface->pVtbl->Duplicate(surface, surface->pVtbl->GetMemoryType(surface), &cropped_buffer);
593  AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "Duplicate() failed with error %d\n", res);
594  surface->pVtbl->Release(surface);
595  surface = (AMFSurface*)cropped_buffer;
596  }
597  else
598  surface->pVtbl->SetCrop(surface, (amf_int32)crop_x, (amf_int32)crop_y, (amf_int32)crop_w, (amf_int32)crop_h);
599  }
600  else
601  surface->pVtbl->SetCrop(surface, (amf_int32)crop_x, (amf_int32)crop_y, (amf_int32)crop_w, (amf_int32)crop_h);
602  }
603  else if (hw_surface) {
604  // input HW surfaces can be vertically aligned by 16; tell AMF the real size
605  surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height);
606  }
607 
608  surface->pVtbl->SetPts(surface, frame->pts);
609  *ppSurface = surface;
610  return 0;
611 }
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
amf_avframe_to_amfsurface
int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface **ppSurface)
Definition: vf_amf_common.c:463
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
out
static FILE * out
Definition: movenc.c:55
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1068
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3460
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:200
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
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
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:337
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:472
pixdesc.h
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:783
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:263
AVCOL_TRC_UNSPECIFIED
@ AVCOL_TRC_UNSPECIFIED
Definition: pixfmt.h:675
ff_make_pixel_format_list
av_warn_unused_result AVFilterFormats * ff_make_pixel_format_list(const enum AVPixelFormat *fmts)
Create a list of supported pixel formats.
data
const char data[16]
Definition: mxf.c:149
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:707
ff_scale_eval_dimensions
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
AVFilterContext::hw_device_ctx
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in.
Definition: avfilter.h:336
amf_setup_input_output_formats
int amf_setup_input_output_formats(AVFilterContext *avctx, const enum AVPixelFormat *input_pix_fmts, const enum AVPixelFormat *output_pix_fmts)
Definition: vf_amf_common.c:181
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AMF_RETURN_IF_FALSE
#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value,...)
Error handling helper.
Definition: amfenc.h:169
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
AV_PIX_FMT_AMF_SURFACE
@ AV_PIX_FMT_AMF_SURFACE
HW acceleration through AMF.
Definition: pixfmt.h:477
av_amf_display_mastering_meta_to_hdrmeta
int av_amf_display_mastering_meta_to_hdrmeta(const AVMasteringDisplayMetadata *display_meta, AMFHDRMetadata *hdrmeta)
Definition: hwcontext_amf.c:186
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
formats.h
amf_free_amfsurface
void amf_free_amfsurface(void *opaque, uint8_t *data)
Definition: vf_amf_common.c:384
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:288
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:128
AV_HWDEVICE_TYPE_D3D11VA
@ AV_HWDEVICE_TYPE_D3D11VA
Definition: hwcontext.h:35
av_av_to_amf_format
enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
Definition: hwcontext_amf.c:133
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_amf_get_color_profile
enum AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM av_amf_get_color_profile(enum AVColorRange color_range, enum AVColorSpace color_space)
Definition: hwcontext_amf.c:155
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
AV_PIX_FMT_DXVA2_VLD
@ AV_PIX_FMT_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
Definition: pixfmt.h:134
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:199
AVCOL_SPC_SMPTE170M
@ 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
ff_formats_ref
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:756
vf_amf_common.h
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
AV_HWDEVICE_TYPE_AMF
@ AV_HWDEVICE_TYPE_AMF
Definition: hwcontext.h:41
AMFFilterContext
Definition: vf_amf_common.h:29
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
AMF_GOTO_FAIL_IF_FALSE
#define AMF_GOTO_FAIL_IF_FALSE(avctx, exp, ret_value,...)
Definition: hwcontext_amf_internal.h:34
hwcontext_amf.h
av_hwdevice_get_type_name
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition: hwcontext.c:120
AVCOL_PRI_UNSPECIFIED
@ AVCOL_PRI_UNSPECIFIED
Definition: pixfmt.h:645
if
if(ret)
Definition: filter_design.txt:179
fail
#define fail
Definition: test.h:478
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:599
av_buffer_unref
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:139
AV_HWDEVICE_TYPE_DXVA2
@ AV_HWDEVICE_TYPE_DXVA2
Definition: hwcontext.h:32
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:129
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:281
double
double
Definition: af_crystalizer.c:132
avfilter_internal.h
AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_UNSPECIFIED
Definition: pixfmt.h:749
index
int index
Definition: gxfenc.c:90
av_buffer_create
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:55
AVCOL_TRC_SMPTE2084
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
Definition: pixfmt.h:689
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
av_amf_extract_hdr_metadata
int av_amf_extract_hdr_metadata(const AVFrame *frame, AMFHDRMetadata *hdrmeta)
Definition: hwcontext_amf.c:233
scale_eval.h
amf_copy_surface
int amf_copy_surface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface *surface)
Definition: vf_amf_common.c:245
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:336
amf_filter_filter_frame
int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_amf_common.c:81
amf_filter_uninit
void amf_filter_uninit(AVFilterContext *avctx)
Definition: vf_amf_common.c:59
av_hwdevice_ctx_create_derived
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
AVCOL_SPC_BT2020_NCL
@ AVCOL_SPC_BT2020_NCL
ITU-R BT2020 non-constant luminance system.
Definition: pixfmt.h:717
AVColorSpace
AVColorSpace
YUV colorspace type.
Definition: pixfmt.h:706
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
AVCOL_SPC_UNSPECIFIED
@ AVCOL_SPC_UNSPECIFIED
Definition: pixfmt.h:709
amf_filter_init
int amf_filter_init(AVFilterContext *avctx)
Definition: vf_amf_common.c:42
AVCOL_RANGE_MPEG
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition: pixfmt.h:766
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
ret
ret
Definition: filter_design.txt:187
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:75
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
av_hwdevice_ctx_create
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
av_get_pix_fmt
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:3392
hwcontext_amf_internal.h
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
avfilter.h
amf_init_filter_config
int amf_init_filter_config(AVFilterLink *outlink, enum AVPixelFormat *in_format)
Definition: vf_amf_common.c:269
av_mul_q
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
AVFilterContext
An instance of a filter.
Definition: avfilter.h:273
desc
const char * desc
Definition: libsvtav1.c:83
mem.h
AVFilterFormatsConfig::formats
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition: avfilter.h:125
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
amf_amfsurface_to_avframe
AVFrame * amf_amfsurface_to_avframe(AVFilterContext *avctx, AMFSurface *pSurface)
Definition: vf_amf_common.c:390
imgutils.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_amf_light_metadata_to_hdrmeta
int av_amf_light_metadata_to_hdrmeta(const AVContentLightMetadata *light_meta, AMFHDRMetadata *hdrmeta)
Definition: hwcontext_amf.c:222
planes
static const struct @606 planes[]
av_image_copy
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
AVCOL_SPC_BT709
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition: pixfmt.h:708
AVColorRange
AVColorRange
Visual content value range.
Definition: pixfmt.h:748
av_hwframe_get_buffer
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
ff_scale_adjust_dimensions
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
av_get_pix_fmt_name
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
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:285