Coverage Report

Created: 2026-03-12 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mpv/video/mp_image.c
Line
Count
Source
1
/*
2
 * This file is part of mpv.
3
 *
4
 * mpv 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
 * mpv 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
12
 * GNU 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 mpv.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#include <limits.h>
19
#include <assert.h>
20
21
#include <libavutil/mem.h>
22
#include <libavutil/common.h>
23
#include <libavutil/display.h>
24
#include <libavutil/dovi_meta.h>
25
#include <libavutil/bswap.h>
26
#include <libavutil/hwcontext.h>
27
#include <libavutil/intreadwrite.h>
28
#include <libavutil/rational.h>
29
#include <libavcodec/avcodec.h>
30
#include <libavutil/mastering_display_metadata.h>
31
#include <libplacebo/utils/libav.h>
32
33
#include "mpv_talloc.h"
34
35
#include "common/av_common.h"
36
#include "common/common.h"
37
#include "fmt-conversion.h"
38
#include "hwdec.h"
39
#include "mp_image.h"
40
#include "osdep/threads.h"
41
#include "sws_utils.h"
42
#include "out/placebo/utils.h"
43
44
// Determine strides, plane sizes, and total required size for an image
45
// allocation. Returns total size on success, <0 on error. Unused planes
46
// have out_stride/out_plane_size to 0, and out_plane_offset set to -1 up
47
// until MP_MAX_PLANES-1.
48
static int mp_image_layout(int imgfmt, int w, int h, int stride_align,
49
                           int out_stride[MP_MAX_PLANES],
50
                           int out_plane_offset[MP_MAX_PLANES],
51
                           int out_plane_size[MP_MAX_PLANES])
52
41.4k
{
53
41.4k
    struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt);
54
55
41.4k
    w = MP_ALIGN_UP(w, desc.align_x);
56
41.4k
    h = MP_ALIGN_UP(h, desc.align_y);
57
58
41.4k
    struct mp_image_params params = {.imgfmt = imgfmt, .w = w, .h = h};
59
60
41.4k
    if (!mp_image_params_valid(&params) || desc.flags & MP_IMGFLAG_HWACCEL)
61
26
        return -1;
62
63
    // Note: for non-mod-2 4:2:0 YUV frames, we have to allocate an additional
64
    //       top/right border. This is needed for correct handling of such
65
    //       images in filter and VO code (e.g. vo_vdpau or vo_gpu).
66
67
207k
    for (int n = 0; n < MP_MAX_PLANES; n++) {
68
165k
        int alloc_w = mp_chroma_div_up(w, desc.xs[n]);
69
165k
        int alloc_h = MP_ALIGN_UP(h, 32) >> desc.ys[n];
70
165k
        int line_bytes = (alloc_w * desc.bpp[n] + 7) / 8;
71
165k
        out_stride[n] = MP_ALIGN_NPOT(line_bytes, stride_align);
72
165k
        out_plane_size[n] = out_stride[n] * alloc_h;
73
165k
    }
74
41.4k
    if (desc.flags & MP_IMGFLAG_PAL)
75
0
        out_plane_size[1] = AVPALETTE_SIZE;
76
77
41.4k
    int sum = 0;
78
207k
    for (int n = 0; n < MP_MAX_PLANES; n++) {
79
165k
        out_plane_offset[n] = out_plane_size[n] ? sum : -1;
80
165k
        sum += out_plane_size[n];
81
165k
    }
82
83
41.4k
    return sum;
84
41.4k
}
85
86
// Return the total size needed for an image allocation of the given
87
// configuration (imgfmt, w, h must be set). Returns -1 on error.
88
// Assumes the allocation is already aligned on stride_align (otherwise you
89
// need to add padding yourself).
90
int mp_image_get_alloc_size(int imgfmt, int w, int h, int stride_align)
91
20.7k
{
92
20.7k
    int stride[MP_MAX_PLANES];
93
20.7k
    int plane_offset[MP_MAX_PLANES];
94
20.7k
    int plane_size[MP_MAX_PLANES];
95
20.7k
    return mp_image_layout(imgfmt, w, h, stride_align, stride, plane_offset,
96
20.7k
                           plane_size);
97
20.7k
}
98
99
// Fill the mpi->planes and mpi->stride fields of the given mpi with data
100
// from buffer according to the mpi's w/h/imgfmt fields. See mp_image_from_buffer
101
// aboud remarks how to allocate/use buffer/buffer_size.
102
// This does not free the data. You are expected to setup refcounting by
103
// setting mp_image.bufs before or after this function is called.
104
// Returns true on success, false on failure.
105
static bool mp_image_fill_alloc(struct mp_image *mpi, int stride_align,
106
                                void *buffer, int buffer_size)
107
20.7k
{
108
20.7k
    int stride[MP_MAX_PLANES];
109
20.7k
    int plane_offset[MP_MAX_PLANES];
110
20.7k
    int plane_size[MP_MAX_PLANES];
111
20.7k
    int size = mp_image_layout(mpi->imgfmt, mpi->w, mpi->h, stride_align,
112
20.7k
                               stride, plane_offset, plane_size);
113
20.7k
    if (size < 0 || size > buffer_size)
114
0
        return false;
115
116
20.7k
    int align = MP_ALIGN_UP((uintptr_t)buffer, stride_align) - (uintptr_t)buffer;
117
20.7k
    if (buffer_size - size < align)
118
0
        return false;
119
20.7k
    uint8_t *s = buffer;
120
20.7k
    s += align;
121
122
103k
    for (int n = 0; n < MP_MAX_PLANES; n++) {
123
82.8k
        mpi->planes[n] = plane_offset[n] >= 0 ? s + plane_offset[n] : NULL;
124
82.8k
        mpi->stride[n] = stride[n];
125
82.8k
    }
126
127
20.7k
    return true;
128
20.7k
}
129
130
// Create a mp_image from the provided buffer. The mp_image is filled according
131
// to the imgfmt/w/h parameters, and respecting the stride_align parameter to
132
// align the plane start pointers and strides. Once the last reference to the
133
// returned image is destroyed, free(free_opaque, buffer) is called. (Be aware
134
// that this can happen from any thread.)
135
// The allocated size of buffer must be given by buffer_size. buffer_size should
136
// be at least the value returned by mp_image_get_alloc_size(). If buffer is not
137
// already aligned to stride_align, the function will attempt to align the
138
// pointer itself by incrementing the buffer pointer until their alignment is
139
// achieved (if buffer_size is not large enough to allow aligning the buffer
140
// safely, the function fails). To be safe, you may want to overallocate the
141
// buffer by stride_align bytes, and include the overallocation in buffer_size.
142
// Returns NULL on failure. On failure, the free() callback is not called.
143
struct mp_image *mp_image_from_buffer(int imgfmt, int w, int h, int stride_align,
144
                                      uint8_t *buffer, int buffer_size,
145
                                      void *free_opaque,
146
                                      void (*free)(void *opaque, uint8_t *data))
147
0
{
148
0
    struct mp_image *mpi = mp_image_new_dummy_ref(NULL);
149
0
    mp_image_setfmt(mpi, imgfmt);
150
0
    mp_image_set_size(mpi, w, h);
151
152
0
    if (!mp_image_fill_alloc(mpi, stride_align, buffer, buffer_size))
153
0
        goto fail;
154
155
0
    mpi->bufs[0] = av_buffer_create(buffer, buffer_size, free, free_opaque, 0);
156
0
    if (!mpi->bufs[0])
157
0
        goto fail;
158
159
0
    return mpi;
160
161
0
fail:
162
0
    talloc_free(mpi);
163
0
    return NULL;
164
0
}
165
166
static bool mp_image_alloc_planes(struct mp_image *mpi)
167
20.7k
{
168
20.7k
    mp_assert(!mpi->planes[0]);
169
20.7k
    mp_assert(!mpi->bufs[0]);
170
171
20.7k
    int align = MP_IMAGE_BYTE_ALIGN;
172
173
20.7k
    int size = mp_image_get_alloc_size(mpi->imgfmt, mpi->w, mpi->h, align);
174
20.7k
    if (size < 0)
175
26
        return false;
176
177
    // Note: mp_image_pool assumes this creates only 1 AVBufferRef.
178
20.7k
    mpi->bufs[0] = av_buffer_alloc(size + align);
179
20.7k
    if (!mpi->bufs[0])
180
0
        return false;
181
182
20.7k
    if (!mp_image_fill_alloc(mpi, align, mpi->bufs[0]->data, mpi->bufs[0]->size)) {
183
0
        av_buffer_unref(&mpi->bufs[0]);
184
0
        return false;
185
0
    }
186
187
20.7k
    return true;
188
20.7k
}
189
190
void mp_image_sethwfmt(struct mp_image *mpi, enum mp_imgfmt hw_fmt, enum mp_imgfmt sw_fmt)
191
413k
{
192
413k
    struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(sw_fmt ? sw_fmt : hw_fmt);
193
413k
    mpi->params.imgfmt = hw_fmt;
194
413k
    mpi->params.hw_subfmt = sw_fmt;
195
413k
    mpi->fmt = fmt;
196
413k
    mpi->imgfmt = hw_fmt;
197
413k
    mpi->num_planes = fmt.num_planes;
198
413k
    mpi->params.repr.alpha = (fmt.flags & MP_IMGFLAG_ALPHA) ? PL_ALPHA_INDEPENDENT
199
413k
#if PL_API_VER >= 344
200
413k
                                                            : PL_ALPHA_NONE;
201
#else
202
                                                            : PL_ALPHA_UNKNOWN;
203
#endif
204
    // Calculate bit encoding from all components (excluding alpha)
205
413k
    struct pl_bit_encoding bits = {0};
206
413k
    const int num_comps = mp_imgfmt_desc_get_num_comps(&fmt);
207
1.60M
    for (int c = 0; c < MPMIN(num_comps, 3); c++) {
208
1.19M
        struct pl_bit_encoding cbits = {
209
1.19M
            .sample_depth = fmt.comps[c].size,
210
1.19M
            .color_depth  = fmt.comps[c].size - abs(fmt.comps[c].pad),
211
1.19M
            .bit_shift    = MPMAX(fmt.comps[c].pad, 0),
212
1.19M
        };
213
214
1.19M
        if (bits.sample_depth && !pl_bit_encoding_equal(&bits, &cbits)) {
215
            // Bit encoding differs between components, cannot handle this
216
1.35k
            bits = (struct pl_bit_encoding) {0};
217
1.35k
            break;
218
1.35k
        }
219
220
1.18M
        bits = cbits;
221
1.18M
    }
222
413k
    mpi->params.repr.bits = bits;
223
413k
}
224
225
void mp_image_setfmt(struct mp_image *mpi, enum mp_imgfmt fmt)
226
44.5k
{
227
44.5k
    mp_image_sethwfmt(mpi, fmt, IMGFMT_NONE);
228
44.5k
}
229
230
static void mp_image_destructor(void *ptr)
231
1.14M
{
232
1.14M
    mp_image_t *mpi = ptr;
233
5.73M
    for (int p = 0; p < MP_MAX_PLANES; p++)
234
4.58M
        av_buffer_unref(&mpi->bufs[p]);
235
1.14M
    av_buffer_unref(&mpi->hwctx);
236
1.14M
    av_buffer_unref(&mpi->icc_profile);
237
1.14M
    av_buffer_unref(&mpi->a53_cc);
238
1.14M
    av_buffer_unref(&mpi->dovi);
239
1.14M
    av_buffer_unref(&mpi->film_grain);
240
1.23M
    for (int n = 0; n < mpi->num_ff_side_data; n++)
241
92.0k
        av_buffer_unref(&mpi->ff_side_data[n].buf);
242
1.14M
    talloc_free(mpi->ff_side_data);
243
1.14M
}
244
245
int mp_chroma_div_up(int size, int shift)
246
628k
{
247
628k
    return (size + (1 << shift) - 1) >> shift;
248
628k
}
249
250
// Return the storage width in pixels of the given plane.
251
int mp_image_plane_w(struct mp_image *mpi, int plane)
252
203k
{
253
203k
    return mp_chroma_div_up(mpi->w, mpi->fmt.xs[plane]);
254
203k
}
255
256
// Return the storage height in pixels of the given plane.
257
int mp_image_plane_h(struct mp_image *mpi, int plane)
258
203k
{
259
203k
    return mp_chroma_div_up(mpi->h, mpi->fmt.ys[plane]);
260
203k
}
261
262
// Caller has to make sure this doesn't exceed the allocated plane data/strides.
263
void mp_image_set_size(struct mp_image *mpi, int w, int h)
264
462k
{
265
462k
    mp_assert(w >= 0 && h >= 0);
266
462k
    mpi->w = mpi->params.w = w;
267
462k
    mpi->h = mpi->params.h = h;
268
462k
}
269
270
void mp_image_set_params(struct mp_image *image,
271
                         const struct mp_image_params *params)
272
1.31k
{
273
    // possibly initialize other stuff
274
1.31k
    mp_image_setfmt(image, params->imgfmt);
275
1.31k
    mp_image_set_size(image, params->w, params->h);
276
1.31k
    image->params = *params;
277
1.31k
}
278
279
struct mp_image *mp_image_alloc(int imgfmt, int w, int h)
280
20.7k
{
281
20.7k
    struct mp_image *mpi = talloc_zero(NULL, struct mp_image);
282
20.7k
    talloc_set_destructor(mpi, mp_image_destructor);
283
284
20.7k
    mp_image_set_size(mpi, w, h);
285
20.7k
    mp_image_setfmt(mpi, imgfmt);
286
20.7k
    if (!mp_image_alloc_planes(mpi)) {
287
26
        talloc_free(mpi);
288
26
        return NULL;
289
26
    }
290
20.7k
    return mpi;
291
20.7k
}
292
293
int mp_image_approx_byte_size(struct mp_image *img)
294
0
{
295
0
    int total = sizeof(*img);
296
297
0
    for (int n = 0; n < MP_MAX_PLANES; n++) {
298
0
        struct AVBufferRef *buf = img->bufs[n];
299
0
        if (buf)
300
0
            total += buf->size;
301
0
    }
302
303
0
    return total;
304
0
}
305
306
struct mp_image *mp_image_new_copy(struct mp_image *img)
307
0
{
308
0
    struct mp_image *new = mp_image_alloc(img->imgfmt, img->w, img->h);
309
0
    if (!new)
310
0
        return NULL;
311
0
    mp_image_copy(new, img);
312
0
    mp_image_copy_attributes(new, img);
313
0
    return new;
314
0
}
315
316
// Make dst take over the image data of src, and free src.
317
// This is basically a safe version of *dst = *src; free(src);
318
// Only works with ref-counted images, and can't change image size/format.
319
void mp_image_steal_data(struct mp_image *dst, struct mp_image *src)
320
0
{
321
0
    mp_assert(dst->imgfmt == src->imgfmt && dst->w == src->w && dst->h == src->h);
322
0
    mp_assert(dst->bufs[0] && src->bufs[0]);
323
324
0
    mp_image_destructor(dst); // unref old
325
0
    talloc_free_children(dst);
326
327
0
    *dst = *src;
328
329
0
    *src = (struct mp_image){0};
330
0
    talloc_free(src);
331
0
}
332
333
// Unref most data buffer (and clear the data array), but leave other fields
334
// allocated. In particular, mp_image.hwctx is preserved.
335
void mp_image_unref_data(struct mp_image *img)
336
0
{
337
0
    for (int n = 0; n < MP_MAX_PLANES; n++) {
338
0
        img->planes[n] = NULL;
339
0
        img->stride[n] = 0;
340
0
        av_buffer_unref(&img->bufs[n]);
341
0
    }
342
0
}
343
344
static void ref_buffer(AVBufferRef **dst)
345
9.80M
{
346
9.80M
    if (*dst) {
347
2.58M
        *dst = av_buffer_ref(*dst);
348
2.58M
        MP_HANDLE_OOM(*dst);
349
2.58M
    }
350
9.80M
}
351
352
// Return a new reference to img. The returned reference is owned by the caller,
353
// while img is left untouched.
354
struct mp_image *mp_image_new_ref(struct mp_image *img)
355
1.07M
{
356
1.07M
    if (!img)
357
0
        return NULL;
358
359
1.07M
    if (!img->bufs[0])
360
0
        return mp_image_new_copy(img);
361
362
1.07M
    struct mp_image *new = talloc_ptrtype(NULL, new);
363
1.07M
    talloc_set_destructor(new, mp_image_destructor);
364
1.07M
    *new = *img;
365
366
5.39M
    for (int p = 0; p < MP_MAX_PLANES; p++)
367
4.31M
        ref_buffer(&new->bufs[p]);
368
369
1.07M
    ref_buffer(&new->hwctx);
370
1.07M
    ref_buffer(&new->icc_profile);
371
1.07M
    ref_buffer(&new->a53_cc);
372
1.07M
    ref_buffer(&new->dovi);
373
1.07M
    ref_buffer(&new->film_grain);
374
375
1.07M
    new->ff_side_data = talloc_memdup(NULL, new->ff_side_data,
376
1.07M
                        new->num_ff_side_data * sizeof(new->ff_side_data[0]));
377
1.17M
    for (int n = 0; n < new->num_ff_side_data; n++)
378
92.0k
        ref_buffer(&new->ff_side_data[n].buf);
379
380
1.07M
    return new;
381
1.07M
}
382
383
struct free_args {
384
    void *arg;
385
    void (*free)(void *arg);
386
};
387
388
static void call_free(void *opaque, uint8_t *data)
389
0
{
390
0
    struct free_args *args = opaque;
391
0
    args->free(args->arg);
392
0
    talloc_free(args);
393
0
}
394
395
// Create a new mp_image based on img, but don't set any buffers.
396
// Using this is only valid until the original img is unreferenced (including
397
// implicit unreferencing of the data by mp_image_make_writeable()), unless
398
// a new reference is set.
399
struct mp_image *mp_image_new_dummy_ref(struct mp_image *img)
400
46.0k
{
401
46.0k
    struct mp_image *new = talloc_ptrtype(NULL, new);
402
46.0k
    talloc_set_destructor(new, mp_image_destructor);
403
46.0k
    *new = img ? *img : (struct mp_image){0};
404
230k
    for (int p = 0; p < MP_MAX_PLANES; p++)
405
184k
        new->bufs[p] = NULL;
406
46.0k
    new->hwctx = NULL;
407
46.0k
    new->icc_profile = NULL;
408
46.0k
    new->a53_cc = NULL;
409
46.0k
    new->dovi = NULL;
410
46.0k
    new->film_grain = NULL;
411
46.0k
    new->num_ff_side_data = 0;
412
46.0k
    new->ff_side_data = NULL;
413
46.0k
    return new;
414
46.0k
}
415
416
// Return a reference counted reference to img. If the reference count reaches
417
// 0, call free(free_arg). The data passed by img must not be free'd before
418
// that. The new reference will be writeable.
419
// On allocation failure, unref the frame and return NULL.
420
// This is only used for hw decoding; this is important, because libav* expects
421
// all plane data to be accounted for by AVBufferRefs.
422
struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *free_arg,
423
                                         void (*free)(void *arg))
424
0
{
425
0
    struct mp_image *new = mp_image_new_dummy_ref(img);
426
427
0
    struct free_args *args = talloc_ptrtype(NULL, args);
428
0
    *args = (struct free_args){free_arg, free};
429
0
    new->bufs[0] = av_buffer_create(NULL, 0, call_free, args,
430
0
                                    AV_BUFFER_FLAG_READONLY);
431
0
    if (new->bufs[0])
432
0
        return new;
433
0
    talloc_free(new);
434
0
    return NULL;
435
0
}
436
437
bool mp_image_is_writeable(struct mp_image *img)
438
28.6k
{
439
28.6k
    if (!img->bufs[0])
440
0
        return true; // not ref-counted => always considered writeable
441
57.2k
    for (int p = 0; p < MP_MAX_PLANES; p++) {
442
57.2k
        if (!img->bufs[p])
443
28.6k
            break;
444
28.6k
        if (!av_buffer_is_writable(img->bufs[p]))
445
0
            return false;
446
28.6k
    }
447
28.6k
    return true;
448
28.6k
}
449
450
// Make the image data referenced by img writeable. This allocates new data
451
// if the data wasn't already writeable, and img->planes[] and img->stride[]
452
// will be set to the copy.
453
// Returns success; if false is returned, the image could not be made writeable.
454
bool mp_image_make_writeable(struct mp_image *img)
455
72
{
456
72
    if (mp_image_is_writeable(img))
457
72
        return true;
458
459
0
    struct mp_image *new = mp_image_new_copy(img);
460
0
    if (!new)
461
0
        return false;
462
0
    mp_image_steal_data(img, new);
463
0
    mp_assert(mp_image_is_writeable(img));
464
0
    return true;
465
0
}
466
467
// Helper function: unrefs *p_img, and sets *p_img to a new ref of new_value.
468
// Only unrefs *p_img and sets it to NULL if out of memory.
469
void mp_image_setrefp(struct mp_image **p_img, struct mp_image *new_value)
470
53
{
471
53
    if (*p_img != new_value) {
472
53
        talloc_free(*p_img);
473
53
        *p_img = new_value ? mp_image_new_ref(new_value) : NULL;
474
53
    }
475
53
}
476
477
// Mere helper function (mp_image can be directly free'd with talloc_free)
478
void mp_image_unrefp(struct mp_image **p_img)
479
1.91M
{
480
1.91M
    talloc_free(*p_img);
481
1.91M
    *p_img = NULL;
482
1.91M
}
483
484
void memcpy_pic(void *dst, const void *src, int bytesPerLine, int height,
485
                int dstStride, int srcStride)
486
77.9k
{
487
77.9k
    if (bytesPerLine == dstStride && dstStride == srcStride && height) {
488
65.3k
        if (srcStride < 0) {
489
0
            src = (uint8_t*)src + (height - 1) * srcStride;
490
0
            dst = (uint8_t*)dst + (height - 1) * dstStride;
491
0
            srcStride = -srcStride;
492
0
        }
493
494
65.3k
        memcpy(dst, src, srcStride * (height - 1) + bytesPerLine);
495
65.3k
    } else {
496
9.75M
        for (int i = 0; i < height; i++) {
497
9.74M
            memcpy(dst, src, bytesPerLine);
498
9.74M
            src = (uint8_t*)src + srcStride;
499
9.74M
            dst = (uint8_t*)dst + dstStride;
500
9.74M
        }
501
12.6k
    }
502
77.9k
}
503
504
void mp_image_copy(struct mp_image *dst, struct mp_image *src)
505
28.4k
{
506
28.4k
    mp_assert(dst->imgfmt == src->imgfmt);
507
28.4k
    mp_assert(dst->w == src->w && dst->h == src->h);
508
28.4k
    mp_assert(mp_image_is_writeable(dst));
509
105k
    for (int n = 0; n < dst->num_planes; n++) {
510
77.1k
        int line_bytes = (mp_image_plane_w(dst, n) * dst->fmt.bpp[n] + 7) / 8;
511
77.1k
        int plane_h = mp_image_plane_h(dst, n);
512
77.1k
        memcpy_pic(dst->planes[n], src->planes[n], line_bytes, plane_h,
513
77.1k
                   dst->stride[n], src->stride[n]);
514
77.1k
    }
515
28.4k
    if (dst->fmt.flags & MP_IMGFLAG_PAL)
516
0
        memcpy(dst->planes[1], src->planes[1], AVPALETTE_SIZE);
517
28.4k
}
518
519
static enum pl_color_system mp_image_params_get_forced_csp(struct mp_image_params *params)
520
196k
{
521
196k
    int imgfmt = params->hw_subfmt ? params->hw_subfmt : params->imgfmt;
522
196k
    enum pl_color_system csp = mp_imgfmt_get_forced_csp(imgfmt);
523
524
196k
    if (csp == PL_COLOR_SYSTEM_RGB && params->repr.sys == PL_COLOR_SYSTEM_XYZ)
525
1.09k
        csp = PL_COLOR_SYSTEM_XYZ;
526
527
196k
    return csp;
528
196k
}
529
530
static void assign_bufref(AVBufferRef **dst, AVBufferRef *new)
531
203k
{
532
203k
    av_buffer_unref(dst);
533
203k
    if (new) {
534
0
        *dst = av_buffer_ref(new);
535
0
        MP_HANDLE_OOM(*dst);
536
0
    }
537
203k
}
538
539
void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src)
540
50.9k
{
541
50.9k
    mp_assert(dst != src);
542
543
50.9k
    dst->pict_type = src->pict_type;
544
50.9k
    dst->fields = src->fields;
545
50.9k
    dst->pts = src->pts;
546
50.9k
    dst->dts = src->dts;
547
50.9k
    dst->pkt_duration = src->pkt_duration;
548
50.9k
    dst->params.vflip = src->params.vflip;
549
50.9k
    dst->params.rotate = src->params.rotate;
550
50.9k
    dst->params.stereo3d = src->params.stereo3d;
551
50.9k
    dst->params.p_w = src->params.p_w;
552
50.9k
    dst->params.p_h = src->params.p_h;
553
50.9k
    dst->params.color = src->params.color;
554
50.9k
    dst->params.repr = src->params.repr;
555
50.9k
    dst->params.light = src->params.light;
556
50.9k
    dst->params.chroma_location = src->params.chroma_location;
557
50.9k
    dst->params.crop = src->params.crop;
558
50.9k
    dst->nominal_fps = src->nominal_fps;
559
50.9k
    dst->params.primaries_orig = src->params.primaries_orig;
560
50.9k
    dst->params.transfer_orig = src->params.transfer_orig;
561
50.9k
    dst->params.sys_orig = src->params.sys_orig;
562
563
    // ensure colorspace consistency
564
50.9k
    enum pl_color_system dst_forced_csp = mp_image_params_get_forced_csp(&dst->params);
565
50.9k
    if (mp_image_params_get_forced_csp(&src->params) != dst_forced_csp) {
566
7.03k
        dst->params.repr.sys = dst_forced_csp != PL_COLOR_SYSTEM_UNKNOWN ?
567
4.60k
                                    dst_forced_csp :
568
7.03k
                                    mp_csp_guess_colorspace(src->w, src->h);
569
7.03k
    }
570
571
50.9k
    if ((dst->fmt.flags & MP_IMGFLAG_PAL) && (src->fmt.flags & MP_IMGFLAG_PAL)) {
572
0
        if (dst->planes[1] && src->planes[1]) {
573
0
            if (mp_image_make_writeable(dst))
574
0
                memcpy(dst->planes[1], src->planes[1], AVPALETTE_SIZE);
575
0
        }
576
0
    }
577
50.9k
    assign_bufref(&dst->icc_profile, src->icc_profile);
578
50.9k
    assign_bufref(&dst->dovi, src->dovi);
579
50.9k
    assign_bufref(&dst->film_grain, src->film_grain);
580
50.9k
    assign_bufref(&dst->a53_cc, src->a53_cc);
581
582
50.9k
    for (int n = 0; n < dst->num_ff_side_data; n++)
583
0
        av_buffer_unref(&dst->ff_side_data[n].buf);
584
585
50.9k
    MP_RESIZE_ARRAY(NULL, dst->ff_side_data, src->num_ff_side_data);
586
50.9k
    dst->num_ff_side_data = src->num_ff_side_data;
587
588
50.9k
    for (int n = 0; n < dst->num_ff_side_data; n++) {
589
0
        dst->ff_side_data[n].type = src->ff_side_data[n].type;
590
0
        dst->ff_side_data[n].buf = av_buffer_ref(src->ff_side_data[n].buf);
591
0
        MP_HANDLE_OOM(dst->ff_side_data[n].buf);
592
0
    }
593
50.9k
}
594
595
// Crop the given image to (x0, y0)-(x1, y1) (bottom/right border exclusive)
596
// x0/y0 must be naturally aligned.
597
void mp_image_crop(struct mp_image *img, int x0, int y0, int x1, int y1)
598
71.7k
{
599
71.7k
    mp_assert(x0 >= 0 && y0 >= 0);
600
71.7k
    mp_assert(x0 <= x1 && y0 <= y1);
601
71.7k
    mp_assert(x1 <= img->w && y1 <= img->h);
602
71.7k
    mp_assert(!(x0 & (img->fmt.align_x - 1)));
603
71.7k
    mp_assert(!(y0 & (img->fmt.align_y - 1)));
604
605
260k
    for (int p = 0; p < img->num_planes; ++p) {
606
189k
        img->planes[p] += (y0 >> img->fmt.ys[p]) * img->stride[p] +
607
189k
                          (x0 >> img->fmt.xs[p]) * img->fmt.bpp[p] / 8;
608
189k
    }
609
71.7k
    mp_image_set_size(img, x1 - x0, y1 - y0);
610
71.7k
}
611
612
void mp_image_crop_rc(struct mp_image *img, struct mp_rect rc)
613
8
{
614
8
    mp_image_crop(img, rc.x0, rc.y0, rc.x1, rc.y1);
615
8
}
616
617
// Repeatedly write count patterns of src[0..src_size] to p.
618
static void memset_pattern(void *p, size_t count, uint8_t *src, size_t src_size)
619
5.96M
{
620
5.96M
    mp_assert(src_size >= 1);
621
622
5.96M
    if (src_size == 1) {
623
4.30M
        memset(p, src[0], count);
624
4.30M
    } else if (src_size == 2) { // >8 bit YUV => common, be slightly less naive
625
1.21M
        uint16_t val;
626
1.21M
        memcpy(&val, src, 2);
627
1.21M
        uint16_t *p16 = p;
628
362M
        while (count--)
629
361M
            *p16++ = val;
630
1.21M
    } else {
631
137M
        while (count--) {
632
137M
            memcpy(p, src, src_size);
633
137M
            p = (char *)p + src_size;
634
137M
        }
635
440k
    }
636
5.96M
}
637
638
static bool endian_swap_bytes(void *d, size_t bytes, size_t word_size)
639
3.76k
{
640
3.76k
    if (word_size != 2 && word_size != 4)
641
0
        return false;
642
643
3.76k
    size_t num_words = bytes / word_size;
644
3.76k
    uint8_t *ud = d;
645
646
3.76k
    switch (word_size) {
647
3.76k
    case 2:
648
6.72k
        for (size_t x = 0; x < num_words; x++)
649
3.76k
            AV_WL16(ud + x * 2, AV_RB16(ud + x * 2));
650
3.76k
        break;
651
0
    case 4:
652
0
        for (size_t x = 0; x < num_words; x++)
653
0
            AV_WL32(ud + x * 2, AV_RB32(ud + x * 2));
654
0
        break;
655
0
    default:
656
0
        MP_ASSERT_UNREACHABLE();
657
3.76k
    }
658
659
3.76k
    return true;
660
3.76k
}
661
662
// Bottom/right border is allowed not to be aligned, but it might implicitly
663
// overwrite pixel data until the alignment (align_x/align_y) is reached.
664
// Alpha is cleared to 0 (fully transparent).
665
void mp_image_clear(struct mp_image *img, int x0, int y0, int x1, int y1)
666
48.1k
{
667
48.1k
    mp_assert(x0 >= 0 && y0 >= 0);
668
48.1k
    mp_assert(x0 <= x1 && y0 <= y1);
669
48.1k
    mp_assert(x1 <= img->w && y1 <= img->h);
670
48.1k
    mp_assert(!(x0 & (img->fmt.align_x - 1)));
671
48.1k
    mp_assert(!(y0 & (img->fmt.align_y - 1)));
672
673
48.1k
    struct mp_image area = *img;
674
48.1k
    struct mp_imgfmt_desc *fmt = &area.fmt;
675
48.1k
    mp_image_crop(&area, x0, y0, x1, y1);
676
677
    // "Black" color for each plane.
678
48.1k
    uint8_t plane_clear[MP_MAX_PLANES][8] = {0};
679
48.1k
    int plane_size[MP_MAX_PLANES] = {0};
680
48.1k
    int misery = 1; // pixel group width
681
682
    // YUV integer chroma needs special consideration, and technically luma is
683
    // usually not 0 either.
684
48.1k
    if ((fmt->flags & (MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_PACKED_SS_YUV)) &&
685
48.1k
        (fmt->flags & MP_IMGFLAG_TYPE_MASK) == MP_IMGFLAG_TYPE_UINT &&
686
48.1k
        (fmt->flags & MP_IMGFLAG_COLOR_MASK) == MP_IMGFLAG_COLOR_YUV)
687
30.8k
    {
688
30.8k
        uint64_t plane_clear_i[MP_MAX_PLANES] = {0};
689
690
        // Need to handle "multiple" pixels with packed YUV.
691
30.8k
        uint8_t luma_offsets[4] = {0};
692
30.8k
        if (fmt->flags & MP_IMGFLAG_PACKED_SS_YUV) {
693
156
            misery = fmt->align_x;
694
156
            if (misery <= MP_ARRAY_SIZE(luma_offsets)) // ignore if out of bounds
695
156
                mp_imgfmt_get_packed_yuv_locations(fmt->id, luma_offsets);
696
156
        }
697
698
154k
        for (int c = 0; c < 4; c++) {
699
123k
            struct mp_imgfmt_comp_desc *cd = &fmt->comps[c];
700
123k
            int plane_bits = fmt->bpp[cd->plane] * misery;
701
123k
            if (plane_bits <= 64 && plane_bits % 8u == 0 && cd->size) {
702
89.9k
                plane_size[cd->plane] = plane_bits / 8u;
703
89.9k
                int depth = cd->size + MPMIN(cd->pad, 0);
704
89.9k
                double m, o;
705
89.9k
                mp_get_csp_uint_mul(area.params.repr.sys,
706
89.9k
                                    area.params.repr.levels,
707
89.9k
                                    depth, c + 1, &m, &o);
708
89.9k
                uint64_t val = MPCLAMP(lrint((0 - o) / m), 0, 1ull << depth);
709
89.9k
                plane_clear_i[cd->plane] |= val << cd->offset;
710
90.1k
                for (int x = 1; x < (c ? 0 : misery); x++)
711
156
                    plane_clear_i[cd->plane] |= val << luma_offsets[x];
712
89.9k
            }
713
123k
        }
714
715
154k
        for (int p = 0; p < MP_MAX_PLANES; p++) {
716
123k
            if (!plane_clear_i[p])
717
49.8k
                plane_size[p] = 0;
718
123k
            memcpy(&plane_clear[p][0], &plane_clear_i[p], 8); // endian dependent
719
720
123k
            if (fmt->endian_shift) {
721
3.76k
                endian_swap_bytes(&plane_clear[p][0], plane_size[p],
722
3.76k
                                  1 << fmt->endian_shift);
723
3.76k
            }
724
123k
        }
725
30.8k
    }
726
727
174k
    for (int p = 0; p < area.num_planes; p++) {
728
126k
        int p_h = mp_image_plane_h(&area, p);
729
126k
        int p_w = mp_image_plane_w(&area, p);
730
8.91M
        for (int y = 0; y < p_h; y++) {
731
8.78M
            void *ptr = area.planes[p] + (ptrdiff_t)area.stride[p] * y;
732
8.78M
            if (plane_size[p]) {
733
5.96M
                memset_pattern(ptr, p_w / misery, plane_clear[p], plane_size[p]);
734
5.96M
            } else {
735
2.82M
                memset(ptr, 0, mp_image_plane_bytes(&area, p, 0, area.w));
736
2.82M
            }
737
8.78M
        }
738
126k
    }
739
48.1k
}
740
741
void mp_image_clear_rc(struct mp_image *mpi, struct mp_rect rc)
742
0
{
743
0
    mp_image_clear(mpi, rc.x0, rc.y0, rc.x1, rc.y1);
744
0
}
745
746
// Clear the are of the image _not_ covered by rc.
747
void mp_image_clear_rc_inv(struct mp_image *mpi, struct mp_rect rc)
748
0
{
749
0
    struct mp_rect clr[4];
750
0
    int cnt = mp_rect_subtract(&(struct mp_rect){0, 0, mpi->w, mpi->h}, &rc, clr);
751
0
    for (int n = 0; n < cnt; n++)
752
0
        mp_image_clear_rc(mpi, clr[n]);
753
0
}
754
755
void mp_image_vflip(struct mp_image *img)
756
0
{
757
0
    for (int p = 0; p < img->num_planes; p++) {
758
0
        int plane_h = mp_image_plane_h(img, p);
759
0
        img->planes[p] = img->planes[p] + img->stride[p] * (plane_h - 1);
760
0
        img->stride[p] = -img->stride[p];
761
0
    }
762
0
}
763
764
bool mp_image_crop_valid(const struct mp_image_params *p)
765
634k
{
766
634k
    return p->crop.x1 > p->crop.x0 && p->crop.y1 > p->crop.y0 &&
767
630k
           p->crop.x0 >= 0 && p->crop.y0 >= 0 &&
768
630k
           p->crop.x1 <= p->w && p->crop.y1 <= p->h;
769
634k
}
770
771
// Display size derived from image size and pixel aspect ratio.
772
void mp_image_params_get_dsize(const struct mp_image_params *p,
773
                               int *d_w, int *d_h)
774
64.2k
{
775
64.2k
    if (mp_image_crop_valid(p))
776
61.0k
    {
777
61.0k
        *d_w = mp_rect_w(p->crop);
778
61.0k
        *d_h = mp_rect_h(p->crop);
779
61.0k
    } else {
780
3.21k
        *d_w = p->w;
781
3.21k
        *d_h = p->h;
782
3.21k
    }
783
784
64.2k
    if (p->p_w > p->p_h && p->p_h >= 1)
785
19.2k
        *d_w = MPCLAMP(*d_w * (int64_t)p->p_w / p->p_h, 1, INT_MAX);
786
64.2k
    if (p->p_h > p->p_w && p->p_w >= 1)
787
5.06k
        *d_h = MPCLAMP(*d_h * (int64_t)p->p_h / p->p_w, 1, INT_MAX);
788
64.2k
}
789
790
void mp_image_params_set_dsize(struct mp_image_params *p, int d_w, int d_h)
791
37.0k
{
792
37.0k
    AVRational ds = av_div_q((AVRational){d_w, d_h}, (AVRational){p->w, p->h});
793
37.0k
    p->p_w = ds.num;
794
37.0k
    p->p_h = ds.den;
795
37.0k
}
796
797
char *mp_image_params_to_str_buf(char *b, size_t bs,
798
                                 const struct mp_image_params *p)
799
213k
{
800
213k
    if (p && p->imgfmt) {
801
213k
        snprintf(b, bs, "%dx%d", p->w, p->h);
802
213k
        if (p->p_w != p->p_h || !p->p_w)
803
59.3k
            mp_snprintf_cat(b, bs, " [%d:%d]", p->p_w, p->p_h);
804
213k
        mp_snprintf_cat(b, bs, " %s", mp_imgfmt_to_name(p->imgfmt));
805
213k
        if (p->hw_subfmt)
806
0
            mp_snprintf_cat(b, bs, "[%s]", mp_imgfmt_to_name(p->hw_subfmt));
807
213k
        mp_snprintf_cat(b, bs, " %s/%s/%s/%s/%s",
808
213k
                        m_opt_choice_str(pl_csp_names, p->repr.sys),
809
213k
                        m_opt_choice_str(pl_csp_prim_names, p->color.primaries),
810
213k
                        m_opt_choice_str(pl_csp_trc_names, p->color.transfer),
811
213k
                        m_opt_choice_str(pl_csp_levels_names, p->repr.levels),
812
213k
                        m_opt_choice_str(mp_csp_light_names, p->light));
813
213k
        mp_snprintf_cat(b, bs, " CL=%s",
814
213k
                        m_opt_choice_str(pl_chroma_names, p->chroma_location));
815
213k
        if (mp_image_crop_valid(p)) {
816
211k
            mp_snprintf_cat(b, bs, " crop=%dx%d+%d+%d", mp_rect_w(p->crop),
817
211k
                            mp_rect_h(p->crop), p->crop.x0, p->crop.y0);
818
211k
        }
819
213k
        if (p->rotate)
820
622
            mp_snprintf_cat(b, bs, " rot=%d", p->rotate);
821
213k
        if (p->stereo3d > 0) {
822
0
            mp_snprintf_cat(b, bs, " stereo=%s",
823
0
                            MP_STEREO3D_NAME_DEF(p->stereo3d, "?"));
824
0
        }
825
213k
        if (p->repr.alpha) {
826
202k
            mp_snprintf_cat(b, bs, " A=%s",
827
202k
                            m_opt_choice_str(pl_alpha_names, p->repr.alpha));
828
202k
        }
829
213k
    } else {
830
0
        snprintf(b, bs, "???");
831
0
    }
832
213k
    return b;
833
213k
}
834
835
// Return whether the image parameters are valid.
836
// Some non-essential fields are allowed to be unset (like colorspace flags).
837
bool mp_image_params_valid(const struct mp_image_params *p)
838
41.4k
{
839
    // av_image_check_size has similar checks and triggers around 16000*16000
840
    // It's mostly needed to deal with the fact that offsets are sometimes
841
    // ints. We also should (for now) do the same as FFmpeg, to be sure large
842
    // images don't crash with libswscale or when wrapping with AVFrame and
843
    // passing the result to filters.
844
41.4k
    if (p->w <= 0 || p->h <= 0 || (p->w + 128LL) * (p->h + 128LL) >= INT_MAX / 8)
845
26
        return false;
846
847
41.4k
    if (p->p_w < 0 || p->p_h < 0)
848
0
        return false;
849
850
41.4k
    if (p->rotate < 0 || p->rotate >= 360)
851
0
        return false;
852
853
41.4k
    struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(p->imgfmt);
854
41.4k
    if (!desc.id)
855
0
        return false;
856
857
41.4k
    if (p->hw_subfmt && !(desc.flags & MP_IMGFLAG_HWACCEL))
858
0
        return false;
859
860
41.4k
    return true;
861
41.4k
}
862
863
bool mp_image_params_equal(const struct mp_image_params *p1,
864
                           const struct mp_image_params *p2)
865
3.06M
{
866
3.06M
    return p1->imgfmt == p2->imgfmt &&
867
2.71M
           p1->hw_subfmt == p2->hw_subfmt &&
868
2.71M
           p1->w == p2->w && p1->h == p2->h &&
869
2.68M
           p1->p_w == p2->p_w && p1->p_h == p2->p_h &&
870
2.67M
           p1->force_window == p2->force_window &&
871
2.67M
           pl_color_space_equal(&p1->color, &p2->color) &&
872
2.67M
           pl_color_repr_equal(&p1->repr, &p2->repr) &&
873
2.67M
           p1->light == p2->light &&
874
2.67M
           p1->chroma_location == p2->chroma_location &&
875
2.67M
           p1->vflip == p2->vflip &&
876
2.67M
           p1->rotate == p2->rotate &&
877
2.67M
           p1->stereo3d == p2->stereo3d &&
878
2.67M
           mp_rect_equals(&p1->crop, &p2->crop);
879
3.06M
}
880
881
bool mp_image_params_static_equal(const struct mp_image_params *p1,
882
                                  const struct mp_image_params *p2)
883
525k
{
884
    // Compare only static video parameters, excluding dynamic metadata.
885
525k
    struct mp_image_params a = *p1;
886
525k
    struct mp_image_params b = *p2;
887
525k
    a.repr.dovi = b.repr.dovi = NULL;
888
525k
    a.color.hdr = b.color.hdr = (struct pl_hdr_metadata){0};
889
525k
    return mp_image_params_equal(&a, &b);
890
525k
}
891
892
void mp_image_params_update_dynamic(struct mp_image_params *dst,
893
                                    const struct mp_image_params *src,
894
                                    bool has_peak_detect_values)
895
332k
{
896
332k
    dst->repr.dovi = src->repr.dovi;
897
    // Don't overwrite peak-detected HDR metadata if available.
898
332k
    float max_pq_y = dst->color.hdr.max_pq_y;
899
332k
    float avg_pq_y = dst->color.hdr.avg_pq_y;
900
332k
    dst->color.hdr = src->color.hdr;
901
332k
    if (has_peak_detect_values) {
902
0
        dst->color.hdr.max_pq_y = max_pq_y;
903
0
        dst->color.hdr.avg_pq_y = avg_pq_y;
904
0
    }
905
332k
}
906
907
// Restore color system, transfer, and primaries to their original values
908
// before dovi mapping.
909
void mp_image_params_restore_dovi_mapping(struct mp_image_params *params)
910
0
{
911
0
    if (params->repr.sys != PL_COLOR_SYSTEM_DOLBYVISION)
912
0
        return;
913
0
    params->color.primaries = params->primaries_orig;
914
0
    params->color.transfer = params->transfer_orig;
915
0
    params->repr.sys = params->sys_orig;
916
0
    if (!pl_color_transfer_is_hdr(params->transfer_orig))
917
0
        params->color.hdr = (struct pl_hdr_metadata){0};
918
0
    if (params->transfer_orig != PL_COLOR_TRC_PQ)
919
0
        params->color.hdr.max_pq_y = params->color.hdr.avg_pq_y = 0;
920
0
}
921
922
// Set most image parameters, but not image format or size.
923
// Display size is used to set the PAR.
924
void mp_image_set_attributes(struct mp_image *image,
925
                             const struct mp_image_params *params)
926
0
{
927
0
    struct mp_image_params nparams = *params;
928
0
    nparams.imgfmt = image->imgfmt;
929
0
    nparams.w = image->w;
930
0
    nparams.h = image->h;
931
0
    if (nparams.imgfmt != params->imgfmt) {
932
0
        nparams.repr = (struct pl_color_repr){0};
933
0
        nparams.color = (struct pl_color_space){0};
934
0
    }
935
0
    mp_image_set_params(image, &nparams);
936
0
}
937
938
static enum pl_color_levels infer_levels(enum mp_imgfmt imgfmt)
939
15.2k
{
940
15.2k
    switch (imgfmt2pixfmt(imgfmt)) {
941
0
    case AV_PIX_FMT_YUVJ420P:
942
0
    case AV_PIX_FMT_YUVJ411P:
943
0
    case AV_PIX_FMT_YUVJ422P:
944
0
    case AV_PIX_FMT_YUVJ444P:
945
0
    case AV_PIX_FMT_YUVJ440P:
946
780
    case AV_PIX_FMT_GRAY8:
947
782
    case AV_PIX_FMT_YA8:
948
782
    case AV_PIX_FMT_GRAY9LE:
949
782
    case AV_PIX_FMT_GRAY9BE:
950
782
    case AV_PIX_FMT_GRAY10LE:
951
782
    case AV_PIX_FMT_GRAY10BE:
952
782
    case AV_PIX_FMT_GRAY12LE:
953
782
    case AV_PIX_FMT_GRAY12BE:
954
782
    case AV_PIX_FMT_GRAY14LE:
955
782
    case AV_PIX_FMT_GRAY14BE:
956
1.01k
    case AV_PIX_FMT_GRAY16LE:
957
1.01k
    case AV_PIX_FMT_GRAY16BE:
958
1.01k
    case AV_PIX_FMT_YA16BE:
959
1.01k
    case AV_PIX_FMT_YA16LE:
960
1.01k
        return PL_COLOR_LEVELS_FULL;
961
14.2k
    default:
962
14.2k
        return PL_COLOR_LEVELS_LIMITED;
963
15.2k
    }
964
15.2k
}
965
966
// If details like params->colorspace/colorlevels are missing, guess them from
967
// the other settings. Also, even if they are set, make them consistent with
968
// the colorspace as implied by the pixel format.
969
void mp_image_params_guess_csp(struct mp_image_params *params)
970
94.3k
{
971
94.3k
    enum pl_color_system forced_csp = mp_image_params_get_forced_csp(params);
972
94.3k
    if (forced_csp == PL_COLOR_SYSTEM_UNKNOWN) { // YUV/other
973
69.2k
        if (params->repr.sys != PL_COLOR_SYSTEM_BT_601 &&
974
24.4k
            params->repr.sys != PL_COLOR_SYSTEM_BT_709 &&
975
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_BT_2020_NC &&
976
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_BT_2020_C &&
977
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_BT_2100_PQ &&
978
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_BT_2100_HLG &&
979
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_DOLBYVISION &&
980
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_SMPTE_240M &&
981
18.2k
            params->repr.sys != PL_COLOR_SYSTEM_YCGCO
982
18.2k
#if PL_API_VER >= 358
983
18.2k
            && params->repr.sys != PL_COLOR_SYSTEM_YCGCO_RE
984
18.2k
            && params->repr.sys != PL_COLOR_SYSTEM_YCGCO_RO
985
69.2k
#endif
986
69.2k
        ) {
987
            // Makes no sense, so guess instead
988
            // YCGCO should be separate, but libavcodec disagrees
989
18.2k
            params->repr.sys = PL_COLOR_SYSTEM_UNKNOWN;
990
18.2k
        }
991
69.2k
        if (params->repr.sys == PL_COLOR_SYSTEM_UNKNOWN)
992
18.2k
            params->repr.sys = mp_csp_guess_colorspace(params->w, params->h);
993
69.2k
        if (params->repr.levels == PL_COLOR_LEVELS_UNKNOWN) {
994
15.2k
            if (params->color.transfer == PL_COLOR_TRC_V_LOG) {
995
0
                params->repr.levels = PL_COLOR_LEVELS_FULL;
996
15.2k
            } else {
997
15.2k
                params->repr.levels = infer_levels(params->imgfmt);
998
15.2k
            }
999
15.2k
        }
1000
69.2k
        if (params->color.primaries == PL_COLOR_PRIM_UNKNOWN) {
1001
            // Guess based on the colormatrix as a first priority
1002
18.8k
            if (params->repr.sys == PL_COLOR_SYSTEM_BT_2020_NC ||
1003
18.8k
                params->repr.sys == PL_COLOR_SYSTEM_BT_2020_C) {
1004
7
                params->color.primaries = PL_COLOR_PRIM_BT_2020;
1005
18.8k
            } else if (params->repr.sys == PL_COLOR_SYSTEM_BT_709) {
1006
2.32k
                params->color.primaries = PL_COLOR_PRIM_BT_709;
1007
16.4k
            } else {
1008
                // Ambiguous colormatrix for BT.601, guess based on res
1009
16.4k
                params->color.primaries = mp_csp_guess_primaries(params->w, params->h);
1010
16.4k
            }
1011
18.8k
        }
1012
69.2k
        if (params->color.transfer == PL_COLOR_TRC_UNKNOWN)
1013
18.7k
            params->color.transfer = params->repr.levels == PL_COLOR_LEVELS_LIMITED ?
1014
17.3k
                                        PL_COLOR_TRC_BT_1886 : PL_COLOR_TRC_SRGB;
1015
69.2k
    } else if (forced_csp == PL_COLOR_SYSTEM_RGB) {
1016
20.4k
        params->repr.sys = PL_COLOR_SYSTEM_RGB;
1017
20.4k
        params->repr.levels = PL_COLOR_LEVELS_FULL;
1018
1019
        // The majority of RGB content is either sRGB or (rarely) some other
1020
        // color space which we don't even handle, like AdobeRGB or
1021
        // ProPhotoRGB. The only reasonable thing we can do is assume it's
1022
        // sRGB and hope for the best, which should usually just work out fine.
1023
        // Note: sRGB primaries = BT.709 primaries
1024
20.4k
        if (params->color.primaries == PL_COLOR_PRIM_UNKNOWN)
1025
5.16k
            params->color.primaries = PL_COLOR_PRIM_BT_709;
1026
20.4k
        if (params->color.transfer == PL_COLOR_TRC_UNKNOWN)
1027
5.19k
            params->color.transfer = PL_COLOR_TRC_SRGB;
1028
20.4k
    } else if (forced_csp == PL_COLOR_SYSTEM_XYZ) {
1029
4.62k
        params->repr.sys = PL_COLOR_SYSTEM_XYZ;
1030
4.62k
        params->repr.levels = PL_COLOR_LEVELS_FULL;
1031
        // Force gamma to ST428 as this is the only correct for DCDM X'Y'Z'
1032
4.62k
        params->color.transfer = PL_COLOR_TRC_ST428;
1033
        // Don't care about primaries, they shouldn't be used, or if anything
1034
        // MP_CSP_PRIM_ST428 should be defined.
1035
4.62k
    } else {
1036
        // We have no clue.
1037
0
        params->repr.sys = PL_COLOR_SYSTEM_UNKNOWN;
1038
0
        params->repr.levels = PL_COLOR_LEVELS_UNKNOWN;
1039
0
        params->color.primaries = PL_COLOR_PRIM_UNKNOWN;
1040
0
        params->color.transfer = PL_COLOR_TRC_UNKNOWN;
1041
0
    }
1042
1043
    // If the signal peak is unknown, we're forced to pick the TRC's
1044
    // nominal range as the signal peak to prevent clipping
1045
94.3k
    pl_color_space_infer(&params->color);
1046
1047
94.3k
    if (!pl_color_space_is_hdr(&params->color)) {
1048
        // Some clips have leftover HDR metadata after conversion to SDR, so to
1049
        // avoid blowing up the tone mapping code, strip/sanitize it
1050
94.2k
        params->color.hdr = pl_hdr_metadata_empty;
1051
94.2k
    }
1052
1053
94.3k
    if (mp_imgfmt_is_subsampled(params->hw_subfmt ? params->hw_subfmt : params->imgfmt)) {
1054
30.4k
        if (params->chroma_location == PL_CHROMA_UNKNOWN) {
1055
2.70k
            if (params->repr.levels == PL_COLOR_LEVELS_LIMITED)
1056
2.40k
                params->chroma_location = PL_CHROMA_LEFT;
1057
2.70k
            if (params->repr.levels == PL_COLOR_LEVELS_FULL)
1058
301
                params->chroma_location = PL_CHROMA_CENTER;
1059
2.70k
        }
1060
63.8k
    } else {
1061
        // Set to center for non-subsampled formats.
1062
63.8k
        params->chroma_location = PL_CHROMA_CENTER;
1063
63.8k
    }
1064
1065
94.3k
    if (params->light == MP_CSP_LIGHT_AUTO) {
1066
        // HLG is always scene-referred (using its own OOTF), everything else
1067
        // we assume is display-referred by default.
1068
25.8k
        if (params->color.transfer == PL_COLOR_TRC_HLG) {
1069
0
            params->light = MP_CSP_LIGHT_SCENE_HLG;
1070
25.8k
        } else {
1071
25.8k
            params->light = MP_CSP_LIGHT_DISPLAY;
1072
25.8k
        }
1073
25.8k
    }
1074
94.3k
}
1075
1076
// Create a new mp_image reference to av_frame.
1077
struct mp_image *mp_image_from_av_frame(struct AVFrame *src)
1078
368k
{
1079
368k
    struct mp_image *dst = &(struct mp_image){0};
1080
368k
    AVFrameSideData *sd;
1081
1082
1.84M
    for (int p = 0; p < MP_MAX_PLANES; p++)
1083
1.47M
        dst->bufs[p] = src->buf[p];
1084
1085
368k
    dst->hwctx = src->hw_frames_ctx;
1086
1087
368k
    if (dst->hwctx) {
1088
0
        AVHWFramesContext *fctx = (void *)dst->hwctx->data;
1089
0
        dst->params.hw_subfmt = pixfmt2imgfmt(fctx->sw_format);
1090
0
    }
1091
1092
368k
    mp_image_sethwfmt(dst, pixfmt2imgfmt(src->format), dst->params.hw_subfmt);
1093
368k
    mp_image_set_size(dst, src->width, src->height);
1094
1095
368k
    dst->params.p_w = src->sample_aspect_ratio.num;
1096
368k
    dst->params.p_h = src->sample_aspect_ratio.den;
1097
1098
1.84M
    for (int i = 0; i < 4; i++) {
1099
1.47M
        dst->planes[i] = src->data[i];
1100
1.47M
        dst->stride[i] = src->linesize[i];
1101
1.47M
    }
1102
1103
368k
    dst->pict_type = src->pict_type;
1104
1105
368k
    dst->params.crop.x0 = src->crop_left;
1106
368k
    dst->params.crop.y0 = src->crop_top;
1107
368k
    dst->params.crop.x1 = src->width - src->crop_right;
1108
368k
    dst->params.crop.y1 = src->height - src->crop_bottom;
1109
1110
368k
    dst->fields = 0;
1111
368k
    if (src->flags & AV_FRAME_FLAG_INTERLACED)
1112
4.79k
        dst->fields |= MP_IMGFIELD_INTERLACED;
1113
368k
    if (src->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)
1114
22.3k
        dst->fields |= MP_IMGFIELD_TOP_FIRST;
1115
368k
    if (src->repeat_pict == 1)
1116
192
        dst->fields |= MP_IMGFIELD_REPEAT_FIRST;
1117
1118
368k
    dst->params.repr.sys = pl_system_from_av(src->colorspace);
1119
368k
    dst->params.repr.levels = pl_levels_from_av(src->color_range);
1120
1121
368k
    dst->params.color = (struct pl_color_space){
1122
368k
        .primaries = pl_primaries_from_av(src->color_primaries),
1123
368k
        .transfer = pl_transfer_from_av(src->color_trc),
1124
368k
    };
1125
1126
368k
    dst->params.chroma_location = pl_chroma_from_av(src->chroma_location);
1127
1128
368k
    if (src->opaque_ref) {
1129
0
        struct mp_image_params *p = (void *)src->opaque_ref->data;
1130
0
        dst->params.stereo3d = p->stereo3d;
1131
        // Might be incorrect if colorspace changes.
1132
0
        dst->params.light = p->light;
1133
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(60, 11, 100) || PL_API_VER < 356
1134
        dst->params.repr.alpha = p->repr.alpha;
1135
#endif
1136
0
    }
1137
1138
368k
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(60, 11, 100) && PL_API_VER >= 356
1139
    // mp_image_setfmt sets to PL_ALPHA_INDEPENDENT, if format has alpha.
1140
368k
    if (dst->params.repr.alpha == PL_ALPHA_INDEPENDENT)
1141
192k
        dst->params.repr.alpha = pl_alpha_from_av(src->alpha_mode);
1142
368k
#endif
1143
1144
368k
    sd = av_frame_get_side_data(src, AV_FRAME_DATA_DISPLAYMATRIX);
1145
368k
    if (sd) {
1146
86
        int32_t *matrix = (int32_t *) sd->data;
1147
        // determinant
1148
86
        int vflip = ((int64_t)matrix[0] * (int64_t)matrix[4]
1149
86
                    - (int64_t)matrix[1] * (int64_t)matrix[3]) < 0;
1150
86
        double r = av_display_rotation_get(matrix);
1151
86
        if (!isnan(r)) {
1152
86
            dst->params.rotate = (((int)(-r) % 360) + 360) % 360;
1153
86
            dst->params.vflip = vflip;
1154
86
        }
1155
86
    }
1156
1157
368k
    sd = av_frame_get_side_data(src, AV_FRAME_DATA_ICC_PROFILE);
1158
368k
    if (sd)
1159
6
        dst->icc_profile = sd->buf;
1160
1161
368k
    AVFrameSideData *mdm = av_frame_get_side_data(src, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
1162
368k
    AVFrameSideData *clm = av_frame_get_side_data(src, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
1163
368k
    AVFrameSideData *dhp = av_frame_get_side_data(src, AV_FRAME_DATA_DYNAMIC_HDR_PLUS);
1164
368k
    pl_map_hdr_metadata(&dst->params.color.hdr, &(struct pl_av_hdr_metadata) {
1165
368k
        .mdm = (void *)(mdm ? mdm->data : NULL),
1166
368k
        .clm = (void *)(clm ? clm->data : NULL),
1167
368k
        .dhp = (void *)(dhp ? dhp->data : NULL),
1168
368k
    });
1169
1170
368k
    sd = av_frame_get_side_data(src, AV_FRAME_DATA_A53_CC);
1171
368k
    if (sd)
1172
1.66k
        dst->a53_cc = sd->buf;
1173
1174
368k
    dst->params.primaries_orig = dst->params.color.primaries;
1175
368k
    dst->params.transfer_orig = dst->params.color.transfer;
1176
368k
    dst->params.sys_orig = dst->params.repr.sys;
1177
368k
    AVBufferRef *dovi = NULL;
1178
368k
    sd = av_frame_get_side_data(src, AV_FRAME_DATA_DOVI_METADATA);
1179
368k
    if (sd) {
1180
0
#ifdef PL_HAVE_LAV_DOLBY_VISION
1181
0
        const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->buf->data;
1182
0
        const AVDOVIRpuDataHeader *header = av_dovi_get_header(metadata);
1183
0
        if (header->disable_residual_flag) {
1184
0
            dst->dovi = dovi = av_buffer_alloc(sizeof(struct pl_dovi_metadata));
1185
0
            MP_HANDLE_OOM(dovi);
1186
0
#if PL_API_VER >= 343
1187
0
            pl_map_avdovi_metadata(&dst->params.color, &dst->params.repr,
1188
0
                                   (void *)dst->dovi->data, metadata);
1189
#else
1190
            struct pl_frame frame;
1191
            frame.repr = dst->params.repr;
1192
            frame.color = dst->params.color;
1193
            pl_frame_map_avdovi_metadata(&frame, (void *)dst->dovi->data, metadata);
1194
            dst->params.repr = frame.repr;
1195
            dst->params.color = frame.color;
1196
#endif
1197
0
        }
1198
0
#endif
1199
0
    }
1200
1201
368k
    sd = av_frame_get_side_data(src, AV_FRAME_DATA_DOVI_RPU_BUFFER);
1202
368k
    if (sd) {
1203
0
        pl_hdr_metadata_from_dovi_rpu(&dst->params.color.hdr, sd->buf->data,
1204
0
                                      sd->buf->size);
1205
0
    }
1206
1207
368k
    sd = av_frame_get_side_data(src, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
1208
368k
    if (sd)
1209
0
        dst->film_grain = sd->buf;
1210
1211
411k
    for (int n = 0; n < src->nb_side_data; n++) {
1212
42.8k
        sd = src->side_data[n];
1213
42.8k
        struct mp_ff_side_data mpsd = {
1214
42.8k
            .type = sd->type,
1215
42.8k
            .buf = sd->buf,
1216
42.8k
        };
1217
42.8k
        MP_TARRAY_APPEND(NULL, dst->ff_side_data, dst->num_ff_side_data, mpsd);
1218
42.8k
    }
1219
1220
368k
    struct mp_image *res = mp_image_new_ref(dst);
1221
1222
    // Allocated, but non-refcounted data.
1223
368k
    talloc_free(dst->ff_side_data);
1224
368k
    av_buffer_unref(&dovi);
1225
1226
368k
    return res;
1227
368k
}
1228
1229
1230
// Convert the mp_image reference to a AVFrame reference.
1231
struct AVFrame *mp_image_to_av_frame(struct mp_image *src)
1232
0
{
1233
0
    struct mp_image *new_ref = mp_image_new_ref(src);
1234
0
    AVFrame *dst = av_frame_alloc();
1235
0
    if (!dst || !new_ref) {
1236
0
        talloc_free(new_ref);
1237
0
        av_frame_free(&dst);
1238
0
        return NULL;
1239
0
    }
1240
1241
0
    for (int p = 0; p < MP_MAX_PLANES; p++) {
1242
0
        dst->buf[p] = new_ref->bufs[p];
1243
0
        new_ref->bufs[p] = NULL;
1244
0
    }
1245
1246
0
    dst->hw_frames_ctx = new_ref->hwctx;
1247
0
    new_ref->hwctx = NULL;
1248
1249
0
    dst->format = imgfmt2pixfmt(src->imgfmt);
1250
0
    dst->width = src->w;
1251
0
    dst->height = src->h;
1252
1253
0
    dst->crop_left = src->params.crop.x0;
1254
0
    dst->crop_top = src->params.crop.y0;
1255
0
    dst->crop_right = dst->width - src->params.crop.x1;
1256
0
    dst->crop_bottom = dst->height - src->params.crop.y1;
1257
1258
0
    dst->sample_aspect_ratio.num = src->params.p_w;
1259
0
    dst->sample_aspect_ratio.den = src->params.p_h;
1260
1261
0
    for (int i = 0; i < 4; i++) {
1262
0
        dst->data[i] = src->planes[i];
1263
0
        dst->linesize[i] = src->stride[i];
1264
0
    }
1265
0
    dst->extended_data = dst->data;
1266
1267
0
    dst->pict_type = src->pict_type;
1268
0
    if (src->fields & MP_IMGFIELD_INTERLACED)
1269
0
        dst->flags |= AV_FRAME_FLAG_INTERLACED;
1270
0
    if (src->fields & MP_IMGFIELD_TOP_FIRST)
1271
0
        dst->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
1272
0
    if (src->fields & MP_IMGFIELD_REPEAT_FIRST)
1273
0
        dst->repeat_pict = 1;
1274
1275
    // Image params without dovi mapped; should be passed as side data instead
1276
0
    struct mp_image_params params = src->params;
1277
0
    mp_image_params_restore_dovi_mapping(&params);
1278
0
    pl_avframe_set_repr(dst, params.repr);
1279
1280
0
    dst->chroma_location = pl_chroma_to_av(params.chroma_location);
1281
1282
0
    dst->opaque_ref = av_buffer_alloc(sizeof(struct mp_image_params));
1283
0
    MP_HANDLE_OOM(dst->opaque_ref);
1284
0
    *(struct mp_image_params *)dst->opaque_ref->data = params;
1285
1286
0
    if (src->icc_profile) {
1287
0
        AVFrameSideData *sd =
1288
0
            av_frame_new_side_data_from_buf(dst, AV_FRAME_DATA_ICC_PROFILE,
1289
0
                                            new_ref->icc_profile);
1290
0
        MP_HANDLE_OOM(sd);
1291
0
        new_ref->icc_profile = NULL;
1292
0
    }
1293
1294
0
    pl_avframe_set_color(dst, params.color);
1295
1296
0
    {
1297
0
        AVFrameSideData *sd = av_frame_new_side_data(dst,
1298
0
                                                     AV_FRAME_DATA_DISPLAYMATRIX,
1299
0
                                                     sizeof(int32_t) * 9);
1300
0
        MP_HANDLE_OOM(sd);
1301
0
        av_display_rotation_set((int32_t *)sd->data, params.rotate);
1302
0
    }
1303
1304
    // Add back side data, but only for types which are not specially handled
1305
    // above. Keep in mind that the types above will be out of sync anyway.
1306
0
    for (int n = 0; n < new_ref->num_ff_side_data; n++) {
1307
0
        struct mp_ff_side_data *mpsd = &new_ref->ff_side_data[n];
1308
0
        if (!av_frame_get_side_data(dst, mpsd->type)) {
1309
0
            AVFrameSideData *sd = av_frame_new_side_data_from_buf(dst, mpsd->type,
1310
0
                                                                  mpsd->buf);
1311
0
            MP_HANDLE_OOM(sd);
1312
0
            mpsd->buf = NULL;
1313
0
        }
1314
0
    }
1315
1316
0
    talloc_free(new_ref);
1317
1318
0
    if (dst->format == AV_PIX_FMT_NONE)
1319
0
        av_frame_free(&dst);
1320
0
    return dst;
1321
0
}
1322
1323
// Same as mp_image_to_av_frame(), but unref img. (It does so even on failure.)
1324
struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img)
1325
0
{
1326
0
    AVFrame *frame = mp_image_to_av_frame(img);
1327
0
    talloc_free(img);
1328
0
    return frame;
1329
0
}
1330
1331
void memset_pic(void *dst, int fill, int bytesPerLine, int height, int stride)
1332
0
{
1333
0
    if (bytesPerLine == stride && height) {
1334
0
        memset(dst, fill, stride * (height - 1) + bytesPerLine);
1335
0
    } else {
1336
0
        for (int i = 0; i < height; i++) {
1337
0
            memset(dst, fill, bytesPerLine);
1338
0
            dst = (uint8_t *)dst + stride;
1339
0
        }
1340
0
    }
1341
0
}
1342
1343
void memset16_pic(void *dst, int fill, int unitsPerLine, int height, int stride)
1344
0
{
1345
0
    if (fill == 0) {
1346
0
        memset_pic(dst, 0, unitsPerLine * 2, height, stride);
1347
0
    } else {
1348
0
        for (int i = 0; i < height; i++) {
1349
0
            uint16_t *line = dst;
1350
0
            uint16_t *end = line + unitsPerLine;
1351
0
            while (line < end)
1352
0
                *line++ = fill;
1353
0
            dst = (uint8_t *)dst + stride;
1354
0
        }
1355
0
    }
1356
0
}
1357
1358
// Pixel at the given luma position on the given plane. x/y always refer to
1359
// non-subsampled coordinates (even if plane is chroma).
1360
// The coordinates must be aligned to mp_imgfmt_desc.align_x/y (these are byte
1361
// and chroma boundaries).
1362
// You cannot access e.g. individual luma pixels on the luma plane with yuv420p.
1363
void *mp_image_pixel_ptr(struct mp_image *img, int plane, int x, int y)
1364
291k
{
1365
291k
    mp_assert(MP_IS_ALIGNED(x, img->fmt.align_x));
1366
291k
    mp_assert(MP_IS_ALIGNED(y, img->fmt.align_y));
1367
291k
    return mp_image_pixel_ptr_ny(img, plane, x, y);
1368
291k
}
1369
1370
// Like mp_image_pixel_ptr(), but do not require alignment on Y coordinates if
1371
// the plane does not require it. Use with care.
1372
// Useful for addressing luma rows.
1373
void *mp_image_pixel_ptr_ny(struct mp_image *img, int plane, int x, int y)
1374
459k
{
1375
459k
    mp_assert(MP_IS_ALIGNED(x, img->fmt.align_x));
1376
459k
    mp_assert(MP_IS_ALIGNED(y, 1 << img->fmt.ys[plane]));
1377
459k
    return img->planes[plane] +
1378
459k
           img->stride[plane] * (ptrdiff_t)(y >> img->fmt.ys[plane]) +
1379
459k
           (x >> img->fmt.xs[plane]) * (size_t)img->fmt.bpp[plane] / 8;
1380
459k
}
1381
1382
// Return size of pixels [x0, x0+w-1] in bytes. The coordinates refer to non-
1383
// subsampled pixels (basically plane 0), and the size is rounded to chroma
1384
// and byte alignment boundaries for the entire image, even if plane!=0.
1385
// x0!=0 is useful for rounding (e.g. 8 bpp, x0=7, w=7 => 0..15 => 2 bytes).
1386
size_t mp_image_plane_bytes(struct mp_image *img, int plane, int x0, int w)
1387
2.82M
{
1388
2.82M
    int x1 = MP_ALIGN_UP(x0 + w, img->fmt.align_x);
1389
2.82M
    x0 = MP_ALIGN_DOWN(x0, img->fmt.align_x);
1390
2.82M
    size_t bpp = img->fmt.bpp[plane];
1391
2.82M
    int xs = img->fmt.xs[plane];
1392
2.82M
    return (x1 >> xs) * bpp / 8 - (x0 >> xs) * bpp / 8;
1393
2.82M
}