summaryrefslogtreecommitdiffstats
path: root/video/decode/lavc.h
blob: cc098b998ea2173e7c5202b481fd41aa6cc59de1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#ifndef MPV_LAVC_H
#define MPV_LAVC_H

#include <stdbool.h>

#include <libavcodec/avcodec.h>

#include "config.h"

#include "demux/stheader.h"
#include "video/mp_image.h"
#include "video/mp_image_pool.h"
#include "video/hwdec.h"

#define HWDEC_DELAY_QUEUE_COUNT 2

// Maximum number of surfaces the player wants to buffer.
// This number might require adjustment depending on whatever the player does;
// for example, if vo_opengl increases the number of reference surfaces for
// interpolation, this value has to be increased too.
#define HWDEC_EXTRA_SURFACES 6

struct mpv_global;

typedef struct lavc_ctx {
    struct mp_log *log;
    struct MPOpts *opts;
    AVCodecContext *avctx;
    AVFrame *pic;
    struct vd_lavc_hwdec *hwdec;
    AVRational codec_timebase;
    enum AVPixelFormat pix_fmt;
    enum AVDiscard skip_frame;
    bool flushing;
    const char *decoder;
    bool hwdec_failed;
    bool hwdec_notified;

    int framedrop_flags;

    // For HDR side-data caching
    double cached_hdr_peak;

    bool hw_probing;
    struct demux_packet **sent_packets;
    int num_sent_packets;

    struct demux_packet **requeue_packets;
    int num_requeue_packets;

    struct mp_image **delay_queue;
    int num_delay_queue;
    int max_delay_queue;

    // From VO
    struct mp_hwdec_devices *hwdec_devs;

    // For free use by hwdec implementation
    void *hwdec_priv;

    // Set by generic hwaccels.
    struct mp_hwdec_ctx *hwdec_dev;

    int hwdec_fmt;
    int hwdec_w;
    int hwdec_h;
    int hwdec_profile;

    bool hwdec_request_reinit;
    int hwdec_fail_count;

    struct mp_image_pool *hwdec_swpool;

    AVBufferRef *cached_hw_frames_ctx;
} vd_ffmpeg_ctx;

struct vd_lavc_hwdec {
    enum hwdec_type type;
    // If not-0: the IMGFMT_ format that should be accepted in the libavcodec
    // get_format callback.
    int image_format;
    // Always returns a non-hwaccel image format.
    bool copying;
    // Setting this will queue the given number of frames before calling
    // process_image() or returning them to the renderer. This can increase
    // efficiency by not blocking on the hardware pipeline by reading back
    // immediately after decoding.
    int delay_queue;
    // If true, AVCodecContext will destroy the underlying decoder.
    bool volatile_context;
    int (*probe)(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
                 const char *codec);
    int (*init)(struct lavc_ctx *ctx);
    int (*init_decoder)(struct lavc_ctx *ctx, int w, int h);
    void (*uninit)(struct lavc_ctx *ctx);
    // Note: if init_decoder is set, this will always use the values from the
    //       last successful init_decoder call. Otherwise, it's up to you.
    struct mp_image *(*allocate_image)(struct lavc_ctx *ctx, int w, int h);
    // Process the image returned by the libavcodec decoder.
    struct mp_image *(*process_image)(struct lavc_ctx *ctx, struct mp_image *img);
    // For copy hwdecs. If probing is true, don't log errors if unavailable.
    // The returned device will be freed with mp_hwdec_ctx->destroy.
    struct mp_hwdec_ctx *(*create_dev)(struct mpv_global *global,
                                       struct mp_log *log, bool probing);
    // Suffix for libavcodec decoder. If non-NULL, the codec is overridden
    // with hwdec_find_decoder.
    // Intuitively, this will force the corresponding wrapper decoder.
    const char *lavc_suffix;
    // Generic hwaccels set AVCodecContext.hw_frames_ctx in get_format().
    bool generic_hwaccel;
    // If set, AVCodecContext.hw_frames_ctx will be initialized in get_format,
    // and pixfmt_map must be non-NULL.
    bool set_hwframes;
    // Array of pixfmt pairs. The first pixfmt is the AVCodecContext.sw_pix_fmt,
    // the second the required AVHWFramesContext.sw_format.
    const enum AVPixelFormat (*pixfmt_map)[2];
    // The generic hwaccel has a fixed pool size. Enough surfaces need to be
    // preallocated before decoding begins. If false, pool size is left to 0.
    bool static_pool;
};

enum {
    HWDEC_ERR_NO_CTX = -2,
    HWDEC_ERR_NO_CODEC = -3,
    HWDEC_ERR_EMULATED = -4,    // probing successful, but emulated API detected
};

struct hwdec_profile_entry {
    enum AVCodecID av_codec;
    int ff_profile;
    uint64_t hw_profile;
};

const struct hwdec_profile_entry *hwdec_find_profile(
    struct lavc_ctx *ctx, const struct hwdec_profile_entry *table);
bool hwdec_check_codec_support(const char *codec,
                               const struct hwdec_profile_entry *table);
int hwdec_get_max_refs(struct lavc_ctx *ctx);
int hwdec_setup_hw_frames_ctx(struct lavc_ctx *ctx, AVBufferRef *device_ctx,
                              int av_sw_format, int initial_pool_size);

const char *hwdec_find_decoder(const char *codec, const char *suffix);

#define NEW_CUDA_HWACCEL \
    (HAVE_CUDA_HWACCEL && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 94, 100))

#endif