FFmpeg
Loading...
Searching...
No Matches
qsvvpp.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/**
20 * @file
21 * Intel Quick Sync Video VPP base function
22 */
23
24#include "libavutil/common.h"
26#include "libavutil/mem.h"
27#include "libavutil/time.h"
28#include "libavutil/pixdesc.h"
29
30#include "filters.h"
31#include "qsvvpp.h"
32#include "video.h"
33
34#if QSV_ONEVPL
35#include <mfxdispatcher.h>
36#else
37#define MFXUnload(a) do { } while(0)
38#endif
39
40#define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
41 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
42#if QSV_HAVE_OPAQUE
43#define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
44#endif
45#define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
46#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
47
48#define QSV_HAVE_AUDIO !QSV_ONEVPL
49
50static const AVRational default_tb = { 1, 90000 };
51
52typedef struct QSVAsyncFrame {
53 mfxSyncPoint sync;
56
57static const struct {
59 const char *desc;
60} qsv_iopatterns[] = {
61 {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
62 {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
63#if QSV_HAVE_OPAQUE
64 {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
65#endif
66 {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
67 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
68#if QSV_HAVE_OPAQUE
69 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
70#endif
71};
72
74 const char *extra_string)
75{
76 const char *desc = NULL;
77
78 for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) {
80 desc = qsv_iopatterns[i].desc;
81 }
82 }
83 if (!desc)
84 desc = "unknown iopattern";
85
86 av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc);
87 return 0;
88}
89
90static const struct {
91 mfxStatus mfxerr;
92 int averr;
93 const char *desc;
94} qsv_errors[] = {
95 { MFX_ERR_NONE, 0, "success" },
96 { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" },
97 { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" },
98 { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" },
99 { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" },
100 { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" },
101 { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" },
102 { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" },
103 { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" },
104 { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" },
105 /* the following 3 errors should always be handled explicitly, so those "mappings"
106 * are for completeness only */
107 { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" },
108 { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" },
109 { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" },
110 { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" },
111 { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" },
112 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" },
113 { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" },
114 { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" },
115 { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" },
116#if QSV_HAVE_AUDIO
117 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" },
118 { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" },
119#endif
120 { MFX_ERR_GPU_HANG, AVERROR(EIO), "GPU Hang" },
121 { MFX_ERR_REALLOC_SURFACE, AVERROR_UNKNOWN, "need bigger surface for output" },
122
123 { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
124 { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
125 { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
126 { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
127 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
128 { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
129 { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
130 { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
131#if QSV_HAVE_AUDIO
132 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
133#endif
134
135#if QSV_VERSION_ATLEAST(1, 31)
136 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0, "partial output" },
137#endif
139
140static int qsv_map_error(mfxStatus mfx_err, const char **desc)
141{
142 int i;
143 for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) {
144 if (qsv_errors[i].mfxerr == mfx_err) {
145 if (desc)
146 *desc = qsv_errors[i].desc;
147 return qsv_errors[i].averr;
148 }
149 }
150 if (desc)
151 *desc = "unknown error";
152 return AVERROR_UNKNOWN;
153}
154
155int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err,
156 const char *error_string)
157{
158 const char *desc;
159 int ret;
160 ret = qsv_map_error(err, &desc);
161 av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
162 return ret;
163}
164
165int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err,
166 const char *warning_string)
167{
168 const char *desc;
169 int ret;
170 ret = qsv_map_error(err, &desc);
171 av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err);
172 return ret;
173}
174
175/* functions for frameAlloc */
176static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
177 mfxFrameAllocResponse *resp)
178{
179 QSVVPPContext *s = pthis;
180 int i;
181
182 if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
183 !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
184 !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
185 return MFX_ERR_UNSUPPORTED;
186
187 if (req->Type & MFX_MEMTYPE_FROM_VPPIN) {
188 resp->mids = av_mallocz(s->nb_surface_ptrs_in * sizeof(*resp->mids));
189 if (!resp->mids)
190 return AVERROR(ENOMEM);
191
192 for (i = 0; i < s->nb_surface_ptrs_in; i++)
193 resp->mids[i] = s->surface_ptrs_in[i]->Data.MemId;
194
195 resp->NumFrameActual = s->nb_surface_ptrs_in;
196 } else {
197 resp->mids = av_mallocz(s->nb_surface_ptrs_out * sizeof(*resp->mids));
198 if (!resp->mids)
199 return AVERROR(ENOMEM);
200
201 for (i = 0; i < s->nb_surface_ptrs_out; i++)
202 resp->mids[i] = s->surface_ptrs_out[i]->Data.MemId;
203
204 resp->NumFrameActual = s->nb_surface_ptrs_out;
205 }
206
207 return MFX_ERR_NONE;
208}
209
210static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
211{
212 av_freep(&resp->mids);
213 return MFX_ERR_NONE;
214}
215
216static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
217{
218 return MFX_ERR_UNSUPPORTED;
219}
220
221static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
222{
223 return MFX_ERR_UNSUPPORTED;
224}
225
226static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
227{
228 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
229 mfxHDLPair *pair_src = (mfxHDLPair*)mid;
230
231 pair_dst->first = pair_src->first;
232
233 if (pair_src->second != (mfxMemId)MFX_INFINITE)
234 pair_dst->second = pair_src->second;
235 return MFX_ERR_NONE;
236}
237
239{
240 switch (format) {
242 return MFX_FOURCC_YV12;
243 case AV_PIX_FMT_NV12:
244 return MFX_FOURCC_NV12;
246 return MFX_FOURCC_YUY2;
247 case AV_PIX_FMT_BGRA:
248 return MFX_FOURCC_RGB4;
249 case AV_PIX_FMT_P010:
250 return MFX_FOURCC_P010;
251#if CONFIG_VAAPI
253 return MFX_FOURCC_UYVY;
254#endif
255 }
256
257 return MFX_FOURCC_NV12;
258}
259
260static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
261{
262 switch (frame->format) {
263 case AV_PIX_FMT_NV12:
264 case AV_PIX_FMT_P010:
265 surface->Data.Y = frame->data[0];
266 surface->Data.UV = frame->data[1];
267 break;
269 surface->Data.Y = frame->data[0];
270 surface->Data.U = frame->data[1];
271 surface->Data.V = frame->data[2];
272 break;
274 surface->Data.Y = frame->data[0];
275 surface->Data.U = frame->data[0] + 1;
276 surface->Data.V = frame->data[0] + 3;
277 break;
278 case AV_PIX_FMT_RGB32:
279 surface->Data.B = frame->data[0];
280 surface->Data.G = frame->data[0] + 1;
281 surface->Data.R = frame->data[0] + 2;
282 surface->Data.A = frame->data[0] + 3;
283 break;
285 surface->Data.Y = frame->data[0] + 1;
286 surface->Data.U = frame->data[0];
287 surface->Data.V = frame->data[0] + 2;
288 break;
289 default:
290 return MFX_ERR_UNSUPPORTED;
291 }
292 surface->Data.Pitch = frame->linesize[0];
293
294 return 0;
295}
296
297/* fill the surface info */
298static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
299{
300 FilterLink *l = ff_filter_link(link);
302 AVHWFramesContext *frames_ctx;
303 AVQSVFramesContext *frames_hwctx;
305
306 if (link->format == AV_PIX_FMT_QSV) {
307 if (!l->hw_frames_ctx)
308 return AVERROR(EINVAL);
309
310 frames_ctx = (AVHWFramesContext *)l->hw_frames_ctx->data;
311 frames_hwctx = frames_ctx->hwctx;
312 *frameinfo = frames_hwctx->nb_surfaces ? frames_hwctx->surfaces[0].Info : *frames_hwctx->info;
313 } else {
314 pix_fmt = link->format;
316 if (!desc)
317 return AVERROR_BUG;
318
319 frameinfo->CropX = 0;
320 frameinfo->CropY = 0;
321 frameinfo->Width = FFALIGN(link->w, 32);
322 frameinfo->Height = FFALIGN(link->h, 32);
323 frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
324 frameinfo->FourCC = pix_fmt_to_mfx_fourcc(pix_fmt);
325 frameinfo->BitDepthLuma = desc->comp[0].depth;
326 frameinfo->BitDepthChroma = desc->comp[0].depth;
327 frameinfo->Shift = desc->comp[0].depth > 8;
328 if (desc->log2_chroma_w && desc->log2_chroma_h)
329 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420;
330 else if (desc->log2_chroma_w)
331 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422;
332 else
333 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444;
334 }
335
336 frameinfo->CropW = link->w;
337 frameinfo->CropH = link->h;
338 frameinfo->FrameRateExtN = l->frame_rate.num;
339 frameinfo->FrameRateExtD = l->frame_rate.den;
340
341 /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
342 * init will fail */
343 if (frameinfo->FrameRateExtD == 0 || frameinfo->FrameRateExtN == 0) {
344 frameinfo->FrameRateExtN = 25;
345 frameinfo->FrameRateExtD = 1;
346 }
347
348 frameinfo->AspectRatioW = link->sample_aspect_ratio.num ? link->sample_aspect_ratio.num : 1;
349 frameinfo->AspectRatioH = link->sample_aspect_ratio.den ? link->sample_aspect_ratio.den : 1;
350
351 return 0;
352}
353
355{
356 while (list) {
357 /* list->queued==1 means the frame is not cached in VPP
358 * process any more, it can be released to pool. */
359 if ((list->queued == 1) && !list->surface.Data.Locked) {
360 av_frame_free(&list->frame);
361 list->queued = 0;
362 }
363 list = list->next;
364 }
365}
366
367static void clear_frame_list(QSVFrame **list)
368{
369 while (*list) {
371
372 frame = *list;
373 *list = (*list)->next;
374 av_frame_free(&frame->frame);
375 av_freep(&frame);
376 }
377}
378
380{
381 QSVFrame *out = *list;
382
383 for (; out; out = out->next) {
384 if (!out->queued) {
385 out->queued = 1;
386 break;
387 }
388 }
389
390 if (!out) {
391 out = av_mallocz(sizeof(*out));
392 if (!out) {
393 av_log(NULL, AV_LOG_ERROR, "Can't alloc new output frame.\n");
394 return NULL;
395 }
396 out->queued = 1;
397 out->next = *list;
398 *list = out;
399 }
400
401 return out;
402}
403
404/* get the input surface */
406{
407 QSVFrame *qsv_frame;
408 AVFilterContext *ctx = inlink->dst;
409
410 clear_unused_frames(s->in_frame_list);
411
412 qsv_frame = get_free_frame(&s->in_frame_list);
413 if (!qsv_frame)
414 return NULL;
415
416 /* Turn AVFrame into mfxFrameSurface1.
417 * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and
418 * mfxFrameSurface1 is stored in AVFrame->data[3];
419 * for system memory mode, raw video data is stored in
420 * AVFrame, we should map it into mfxFrameSurface1.
421 */
422 if (!IS_SYSTEM_MEMORY(s->in_mem_mode)) {
423 if (picref->format != AV_PIX_FMT_QSV) {
424 av_log(ctx, AV_LOG_ERROR, "QSVVPP gets a wrong frame.\n");
425 return NULL;
426 }
427 qsv_frame->frame = av_frame_clone(picref);
428 qsv_frame->surface = *(mfxFrameSurface1 *)qsv_frame->frame->data[3];
429 } else {
430 /* make a copy if the input is not padded as libmfx requires */
431 if (picref->height & 31 || picref->linesize[0] & 31) {
432 qsv_frame->frame = ff_get_video_buffer(inlink,
433 FFALIGN(inlink->w, 32),
434 FFALIGN(inlink->h, 32));
435 if (!qsv_frame->frame)
436 return NULL;
437
438 qsv_frame->frame->width = picref->width;
439 qsv_frame->frame->height = picref->height;
440
441 if (av_frame_copy(qsv_frame->frame, picref) < 0) {
442 av_frame_free(&qsv_frame->frame);
443 return NULL;
444 }
445 } else
446 qsv_frame->frame = av_frame_clone(picref);
447
448 if (map_frame_to_surface(qsv_frame->frame,
449 &qsv_frame->surface) < 0) {
450 av_log(ctx, AV_LOG_ERROR, "Unsupported frame.\n");
451 return NULL;
452 }
453 }
454
455 qsv_frame->surface.Info = s->frame_infos[FF_INLINK_IDX(inlink)];
456 qsv_frame->surface.Data.TimeStamp = av_rescale_q(qsv_frame->frame->pts,
457 inlink->time_base, default_tb);
458
459 qsv_frame->surface.Info.PicStruct =
460 !(qsv_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE :
461 ((qsv_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF :
462 MFX_PICSTRUCT_FIELD_BFF);
463 if (qsv_frame->frame->repeat_pict == 1)
464 qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
465 else if (qsv_frame->frame->repeat_pict == 2)
466 qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
467 else if (qsv_frame->frame->repeat_pict == 4)
468 qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
469
470 return qsv_frame;
471}
472
473/* get the output surface */
475 const AVFrame *propref)
476{
477 FilterLink *l = ff_filter_link(outlink);
478 AVFilterContext *ctx = outlink->src;
479 QSVFrame *out_frame;
480 int ret;
481
482 clear_unused_frames(s->out_frame_list);
483
484 out_frame = get_free_frame(&s->out_frame_list);
485 if (!out_frame)
486 return NULL;
487
488 /* For video memory, get a hw frame;
489 * For system memory, get a sw frame and map it into a mfx_surface. */
490 if (!IS_SYSTEM_MEMORY(s->out_mem_mode)) {
491 out_frame->frame = av_frame_alloc();
492 if (!out_frame->frame)
493 return NULL;
494
495 ret = av_hwframe_get_buffer(l->hw_frames_ctx, out_frame->frame, 0);
496 if (ret < 0) {
497 av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n");
498 return NULL;
499 }
500
501 out_frame->surface = *(mfxFrameSurface1 *)out_frame->frame->data[3];
502 } else {
503 /* Get a frame with aligned dimensions.
504 * Libmfx need system memory being 128x64 aligned */
505 out_frame->frame = ff_get_video_buffer(outlink,
506 FFALIGN(outlink->w, 128),
507 FFALIGN(outlink->h, 64));
508 if (!out_frame->frame)
509 return NULL;
510
511 ret = map_frame_to_surface(out_frame->frame,
512 &out_frame->surface);
513 if (ret < 0)
514 return NULL;
515 }
516
517 if (propref) {
518 ret = av_frame_copy_props(out_frame->frame, propref);
519 if (ret < 0) {
520 av_frame_free(&out_frame->frame);
521 av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n");
522 return NULL;
523 }
524 }
525
526 if (l->frame_rate.num && l->frame_rate.den)
527 out_frame->frame->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
528 else
529 out_frame->frame->duration = 0;
530
531 out_frame->frame->width = outlink->w;
532 out_frame->frame->height = outlink->h;
533 out_frame->surface.Info = s->vpp_param.vpp.Out;
534
535 for (int i = 0; i < s->vpp_param.NumExtParam; i++) {
536 mfxExtBuffer *extbuf = s->vpp_param.ExtParam[i];
537
538 if (extbuf->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING) {
540 break;
541 }
542 }
543
544 out_frame->surface.Info.PicStruct =
545 !(out_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE :
546 ((out_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF :
547 MFX_PICSTRUCT_FIELD_BFF);
548
549 return out_frame;
550}
551
552/* create the QSV session */
554{
555 AVFilterLink *inlink = avctx->inputs[0];
556 FilterLink *inl = ff_filter_link(inlink);
557 AVFilterLink *outlink = avctx->outputs[0];
558 FilterLink *outl = ff_filter_link(outlink);
559 AVQSVFramesContext *in_frames_hwctx = NULL;
560 AVQSVFramesContext *out_frames_hwctx = NULL;
561
562 AVBufferRef *device_ref;
563 AVHWDeviceContext *device_ctx;
564 AVQSVDeviceContext *device_hwctx;
565 mfxHDL handle;
566 mfxHandleType handle_type;
567 mfxVersion ver;
568 mfxIMPL impl;
569 int ret, i;
570
571 if (inl->hw_frames_ctx) {
573
574 device_ref = frames_ctx->device_ref;
575 in_frames_hwctx = frames_ctx->hwctx;
576
577 s->in_mem_mode = in_frames_hwctx->frame_type;
578
579 s->surface_ptrs_in = av_calloc(in_frames_hwctx->nb_surfaces,
580 sizeof(*s->surface_ptrs_in));
581 if (!s->surface_ptrs_in)
582 return AVERROR(ENOMEM);
583
584 for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
585 s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
586
587 s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
588 } else if (avctx->hw_device_ctx) {
589 device_ref = avctx->hw_device_ctx;
590 s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
591 } else {
592 av_log(avctx, AV_LOG_ERROR, "No hw context provided.\n");
593 return AVERROR(EINVAL);
594 }
595
596 device_ctx = (AVHWDeviceContext *)device_ref->data;
597 device_hwctx = device_ctx->hwctx;
598
599 /* extract the properties of the "master" session given to us */
600 ret = MFXQueryIMPL(device_hwctx->session, &impl);
601 if (ret == MFX_ERR_NONE)
602 ret = MFXQueryVersion(device_hwctx->session, &ver);
603 if (ret != MFX_ERR_NONE) {
604 av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n");
605 return AVERROR_UNKNOWN;
606 }
607
608 if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
609 handle_type = MFX_HANDLE_VA_DISPLAY;
610 } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
611 handle_type = MFX_HANDLE_D3D11_DEVICE;
612 } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
613 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
614 } else {
615 av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n");
616 return AVERROR_UNKNOWN;
617 }
618
619 if (outlink->format == AV_PIX_FMT_QSV) {
620 AVHWFramesContext *out_frames_ctx;
621 AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref);
622 if (!out_frames_ref)
623 return AVERROR(ENOMEM);
624
625#if QSV_HAVE_OPAQUE
626 s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ?
627 MFX_MEMTYPE_OPAQUE_FRAME :
628 MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
629#else
630 s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
631#endif
632
633 out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data;
634 out_frames_hwctx = out_frames_ctx->hwctx;
635
636 out_frames_ctx->format = AV_PIX_FMT_QSV;
637 out_frames_ctx->width = FFALIGN(outlink->w, 32);
638 out_frames_ctx->height = FFALIGN(outlink->h, 32);
639 out_frames_ctx->sw_format = s->out_sw_format;
640
641 if (QSV_RUNTIME_VERSION_ATLEAST(ver, 2, 9) && handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER)
642 out_frames_ctx->initial_pool_size = 0;
643 else {
644 out_frames_ctx->initial_pool_size = 64;
645 if (avctx->extra_hw_frames > 0)
646 out_frames_ctx->initial_pool_size += avctx->extra_hw_frames;
647 }
648
649 out_frames_hwctx->frame_type = s->out_mem_mode;
650
651 ret = av_hwframe_ctx_init(out_frames_ref);
652 if (ret < 0) {
653 av_buffer_unref(&out_frames_ref);
654 av_log(avctx, AV_LOG_ERROR, "Error creating frames_ctx for output pad.\n");
655 return ret;
656 }
657
658 s->surface_ptrs_out = av_calloc(out_frames_hwctx->nb_surfaces,
659 sizeof(*s->surface_ptrs_out));
660 if (!s->surface_ptrs_out) {
661 av_buffer_unref(&out_frames_ref);
662 return AVERROR(ENOMEM);
663 }
664
665 for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
666 s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
667 s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
668
670 outl->hw_frames_ctx = out_frames_ref;
671 } else
672 s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
673
674 ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
675 if (ret < 0)
676 return ff_qsvvpp_print_error(avctx, ret, "Error getting the session handle");
677 else if (ret > 0) {
678 ff_qsvvpp_print_warning(avctx, ret, "Warning in getting the session handle");
679 return AVERROR_UNKNOWN;
680 }
681
682 /* create a "slave" session with those same properties, to be used for vpp */
683 ret = ff_qsvvpp_create_mfx_session(avctx, device_hwctx->loader, impl, &ver,
684 &s->session);
685 if (ret)
686 return ret;
687
688 ret = MFXQueryVersion(s->session, &s->ver);
689 if (ret != MFX_ERR_NONE) {
690 av_log(avctx, AV_LOG_ERROR, "Error querying the runtime version\n");
691 return AVERROR_UNKNOWN;
692 }
693
694 if (handle) {
695 ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
696 if (ret != MFX_ERR_NONE)
697 return AVERROR_UNKNOWN;
698 }
699
700 if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
701 ret = MFXJoinSession(device_hwctx->session, s->session);
702 if (ret != MFX_ERR_NONE)
703 return AVERROR_UNKNOWN;
704 }
705
706#if QSV_HAVE_OPAQUE
707 if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
708 s->opaque_alloc.In.Surfaces = s->surface_ptrs_in;
709 s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
710 s->opaque_alloc.In.Type = s->in_mem_mode;
711
712 s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out;
713 s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
714 s->opaque_alloc.Out.Type = s->out_mem_mode;
715
716 s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
717 s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
718 } else
719#endif
720 if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) {
721 mfxFrameAllocator frame_allocator = {
722 .pthis = s,
723 .Alloc = frame_alloc,
724 .Lock = frame_lock,
725 .Unlock = frame_unlock,
726 .GetHDL = frame_get_hdl,
727 .Free = frame_free,
728 };
729
730 ret = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator);
731 if (ret != MFX_ERR_NONE)
732 return AVERROR_UNKNOWN;
733 }
734
735 return 0;
736}
737
739{
740 return 0;
741}
742
744{
745 int i;
746 int ret;
747 QSVVPPContext *s = avctx->priv;
748
749 s->filter_frame = param->filter_frame;
750 if (!s->filter_frame)
751 s->filter_frame = ff_filter_frame;
752 s->out_sw_format = param->out_sw_format;
753
754 s->set_frame_ext_params = param->set_frame_ext_params;
755 if (!s->set_frame_ext_params)
756 s->set_frame_ext_params = set_frame_ext_params_null;
757
758 /* create the vpp session */
759 ret = init_vpp_session(avctx, s);
760 if (ret < 0)
761 goto failed;
762
763 s->frame_infos = av_calloc(avctx->nb_inputs, sizeof(*s->frame_infos));
764 if (!s->frame_infos) {
765 ret = AVERROR(ENOMEM);
766 goto failed;
767 }
768
769 /* Init each input's information */
770 for (i = 0; i < avctx->nb_inputs; i++) {
771 ret = fill_frameinfo_by_link(&s->frame_infos[i], avctx->inputs[i]);
772 if (ret < 0)
773 goto failed;
774 }
775
776 /* Update input's frame info according to crop */
777 for (i = 0; i < param->num_crop; i++) {
778 QSVVPPCrop *crop = param->crop + i;
779 if (crop->in_idx > avctx->nb_inputs) {
780 ret = AVERROR(EINVAL);
781 goto failed;
782 }
783 s->frame_infos[crop->in_idx].CropX = crop->x;
784 s->frame_infos[crop->in_idx].CropY = crop->y;
785 s->frame_infos[crop->in_idx].CropW = crop->w;
786 s->frame_infos[crop->in_idx].CropH = crop->h;
787 }
788
789 s->vpp_param.vpp.In = s->frame_infos[0];
790
791 ret = fill_frameinfo_by_link(&s->vpp_param.vpp.Out, avctx->outputs[0]);
792 if (ret < 0) {
793 av_log(avctx, AV_LOG_ERROR, "Fail to get frame info from link.\n");
794 goto failed;
795 }
796
797 s->nb_seq_buffers = param->num_ext_buf;
798#if QSV_HAVE_OPAQUE
799 if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode))
800 s->nb_seq_buffers++;
801#endif
802
803 if (s->nb_seq_buffers) {
804 s->seq_buffers = av_calloc(s->nb_seq_buffers, sizeof(*s->seq_buffers));
805 if (!s->seq_buffers) {
806 ret = AVERROR(ENOMEM);
807 goto failed;
808 }
809
810 for (i = 0; i < param->num_ext_buf; i++)
811 s->seq_buffers[i] = param->ext_buf[i];
812
813#if QSV_HAVE_OPAQUE
814 if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode))
815 s->seq_buffers[i] = (mfxExtBuffer *)&s->opaque_alloc;
816#endif
817
818 s->nb_ext_buffers = s->nb_seq_buffers;
819 s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers));
820 if (!s->ext_buffers) {
821 ret = AVERROR(ENOMEM);
822 goto failed;
823 }
824
825 memcpy(s->ext_buffers, s->seq_buffers, s->nb_seq_buffers * sizeof(*s->seq_buffers));
826 }
827
828 s->vpp_param.ExtParam = s->ext_buffers;
829 s->vpp_param.NumExtParam = s->nb_ext_buffers;
830
831 s->got_frame = 0;
832
833 /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
834 s->async_fifo = av_fifo_alloc2(s->async_depth + 1, sizeof(QSVAsyncFrame), 0);
835 if (!s->async_fifo) {
836 ret = AVERROR(ENOMEM);
837 goto failed;
838 }
839
840 s->vpp_param.AsyncDepth = s->async_depth;
841
842 if (IS_SYSTEM_MEMORY(s->in_mem_mode))
843 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
844 else if (IS_VIDEO_MEMORY(s->in_mem_mode))
845 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
846#if QSV_HAVE_OPAQUE
847 else if (IS_OPAQUE_MEMORY(s->in_mem_mode))
848 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
849#endif
850
851 if (IS_SYSTEM_MEMORY(s->out_mem_mode))
852 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
853 else if (IS_VIDEO_MEMORY(s->out_mem_mode))
854 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
855#if QSV_HAVE_OPAQUE
856 else if (IS_OPAQUE_MEMORY(s->out_mem_mode))
857 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
858#endif
859
860 /* Print input memory mode */
861 ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP");
862 /* Print output memory mode */
863 ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP");
864
865 /* Validate VPP params, but don't initial VPP session here */
866 ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param);
867 if (ret < 0) {
868 ret = ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params");
869 goto failed;
870 } else if (ret > 0)
871 ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params");
872
873 return 0;
874
875failed:
876 ff_qsvvpp_close(avctx);
877
878 return ret;
879}
880
882{
883 int ret;
884 mfxExtBuffer *ext_param[QSVVPP_MAX_FRAME_EXTBUFS];
885 QSVVPPFrameParam fp = { 0, ext_param };
886
887 ret = s->set_frame_ext_params(avctx, in->frame, out->frame, &fp);
888 if (ret)
889 return ret;
890
891 if (fp.num_ext_buf) {
892 av_freep(&s->ext_buffers);
893 s->nb_ext_buffers = s->nb_seq_buffers + fp.num_ext_buf;
894
895 s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers));
896 if (!s->ext_buffers)
897 return AVERROR(ENOMEM);
898
899 memcpy(&s->ext_buffers[0], s->seq_buffers, s->nb_seq_buffers * sizeof(*s->seq_buffers));
900 memcpy(&s->ext_buffers[s->nb_seq_buffers], fp.ext_buf, fp.num_ext_buf * sizeof(*fp.ext_buf));
901 s->vpp_param.ExtParam = s->ext_buffers;
902 s->vpp_param.NumExtParam = s->nb_ext_buffers;
903 }
904
905 if (!s->vpp_initted) {
906 s->vpp_param.vpp.In.PicStruct = in->surface.Info.PicStruct;
907 s->vpp_param.vpp.Out.PicStruct = out->surface.Info.PicStruct;
908
909 /* Query VPP params again, including params for frame */
910 ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param);
911 if (ret < 0)
912 return ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params");
913 else if (ret > 0)
914 ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params");
915
916 ret = MFXVideoVPP_Init(s->session, &s->vpp_param);
917 if (ret < 0)
918 return ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp");
919 else if (ret > 0)
920 ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp");
921
922 s->vpp_initted = 1;
923 } else if (fp.num_ext_buf) {
924 ret = MFXVideoVPP_Reset(s->session, &s->vpp_param);
925 if (ret < 0) {
926 ret = ff_qsvvpp_print_error(avctx, ret, "Failed to reset session for qsvvpp");
927 return ret;
928 } else if (ret > 0)
929 ff_qsvvpp_print_warning(avctx, ret, "Warning When resetting session for qsvvpp");
930 }
931
932 return 0;
933}
934
936{
937 QSVVPPContext *s = avctx->priv;
938
939 if (s->session) {
940 MFXVideoVPP_Close(s->session);
941 MFXClose(s->session);
942 s->session = NULL;
943 s->vpp_initted = 0;
944 }
945
946 /* release all the resources */
947 clear_frame_list(&s->in_frame_list);
948 clear_frame_list(&s->out_frame_list);
949 av_freep(&s->surface_ptrs_in);
950 av_freep(&s->surface_ptrs_out);
951 av_freep(&s->seq_buffers);
952 av_freep(&s->ext_buffers);
953 av_freep(&s->frame_infos);
954 av_fifo_freep2(&s->async_fifo);
955
956 return 0;
957}
958
960{
961 AVFilterContext *ctx = inlink->dst;
962 AVFilterLink *outlink = ctx->outputs[0];
963 QSVAsyncFrame aframe;
964 mfxSyncPoint sync;
965 QSVFrame *in_frame, *out_frame;
966 int ret, ret1, filter_ret;
967
968 while (s->eof && av_fifo_read(s->async_fifo, &aframe, 1) >= 0) {
969 if (MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000) < 0)
970 av_log(ctx, AV_LOG_WARNING, "Sync failed.\n");
971
972 filter_ret = s->filter_frame(outlink, aframe.frame->frame);
973 if (filter_ret < 0) {
974 av_frame_free(&aframe.frame->frame);
975 return filter_ret;
976 }
977 aframe.frame->queued--;
978 s->got_frame = 1;
979 aframe.frame->frame = NULL;
980 };
981
982 if (!picref)
983 return 0;
984
985 in_frame = submit_frame(s, inlink, picref);
986 if (!in_frame) {
987 av_log(ctx, AV_LOG_ERROR, "Failed to submit frame on input[%d]\n",
988 FF_INLINK_IDX(inlink));
989 return AVERROR(ENOMEM);
990 }
991
992 do {
993 out_frame = query_frame(s, outlink, in_frame->frame, propref);
994 if (!out_frame) {
995 av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n");
996 return AVERROR(ENOMEM);
997 }
998
999 ret = qsvvpp_init_vpp_session(ctx, s, in_frame, out_frame);
1000 if (ret)
1001 return ret;
1002
1003 do {
1004 ret = MFXVideoVPP_RunFrameVPPAsync(s->session, &in_frame->surface,
1005 &out_frame->surface, NULL, &sync);
1006 if (ret == MFX_WRN_DEVICE_BUSY)
1007 av_usleep(500);
1008 } while (ret == MFX_WRN_DEVICE_BUSY);
1009
1010 if (ret < 0 && ret != MFX_ERR_MORE_SURFACE) {
1011 /* Ignore more_data error */
1012 if (ret == MFX_ERR_MORE_DATA)
1013 return AVERROR(EAGAIN);
1014 break;
1015 }
1016
1017 out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp,
1018 default_tb, outlink->time_base);
1019
1020 out_frame->queued++;
1021 aframe = (QSVAsyncFrame){ sync, out_frame };
1022 av_fifo_write(s->async_fifo, &aframe, 1);
1023
1024 if (av_fifo_can_read(s->async_fifo) > s->async_depth) {
1025 av_fifo_read(s->async_fifo, &aframe, 1);
1026
1027 do {
1028 ret1 = MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000);
1029 } while (ret1 == MFX_WRN_IN_EXECUTION);
1030
1031 if (ret1 < 0) {
1032 ret = ret1;
1033 break;
1034 }
1035
1036 filter_ret = s->filter_frame(outlink, aframe.frame->frame);
1037 if (filter_ret < 0) {
1038 av_frame_free(&aframe.frame->frame);
1039 return filter_ret;
1040 }
1041
1042 aframe.frame->queued--;
1043 s->got_frame = 1;
1044 aframe.frame->frame = NULL;
1045 }
1046 } while(ret == MFX_ERR_MORE_SURFACE);
1047
1048 if (ret < 0)
1049 return ff_qsvvpp_print_error(ctx, ret, "Error running VPP");
1050 else if (ret > 0)
1051 ff_qsvvpp_print_warning(ctx, ret, "Warning in running VPP");
1052
1053 return 0;
1054}
1055
1056#if QSV_ONEVPL
1057
1059 void *loader,
1060 mfxIMPL implementation,
1061 mfxVersion *pver,
1062 mfxSession *psession)
1063{
1064 mfxStatus sts;
1065 mfxSession session = NULL;
1066 uint32_t impl_idx = 0;
1067
1069 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
1070
1071 if (!loader) {
1072 av_log(ctx, AV_LOG_ERROR, "Invalid MFX Loader handle\n");
1073 return AVERROR(EINVAL);
1074 }
1075
1076 while (1) {
1077 /* Enumerate all implementations */
1078 mfxImplDescription *impl_desc;
1079
1080 sts = MFXEnumImplementations(loader, impl_idx,
1081 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
1082 (mfxHDL *)&impl_desc);
1083 /* Failed to find an available implementation */
1084 if (sts == MFX_ERR_NOT_FOUND)
1085 break;
1086 else if (sts != MFX_ERR_NONE) {
1087 impl_idx++;
1088 continue;
1089 }
1090
1091 sts = MFXCreateSession(loader, impl_idx, &session);
1092 MFXDispReleaseImplDescription(loader, impl_desc);
1093 if (sts == MFX_ERR_NONE)
1094 break;
1095
1096 impl_idx++;
1097 }
1098
1099 if (sts < 0)
1100 return ff_qsvvpp_print_error(ctx, sts,
1101 "Error creating a MFX session");
1102
1103 *psession = session;
1104
1105 return 0;
1106}
1107
1108#else
1109
1111 void *loader,
1112 mfxIMPL implementation,
1113 mfxVersion *pver,
1114 mfxSession *psession)
1115{
1116 mfxSession session = NULL;
1117 mfxStatus sts;
1118
1120 "Use Intel(R) Media SDK to create MFX session, API version is "
1121 "%d.%d, the required implementation version is %d.%d\n",
1122 MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1123
1124 *psession = NULL;
1125 sts = MFXInit(implementation, pver, &session);
1126 if (sts < 0)
1127 return ff_qsvvpp_print_error(ctx, sts,
1128 "Error initializing an MFX session");
1129 else if (sts > 0) {
1130 ff_qsvvpp_print_warning(ctx, sts, "Warning in MFX session initialization");
1131 return AVERROR_UNKNOWN;
1132 }
1133
1134 *psession = session;
1135
1136 return 0;
1137}
1138
1139#endif
1140
1142{
1143 /* When process YUV420 frames, FFmpeg uses same alignment on Y/U/V
1144 * planes. VPL and MSDK use Y plane's pitch / 2 as U/V planes's
1145 * pitch, which makes U/V planes 16-bytes aligned. We need to set a
1146 * separate alignment to meet runtime's behaviour.
1147 */
1148 return ff_default_get_video_buffer2(inlink,
1149 FFALIGN(inlink->w, 32),
1150 FFALIGN(inlink->h, 32),
1151 16);
1152}
static const char *const format[]
Definition af_aiir.c:444
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
common internal and external API header
#define NULL
Definition coverity.c:32
static enum AVPixelFormat pix_fmt
static AVFrame * frame
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
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#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
size_t av_fifo_can_read(const AVFifo *f)
Definition fifo.c:87
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
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition frame.h:695
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition frame.h:700
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
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition frame.c:711
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
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
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define FF_INLINK_IDX(link)
Find the index of a link.
Definition filters.h:215
const char * desc
Definition libsvtav1.c:83
uint8_t w
Definition llvidencdsp.c:39
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
int averr
Definition nvenc.c:157
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_P010
Definition pixfmt.h:608
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ 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
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition pixfmt.h:247
#define AV_PIX_FMT_RGB32
Definition pixfmt.h:517
int mfx_iopattern
Definition qsv.c:89
static const struct @263361020336145376152124322306240314177011071374 qsv_iopatterns[]
static const struct @313360353265145032047314164301105156143154063363 qsv_errors[]
mfxStatus mfxerr
Definition qsv.c:122
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
static const AVRational default_tb
Definition qsvvpp.c:50
#define IS_VIDEO_MEMORY(mode)
Definition qsvvpp.c:40
static int qsv_map_error(mfxStatus mfx_err, const char **desc)
Definition qsvvpp.c:140
AVFrame * ff_qsvvpp_get_video_buffer(AVFilterLink *inlink, int w, int h)
Definition qsvvpp.c:1141
static int pix_fmt_to_mfx_fourcc(int format)
Definition qsvvpp.c:238
static void clear_frame_list(QSVFrame **list)
Definition qsvvpp.c:367
int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern, const char *extra_string)
Definition qsvvpp.c:73
static QSVFrame * get_free_frame(QSVFrame **list)
Definition qsvvpp.c:379
static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition qsvvpp.c:176
int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref, AVFrame *propref)
Definition qsvvpp.c:959
static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition qsvvpp.c:226
int ff_qsvvpp_create_mfx_session(void *ctx, void *loader, mfxIMPL implementation, mfxVersion *pver, mfxSession *psession)
Definition qsvvpp.c:1110
static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
Definition qsvvpp.c:298
static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition qsvvpp.c:216
#define IS_SYSTEM_MEMORY(mode)
Definition qsvvpp.c:45
static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
Definition qsvvpp.c:260
static QSVFrame * query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in, const AVFrame *propref)
Definition qsvvpp.c:474
static void clear_unused_frames(QSVFrame *list)
Definition qsvvpp.c:354
int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition qsvvpp.c:155
static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
Definition qsvvpp.c:553
#define MFX_IMPL_VIA_MASK(impl)
Definition qsvvpp.c:46
int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition qsvvpp.c:165
static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition qsvvpp.c:210
static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition qsvvpp.c:221
static int qsvvpp_init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s, const QSVFrame *in, QSVFrame *out)
Definition qsvvpp.c:881
static QSVFrame * submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref)
Definition qsvvpp.c:405
int ff_qsvvpp_close(AVFilterContext *avctx)
Definition qsvvpp.c:935
static int set_frame_ext_params_null(AVFilterContext *ctx, const AVFrame *in, AVFrame *out, QSVVPPFrameParam *fp)
Definition qsvvpp.c:738
int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param)
Definition qsvvpp.c:743
Intel Quick Sync Video VPP base function.
#define QSVVPP_MAX_FRAME_EXTBUFS
Definition qsvvpp.h:55
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
An instance of a filter.
Definition avfilter.h:273
int extra_hw_frames
Sets the number of extra hardware frames which the filter will allocate on its output links for use i...
Definition avfilter.h:352
unsigned nb_inputs
number of input pads
Definition avfilter.h:282
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
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
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
Definition frame.h:716
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
int64_t duration
Duration of the frame, in the same units as pts.
Definition frame.h:820
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:559
int repeat_pict
Number of fields in this frame which should be repeated, i.e.
Definition frame.h:630
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
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
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int initial_pool_size
Initial size of the frame pool.
Definition hwcontext.h:190
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
This struct is allocated as AVHWDeviceContext.hwctx.
void * loader
The mfxLoader handle used for mfxSession creation.
This struct is allocated as AVHWFramesContext.hwctx.
mfxFrameSurface1 * surfaces
A pointer to a mfxFrameSurface1 struct.
int nb_surfaces
Number of frames in the pool.
int frame_type
A combination of MFX_MEMTYPE_* describing the frame pool.
mfxFrameInfo * info
A pointer to a mfxFrameInfo struct.
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
QSVFrame * frame
Definition qsvdec.c:76
mfxSyncPoint * sync
Definition qsvdec.c:75
AVFrame * frame
struct QSVFrame * next
mfxFrameSurface1 surface
int h
Crop rectangle.
Definition qsvvpp.h:107
int in_idx
Input index.
Definition qsvvpp.h:106
mfxExtBuffer ** ext_buf
Definition qsvvpp.h:60
int(* set_frame_ext_params)(AVFilterContext *ctx, const AVFrame *in, AVFrame *out, QSVVPPFrameParam *fp)
callback
Definition qsvvpp.h:113
int num_crop
Definition qsvvpp.h:123
QSVVPPCrop * crop
Definition qsvvpp.h:124
mfxExtBuffer ** ext_buf
Definition qsvvpp.h:117
int(* filter_frame)(AVFilterLink *outlink, AVFrame *frame)
Definition qsvvpp.h:112
enum AVPixelFormat out_sw_format
Definition qsvvpp.h:120
int num_ext_buf
Definition qsvvpp.h:116
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition time.c:93
AVFrame * ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int align)
Definition video.c:49
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89