GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/vaapi_decode.c Lines: 0 330 0.0 %
Date: 2020-09-25 23:16:12 Branches: 0 146 0.0 %

Line Branch Exec Source
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 "libavutil/avassert.h"
20
#include "libavutil/common.h"
21
#include "libavutil/pixdesc.h"
22
23
#include "avcodec.h"
24
#include "decode.h"
25
#include "internal.h"
26
#include "vaapi_decode.h"
27
#include "vaapi_hevc.h"
28
29
30
int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx,
31
                                      VAAPIDecodePicture *pic,
32
                                      int type,
33
                                      const void *data,
34
                                      size_t size)
35
{
36
    VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
37
    VAStatus vas;
38
    VABufferID buffer;
39
40
    av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS);
41
42
    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
43
                         type, size, 1, (void*)data, &buffer);
44
    if (vas != VA_STATUS_SUCCESS) {
45
        av_log(avctx, AV_LOG_ERROR, "Failed to create parameter "
46
               "buffer (type %d): %d (%s).\n",
47
               type, vas, vaErrorStr(vas));
48
        return AVERROR(EIO);
49
    }
50
51
    pic->param_buffers[pic->nb_param_buffers++] = buffer;
52
53
    av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes) "
54
           "is %#x.\n", type, size, buffer);
55
    return 0;
56
}
57
58
59
int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx,
60
                                      VAAPIDecodePicture *pic,
61
                                      const void *params_data,
62
                                      size_t params_size,
63
                                      const void *slice_data,
64
                                      size_t slice_size)
65
{
66
    VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
67
    VAStatus vas;
68
    int index;
69
70
    av_assert0(pic->nb_slices <= pic->slices_allocated);
71
    if (pic->nb_slices == pic->slices_allocated) {
72
        if (pic->slices_allocated > 0)
73
            pic->slices_allocated *= 2;
74
        else
75
            pic->slices_allocated = 64;
76
77
        pic->slice_buffers =
78
            av_realloc_array(pic->slice_buffers,
79
                             pic->slices_allocated,
80
                             2 * sizeof(*pic->slice_buffers));
81
        if (!pic->slice_buffers)
82
            return AVERROR(ENOMEM);
83
    }
84
    av_assert0(pic->nb_slices + 1 <= pic->slices_allocated);
85
86
    index = 2 * pic->nb_slices;
87
88
    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
89
                         VASliceParameterBufferType,
90
                         params_size, 1, (void*)params_data,
91
                         &pic->slice_buffers[index]);
92
    if (vas != VA_STATUS_SUCCESS) {
93
        av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
94
               "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
95
        return AVERROR(EIO);
96
    }
97
98
    av_log(avctx, AV_LOG_DEBUG, "Slice %d param buffer (%zu bytes) "
99
           "is %#x.\n", pic->nb_slices, params_size,
100
           pic->slice_buffers[index]);
101
102
    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
103
                         VASliceDataBufferType,
104
                         slice_size, 1, (void*)slice_data,
105
                         &pic->slice_buffers[index + 1]);
106
    if (vas != VA_STATUS_SUCCESS) {
107
        av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
108
               "data buffer (size %zu): %d (%s).\n",
109
               slice_size, vas, vaErrorStr(vas));
110
        vaDestroyBuffer(ctx->hwctx->display,
111
                        pic->slice_buffers[index]);
112
        return AVERROR(EIO);
113
    }
114
115
    av_log(avctx, AV_LOG_DEBUG, "Slice %d data buffer (%zu bytes) "
116
           "is %#x.\n", pic->nb_slices, slice_size,
117
           pic->slice_buffers[index + 1]);
118
119
    ++pic->nb_slices;
120
    return 0;
121
}
122
123
static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx,
124
                                            VAAPIDecodePicture *pic)
125
{
126
    VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
127
    VAStatus vas;
128
    int i;
129
130
    for (i = 0; i < pic->nb_param_buffers; i++) {
131
        vas = vaDestroyBuffer(ctx->hwctx->display,
132
                              pic->param_buffers[i]);
133
        if (vas != VA_STATUS_SUCCESS) {
134
            av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
135
                   "parameter buffer %#x: %d (%s).\n",
136
                   pic->param_buffers[i], vas, vaErrorStr(vas));
137
        }
138
    }
139
140
    for (i = 0; i < 2 * pic->nb_slices; i++) {
141
        vas = vaDestroyBuffer(ctx->hwctx->display,
142
                              pic->slice_buffers[i]);
143
        if (vas != VA_STATUS_SUCCESS) {
144
            av_log(avctx, AV_LOG_ERROR, "Failed to destroy slice "
145
                   "slice buffer %#x: %d (%s).\n",
146
                   pic->slice_buffers[i], vas, vaErrorStr(vas));
147
        }
148
    }
149
}
150
151
int ff_vaapi_decode_issue(AVCodecContext *avctx,
152
                          VAAPIDecodePicture *pic)
153
{
154
    VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
155
    VAStatus vas;
156
    int err;
157
158
    av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n",
159
           pic->output_surface);
160
161
    vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
162
                         pic->output_surface);
163
    if (vas != VA_STATUS_SUCCESS) {
164
        av_log(avctx, AV_LOG_ERROR, "Failed to begin picture decode "
165
               "issue: %d (%s).\n", vas, vaErrorStr(vas));
166
        err = AVERROR(EIO);
167
        goto fail_with_picture;
168
    }
169
170
    vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
171
                          pic->param_buffers, pic->nb_param_buffers);
172
    if (vas != VA_STATUS_SUCCESS) {
173
        av_log(avctx, AV_LOG_ERROR, "Failed to upload decode "
174
               "parameters: %d (%s).\n", vas, vaErrorStr(vas));
175
        err = AVERROR(EIO);
176
        goto fail_with_picture;
177
    }
178
179
    vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
180
                          pic->slice_buffers, 2 * pic->nb_slices);
181
    if (vas != VA_STATUS_SUCCESS) {
182
        av_log(avctx, AV_LOG_ERROR, "Failed to upload slices: "
183
               "%d (%s).\n", vas, vaErrorStr(vas));
184
        err = AVERROR(EIO);
185
        goto fail_with_picture;
186
    }
187
188
    vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
189
    if (vas != VA_STATUS_SUCCESS) {
190
        av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
191
               "issue: %d (%s).\n", vas, vaErrorStr(vas));
192
        err = AVERROR(EIO);
193
        if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
194
            AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)
195
            goto fail;
196
        else
197
            goto fail_at_end;
198
    }
199
200
    if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
201
        AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)
202
        ff_vaapi_decode_destroy_buffers(avctx, pic);
203
204
    err = 0;
205
    goto exit;
206
207
fail_with_picture:
208
    vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
209
    if (vas != VA_STATUS_SUCCESS) {
210
        av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
211
               "after error: %d (%s).\n", vas, vaErrorStr(vas));
212
    }
213
fail:
214
    ff_vaapi_decode_destroy_buffers(avctx, pic);
215
fail_at_end:
216
exit:
217
    pic->nb_param_buffers = 0;
218
    pic->nb_slices        = 0;
219
    pic->slices_allocated = 0;
220
    av_freep(&pic->slice_buffers);
221
222
    return err;
223
}
224
225
int ff_vaapi_decode_cancel(AVCodecContext *avctx,
226
                           VAAPIDecodePicture *pic)
227
{
228
    ff_vaapi_decode_destroy_buffers(avctx, pic);
229
230
    pic->nb_param_buffers = 0;
231
    pic->nb_slices        = 0;
232
    pic->slices_allocated = 0;
233
    av_freep(&pic->slice_buffers);
234
235
    return 0;
236
}
237
238
static const struct {
239
    uint32_t fourcc;
240
    enum AVPixelFormat pix_fmt;
241
} vaapi_format_map[] = {
242
#define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
243
    // 4:0:0
244
    MAP(Y800, GRAY8),
245
    // 4:2:0
246
    MAP(NV12, NV12),
247
    MAP(YV12, YUV420P),
248
    MAP(IYUV, YUV420P),
249
#ifdef VA_FOURCC_I420
250
    MAP(I420, YUV420P),
251
#endif
252
    MAP(IMC3, YUV420P),
253
    // 4:1:1
254
    MAP(411P, YUV411P),
255
    // 4:2:2
256
    MAP(422H, YUV422P),
257
#ifdef VA_FOURCC_YV16
258
    MAP(YV16, YUV422P),
259
#endif
260
    MAP(YUY2, YUYV422),
261
#ifdef VA_FOURCC_Y210
262
    MAP(Y210,    Y210),
263
#endif
264
    // 4:4:0
265
    MAP(422V, YUV440P),
266
    // 4:4:4
267
    MAP(444P, YUV444P),
268
    // 4:2:0 10-bit
269
#ifdef VA_FOURCC_P010
270
    MAP(P010, P010),
271
#endif
272
#ifdef VA_FOURCC_I010
273
    MAP(I010, YUV420P10),
274
#endif
275
#undef MAP
276
};
277
278
static int vaapi_decode_find_best_format(AVCodecContext *avctx,
279
                                         AVHWDeviceContext *device,
280
                                         VAConfigID config_id,
281
                                         AVHWFramesContext *frames)
282
{
283
    AVVAAPIDeviceContext *hwctx = device->hwctx;
284
    VAStatus vas;
285
    VASurfaceAttrib *attr;
286
    enum AVPixelFormat source_format, best_format, format;
287
    uint32_t best_fourcc, fourcc;
288
    int i, j, nb_attr;
289
290
    source_format = avctx->sw_pix_fmt;
291
    av_assert0(source_format != AV_PIX_FMT_NONE);
292
293
    vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
294
                                   NULL, &nb_attr);
295
    if (vas != VA_STATUS_SUCCESS) {
296
        av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
297
               "%d (%s).\n", vas, vaErrorStr(vas));
298
        return AVERROR(ENOSYS);
299
    }
300
301
    attr = av_malloc_array(nb_attr, sizeof(*attr));
302
    if (!attr)
303
        return AVERROR(ENOMEM);
304
305
    vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
306
                                   attr, &nb_attr);
307
    if (vas != VA_STATUS_SUCCESS) {
308
        av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
309
               "%d (%s).\n", vas, vaErrorStr(vas));
310
        av_freep(&attr);
311
        return AVERROR(ENOSYS);
312
    }
313
314
    best_format = AV_PIX_FMT_NONE;
315
316
    for (i = 0; i < nb_attr; i++) {
317
        if (attr[i].type != VASurfaceAttribPixelFormat)
318
            continue;
319
320
        fourcc = attr[i].value.value.i;
321
        for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) {
322
            if (fourcc == vaapi_format_map[j].fourcc)
323
                break;
324
        }
325
        if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) {
326
            av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format %#x.\n",
327
                   fourcc);
328
            continue;
329
        }
330
        format = vaapi_format_map[j].pix_fmt;
331
        av_log(avctx, AV_LOG_DEBUG, "Considering format %#x -> %s.\n",
332
               fourcc, av_get_pix_fmt_name(format));
333
334
        best_format = av_find_best_pix_fmt_of_2(format, best_format,
335
                                                source_format, 0, NULL);
336
        if (format == best_format)
337
            best_fourcc = fourcc;
338
    }
339
340
    av_freep(&attr);
341
342
    if (best_format == AV_PIX_FMT_NONE) {
343
        av_log(avctx, AV_LOG_ERROR, "No usable formats for decoding!\n");
344
        return AVERROR(EINVAL);
345
    }
346
347
    av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for %s.\n",
348
           av_get_pix_fmt_name(best_format), best_fourcc,
349
           av_get_pix_fmt_name(source_format));
350
351
    frames->sw_format = best_format;
352
    if (avctx->internal->hwaccel_priv_data) {
353
        VAAPIDecodeContext    *ctx = avctx->internal->hwaccel_priv_data;
354
        AVVAAPIFramesContext *avfc = frames->hwctx;
355
356
        ctx->pixel_format_attribute = (VASurfaceAttrib) {
357
            .type          = VASurfaceAttribPixelFormat,
358
            .value.value.i = best_fourcc,
359
        };
360
361
        avfc->attributes    = &ctx->pixel_format_attribute;
362
        avfc->nb_attributes = 1;
363
    }
364
365
    return 0;
366
}
367
368
static const struct {
369
    enum AVCodecID codec_id;
370
    int codec_profile;
371
    VAProfile va_profile;
372
    VAProfile (*profile_parser)(AVCodecContext *avctx);
373
} vaapi_profile_map[] = {
374
#define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
375
    MAP(MPEG2VIDEO,  MPEG2_SIMPLE,    MPEG2Simple ),
376
    MAP(MPEG2VIDEO,  MPEG2_MAIN,      MPEG2Main   ),
377
    MAP(H263,        UNKNOWN,         H263Baseline),
378
    MAP(MPEG4,       MPEG4_SIMPLE,    MPEG4Simple ),
379
    MAP(MPEG4,       MPEG4_ADVANCED_SIMPLE,
380
                               MPEG4AdvancedSimple),
381
    MAP(MPEG4,       MPEG4_MAIN,      MPEG4Main   ),
382
    MAP(H264,        H264_CONSTRAINED_BASELINE,
383
                           H264ConstrainedBaseline),
384
    MAP(H264,        H264_MAIN,       H264Main    ),
385
    MAP(H264,        H264_HIGH,       H264High    ),
386
#if VA_CHECK_VERSION(0, 37, 0)
387
    MAP(HEVC,        HEVC_MAIN,       HEVCMain    ),
388
    MAP(HEVC,        HEVC_MAIN_10,    HEVCMain10  ),
389
    MAP(HEVC,        HEVC_MAIN_STILL_PICTURE,
390
                                      HEVCMain    ),
391
#endif
392
#if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
393
    MAP(HEVC,        HEVC_REXT,       None,
394
                 ff_vaapi_parse_hevc_rext_profile ),
395
#endif
396
    MAP(MJPEG,       MJPEG_HUFFMAN_BASELINE_DCT,
397
                                      JPEGBaseline),
398
    MAP(WMV3,        VC1_SIMPLE,      VC1Simple   ),
399
    MAP(WMV3,        VC1_MAIN,        VC1Main     ),
400
    MAP(WMV3,        VC1_COMPLEX,     VC1Advanced ),
401
    MAP(WMV3,        VC1_ADVANCED,    VC1Advanced ),
402
    MAP(VC1,         VC1_SIMPLE,      VC1Simple   ),
403
    MAP(VC1,         VC1_MAIN,        VC1Main     ),
404
    MAP(VC1,         VC1_COMPLEX,     VC1Advanced ),
405
    MAP(VC1,         VC1_ADVANCED,    VC1Advanced ),
406
    MAP(VP8,         UNKNOWN,       VP8Version0_3 ),
407
#if VA_CHECK_VERSION(0, 38, 0)
408
    MAP(VP9,         VP9_0,           VP9Profile0 ),
409
#endif
410
#if VA_CHECK_VERSION(0, 39, 0)
411
    MAP(VP9,         VP9_2,           VP9Profile2 ),
412
#endif
413
#undef MAP
414
};
415
416
/*
417
 * Set *va_config and the frames_ref fields from the current codec parameters
418
 * in avctx.
419
 */
420
static int vaapi_decode_make_config(AVCodecContext *avctx,
421
                                    AVBufferRef *device_ref,
422
                                    VAConfigID *va_config,
423
                                    AVBufferRef *frames_ref)
424
{
425
    AVVAAPIHWConfig       *hwconfig    = NULL;
426
    AVHWFramesConstraints *constraints = NULL;
427
    VAStatus vas;
428
    int err, i, j;
429
    const AVCodecDescriptor *codec_desc;
430
    VAProfile *profile_list = NULL, matched_va_profile, va_profile;
431
    int profile_count, exact_match, matched_ff_profile, codec_profile;
432
433
    AVHWDeviceContext    *device = (AVHWDeviceContext*)device_ref->data;
434
    AVVAAPIDeviceContext *hwctx = device->hwctx;
435
436
    codec_desc = avcodec_descriptor_get(avctx->codec_id);
437
    if (!codec_desc) {
438
        err = AVERROR(EINVAL);
439
        goto fail;
440
    }
441
442
    profile_count = vaMaxNumProfiles(hwctx->display);
443
    profile_list  = av_malloc_array(profile_count,
444
                                    sizeof(VAProfile));
445
    if (!profile_list) {
446
        err = AVERROR(ENOMEM);
447
        goto fail;
448
    }
449
450
    vas = vaQueryConfigProfiles(hwctx->display,
451
                                profile_list, &profile_count);
452
    if (vas != VA_STATUS_SUCCESS) {
453
        av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: "
454
               "%d (%s).\n", vas, vaErrorStr(vas));
455
        err = AVERROR(ENOSYS);
456
        goto fail;
457
    }
458
459
    matched_va_profile = VAProfileNone;
460
    exact_match = 0;
461
462
    for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) {
463
        int profile_match = 0;
464
        if (avctx->codec_id != vaapi_profile_map[i].codec_id)
465
            continue;
466
        if (avctx->profile == vaapi_profile_map[i].codec_profile ||
467
            vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN)
468
            profile_match = 1;
469
470
        va_profile = vaapi_profile_map[i].profile_parser ?
471
                     vaapi_profile_map[i].profile_parser(avctx) :
472
                     vaapi_profile_map[i].va_profile;
473
        codec_profile = vaapi_profile_map[i].codec_profile;
474
475
        for (j = 0; j < profile_count; j++) {
476
            if (va_profile == profile_list[j]) {
477
                exact_match = profile_match;
478
                break;
479
            }
480
        }
481
        if (j < profile_count) {
482
            matched_va_profile = va_profile;
483
            matched_ff_profile = codec_profile;
484
            if (exact_match)
485
                break;
486
        }
487
    }
488
    av_freep(&profile_list);
489
490
    if (matched_va_profile == VAProfileNone) {
491
        av_log(avctx, AV_LOG_ERROR, "No support for codec %s "
492
               "profile %d.\n", codec_desc->name, avctx->profile);
493
        err = AVERROR(ENOSYS);
494
        goto fail;
495
    }
496
    if (!exact_match) {
497
        if (avctx->hwaccel_flags &
498
            AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) {
499
            av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
500
                   "supported for hardware decode.\n",
501
                   codec_desc->name, avctx->profile);
502
            av_log(avctx, AV_LOG_WARNING, "Using possibly-"
503
                   "incompatible profile %d instead.\n",
504
                   matched_ff_profile);
505
        } else {
506
            av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
507
                   "supported for hardware decode.\n",
508
                   codec_desc->name, avctx->profile);
509
            err = AVERROR(EINVAL);
510
            goto fail;
511
        }
512
    }
513
514
    vas = vaCreateConfig(hwctx->display, matched_va_profile,
515
                         VAEntrypointVLD, NULL, 0,
516
                         va_config);
517
    if (vas != VA_STATUS_SUCCESS) {
518
        av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
519
               "configuration: %d (%s).\n", vas, vaErrorStr(vas));
520
        err = AVERROR(EIO);
521
        goto fail;
522
    }
523
524
    hwconfig = av_hwdevice_hwconfig_alloc(device_ref);
525
    if (!hwconfig) {
526
        err = AVERROR(ENOMEM);
527
        goto fail;
528
    }
529
    hwconfig->config_id = *va_config;
530
531
    constraints =
532
        av_hwdevice_get_hwframe_constraints(device_ref, hwconfig);
533
    if (!constraints) {
534
        err = AVERROR(ENOMEM);
535
        goto fail;
536
    }
537
538
    if (avctx->coded_width  < constraints->min_width  ||
539
        avctx->coded_height < constraints->min_height ||
540
        avctx->coded_width  > constraints->max_width  ||
541
        avctx->coded_height > constraints->max_height) {
542
        av_log(avctx, AV_LOG_ERROR, "Hardware does not support image "
543
               "size %dx%d (constraints: width %d-%d height %d-%d).\n",
544
               avctx->coded_width, avctx->coded_height,
545
               constraints->min_width,  constraints->max_width,
546
               constraints->min_height, constraints->max_height);
547
        err = AVERROR(EINVAL);
548
        goto fail;
549
    }
550
    if (!constraints->valid_sw_formats ||
551
        constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) {
552
        av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any "
553
               "usable surface formats.\n");
554
        err = AVERROR(EINVAL);
555
        goto fail;
556
    }
557
558
    if (frames_ref) {
559
        AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
560
561
        frames->format = AV_PIX_FMT_VAAPI;
562
        frames->width = avctx->coded_width;
563
        frames->height = avctx->coded_height;
564
565
        err = vaapi_decode_find_best_format(avctx, device,
566
                                            *va_config, frames);
567
        if (err < 0)
568
            goto fail;
569
570
        frames->initial_pool_size = 1;
571
        // Add per-codec number of surfaces used for storing reference frames.
572
        switch (avctx->codec_id) {
573
        case AV_CODEC_ID_H264:
574
        case AV_CODEC_ID_HEVC:
575
            frames->initial_pool_size += 16;
576
            break;
577
        case AV_CODEC_ID_VP9:
578
            frames->initial_pool_size += 8;
579
            break;
580
        case AV_CODEC_ID_VP8:
581
            frames->initial_pool_size += 3;
582
            break;
583
        default:
584
            frames->initial_pool_size += 2;
585
        }
586
    }
587
588
    av_hwframe_constraints_free(&constraints);
589
    av_freep(&hwconfig);
590
591
    return 0;
592
593
fail:
594
    av_hwframe_constraints_free(&constraints);
595
    av_freep(&hwconfig);
596
    if (*va_config != VA_INVALID_ID) {
597
        vaDestroyConfig(hwctx->display, *va_config);
598
        *va_config = VA_INVALID_ID;
599
    }
600
    av_freep(&profile_list);
601
    return err;
602
}
603
604
int ff_vaapi_common_frame_params(AVCodecContext *avctx,
605
                                 AVBufferRef *hw_frames_ctx)
606
{
607
    AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data;
608
    AVHWDeviceContext *device_ctx = hw_frames->device_ctx;
609
    AVVAAPIDeviceContext *hwctx;
610
    VAConfigID va_config = VA_INVALID_ID;
611
    int err;
612
613
    if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI)
614
        return AVERROR(EINVAL);
615
    hwctx = device_ctx->hwctx;
616
617
    err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config,
618
                                   hw_frames_ctx);
619
    if (err)
620
        return err;
621
622
    if (va_config != VA_INVALID_ID)
623
        vaDestroyConfig(hwctx->display, va_config);
624
625
    return 0;
626
}
627
628
int ff_vaapi_decode_init(AVCodecContext *avctx)
629
{
630
    VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
631
    VAStatus vas;
632
    int err;
633
634
    ctx->va_config  = VA_INVALID_ID;
635
    ctx->va_context = VA_INVALID_ID;
636
637
#if FF_API_STRUCT_VAAPI_CONTEXT
638
    if (avctx->hwaccel_context) {
639
        av_log(avctx, AV_LOG_WARNING, "Using deprecated struct "
640
               "vaapi_context in decode.\n");
641
642
        ctx->have_old_context = 1;
643
        ctx->old_context = avctx->hwaccel_context;
644
645
        // Really we only want the VAAPI device context, but this
646
        // allocates a whole generic device context because we don't
647
        // have any other way to determine how big it should be.
648
        ctx->device_ref =
649
            av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
650
        if (!ctx->device_ref) {
651
            err = AVERROR(ENOMEM);
652
            goto fail;
653
        }
654
        ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
655
        ctx->hwctx  = ctx->device->hwctx;
656
657
        ctx->hwctx->display = ctx->old_context->display;
658
659
        // The old VAAPI decode setup assumed this quirk was always
660
        // present, so set it here to avoid the behaviour changing.
661
        ctx->hwctx->driver_quirks =
662
            AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS;
663
664
    }
665
#endif
666
667
#if FF_API_STRUCT_VAAPI_CONTEXT
668
    if (ctx->have_old_context) {
669
        ctx->va_config  = ctx->old_context->config_id;
670
        ctx->va_context = ctx->old_context->context_id;
671
672
        av_log(avctx, AV_LOG_DEBUG, "Using user-supplied decoder "
673
               "context: %#x/%#x.\n", ctx->va_config, ctx->va_context);
674
    } else {
675
#endif
676
677
    err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI);
678
    if (err < 0)
679
        goto fail;
680
681
    ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
682
    ctx->hwfc   = ctx->frames->hwctx;
683
    ctx->device = ctx->frames->device_ctx;
684
    ctx->hwctx  = ctx->device->hwctx;
685
686
    err = vaapi_decode_make_config(avctx, ctx->frames->device_ref,
687
                                   &ctx->va_config, avctx->hw_frames_ctx);
688
    if (err)
689
        goto fail;
690
691
    vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
692
                          avctx->coded_width, avctx->coded_height,
693
                          VA_PROGRESSIVE,
694
                          ctx->hwfc->surface_ids,
695
                          ctx->hwfc->nb_surfaces,
696
                          &ctx->va_context);
697
    if (vas != VA_STATUS_SUCCESS) {
698
        av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
699
               "context: %d (%s).\n", vas, vaErrorStr(vas));
700
        err = AVERROR(EIO);
701
        goto fail;
702
    }
703
704
    av_log(avctx, AV_LOG_DEBUG, "Decode context initialised: "
705
           "%#x/%#x.\n", ctx->va_config, ctx->va_context);
706
#if FF_API_STRUCT_VAAPI_CONTEXT
707
    }
708
#endif
709
710
    return 0;
711
712
fail:
713
    ff_vaapi_decode_uninit(avctx);
714
    return err;
715
}
716
717
int ff_vaapi_decode_uninit(AVCodecContext *avctx)
718
{
719
    VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
720
    VAStatus vas;
721
722
#if FF_API_STRUCT_VAAPI_CONTEXT
723
    if (ctx->have_old_context) {
724
        av_buffer_unref(&ctx->device_ref);
725
    } else {
726
#endif
727
728
    if (ctx->va_context != VA_INVALID_ID) {
729
        vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context);
730
        if (vas != VA_STATUS_SUCCESS) {
731
            av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
732
                   "context %#x: %d (%s).\n",
733
                   ctx->va_context, vas, vaErrorStr(vas));
734
        }
735
    }
736
    if (ctx->va_config != VA_INVALID_ID) {
737
        vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
738
        if (vas != VA_STATUS_SUCCESS) {
739
            av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
740
                   "configuration %#x: %d (%s).\n",
741
                   ctx->va_config, vas, vaErrorStr(vas));
742
        }
743
    }
744
745
#if FF_API_STRUCT_VAAPI_CONTEXT
746
    }
747
#endif
748
749
    return 0;
750
}