Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/huffyuvenc.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2002-2014 Michael Niedermayer <michaelni@gmx.at>
3
 *
4
 * see https://multimedia.cx/huffyuv.txt for a description of
5
 * the algorithm used
6
 *
7
 * This file is part of FFmpeg.
8
 *
9
 * FFmpeg is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * FFmpeg is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with FFmpeg; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 *
23
 * yuva, gray, 4:4:4, 4:1:1, 4:1:0 and >8 bit per sample support sponsored by NOA
24
 */
25
26
/**
27
 * @file
28
 * huffyuv encoder
29
 */
30
31
#include "config_components.h"
32
33
#include "avcodec.h"
34
#include "bswapdsp.h"
35
#include "codec_internal.h"
36
#include "encode.h"
37
#include "huffyuv.h"
38
#include "huffman.h"
39
#include "huffyuvencdsp.h"
40
#include "lossless_videoencdsp.h"
41
#include "put_bits.h"
42
#include "libavutil/mem.h"
43
#include "libavutil/opt.h"
44
#include "libavutil/pixdesc.h"
45
46
typedef struct HYuvEncContext {
47
    AVClass *class;
48
    AVCodecContext *avctx;
49
    PutBitContext pb;
50
    /* Predictor, use int for AVOption */
51
    int predictor;
52
    int interlaced;
53
    int decorrelate;
54
    int bitstream_bpp;
55
    int version;
56
    int bps;
57
    unsigned mask;                          // (1<<bps)-1
58
    int vlc_n;                              // number of vlc codes (FFMIN(1<<bps, MAX_VLC_N))
59
    int alpha;
60
    int chroma;
61
    int yuv;
62
    int chroma_h_shift;
63
    int chroma_v_shift;
64
    int flags;
65
    int context;
66
    int picture_number;
67
68
    union {
69
        uint8_t  *temp[3];
70
        uint16_t *temp16[3];
71
    };
72
    uint64_t stats[4][MAX_VLC_N];
73
    uint8_t len[4][MAX_VLC_N];
74
    uint32_t bits[4][MAX_VLC_N];
75
    BswapDSPContext bdsp;
76
    HuffYUVEncDSPContext hencdsp;
77
    LLVidEncDSPContext llvidencdsp;
78
    int non_determ; // non-deterministic, multi-threaded encoder allowed
79
} HYuvEncContext;
80
81
static inline void diff_bytes(HYuvEncContext *s, uint8_t *dst,
82
                              const uint8_t *src0, const uint8_t *src1, int w)
83
0
{
84
0
    if (s->bps <= 8) {
85
0
        s->llvidencdsp.diff_bytes(dst, src0, src1, w);
86
0
    } else {
87
0
        s->hencdsp.diff_int16((uint16_t *)dst, (const uint16_t *)src0, (const uint16_t *)src1, s->mask, w);
88
0
    }
89
0
}
90
91
static inline int sub_left_prediction(HYuvEncContext *s, uint8_t *dst,
92
                                      const uint8_t *src, int w, int left)
93
9.50M
{
94
9.50M
    int i;
95
9.50M
    int min_width = FFMIN(w, 32);
96
97
9.50M
    if (s->bps <= 8) {
98
24.2M
        for (i = 0; i < min_width; i++) { /* scalar loop before dsp call */
99
18.2M
            const int temp = src[i];
100
18.2M
            dst[i] = temp - left;
101
18.2M
            left   = temp;
102
18.2M
        }
103
5.92M
        if (w < 32)
104
5.86M
            return left;
105
59.4k
        s->llvidencdsp.diff_bytes(dst + 32, src + 32, src + 31, w - 32);
106
59.4k
        return src[w-1];
107
5.92M
    } else {
108
3.58M
        const uint16_t *src16 = (const uint16_t *)src;
109
3.58M
        uint16_t       *dst16 = (      uint16_t *)dst;
110
11.9M
        for (i = 0; i < min_width; i++) { /* scalar loop before dsp call */
111
8.41M
            const int temp = src16[i];
112
8.41M
            dst16[i] = temp - left;
113
8.41M
            left   = temp;
114
8.41M
        }
115
3.58M
        if (w < 32)
116
3.55M
            return left;
117
28.1k
        s->hencdsp.diff_int16(dst16 + 32, src16 + 32, src16 + 31, s->mask, w - 32);
118
28.1k
        return src16[w-1];
119
3.58M
    }
120
9.50M
}
121
122
static inline void sub_left_prediction_bgr32(HYuvEncContext *s, uint8_t *dst,
123
                                             const uint8_t *src, int w,
124
                                             int *red, int *green, int *blue,
125
                                             int *alpha)
126
1.38M
{
127
1.38M
    int i;
128
1.38M
    int r, g, b, a;
129
1.38M
    int min_width = FFMIN(w, 8);
130
1.38M
    r = *red;
131
1.38M
    g = *green;
132
1.38M
    b = *blue;
133
1.38M
    a = *alpha;
134
135
5.46M
    for (i = 0; i < min_width; i++) {
136
4.07M
        const int rt = src[i * 4 + R];
137
4.07M
        const int gt = src[i * 4 + G];
138
4.07M
        const int bt = src[i * 4 + B];
139
4.07M
        const int at = src[i * 4 + A];
140
4.07M
        dst[i * 4 + R] = rt - r;
141
4.07M
        dst[i * 4 + G] = gt - g;
142
4.07M
        dst[i * 4 + B] = bt - b;
143
4.07M
        dst[i * 4 + A] = at - a;
144
4.07M
        r = rt;
145
4.07M
        g = gt;
146
4.07M
        b = bt;
147
4.07M
        a = at;
148
4.07M
    }
149
150
1.38M
    s->llvidencdsp.diff_bytes(dst + 32, src + 32, src + 32 - 4, w * 4 - 32);
151
152
1.38M
    *red   = src[(w - 1) * 4 + R];
153
1.38M
    *green = src[(w - 1) * 4 + G];
154
1.38M
    *blue  = src[(w - 1) * 4 + B];
155
1.38M
    *alpha = src[(w - 1) * 4 + A];
156
1.38M
}
157
158
static inline void sub_left_prediction_rgb24(HYuvEncContext *s, uint8_t *dst,
159
                                             const uint8_t *src, int w,
160
                                             int *red, int *green, int *blue)
161
1.32M
{
162
1.32M
    int i;
163
1.32M
    int r, g, b;
164
1.32M
    r = *red;
165
1.32M
    g = *green;
166
1.32M
    b = *blue;
167
5.15M
    for (i = 0; i < FFMIN(w, 16); i++) {
168
3.82M
        const int rt = src[i * 3 + 0];
169
3.82M
        const int gt = src[i * 3 + 1];
170
3.82M
        const int bt = src[i * 3 + 2];
171
3.82M
        dst[i * 3 + 0] = rt - r;
172
3.82M
        dst[i * 3 + 1] = gt - g;
173
3.82M
        dst[i * 3 + 2] = bt - b;
174
3.82M
        r = rt;
175
3.82M
        g = gt;
176
3.82M
        b = bt;
177
3.82M
    }
178
179
1.32M
    s->llvidencdsp.diff_bytes(dst + 48, src + 48, src + 48 - 3, w * 3 - 48);
180
181
1.32M
    *red   = src[(w - 1) * 3 + 0];
182
1.32M
    *green = src[(w - 1) * 3 + 1];
183
1.32M
    *blue  = src[(w - 1) * 3 + 2];
184
1.32M
}
185
186
static void sub_median_prediction(HYuvEncContext *s, uint8_t *dst,
187
                                  const uint8_t *src1, const uint8_t *src2,
188
                                  int w, int *left, int *left_top)
189
0
{
190
0
    if (s->bps <= 8) {
191
0
        s->llvidencdsp.sub_median_pred(dst, src1, src2, w , left, left_top);
192
0
    } else {
193
0
        s->hencdsp.sub_hfyu_median_pred_int16((uint16_t *)dst, (const uint16_t *)src1,
194
0
                                              (const uint16_t *)src2, s->mask, w, left, left_top);
195
0
    }
196
0
}
197
198
static int store_table(HYuvEncContext *s, const uint8_t *len, uint8_t *buf)
199
2.82k
{
200
2.82k
    int i;
201
2.82k
    int index = 0;
202
2.82k
    int n = s->vlc_n;
203
204
98.3k
    for (i = 0; i < n;) {
205
95.4k
        int val = len[i];
206
95.4k
        int repeat = 0;
207
208
5.25M
        for (; i < n && len[i] == val && repeat < 255; i++)
209
5.16M
            repeat++;
210
211
95.4k
        av_assert0(val < 32 && val >0 && repeat < 256 && repeat>0);
212
95.4k
        if (repeat > 7) {
213
48.5k
            buf[index++] = val;
214
48.5k
            buf[index++] = repeat;
215
48.5k
        } else {
216
46.9k
            buf[index++] = val | (repeat << 5);
217
46.9k
        }
218
95.4k
    }
219
220
2.82k
    return index;
221
2.82k
}
222
223
static int store_huffman_tables(HYuvEncContext *s, uint8_t *buf)
224
937
{
225
937
    int i, ret;
226
937
    int size = 0;
227
937
    int count = 3;
228
229
937
    if (s->version > 2)
230
261
        count = 1 + s->alpha + 2*s->chroma;
231
232
3.76k
    for (i = 0; i < count; i++) {
233
2.82k
        if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], s->vlc_n, 0)) < 0)
234
0
            return ret;
235
236
2.82k
        ret = ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->vlc_n);
237
2.82k
        if (ret < 0)
238
0
            return ret;
239
240
2.82k
        size += store_table(s, s->len[i], buf + size);
241
2.82k
    }
242
937
    return size;
243
937
}
244
245
static av_cold int encode_init(AVCodecContext *avctx)
246
953
{
247
953
    HYuvEncContext *s = avctx->priv_data;
248
953
    int i, j;
249
953
    int ret;
250
953
    const AVPixFmtDescriptor *desc;
251
252
953
    s->avctx = avctx;
253
953
    s->flags = avctx->flags;
254
255
953
    ff_bswapdsp_init(&s->bdsp);
256
953
    ff_llvidencdsp_init(&s->llvidencdsp);
257
258
953
    avctx->extradata = av_mallocz(3*MAX_N + 4);
259
953
    if (!avctx->extradata)
260
0
        return AVERROR(ENOMEM);
261
953
    if (s->flags&AV_CODEC_FLAG_PASS1) {
262
0
#define STATS_OUT_SIZE 21*MAX_N*3 + 4
263
0
        avctx->stats_out = av_mallocz(STATS_OUT_SIZE); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132
264
0
        if (!avctx->stats_out)
265
0
            return AVERROR(ENOMEM);
266
0
    }
267
953
    s->version = 2;
268
269
953
    desc   = av_pix_fmt_desc_get(avctx->pix_fmt);
270
953
    s->bps = desc->comp[0].depth;
271
953
    s->yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && desc->nb_components >= 2;
272
953
    s->chroma = desc->nb_components > 2;
273
953
    s->alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
274
953
    s->chroma_h_shift = desc->log2_chroma_w;
275
953
    s->chroma_v_shift = desc->log2_chroma_h;
276
277
953
    s->mask  = (1 << s->bps) - 1;
278
953
    s->vlc_n = FFMIN(1 << s->bps, MAX_VLC_N);
279
280
953
    ff_huffyuvencdsp_init(&s->hencdsp, s->bps, avctx->width >> s->chroma_h_shift);
281
282
953
    switch (avctx->pix_fmt) {
283
105
    case AV_PIX_FMT_YUV420P:
284
248
    case AV_PIX_FMT_YUV422P:
285
248
        if (avctx->width & 1) {
286
16
            av_log(avctx, AV_LOG_ERROR, "Width must be even for this colorspace.\n");
287
16
            return AVERROR(EINVAL);
288
16
        }
289
232
        s->bitstream_bpp = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 12 : 16;
290
232
        break;
291
17
    case AV_PIX_FMT_YUV444P:
292
46
    case AV_PIX_FMT_YUV410P:
293
60
    case AV_PIX_FMT_YUV411P:
294
70
    case AV_PIX_FMT_YUV440P:
295
73
    case AV_PIX_FMT_GBRP:
296
75
    case AV_PIX_FMT_GBRP9:
297
76
    case AV_PIX_FMT_GBRP10:
298
80
    case AV_PIX_FMT_GBRP12:
299
82
    case AV_PIX_FMT_GBRP14:
300
84
    case AV_PIX_FMT_GBRP16:
301
88
    case AV_PIX_FMT_GRAY8:
302
114
    case AV_PIX_FMT_GRAY16:
303
118
    case AV_PIX_FMT_YUVA444P:
304
124
    case AV_PIX_FMT_YUVA420P:
305
133
    case AV_PIX_FMT_YUVA422P:
306
136
    case AV_PIX_FMT_GBRAP:
307
137
    case AV_PIX_FMT_YUV420P9:
308
140
    case AV_PIX_FMT_YUV420P10:
309
144
    case AV_PIX_FMT_YUV420P12:
310
152
    case AV_PIX_FMT_YUV420P14:
311
155
    case AV_PIX_FMT_YUV420P16:
312
163
    case AV_PIX_FMT_YUV422P9:
313
165
    case AV_PIX_FMT_YUV422P10:
314
168
    case AV_PIX_FMT_YUV422P12:
315
174
    case AV_PIX_FMT_YUV422P14:
316
191
    case AV_PIX_FMT_YUV422P16:
317
194
    case AV_PIX_FMT_YUV444P9:
318
195
    case AV_PIX_FMT_YUV444P10:
319
197
    case AV_PIX_FMT_YUV444P12:
320
198
    case AV_PIX_FMT_YUV444P14:
321
209
    case AV_PIX_FMT_YUV444P16:
322
217
    case AV_PIX_FMT_YUVA420P9:
323
224
    case AV_PIX_FMT_YUVA420P10:
324
233
    case AV_PIX_FMT_YUVA420P16:
325
235
    case AV_PIX_FMT_YUVA422P9:
326
238
    case AV_PIX_FMT_YUVA422P10:
327
243
    case AV_PIX_FMT_YUVA422P16:
328
245
    case AV_PIX_FMT_YUVA444P9:
329
254
    case AV_PIX_FMT_YUVA444P10:
330
261
    case AV_PIX_FMT_YUVA444P16:
331
261
        s->version = 3;
332
261
        break;
333
295
    case AV_PIX_FMT_RGB32:
334
295
        s->bitstream_bpp = 32;
335
295
        break;
336
149
    case AV_PIX_FMT_RGB24:
337
149
        s->bitstream_bpp = 24;
338
149
        break;
339
0
    default:
340
0
        av_unreachable("Already checked via CODEC_PIXFMTS");
341
953
    }
342
343
937
    avctx->bits_per_coded_sample = s->bitstream_bpp;
344
937
    s->decorrelate = s->bitstream_bpp >= 24 && !s->yuv && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR);
345
937
    s->interlaced = avctx->flags & AV_CODEC_FLAG_INTERLACED_ME ? 1 : 0;
346
937
    if (s->context) {
347
0
        if (s->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) {
348
0
            av_log(avctx, AV_LOG_ERROR,
349
0
                   "context=1 is not compatible with "
350
0
                   "2 pass huffyuv encoding\n");
351
0
            return AVERROR(EINVAL);
352
0
        }
353
0
    }
354
355
937
    if (avctx->codec->id == AV_CODEC_ID_HUFFYUV) {
356
356
        if (s->interlaced != ( avctx->height > 288 ))
357
66
            av_log(avctx, AV_LOG_INFO,
358
66
                   "using huffyuv 2.2.0 or newer interlacing flag\n");
359
356
    }
360
361
937
    if (s->version > 3 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
362
0
        av_log(avctx, AV_LOG_ERROR, "Ver > 3 is under development, files encoded with it may not be decodable with future versions!!!\n"
363
0
               "Use vstrict=-2 / -strict -2 to use it anyway.\n");
364
0
        return AVERROR(EINVAL);
365
0
    }
366
367
937
    if (s->bitstream_bpp >= 24 && s->predictor == MEDIAN && s->version <= 2) {
368
0
        av_log(avctx, AV_LOG_ERROR,
369
0
               "Error: RGB is incompatible with median predictor\n");
370
0
        return AVERROR(EINVAL);
371
0
    }
372
373
937
    avctx->extradata[0] = s->predictor | (s->decorrelate << 6);
374
937
    avctx->extradata[2] = s->interlaced ? 0x10 : 0x20;
375
937
    if (s->context)
376
0
        avctx->extradata[2] |= 0x40;
377
937
    if (s->version < 3) {
378
676
        avctx->extradata[1] = s->bitstream_bpp;
379
676
        avctx->extradata[3] = 0;
380
676
    } else {
381
261
        avctx->extradata[1] = ((s->bps-1)<<4) | s->chroma_h_shift | (s->chroma_v_shift<<2);
382
261
        if (s->chroma)
383
231
            avctx->extradata[2] |= s->yuv ? 1 : 2;
384
261
        if (s->alpha)
385
74
            avctx->extradata[2] |= 4;
386
261
        avctx->extradata[3] = 1;
387
261
    }
388
937
    avctx->extradata_size = 4;
389
390
937
    if (avctx->stats_in) {
391
0
        char *p = avctx->stats_in;
392
393
0
        for (i = 0; i < 4; i++)
394
0
            for (j = 0; j < s->vlc_n; j++)
395
0
                s->stats[i][j] = 1;
396
397
0
        for (;;) {
398
0
            for (i = 0; i < 4; i++) {
399
0
                char *next;
400
401
0
                for (j = 0; j < s->vlc_n; j++) {
402
0
                    s->stats[i][j] += strtol(p, &next, 0);
403
0
                    if (next == p) return -1;
404
0
                    p = next;
405
0
                }
406
0
            }
407
0
            if (p[0] == 0 || p[1] == 0 || p[2] == 0) break;
408
0
        }
409
937
    } else {
410
4.68k
        for (i = 0; i < 4; i++)
411
7.52M
            for (j = 0; j < s->vlc_n; j++) {
412
7.52M
                int d = FFMIN(j, s->vlc_n - j);
413
414
7.52M
                s->stats[i][j] = 100000000 / (d*d + 1);
415
7.52M
            }
416
937
    }
417
418
937
    ret = store_huffman_tables(s, avctx->extradata + avctx->extradata_size);
419
937
    if (ret < 0)
420
0
        return ret;
421
937
    avctx->extradata_size += ret;
422
423
937
    if (s->context) {
424
0
        for (i = 0; i < 4; i++) {
425
0
            int pels = avctx->width * avctx->height / (i ? 40 : 10);
426
0
            for (j = 0; j < s->vlc_n; j++) {
427
0
                int d = FFMIN(j, s->vlc_n - j);
428
0
                s->stats[i][j] = pels/(d*d + 1);
429
0
            }
430
0
        }
431
937
    } else {
432
4.68k
        for (i = 0; i < 4; i++)
433
7.52M
            for (j = 0; j < s->vlc_n; j++)
434
7.52M
                s->stats[i][j]= 0;
435
937
    }
436
437
937
    s->picture_number=0;
438
439
3.74k
    for (int i = 0; i < 3; i++) {
440
2.81k
        s->temp[i] = av_malloc(4 * avctx->width + 16);
441
2.81k
        if (!s->temp[i])
442
0
            return AVERROR(ENOMEM);
443
2.81k
    }
444
445
937
    return 0;
446
937
}
447
static int encode_422_bitstream(HYuvEncContext *s, int offset, int count)
448
1.19M
{
449
1.19M
    int i;
450
1.19M
    const uint8_t *y = s->temp[0] + offset;
451
1.19M
    const uint8_t *u = s->temp[1] + offset / 2;
452
1.19M
    const uint8_t *v = s->temp[2] + offset / 2;
453
454
1.19M
    if (put_bytes_left(&s->pb, 0) < 2 * 4 * count) {
455
0
        av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
456
0
        return -1;
457
0
    }
458
459
1.19M
#define LOAD4\
460
5.31M
            int y0 = y[2 * i];\
461
5.31M
            int y1 = y[2 * i + 1];\
462
5.31M
            int u0 = u[i];\
463
5.31M
            int v0 = v[i];
464
465
1.19M
    count /= 2;
466
467
1.19M
    if (s->flags & AV_CODEC_FLAG_PASS1) {
468
0
        for(i = 0; i < count; i++) {
469
0
            LOAD4;
470
0
            s->stats[0][y0]++;
471
0
            s->stats[1][u0]++;
472
0
            s->stats[0][y1]++;
473
0
            s->stats[2][v0]++;
474
0
        }
475
0
    }
476
1.19M
    if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)
477
0
        return 0;
478
1.19M
    if (s->context) {
479
0
        for (i = 0; i < count; i++) {
480
0
            LOAD4;
481
0
            s->stats[0][y0]++;
482
0
            put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);
483
0
            s->stats[1][u0]++;
484
0
            put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]);
485
0
            s->stats[0][y1]++;
486
0
            put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
487
0
            s->stats[2][v0]++;
488
0
            put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]);
489
0
        }
490
1.19M
    } else {
491
6.51M
        for(i = 0; i < count; i++) {
492
5.31M
            LOAD4;
493
5.31M
            put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);
494
5.31M
            put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]);
495
5.31M
            put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
496
5.31M
            put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]);
497
5.31M
        }
498
1.19M
    }
499
1.19M
    return 0;
500
1.19M
}
501
502
static int encode_plane_bitstream(HYuvEncContext *s, int width, int plane)
503
5.73M
{
504
5.73M
    int count = width/2;
505
506
5.73M
    if (put_bytes_left(&s->pb, 0) < count * s->bps / 2) {
507
0
        av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
508
0
        return -1;
509
0
    }
510
511
5.73M
#define LOADEND\
512
5.73M
            int y0 = s->temp[0][width-1];
513
5.73M
#define LOADEND_14\
514
5.73M
            int y0 = s->temp16[0][width-1] & mask;
515
5.73M
#define LOADEND_16\
516
5.73M
            int y0 = s->temp16[0][width-1];
517
5.73M
#define STATEND\
518
5.73M
            s->stats[plane][y0]++;
519
5.73M
#define STATEND_16\
520
5.73M
            s->stats[plane][y0>>2]++;
521
5.73M
#define WRITEEND\
522
5.73M
            put_bits(&s->pb, s->len[plane][y0], s->bits[plane][y0]);
523
5.73M
#define WRITEEND_16\
524
5.73M
            put_bits(&s->pb, s->len[plane][y0>>2], s->bits[plane][y0>>2]);\
525
5.73M
            put_bits(&s->pb, 2, y0&3);
526
527
5.73M
#define LOAD2\
528
5.73M
            int y0 = s->temp[0][2 * i];\
529
5.73M
            int y1 = s->temp[0][2 * i + 1];
530
5.73M
#define LOAD2_14\
531
5.73M
            int y0 = s->temp16[0][2 * i] & mask;\
532
5.73M
            int y1 = s->temp16[0][2 * i + 1] & mask;
533
5.73M
#define LOAD2_16\
534
5.73M
            int y0 = s->temp16[0][2 * i];\
535
5.73M
            int y1 = s->temp16[0][2 * i + 1];
536
5.73M
#define STAT2\
537
5.73M
            s->stats[plane][y0]++;\
538
5.73M
            s->stats[plane][y1]++;
539
5.73M
#define STAT2_16\
540
5.73M
            s->stats[plane][y0>>2]++;\
541
5.73M
            s->stats[plane][y1>>2]++;
542
5.73M
#define WRITE2\
543
5.73M
            put_bits(&s->pb, s->len[plane][y0], s->bits[plane][y0]);\
544
5.73M
            put_bits(&s->pb, s->len[plane][y1], s->bits[plane][y1]);
545
5.73M
#define WRITE2_16\
546
5.73M
            put_bits(&s->pb, s->len[plane][y0>>2], s->bits[plane][y0>>2]);\
547
5.73M
            put_bits(&s->pb, 2, y0&3);\
548
5.73M
            put_bits(&s->pb, s->len[plane][y1>>2], s->bits[plane][y1>>2]);\
549
5.73M
            put_bits(&s->pb, 2, y1&3);
550
551
5.73M
#define ENCODE_PLANE(LOAD, LOADEND, WRITE, WRITEEND, STAT, STATEND)   \
552
5.73M
do {                                                                  \
553
5.73M
    if (s->flags & AV_CODEC_FLAG_PASS1) {                             \
554
0
        for (int i = 0; i < count; i++) {                             \
555
0
            LOAD;                                                     \
556
0
            STAT;                                                     \
557
0
        }                                                             \
558
0
        if (width & 1) {                                              \
559
0
            LOADEND;                                                  \
560
0
            STATEND;                                                  \
561
0
        }                                                             \
562
0
    }                                                                 \
563
5.73M
    if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)                  \
564
5.73M
        return 0;                                                     \
565
5.73M
                                                                      \
566
5.73M
    if (s->context) {                                                 \
567
0
        for (int i = 0; i < count; i++) {                             \
568
0
            LOAD;                                                     \
569
0
            STAT;                                                     \
570
0
            WRITE;                                                    \
571
0
        }                                                             \
572
0
        if (width & 1) {                                              \
573
0
            LOADEND;                                                  \
574
0
            STATEND;                                                  \
575
0
            WRITEEND;                                                 \
576
0
        }                                                             \
577
5.73M
    } else {                                                          \
578
22.3M
        for (int i = 0; i < count; i++) {                             \
579
16.6M
            LOAD;                                                     \
580
16.6M
            WRITE;                                                    \
581
16.6M
        }                                                             \
582
5.73M
        if (width & 1) {                                              \
583
3.01M
            LOADEND;                                                  \
584
3.01M
            WRITEEND;                                                 \
585
3.01M
        }                                                             \
586
5.73M
    }                                                                 \
587
5.73M
} while (0)
588
589
5.73M
    if (s->bps <= 8) {
590
2.15M
        ENCODE_PLANE(LOAD2, LOADEND, WRITE2, WRITEEND, STAT2, STATEND);
591
3.58M
    } else if (s->bps <= 14) {
592
1.13M
        unsigned mask = s->mask;
593
594
1.13M
        ENCODE_PLANE(LOAD2_14, LOADEND_14, WRITE2, WRITEEND, STAT2, STATEND);
595
2.44M
    } else {
596
2.44M
        ENCODE_PLANE(LOAD2_16, LOADEND_16, WRITE2_16, WRITEEND_16, STAT2_16, STATEND_16);
597
2.44M
    }
598
5.73M
#undef LOAD2
599
5.73M
#undef STAT2
600
5.73M
#undef WRITE2
601
5.73M
    return 0;
602
5.73M
}
603
604
static int encode_gray_bitstream(HYuvEncContext *s, int count)
605
193k
{
606
193k
    int i;
607
608
193k
    if (put_bytes_left(&s->pb, 0) < 4 * count) {
609
0
        av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
610
0
        return -1;
611
0
    }
612
613
193k
#define LOAD2\
614
1.28M
            int y0 = s->temp[0][2 * i];\
615
1.28M
            int y1 = s->temp[0][2 * i + 1];
616
193k
#define STAT2\
617
193k
            s->stats[0][y0]++;\
618
0
            s->stats[0][y1]++;
619
193k
#define WRITE2\
620
1.28M
            put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);\
621
1.28M
            put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
622
623
193k
    count /= 2;
624
625
193k
    if (s->flags & AV_CODEC_FLAG_PASS1) {
626
0
        for (i = 0; i < count; i++) {
627
0
            LOAD2;
628
0
            STAT2;
629
0
        }
630
0
    }
631
193k
    if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)
632
0
        return 0;
633
634
193k
    if (s->context) {
635
0
        for (i = 0; i < count; i++) {
636
0
            LOAD2;
637
0
            STAT2;
638
0
            WRITE2;
639
0
        }
640
193k
    } else {
641
1.48M
        for (i = 0; i < count; i++) {
642
1.28M
            LOAD2;
643
1.28M
            WRITE2;
644
1.28M
        }
645
193k
    }
646
193k
    return 0;
647
193k
}
648
649
static inline int encode_bgra_bitstream(HYuvEncContext *s, int count, int planes)
650
2.71M
{
651
2.71M
    int i;
652
653
2.71M
    if (put_bytes_left(&s->pb, 0) < 4 * planes * count) {
654
10
        av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
655
10
        return -1;
656
10
    }
657
658
2.71M
#define LOAD_GBRA                                                       \
659
23.6M
    int g = s->temp[0][planes == 3 ? 3 * i + 1 : 4 * i + G];            \
660
23.6M
    int b =(s->temp[0][planes == 3 ? 3 * i + 2 : 4 * i + B] - g) & 0xFF;\
661
23.6M
    int r =(s->temp[0][planes == 3 ? 3 * i + 0 : 4 * i + R] - g) & 0xFF;\
662
23.6M
    int a = s->temp[0][planes * i + A];
663
664
2.71M
#define STAT_BGRA                                                       \
665
2.71M
    s->stats[0][b]++;                                                   \
666
0
    s->stats[1][g]++;                                                   \
667
0
    s->stats[2][r]++;                                                   \
668
0
    if (planes == 4)                                                    \
669
0
        s->stats[2][a]++;
670
671
2.71M
#define WRITE_GBRA                                                      \
672
23.6M
    put_bits(&s->pb, s->len[1][g], s->bits[1][g]);                      \
673
23.6M
    put_bits(&s->pb, s->len[0][b], s->bits[0][b]);                      \
674
23.6M
    put_bits(&s->pb, s->len[2][r], s->bits[2][r]);                      \
675
23.6M
    if (planes == 4)                                                    \
676
23.6M
        put_bits(&s->pb, s->len[2][a], s->bits[2][a]);
677
678
2.71M
    if ((s->flags & AV_CODEC_FLAG_PASS1) &&
679
0
        (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)) {
680
0
        for (i = 0; i < count; i++) {
681
0
            LOAD_GBRA;
682
0
            STAT_BGRA;
683
0
        }
684
2.71M
    } else if (s->context || (s->flags & AV_CODEC_FLAG_PASS1)) {
685
0
        for (i = 0; i < count; i++) {
686
0
            LOAD_GBRA;
687
0
            STAT_BGRA;
688
0
            WRITE_GBRA;
689
0
        }
690
2.71M
    } else {
691
26.3M
        for (i = 0; i < count; i++) {
692
23.6M
            LOAD_GBRA;
693
23.6M
            WRITE_GBRA;
694
23.6M
        }
695
2.71M
    }
696
2.71M
    return 0;
697
2.71M
}
698
699
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
700
                        const AVFrame *p, int *got_packet)
701
19.1k
{
702
19.1k
    HYuvEncContext *s = avctx->priv_data;
703
19.1k
    const int width = avctx->width;
704
19.1k
    const int width2 = avctx->width >> 1;
705
19.1k
    const int height = avctx->height;
706
19.1k
    const int fake_ystride = (1 + s->interlaced) * p->linesize[0];
707
19.1k
    const int fake_ustride = (1 + s->interlaced) * p->linesize[1];
708
19.1k
    const int fake_vstride = (1 + s->interlaced) * p->linesize[2];
709
19.1k
    int i, j, size = 0, ret;
710
711
19.1k
    if ((ret = ff_alloc_packet(avctx, pkt, width * height * 3 * 4 + FF_INPUT_BUFFER_MIN_SIZE)) < 0)
712
0
        return ret;
713
714
19.1k
    if (s->context) {
715
0
        size = store_huffman_tables(s, pkt->data);
716
0
        if (size < 0)
717
0
            return size;
718
719
0
        for (i = 0; i < 4; i++)
720
0
            for (j = 0; j < s->vlc_n; j++)
721
0
                s->stats[i][j] >>= 1;
722
0
    }
723
724
19.1k
    init_put_bits(&s->pb, pkt->data + size, pkt->size - size);
725
726
19.1k
    if (avctx->pix_fmt == AV_PIX_FMT_YUV422P ||
727
18.1k
        avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
728
2.53k
        int lefty, leftu, leftv, y, cy;
729
730
2.53k
        put_bits(&s->pb, 8, leftv = p->data[2][0]);
731
2.53k
        put_bits(&s->pb, 8, lefty = p->data[0][1]);
732
2.53k
        put_bits(&s->pb, 8, leftu = p->data[1][0]);
733
2.53k
        put_bits(&s->pb, 8,         p->data[0][0]);
734
735
2.53k
        lefty = sub_left_prediction(s, s->temp[0], p->data[0], width , 0);
736
2.53k
        leftu = sub_left_prediction(s, s->temp[1], p->data[1], width2, 0);
737
2.53k
        leftv = sub_left_prediction(s, s->temp[2], p->data[2], width2, 0);
738
739
2.53k
        encode_422_bitstream(s, 2, width-2);
740
741
2.53k
        if (s->predictor==MEDIAN) {
742
0
            int lefttopy, lefttopu, lefttopv;
743
0
            cy = y = 1;
744
0
            if (s->interlaced) {
745
0
                lefty = sub_left_prediction(s, s->temp[0], p->data[0] + p->linesize[0], width , lefty);
746
0
                leftu = sub_left_prediction(s, s->temp[1], p->data[1] + p->linesize[1], width2, leftu);
747
0
                leftv = sub_left_prediction(s, s->temp[2], p->data[2] + p->linesize[2], width2, leftv);
748
749
0
                encode_422_bitstream(s, 0, width);
750
0
                y++; cy++;
751
0
            }
752
753
0
            lefty = sub_left_prediction(s, s->temp[0], p->data[0] + fake_ystride, 4, lefty);
754
0
            leftu = sub_left_prediction(s, s->temp[1], p->data[1] + fake_ustride, 2, leftu);
755
0
            leftv = sub_left_prediction(s, s->temp[2], p->data[2] + fake_vstride, 2, leftv);
756
757
0
            encode_422_bitstream(s, 0, 4);
758
759
0
            lefttopy = p->data[0][3];
760
0
            lefttopu = p->data[1][1];
761
0
            lefttopv = p->data[2][1];
762
0
            s->llvidencdsp.sub_median_pred(s->temp[0], p->data[0] + 4, p->data[0] + fake_ystride + 4, width  - 4, &lefty, &lefttopy);
763
0
            s->llvidencdsp.sub_median_pred(s->temp[1], p->data[1] + 2, p->data[1] + fake_ustride + 2, width2 - 2, &leftu, &lefttopu);
764
0
            s->llvidencdsp.sub_median_pred(s->temp[2], p->data[2] + 2, p->data[2] + fake_vstride + 2, width2 - 2, &leftv, &lefttopv);
765
0
            encode_422_bitstream(s, 0, width - 4);
766
0
            y++; cy++;
767
768
0
            for (; y < height; y++,cy++) {
769
0
                const uint8_t *ydst, *udst, *vdst;
770
771
0
                if (s->bitstream_bpp == 12) {
772
0
                    while (2 * cy > y) {
773
0
                        ydst = p->data[0] + p->linesize[0] * y;
774
0
                        s->llvidencdsp.sub_median_pred(s->temp[0], ydst - fake_ystride, ydst, width, &lefty, &lefttopy);
775
0
                        encode_gray_bitstream(s, width);
776
0
                        y++;
777
0
                    }
778
0
                    if (y >= height) break;
779
0
                }
780
0
                ydst = p->data[0] + p->linesize[0] * y;
781
0
                udst = p->data[1] + p->linesize[1] * cy;
782
0
                vdst = p->data[2] + p->linesize[2] * cy;
783
784
0
                s->llvidencdsp.sub_median_pred(s->temp[0], ydst - fake_ystride, ydst, width,  &lefty, &lefttopy);
785
0
                s->llvidencdsp.sub_median_pred(s->temp[1], udst - fake_ustride, udst, width2, &leftu, &lefttopu);
786
0
                s->llvidencdsp.sub_median_pred(s->temp[2], vdst - fake_vstride, vdst, width2, &leftv, &lefttopv);
787
788
0
                encode_422_bitstream(s, 0, width);
789
0
            }
790
2.53k
        } else {
791
1.19M
            for (cy = y = 1; y < height; y++, cy++) {
792
1.18M
                const uint8_t *ydst, *udst, *vdst;
793
794
                /* encode a luma only line & y++ */
795
1.18M
                if (s->bitstream_bpp == 12) {
796
193k
                    ydst = p->data[0] + p->linesize[0] * y;
797
798
193k
                    if (s->predictor == PLANE && s->interlaced < y) {
799
0
                        s->llvidencdsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width);
800
801
0
                        lefty = sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty);
802
193k
                    } else {
803
193k
                        lefty = sub_left_prediction(s, s->temp[0], ydst, width , lefty);
804
193k
                    }
805
193k
                    encode_gray_bitstream(s, width);
806
193k
                    y++;
807
193k
                    if (y >= height) break;
808
193k
                }
809
810
1.18M
                ydst = p->data[0] + p->linesize[0] * y;
811
1.18M
                udst = p->data[1] + p->linesize[1] * cy;
812
1.18M
                vdst = p->data[2] + p->linesize[2] * cy;
813
814
1.18M
                if (s->predictor == PLANE && s->interlaced < cy) {
815
0
                    s->llvidencdsp.diff_bytes(s->temp[1],          ydst, ydst - fake_ystride, width);
816
0
                    s->llvidencdsp.diff_bytes(s->temp[2],          udst, udst - fake_ustride, width2);
817
0
                    s->llvidencdsp.diff_bytes(s->temp[2] + width2, vdst, vdst - fake_vstride, width2);
818
819
0
                    lefty = sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty);
820
0
                    leftu = sub_left_prediction(s, s->temp[1], s->temp[2], width2, leftu);
821
0
                    leftv = sub_left_prediction(s, s->temp[2], s->temp[2] + width2, width2, leftv);
822
1.18M
                } else {
823
1.18M
                    lefty = sub_left_prediction(s, s->temp[0], ydst, width , lefty);
824
1.18M
                    leftu = sub_left_prediction(s, s->temp[1], udst, width2, leftu);
825
1.18M
                    leftv = sub_left_prediction(s, s->temp[2], vdst, width2, leftv);
826
1.18M
                }
827
828
1.18M
                encode_422_bitstream(s, 0, width);
829
1.18M
            }
830
2.53k
        }
831
16.6k
    } else if(avctx->pix_fmt == AV_PIX_FMT_RGB32) {
832
12.0k
        const uint8_t *data = p->data[0] + (height - 1) * p->linesize[0];
833
12.0k
        const int stride = -p->linesize[0];
834
12.0k
        const int fake_stride = -fake_ystride;
835
12.0k
        int leftr, leftg, leftb, lefta;
836
837
12.0k
        put_bits(&s->pb, 8, lefta = data[A]);
838
12.0k
        put_bits(&s->pb, 8, leftr = data[R]);
839
12.0k
        put_bits(&s->pb, 8, leftg = data[G]);
840
12.0k
        put_bits(&s->pb, 8, leftb = data[B]);
841
842
12.0k
        sub_left_prediction_bgr32(s, s->temp[0], data + 4, width - 1,
843
12.0k
                                  &leftr, &leftg, &leftb, &lefta);
844
12.0k
        encode_bgra_bitstream(s, width - 1, 4);
845
846
1.38M
        for (int y = 1; y < height; y++) {
847
1.37M
            const uint8_t *dst = data + y*stride;
848
1.37M
            if (s->predictor == PLANE && s->interlaced < y) {
849
0
                s->llvidencdsp.diff_bytes(s->temp[1], dst, dst - fake_stride, width * 4);
850
0
                sub_left_prediction_bgr32(s, s->temp[0], s->temp[1], width,
851
0
                                          &leftr, &leftg, &leftb, &lefta);
852
1.37M
            } else {
853
1.37M
                sub_left_prediction_bgr32(s, s->temp[0], dst, width,
854
1.37M
                                          &leftr, &leftg, &leftb, &lefta);
855
1.37M
            }
856
1.37M
            encode_bgra_bitstream(s, width, 4);
857
1.37M
        }
858
12.0k
    } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
859
1.47k
        const uint8_t *data = p->data[0] + (height - 1) * p->linesize[0];
860
1.47k
        const int stride = -p->linesize[0];
861
1.47k
        const int fake_stride = -fake_ystride;
862
1.47k
        int leftr, leftg, leftb;
863
864
1.47k
        put_bits(&s->pb, 8, leftr = data[0]);
865
1.47k
        put_bits(&s->pb, 8, leftg = data[1]);
866
1.47k
        put_bits(&s->pb, 8, leftb = data[2]);
867
1.47k
        put_bits(&s->pb, 8, 0);
868
869
1.47k
        sub_left_prediction_rgb24(s, s->temp[0], data + 3, width - 1,
870
1.47k
                                  &leftr, &leftg, &leftb);
871
1.47k
        encode_bgra_bitstream(s, width-1, 3);
872
873
1.32M
        for (int y = 1; y < height; y++) {
874
1.32M
            const uint8_t *dst = data + y * stride;
875
1.32M
            if (s->predictor == PLANE && s->interlaced < y) {
876
0
                s->llvidencdsp.diff_bytes(s->temp[1], dst, dst - fake_stride,
877
0
                                      width * 3);
878
0
                sub_left_prediction_rgb24(s, s->temp[0], s->temp[1], width,
879
0
                                          &leftr, &leftg, &leftb);
880
1.32M
            } else {
881
1.32M
                sub_left_prediction_rgb24(s, s->temp[0], dst, width,
882
1.32M
                                          &leftr, &leftg, &leftb);
883
1.32M
            }
884
1.32M
            encode_bgra_bitstream(s, width, 3);
885
1.32M
        }
886
3.16k
    } else if (s->version > 2) {
887
3.16k
        int plane;
888
10.6k
        for (plane = 0; plane < 1 + 2*s->chroma + s->alpha; plane++) {
889
7.46k
            int left, y;
890
7.46k
            int w = width;
891
7.46k
            int h = height;
892
7.46k
            int fake_stride = fake_ystride;
893
894
7.46k
            if (s->chroma && (plane == 1 || plane == 2)) {
895
3.48k
                w >>= s->chroma_h_shift;
896
3.48k
                h >>= s->chroma_v_shift;
897
3.48k
                fake_stride = plane == 1 ? fake_ustride : fake_vstride;
898
3.48k
            }
899
900
7.46k
            left = sub_left_prediction(s, s->temp[0], p->data[plane], w , 0);
901
902
7.46k
            encode_plane_bitstream(s, w, plane);
903
904
7.46k
            if (s->predictor==MEDIAN) {
905
0
                int lefttop;
906
0
                y = 1;
907
0
                if (s->interlaced) {
908
0
                    left = sub_left_prediction(s, s->temp[0], p->data[plane] + p->linesize[plane], w , left);
909
910
0
                    encode_plane_bitstream(s, w, plane);
911
0
                    y++;
912
0
                }
913
914
0
                lefttop = p->data[plane][0];
915
916
0
                for (; y < h; y++) {
917
0
                    const uint8_t *dst = p->data[plane] + p->linesize[plane] * y;
918
919
0
                    sub_median_prediction(s, s->temp[0], dst - fake_stride, dst, w , &left, &lefttop);
920
921
0
                    encode_plane_bitstream(s, w, plane);
922
0
                }
923
7.46k
            } else {
924
5.73M
                for (y = 1; y < h; y++) {
925
5.73M
                    const uint8_t *dst = p->data[plane] + p->linesize[plane] * y;
926
927
5.73M
                    if (s->predictor == PLANE && s->interlaced < y) {
928
0
                        diff_bytes(s, s->temp[1], dst, dst - fake_stride, w);
929
930
0
                        left = sub_left_prediction(s, s->temp[0], s->temp[1], w , left);
931
5.73M
                    } else {
932
5.73M
                        left = sub_left_prediction(s, s->temp[0], dst, w , left);
933
5.73M
                    }
934
935
5.73M
                    encode_plane_bitstream(s, w, plane);
936
5.73M
                }
937
7.46k
            }
938
7.46k
        }
939
3.16k
    } else {
940
0
        av_log(avctx, AV_LOG_ERROR, "Format not supported!\n");
941
0
    }
942
943
19.1k
    size += (put_bits_count(&s->pb) + 31) / 8;
944
19.1k
    put_bits(&s->pb, 16, 0);
945
19.1k
    put_bits(&s->pb, 15, 0);
946
19.1k
    size /= 4;
947
948
19.1k
    if ((s->flags & AV_CODEC_FLAG_PASS1) && (s->picture_number & 31) == 0) {
949
0
        int j;
950
0
        char *p = avctx->stats_out;
951
0
        char *end = p + STATS_OUT_SIZE;
952
0
        for (i = 0; i < 4; i++) {
953
0
            for (j = 0; j < s->vlc_n; j++) {
954
0
                snprintf(p, end-p, "%"PRIu64" ", s->stats[i][j]);
955
0
                p += strlen(p);
956
0
                s->stats[i][j]= 0;
957
0
            }
958
0
            snprintf(p, end-p, "\n");
959
0
            p++;
960
0
            if (end <= p)
961
0
                return AVERROR(ENOMEM);
962
0
        }
963
19.1k
    } else if (avctx->stats_out)
964
0
        avctx->stats_out[0] = '\0';
965
19.1k
    if (!(s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)) {
966
19.1k
        flush_put_bits(&s->pb);
967
19.1k
        s->bdsp.bswap_buf((uint32_t *) pkt->data, (uint32_t *) pkt->data, size);
968
19.1k
    }
969
970
19.1k
    s->picture_number++;
971
972
19.1k
    pkt->size   = size * 4;
973
19.1k
    *got_packet = 1;
974
975
19.1k
    return 0;
976
19.1k
}
977
978
static av_cold int encode_end(AVCodecContext *avctx)
979
953
{
980
953
    HYuvEncContext *s = avctx->priv_data;
981
982
953
    av_freep(&avctx->stats_out);
983
984
3.81k
    for (int i = 0; i < 3; i++)
985
2.85k
        av_freep(&s->temp[i]);
986
987
953
    return 0;
988
953
}
989
990
#define OFFSET(x) offsetof(HYuvEncContext, x)
991
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
992
993
static const AVOption options[] = {
994
    /* ffvhuff-only options */
995
    { "context", "Set per-frame huffman tables", OFFSET(context), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
996
    /* Common options */
997
    { "non_deterministic", "Allow multithreading for e.g. context=1 at the expense of determinism",
998
      OFFSET(non_determ), AV_OPT_TYPE_BOOL, { .i64 = 0 },
999
      0, 1, VE },
1000
    { "pred", "Prediction method", OFFSET(predictor), AV_OPT_TYPE_INT, { .i64 = LEFT }, LEFT, MEDIAN, VE, .unit = "pred" },
1001
        { "left",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LEFT },   INT_MIN, INT_MAX, VE, .unit = "pred" },
1002
        { "plane",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PLANE },  INT_MIN, INT_MAX, VE, .unit = "pred" },
1003
        { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MEDIAN }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1004
    { NULL },
1005
};
1006
1007
static const AVClass normal_class = {
1008
    .class_name = "huffyuv",
1009
    .item_name  = av_default_item_name,
1010
    .option     = options + 1,
1011
    .version    = LIBAVUTIL_VERSION_INT,
1012
};
1013
1014
const FFCodec ff_huffyuv_encoder = {
1015
    .p.name         = "huffyuv",
1016
    CODEC_LONG_NAME("Huffyuv / HuffYUV"),
1017
    .p.type         = AVMEDIA_TYPE_VIDEO,
1018
    .p.id           = AV_CODEC_ID_HUFFYUV,
1019
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
1020
                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
1021
    .priv_data_size = sizeof(HYuvEncContext),
1022
    .init           = encode_init,
1023
    FF_CODEC_ENCODE_CB(encode_frame),
1024
    .close          = encode_end,
1025
    .p.priv_class   = &normal_class,
1026
    CODEC_PIXFMTS(AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32),
1027
    .color_ranges   = AVCOL_RANGE_MPEG,
1028
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
1029
};
1030
1031
#if CONFIG_FFVHUFF_ENCODER
1032
static const AVClass ff_class = {
1033
    .class_name = "ffvhuff",
1034
    .item_name  = av_default_item_name,
1035
    .option     = options,
1036
    .version    = LIBAVUTIL_VERSION_INT,
1037
};
1038
1039
const FFCodec ff_ffvhuff_encoder = {
1040
    .p.name         = "ffvhuff",
1041
    CODEC_LONG_NAME("Huffyuv FFmpeg variant"),
1042
    .p.type         = AVMEDIA_TYPE_VIDEO,
1043
    .p.id           = AV_CODEC_ID_FFVHUFF,
1044
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
1045
                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
1046
    .priv_data_size = sizeof(HYuvEncContext),
1047
    .init           = encode_init,
1048
    FF_CODEC_ENCODE_CB(encode_frame),
1049
    .close          = encode_end,
1050
    .p.priv_class   = &ff_class,
1051
    CODEC_PIXFMTS(
1052
        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P,
1053
        AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P,
1054
        AV_PIX_FMT_GBRP,
1055
        AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
1056
        AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16,
1057
        AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
1058
        AV_PIX_FMT_GBRAP,
1059
        AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV420P16,
1060
        AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV422P16,
1061
        AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16,
1062
        AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16,
1063
        AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P16,
1064
        AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16,
1065
        AV_PIX_FMT_RGB24,
1066
        AV_PIX_FMT_RGB32),
1067
    .color_ranges   = AVCOL_RANGE_MPEG,
1068
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
1069
};
1070
#endif