GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/fftools/ffmpeg_hw.c Lines: 45 304 14.8 %
Date: 2020-07-11 02:49:52 Branches: 18 168 10.7 %

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 <string.h>
20
21
#include "libavutil/avstring.h"
22
#include "libavutil/pixdesc.h"
23
#include "libavfilter/buffersink.h"
24
25
#include "ffmpeg.h"
26
27
static int nb_hw_devices;
28
static HWDevice **hw_devices;
29
30
1601
static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type)
31
{
32
1601
    HWDevice *found = NULL;
33
    int i;
34
1601
    for (i = 0; i < nb_hw_devices; i++) {
35
        if (hw_devices[i]->type == type) {
36
            if (found)
37
                return NULL;
38
            found = hw_devices[i];
39
        }
40
    }
41
1601
    return found;
42
}
43
44
HWDevice *hw_device_get_by_name(const char *name)
45
{
46
    int i;
47
    for (i = 0; i < nb_hw_devices; i++) {
48
        if (!strcmp(hw_devices[i]->name, name))
49
            return hw_devices[i];
50
    }
51
    return NULL;
52
}
53
54
static HWDevice *hw_device_add(void)
55
{
56
    int err;
57
    err = av_reallocp_array(&hw_devices, nb_hw_devices + 1,
58
                            sizeof(*hw_devices));
59
    if (err) {
60
        nb_hw_devices = 0;
61
        return NULL;
62
    }
63
    hw_devices[nb_hw_devices] = av_mallocz(sizeof(HWDevice));
64
    if (!hw_devices[nb_hw_devices])
65
        return NULL;
66
    return hw_devices[nb_hw_devices++];
67
}
68
69
static char *hw_device_default_name(enum AVHWDeviceType type)
70
{
71
    // Make an automatic name of the form "type%d".  We arbitrarily
72
    // limit at 1000 anonymous devices of the same type - there is
73
    // probably something else very wrong if you get to this limit.
74
    const char *type_name = av_hwdevice_get_type_name(type);
75
    char *name;
76
    size_t index_pos;
77
    int index, index_limit = 1000;
78
    index_pos = strlen(type_name);
79
    name = av_malloc(index_pos + 4);
80
    if (!name)
81
        return NULL;
82
    for (index = 0; index < index_limit; index++) {
83
        snprintf(name, index_pos + 4, "%s%d", type_name, index);
84
        if (!hw_device_get_by_name(name))
85
            break;
86
    }
87
    if (index >= index_limit) {
88
        av_freep(&name);
89
        return NULL;
90
    }
91
    return name;
92
}
93
94
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
95
{
96
    // "type=name:device,key=value,key2=value2"
97
    // "type:device,key=value,key2=value2"
98
    // -> av_hwdevice_ctx_create()
99
    // "type=name@name"
100
    // "type@name"
101
    // -> av_hwdevice_ctx_create_derived()
102
103
    AVDictionary *options = NULL;
104
    const char *type_name = NULL, *name = NULL, *device = NULL;
105
    enum AVHWDeviceType type;
106
    HWDevice *dev, *src;
107
    AVBufferRef *device_ref = NULL;
108
    int err;
109
    const char *errmsg, *p, *q;
110
    size_t k;
111
112
    k = strcspn(arg, ":=@");
113
    p = arg + k;
114
115
    type_name = av_strndup(arg, k);
116
    if (!type_name) {
117
        err = AVERROR(ENOMEM);
118
        goto fail;
119
    }
120
    type = av_hwdevice_find_type_by_name(type_name);
121
    if (type == AV_HWDEVICE_TYPE_NONE) {
122
        errmsg = "unknown device type";
123
        goto invalid;
124
    }
125
126
    if (*p == '=') {
127
        k = strcspn(p + 1, ":@");
128
129
        name = av_strndup(p + 1, k);
130
        if (!name) {
131
            err = AVERROR(ENOMEM);
132
            goto fail;
133
        }
134
        if (hw_device_get_by_name(name)) {
135
            errmsg = "named device already exists";
136
            goto invalid;
137
        }
138
139
        p += 1 + k;
140
    } else {
141
        name = hw_device_default_name(type);
142
        if (!name) {
143
            err = AVERROR(ENOMEM);
144
            goto fail;
145
        }
146
    }
147
148
    if (!*p) {
149
        // New device with no parameters.
150
        err = av_hwdevice_ctx_create(&device_ref, type,
151
                                     NULL, NULL, 0);
152
        if (err < 0)
153
            goto fail;
154
155
    } else if (*p == ':') {
156
        // New device with some parameters.
157
        ++p;
158
        q = strchr(p, ',');
159
        if (q) {
160
            if (q - p > 0) {
161
                device = av_strndup(p, q - p);
162
                if (!device) {
163
                    err = AVERROR(ENOMEM);
164
                    goto fail;
165
                }
166
            }
167
            err = av_dict_parse_string(&options, q + 1, "=", ",", 0);
168
            if (err < 0) {
169
                errmsg = "failed to parse options";
170
                goto invalid;
171
            }
172
        }
173
174
        err = av_hwdevice_ctx_create(&device_ref, type,
175
                                     q ? device : p[0] ? p : NULL,
176
                                     options, 0);
177
        if (err < 0)
178
            goto fail;
179
180
    } else if (*p == '@') {
181
        // Derive from existing device.
182
183
        src = hw_device_get_by_name(p + 1);
184
        if (!src) {
185
            errmsg = "invalid source device name";
186
            goto invalid;
187
        }
188
189
        err = av_hwdevice_ctx_create_derived(&device_ref, type,
190
                                             src->device_ref, 0);
191
        if (err < 0)
192
            goto fail;
193
    } else {
194
        errmsg = "parse error";
195
        goto invalid;
196
    }
197
198
    dev = hw_device_add();
199
    if (!dev) {
200
        err = AVERROR(ENOMEM);
201
        goto fail;
202
    }
203
204
    dev->name = name;
205
    dev->type = type;
206
    dev->device_ref = device_ref;
207
208
    if (dev_out)
209
        *dev_out = dev;
210
211
    name = NULL;
212
    err = 0;
213
done:
214
    av_freep(&type_name);
215
    av_freep(&name);
216
    av_freep(&device);
217
    av_dict_free(&options);
218
    return err;
219
invalid:
220
    av_log(NULL, AV_LOG_ERROR,
221
           "Invalid device specification \"%s\": %s\n", arg, errmsg);
222
    err = AVERROR(EINVAL);
223
    goto done;
224
fail:
225
    av_log(NULL, AV_LOG_ERROR,
226
           "Device creation failed: %d.\n", err);
227
    av_buffer_unref(&device_ref);
228
    goto done;
229
}
230
231
static int hw_device_init_from_type(enum AVHWDeviceType type,
232
                                    const char *device,
233
                                    HWDevice **dev_out)
234
{
235
    AVBufferRef *device_ref = NULL;
236
    HWDevice *dev;
237
    char *name;
238
    int err;
239
240
    name = hw_device_default_name(type);
241
    if (!name) {
242
        err = AVERROR(ENOMEM);
243
        goto fail;
244
    }
245
246
    err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
247
    if (err < 0) {
248
        av_log(NULL, AV_LOG_ERROR,
249
               "Device creation failed: %d.\n", err);
250
        goto fail;
251
    }
252
253
    dev = hw_device_add();
254
    if (!dev) {
255
        err = AVERROR(ENOMEM);
256
        goto fail;
257
    }
258
259
    dev->name = name;
260
    dev->type = type;
261
    dev->device_ref = device_ref;
262
263
    if (dev_out)
264
        *dev_out = dev;
265
266
    return 0;
267
268
fail:
269
    av_freep(&name);
270
    av_buffer_unref(&device_ref);
271
    return err;
272
}
273
274
5955
void hw_device_free_all(void)
275
{
276
    int i;
277
5955
    for (i = 0; i < nb_hw_devices; i++) {
278
        av_freep(&hw_devices[i]->name);
279
        av_buffer_unref(&hw_devices[i]->device_ref);
280
        av_freep(&hw_devices[i]);
281
    }
282
5955
    av_freep(&hw_devices);
283
5955
    nb_hw_devices = 0;
284
5955
}
285
286
5780
static HWDevice *hw_device_match_by_codec(const AVCodec *codec)
287
{
288
    const AVCodecHWConfig *config;
289
    HWDevice *dev;
290
    int i;
291
5780
    for (i = 0;; i++) {
292
7381
        config = avcodec_get_hw_config(codec, i);
293
7381
        if (!config)
294
5780
            return NULL;
295
1601
        if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
296
            continue;
297
1601
        dev = hw_device_get_by_type(config->device_type);
298
1601
        if (dev)
299
            return dev;
300
    }
301
}
302
303
5780
int hw_device_setup_for_decode(InputStream *ist)
304
{
305
    const AVCodecHWConfig *config;
306
    enum AVHWDeviceType type;
307
5780
    HWDevice *dev = NULL;
308
5780
    int err, auto_device = 0;
309
310
5780
    if (ist->hwaccel_device) {
311
        dev = hw_device_get_by_name(ist->hwaccel_device);
312
        if (!dev) {
313
            if (ist->hwaccel_id == HWACCEL_AUTO) {
314
                auto_device = 1;
315
            } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
316
                type = ist->hwaccel_device_type;
317
                err = hw_device_init_from_type(type, ist->hwaccel_device,
318
                                               &dev);
319
            } else {
320
                // This will be dealt with by API-specific initialisation
321
                // (using hwaccel_device), so nothing further needed here.
322
                return 0;
323
            }
324
        } else {
325
            if (ist->hwaccel_id == HWACCEL_AUTO) {
326
                ist->hwaccel_device_type = dev->type;
327
            } else if (ist->hwaccel_device_type != dev->type) {
328
                av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device "
329
                       "specified for decoder: device %s of type %s is not "
330
                       "usable with hwaccel %s.\n", dev->name,
331
                       av_hwdevice_get_type_name(dev->type),
332
                       av_hwdevice_get_type_name(ist->hwaccel_device_type));
333
                return AVERROR(EINVAL);
334
            }
335
        }
336
    } else {
337
5780
        if (ist->hwaccel_id == HWACCEL_AUTO) {
338
            auto_device = 1;
339
5780
        } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
340
            type = ist->hwaccel_device_type;
341
            dev = hw_device_get_by_type(type);
342
            if (!dev)
343
                err = hw_device_init_from_type(type, NULL, &dev);
344
        } else {
345
5780
            dev = hw_device_match_by_codec(ist->dec);
346
5780
            if (!dev) {
347
                // No device for this codec, but not using generic hwaccel
348
                // and therefore may well not need one - ignore.
349
5780
                return 0;
350
            }
351
        }
352
    }
353
354
    if (auto_device) {
355
        int i;
356
        if (!avcodec_get_hw_config(ist->dec, 0)) {
357
            // Decoder does not support any hardware devices.
358
            return 0;
359
        }
360
        for (i = 0; !dev; i++) {
361
            config = avcodec_get_hw_config(ist->dec, i);
362
            if (!config)
363
                break;
364
            type = config->device_type;
365
            dev = hw_device_get_by_type(type);
366
            if (dev) {
367
                av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
368
                       "hwaccel type %s with existing device %s.\n",
369
                       av_hwdevice_get_type_name(type), dev->name);
370
            }
371
        }
372
        for (i = 0; !dev; i++) {
373
            config = avcodec_get_hw_config(ist->dec, i);
374
            if (!config)
375
                break;
376
            type = config->device_type;
377
            // Try to make a new device of this type.
378
            err = hw_device_init_from_type(type, ist->hwaccel_device,
379
                                           &dev);
380
            if (err < 0) {
381
                // Can't make a device of this type.
382
                continue;
383
            }
384
            if (ist->hwaccel_device) {
385
                av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
386
                       "hwaccel type %s with new device created "
387
                       "from %s.\n", av_hwdevice_get_type_name(type),
388
                       ist->hwaccel_device);
389
            } else {
390
                av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
391
                       "hwaccel type %s with new default device.\n",
392
                       av_hwdevice_get_type_name(type));
393
            }
394
        }
395
        if (dev) {
396
            ist->hwaccel_device_type = type;
397
        } else {
398
            av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
399
                   "disabled: no device found.\n");
400
            ist->hwaccel_id = HWACCEL_NONE;
401
            return 0;
402
        }
403
    }
404
405
    if (!dev) {
406
        av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available "
407
               "for decoder: device type %s needed for codec %s.\n",
408
               av_hwdevice_get_type_name(type), ist->dec->name);
409
        return err;
410
    }
411
412
    ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
413
    if (!ist->dec_ctx->hw_device_ctx)
414
        return AVERROR(ENOMEM);
415
416
    return 0;
417
}
418
419
5805
int hw_device_setup_for_encode(OutputStream *ost)
420
{
421
    const AVCodecHWConfig *config;
422
5805
    HWDevice *dev = NULL;
423
5805
    AVBufferRef *frames_ref = NULL;
424
    int i;
425
426
5805
    if (ost->filter) {
427
5775
        frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter);
428
5775
        if (frames_ref &&
429
            ((AVHWFramesContext*)frames_ref->data)->format ==
430
            ost->enc_ctx->pix_fmt) {
431
            // Matching format, will try to use hw_frames_ctx.
432
        } else {
433
5775
            frames_ref = NULL;
434
        }
435
    }
436
437
5805
    for (i = 0;; i++) {
438
5805
        config = avcodec_get_hw_config(ost->enc, i);
439
5805
        if (!config)
440
5805
            break;
441
442
        if (frames_ref &&
443
            config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX &&
444
            (config->pix_fmt == AV_PIX_FMT_NONE ||
445
             config->pix_fmt == ost->enc_ctx->pix_fmt)) {
446
            av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input "
447
                   "frames context (format %s) with %s encoder.\n",
448
                   av_get_pix_fmt_name(ost->enc_ctx->pix_fmt),
449
                   ost->enc->name);
450
            ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref);
451
            if (!ost->enc_ctx->hw_frames_ctx)
452
                return AVERROR(ENOMEM);
453
            return 0;
454
        }
455
456
        if (!dev &&
457
            config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)
458
            dev = hw_device_get_by_type(config->device_type);
459
    }
460
461
5805
    if (dev) {
462
        av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s "
463
               "(type %s) with %s encoder.\n", dev->name,
464
               av_hwdevice_get_type_name(dev->type), ost->enc->name);
465
        ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
466
        if (!ost->enc_ctx->hw_device_ctx)
467
            return AVERROR(ENOMEM);
468
    } else {
469
        // No device required, or no device available.
470
    }
471
5805
    return 0;
472
}
473
474
static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
475
{
476
    InputStream *ist = avctx->opaque;
477
    AVFrame *output = NULL;
478
    enum AVPixelFormat output_format = ist->hwaccel_output_format;
479
    int err;
480
481
    if (input->format == output_format) {
482
        // Nothing to do.
483
        return 0;
484
    }
485
486
    output = av_frame_alloc();
487
    if (!output)
488
        return AVERROR(ENOMEM);
489
490
    output->format = output_format;
491
492
    err = av_hwframe_transfer_data(output, input, 0);
493
    if (err < 0) {
494
        av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to "
495
               "output frame: %d.\n", err);
496
        goto fail;
497
    }
498
499
    err = av_frame_copy_props(output, input);
500
    if (err < 0) {
501
        av_frame_unref(output);
502
        goto fail;
503
    }
504
505
    av_frame_unref(input);
506
    av_frame_move_ref(input, output);
507
    av_frame_free(&output);
508
509
    return 0;
510
511
fail:
512
    av_frame_free(&output);
513
    return err;
514
}
515
516
int hwaccel_decode_init(AVCodecContext *avctx)
517
{
518
    InputStream *ist = avctx->opaque;
519
520
    ist->hwaccel_retrieve_data = &hwaccel_retrieve_data;
521
522
    return 0;
523
}
524
525
5809
int hw_device_setup_for_filter(FilterGraph *fg)
526
{
527
    HWDevice *dev;
528
    int i;
529
530
    // If the user has supplied exactly one hardware device then just
531
    // give it straight to every filter for convenience.  If more than
532
    // one device is available then the user needs to pick one explcitly
533
    // with the filter_hw_device option.
534
5809
    if (filter_hw_device)
535
        dev = filter_hw_device;
536
5809
    else if (nb_hw_devices == 1)
537
        dev = hw_devices[0];
538
    else
539
5809
        dev = NULL;
540
541
5809
    if (dev) {
542
        for (i = 0; i < fg->graph->nb_filters; i++) {
543
            fg->graph->filters[i]->hw_device_ctx =
544
                av_buffer_ref(dev->device_ref);
545
            if (!fg->graph->filters[i]->hw_device_ctx)
546
                return AVERROR(ENOMEM);
547
        }
548
    }
549
550
5809
    return 0;
551
}