Coverage Report

Created: 2026-04-01 07:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/escape130.c
Line
Count
Source
1
/*
2
 * Escape 130 video decoder
3
 * Copyright (C) 2008 Eli Friedman (eli.friedman <at> gmail.com)
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "libavutil/attributes.h"
23
#include "libavutil/mem.h"
24
25
#define BITSTREAM_READER_LE
26
#include "avcodec.h"
27
#include "codec_internal.h"
28
#include "decode.h"
29
#include "get_bits.h"
30
31
typedef struct Escape130Context {
32
    uint8_t *old_y_avg;
33
34
    uint8_t *new_y, *old_y;
35
    uint8_t *new_u, *old_u;
36
    uint8_t *new_v, *old_v;
37
38
    uint8_t *buf1, *buf2;
39
    int     linesize[3];
40
} Escape130Context;
41
42
static const uint8_t offset_table[] = { 2, 4, 10, 20 };
43
static const int8_t sign_table[64][4] = {
44
    {  0,  0,  0,  0 },
45
    { -1,  1,  0,  0 },
46
    {  1, -1,  0,  0 },
47
    { -1,  0,  1,  0 },
48
    { -1,  1,  1,  0 },
49
    {  0, -1,  1,  0 },
50
    {  1, -1,  1,  0 },
51
    { -1, -1,  1,  0 },
52
    {  1,  0, -1,  0 },
53
    {  0,  1, -1,  0 },
54
    {  1,  1, -1,  0 },
55
    { -1,  1, -1,  0 },
56
    {  1, -1, -1,  0 },
57
    { -1,  0,  0,  1 },
58
    { -1,  1,  0,  1 },
59
    {  0, -1,  0,  1 },
60
61
    {  0,  0,  0,  0 },
62
    {  1, -1,  0,  1 },
63
    { -1, -1,  0,  1 },
64
    { -1,  0,  1,  1 },
65
    { -1,  1,  1,  1 },
66
    {  0, -1,  1,  1 },
67
    {  1, -1,  1,  1 },
68
    { -1, -1,  1,  1 },
69
    {  0,  0, -1,  1 },
70
    {  1,  0, -1,  1 },
71
    { -1,  0, -1,  1 },
72
    {  0,  1, -1,  1 },
73
    {  1,  1, -1,  1 },
74
    { -1,  1, -1,  1 },
75
    {  0, -1, -1,  1 },
76
    {  1, -1, -1,  1 },
77
78
    {  0,  0,  0,  0 },
79
    { -1, -1, -1,  1 },
80
    {  1,  0,  0, -1 },
81
    {  0,  1,  0, -1 },
82
    {  1,  1,  0, -1 },
83
    { -1,  1,  0, -1 },
84
    {  1, -1,  0, -1 },
85
    {  0,  0,  1, -1 },
86
    {  1,  0,  1, -1 },
87
    { -1,  0,  1, -1 },
88
    {  0,  1,  1, -1 },
89
    {  1,  1,  1, -1 },
90
    { -1,  1,  1, -1 },
91
    {  0, -1,  1, -1 },
92
    {  1, -1,  1, -1 },
93
    { -1, -1,  1, -1 },
94
95
    {  0,  0,  0,  0 },
96
    {  1,  0, -1, -1 },
97
    {  0,  1, -1, -1 },
98
    {  1,  1, -1, -1 },
99
    { -1,  1, -1, -1 },
100
    {  1, -1, -1, -1 }
101
};
102
103
static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
104
105
static const int8_t chroma_adjust[2][8] = {
106
    { 1, 1, 0, -1, -1, -1,  0,  1 },
107
    { 0, 1, 1,  1,  0, -1, -1, -1 }
108
};
109
110
static const uint8_t chroma_vals[] = {
111
     20,  28,  36,  44,  52,  60,  68,  76,
112
     84,  92, 100, 106, 112, 116, 120, 124,
113
    128, 132, 136, 140, 144, 150, 156, 164,
114
    172, 180, 188, 196, 204, 212, 220, 228
115
};
116
117
static av_cold int escape130_decode_init(AVCodecContext *avctx)
118
925
{
119
925
    Escape130Context *s = avctx->priv_data;
120
925
    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
121
122
925
    if ((avctx->width & 1) || (avctx->height & 1)) {
123
12
        av_log(avctx, AV_LOG_ERROR,
124
12
               "Dimensions should be a multiple of two.\n");
125
12
        return AVERROR_INVALIDDATA;
126
12
    }
127
128
913
    s->old_y_avg = av_malloc(avctx->width * avctx->height / 4);
129
913
    s->buf1      = av_malloc(avctx->width * avctx->height * 3 / 2);
130
913
    s->buf2      = av_malloc(avctx->width * avctx->height * 3 / 2);
131
913
    if (!s->old_y_avg || !s->buf1 || !s->buf2) {
132
0
        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
133
0
        return AVERROR(ENOMEM);
134
0
    }
135
136
913
    s->linesize[0] = avctx->width;
137
913
    s->linesize[1] =
138
913
    s->linesize[2] = avctx->width / 2;
139
140
913
    s->new_y = s->buf1;
141
913
    s->new_u = s->new_y + avctx->width * avctx->height;
142
913
    s->new_v = s->new_u + avctx->width * avctx->height / 4;
143
913
    s->old_y = s->buf2;
144
913
    s->old_u = s->old_y + avctx->width * avctx->height;
145
913
    s->old_v = s->old_u + avctx->width * avctx->height / 4;
146
913
    memset(s->old_y, 0,    avctx->width * avctx->height);
147
913
    memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
148
913
    memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
149
150
913
    return 0;
151
913
}
152
153
static av_cold int escape130_decode_close(AVCodecContext *avctx)
154
925
{
155
925
    Escape130Context *s = avctx->priv_data;
156
157
925
    av_freep(&s->old_y_avg);
158
925
    av_freep(&s->buf1);
159
925
    av_freep(&s->buf2);
160
161
925
    return 0;
162
925
}
163
164
static int decode_skip_count(GetBitContext* gb)
165
8.11M
{
166
8.11M
    int value;
167
168
8.11M
    if (get_bits_left(gb) < 1+3)
169
5.63k
        return -1;
170
171
8.10M
    value = get_bits1(gb);
172
8.10M
    if (value)
173
3.21M
        return 0;
174
175
4.89M
    value = get_bits(gb, 3);
176
4.89M
    if (value)
177
3.73M
        return value;
178
179
1.15M
    value = get_bits(gb, 8);
180
1.15M
    if (value)
181
1.13M
        return value + 7;
182
183
23.1k
    value = get_bits(gb, 15);
184
23.1k
    if (value)
185
21.6k
        return value + 262;
186
187
1.44k
    return -1;
188
23.1k
}
189
190
static int escape130_decode_frame(AVCodecContext *avctx, AVFrame *pic,
191
                                  int *got_frame, AVPacket *avpkt)
192
223k
{
193
223k
    int buf_size        = avpkt->size;
194
223k
    Escape130Context *s = avctx->priv_data;
195
223k
    GetBitContext gb;
196
223k
    int ret;
197
198
223k
    uint8_t *old_y, *old_cb, *old_cr,
199
223k
            *new_y, *new_cb, *new_cr;
200
223k
    uint8_t *dstY, *dstU, *dstV;
201
223k
    unsigned old_y_stride, old_cb_stride, old_cr_stride,
202
223k
             new_y_stride, new_cb_stride, new_cr_stride;
203
223k
    unsigned total_blocks = avctx->width * avctx->height / 4,
204
223k
             block_index, block_x = 0;
205
223k
    unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
206
223k
    int skip = -1, y_avg = 0, i, j;
207
223k
    uint8_t *ya = s->old_y_avg;
208
209
    // first 16 bytes are header; no useful information in here
210
223k
    if (buf_size <= 16) {
211
111k
        av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
212
111k
        return AVERROR_INVALIDDATA;
213
111k
    }
214
215
111k
    if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
216
0
        return ret;
217
111k
    skip_bits_long(&gb, 16 * 8);
218
219
111k
    new_y  = s->new_y;
220
111k
    new_cb = s->new_u;
221
111k
    new_cr = s->new_v;
222
111k
    new_y_stride  = s->linesize[0];
223
111k
    new_cb_stride = s->linesize[1];
224
111k
    new_cr_stride = s->linesize[2];
225
111k
    old_y  = s->old_y;
226
111k
    old_cb = s->old_u;
227
111k
    old_cr = s->old_v;
228
111k
    old_y_stride  = s->linesize[0];
229
111k
    old_cb_stride = s->linesize[1];
230
111k
    old_cr_stride = s->linesize[2];
231
232
289M
    for (block_index = 0; block_index < total_blocks; block_index++) {
233
        // Note that this call will make us skip the rest of the blocks
234
        // if the frame ends prematurely.
235
288M
        if (skip == -1)
236
8.11M
            skip = decode_skip_count(&gb);
237
288M
        if (skip == -1) {
238
7.08k
            av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
239
7.08k
            return AVERROR_INVALIDDATA;
240
7.08k
        }
241
242
288M
        if (skip) {
243
280M
            y[0] = old_y[0];
244
280M
            y[1] = old_y[1];
245
280M
            y[2] = old_y[old_y_stride];
246
280M
            y[3] = old_y[old_y_stride + 1];
247
280M
            y_avg = ya[0];
248
280M
            cb = old_cb[0];
249
280M
            cr = old_cr[0];
250
280M
        } else {
251
8.10M
            if (get_bits1(&gb)) {
252
4.39M
                unsigned sign_selector       = get_bits(&gb, 6);
253
4.39M
                unsigned difference_selector = get_bits(&gb, 2);
254
4.39M
                y_avg = 2 * get_bits(&gb, 5);
255
21.9M
                for (i = 0; i < 4; i++) {
256
17.5M
                    y[i] = av_clip(y_avg + offset_table[difference_selector] *
257
17.5M
                                   sign_table[sign_selector][i], 0, 63);
258
17.5M
                }
259
4.39M
            } else if (get_bits1(&gb)) {
260
429k
                if (get_bits1(&gb)) {
261
349k
                    y_avg = get_bits(&gb, 6);
262
349k
                } else {
263
80.0k
                    unsigned adjust_index = get_bits(&gb, 3);
264
80.0k
                    y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
265
80.0k
                }
266
2.14M
                for (i = 0; i < 4; i++)
267
1.71M
                    y[i] = y_avg;
268
429k
            }
269
270
8.10M
            if (get_bits1(&gb)) {
271
2.08M
                if (get_bits1(&gb)) {
272
1.72M
                    cb = get_bits(&gb, 5);
273
1.72M
                    cr = get_bits(&gb, 5);
274
1.72M
                } else {
275
357k
                    unsigned adjust_index = get_bits(&gb, 3);
276
357k
                    cb = (cb + chroma_adjust[0][adjust_index]) & 31;
277
357k
                    cr = (cr + chroma_adjust[1][adjust_index]) & 31;
278
357k
                }
279
2.08M
            }
280
8.10M
        }
281
288M
        *ya++ = y_avg;
282
283
288M
        new_y[0]                = y[0];
284
288M
        new_y[1]                = y[1];
285
288M
        new_y[new_y_stride]     = y[2];
286
288M
        new_y[new_y_stride + 1] = y[3];
287
288M
        *new_cb = cb;
288
288M
        *new_cr = cr;
289
290
288M
        old_y += 2;
291
288M
        old_cb++;
292
288M
        old_cr++;
293
288M
        new_y += 2;
294
288M
        new_cb++;
295
288M
        new_cr++;
296
288M
        block_x++;
297
288M
        if (block_x * 2 == avctx->width) {
298
78.9M
            block_x = 0;
299
78.9M
            old_y  += old_y_stride * 2  - avctx->width;
300
78.9M
            old_cb += old_cb_stride     - avctx->width / 2;
301
78.9M
            old_cr += old_cr_stride     - avctx->width / 2;
302
78.9M
            new_y  += new_y_stride * 2  - avctx->width;
303
78.9M
            new_cb += new_cb_stride     - avctx->width / 2;
304
78.9M
            new_cr += new_cr_stride     - avctx->width / 2;
305
78.9M
        }
306
307
288M
        skip--;
308
288M
    }
309
310
104k
    if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
311
2.81k
        return ret;
312
313
101k
    new_y  = s->new_y;
314
101k
    new_cb = s->new_u;
315
101k
    new_cr = s->new_v;
316
101k
    dstY   = pic->data[0];
317
101k
    dstU   = pic->data[1];
318
101k
    dstV   = pic->data[2];
319
15.3M
    for (j = 0; j < avctx->height; j++) {
320
361M
        for (i = 0; i < avctx->width; i++)
321
345M
            dstY[i] = new_y[i] << 2;
322
15.2M
        dstY  += pic->linesize[0];
323
15.2M
        new_y += new_y_stride;
324
15.2M
    }
325
7.73M
    for (j = 0; j < avctx->height / 2; j++) {
326
94.0M
        for (i = 0; i < avctx->width / 2; i++) {
327
86.4M
            dstU[i] = chroma_vals[new_cb[i]];
328
86.4M
            dstV[i] = chroma_vals[new_cr[i]];
329
86.4M
        }
330
7.63M
        dstU   += pic->linesize[1];
331
7.63M
        dstV   += pic->linesize[2];
332
7.63M
        new_cb += new_cb_stride;
333
7.63M
        new_cr += new_cr_stride;
334
7.63M
    }
335
336
101k
    ff_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
337
101k
            buf_size, get_bits_count(&gb) >> 3);
338
339
101k
    FFSWAP(uint8_t*, s->old_y, s->new_y);
340
101k
    FFSWAP(uint8_t*, s->old_u, s->new_u);
341
101k
    FFSWAP(uint8_t*, s->old_v, s->new_v);
342
343
101k
    *got_frame = 1;
344
345
101k
    return buf_size;
346
104k
}
347
348
const FFCodec ff_escape130_decoder = {
349
    .p.name         = "escape130",
350
    CODEC_LONG_NAME("Escape 130"),
351
    .p.type         = AVMEDIA_TYPE_VIDEO,
352
    .p.id           = AV_CODEC_ID_ESCAPE130,
353
    .priv_data_size = sizeof(Escape130Context),
354
    .init           = escape130_decode_init,
355
    .close          = escape130_decode_close,
356
    FF_CODEC_DECODE_CB(escape130_decode_frame),
357
    .p.capabilities = AV_CODEC_CAP_DR1,
358
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
359
};