Coverage Report

Created: 2026-10-28 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/eatgq.c
Line
Count
Source
1
/*
2
 * Electronic Arts TGQ Video Decoder
3
 * Copyright (c) 2007-2008 Peter Ross <pross@xvid.org>
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 St, Fifth Floor, Boston, MA  02110-1301  USA
20
 */
21
22
/**
23
 * @file
24
 * Electronic Arts TGQ Video Decoder
25
 * @author Peter Ross <pross@xvid.org>
26
 *
27
 * Technical details here:
28
 * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGQ
29
 */
30
31
#include "libavutil/attributes.h"
32
#define BITSTREAM_READER_LE
33
34
#include "libavutil/mem_internal.h"
35
36
#include "aandcttab.h"
37
#include "avcodec.h"
38
#include "bytestream.h"
39
#include "codec_internal.h"
40
#include "copy_block.h"
41
#include "decode.h"
42
#include "eaidct.h"
43
#include "get_bits.h"
44
45
typedef struct TgqContext {
46
    AVCodecContext *avctx;
47
    AVFrame *last_frame;
48
    int width, height;
49
    int qtable[64];
50
    DECLARE_ALIGNED(16, int16_t, block)[6][64];
51
} TgqContext;
52
53
static av_cold int tgq_decode_init(AVCodecContext *avctx)
54
1.49k
{
55
1.49k
    TgqContext *s = avctx->priv_data;
56
1.49k
    s->avctx = avctx;
57
1.49k
    avctx->framerate = (AVRational){ 15, 1 };
58
1.49k
    avctx->pix_fmt   = AV_PIX_FMT_YUV420P;
59
1.49k
    s->last_frame = av_frame_alloc();
60
1.49k
    if (!s->last_frame)
61
0
        return AVERROR(ENOMEM);
62
1.49k
    return 0;
63
1.49k
}
64
65
static int tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb)
66
610k
{
67
610k
    const uint8_t *scantable = ff_zigzag_direct;
68
610k
    int i, j, value;
69
610k
    block[0] = get_sbits(gb, 8) * s->qtable[0];
70
38.9M
    for (i = 1; i < 64;) {
71
38.2M
        switch (show_bits(gb, 3)) {
72
10.4k
        case 4:
73
10.4k
            if (i >= 63)
74
244
                return AVERROR_INVALIDDATA;
75
10.1k
            block[scantable[i++]] = 0;
76
10.1k
            av_fallthrough;
77
38.0M
        case 0:
78
38.0M
            block[scantable[i++]] = 0;
79
38.0M
            skip_bits(gb, 3);
80
38.0M
            break;
81
4.42k
        case 5:
82
19.1k
        case 1:
83
19.1k
            skip_bits(gb, 2);
84
19.1k
            value = get_bits(gb, 6);
85
19.1k
            if (value > 64 - i)
86
889
                return AVERROR_INVALIDDATA;
87
159k
            for (j = 0; j < value; j++)
88
141k
                block[scantable[i++]] = 0;
89
18.3k
            break;
90
18.7k
        case 6:
91
18.7k
            skip_bits(gb, 3);
92
18.7k
            block[scantable[i]] = -s->qtable[scantable[i]];
93
18.7k
            i++;
94
18.7k
            break;
95
68.2k
        case 2:
96
68.2k
            skip_bits(gb, 3);
97
68.2k
            block[scantable[i]] = s->qtable[scantable[i]];
98
68.2k
            i++;
99
68.2k
            break;
100
138k
        case 7: // 111b
101
173k
        case 3: // 011b
102
173k
            skip_bits(gb, 2);
103
173k
            if (show_bits(gb, 6) == 0x3F) {
104
10.4k
                skip_bits(gb, 6);
105
10.4k
                block[scantable[i]] = get_sbits(gb, 8) * s->qtable[scantable[i]];
106
163k
            } else {
107
163k
                block[scantable[i]] = get_sbits(gb, 6) * s->qtable[scantable[i]];
108
163k
            }
109
173k
            i++;
110
173k
            break;
111
38.2M
        }
112
38.2M
    }
113
609k
    block[0] += 128 << 4;
114
609k
    return 0;
115
610k
}
116
117
static void tgq_idct_put_mb(TgqContext *s, int16_t (*block)[64], AVFrame *frame,
118
                            int mb_x, int mb_y)
119
101k
{
120
101k
    ptrdiff_t linesize = frame->linesize[0];
121
101k
    uint8_t *dest_y  = frame->data[0] + (mb_y * 16 * linesize)           + mb_x * 16;
122
101k
    uint8_t *dest_cb = frame->data[1] + (mb_y * 8  * frame->linesize[1]) + mb_x * 8;
123
101k
    uint8_t *dest_cr = frame->data[2] + (mb_y * 8  * frame->linesize[2]) + mb_x * 8;
124
125
101k
    ff_ea_idct_put_c(dest_y                   , linesize, block[0]);
126
101k
    ff_ea_idct_put_c(dest_y                + 8, linesize, block[1]);
127
101k
    ff_ea_idct_put_c(dest_y + 8 * linesize    , linesize, block[2]);
128
101k
    ff_ea_idct_put_c(dest_y + 8 * linesize + 8, linesize, block[3]);
129
101k
    if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
130
101k
         ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]);
131
101k
         ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]);
132
101k
    }
133
101k
}
134
135
static inline void tgq_dconly(TgqContext *s, unsigned char *dst,
136
                              ptrdiff_t dst_stride, int dc)
137
137k
{
138
137k
    int level = av_clip_uint8((dc*s->qtable[0] + 2056) >> 4);
139
137k
    int j;
140
1.23M
    for (j = 0; j < 8; j++)
141
1.09M
        memset(dst + j * dst_stride, level, 8);
142
137k
}
143
144
static void tgq_idct_put_mb_dconly(TgqContext *s, AVFrame *frame,
145
                                   int mb_x, int mb_y, const int8_t *dc)
146
22.8k
{
147
22.8k
    ptrdiff_t linesize = frame->linesize[0];
148
22.8k
    uint8_t *dest_y  = frame->data[0] + (mb_y * 16 * linesize)             + mb_x * 16;
149
22.8k
    uint8_t *dest_cb = frame->data[1] + (mb_y * 8  * frame->linesize[1]) + mb_x * 8;
150
22.8k
    uint8_t *dest_cr = frame->data[2] + (mb_y * 8  * frame->linesize[2]) + mb_x * 8;
151
22.8k
    tgq_dconly(s, dest_y,                    linesize, dc[0]);
152
22.8k
    tgq_dconly(s, dest_y                + 8, linesize, dc[1]);
153
22.8k
    tgq_dconly(s, dest_y + 8 * linesize,     linesize, dc[2]);
154
22.8k
    tgq_dconly(s, dest_y + 8 * linesize + 8, linesize, dc[3]);
155
22.8k
    if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
156
22.8k
        tgq_dconly(s, dest_cb, frame->linesize[1], dc[4]);
157
22.8k
        tgq_dconly(s, dest_cr, frame->linesize[2], dc[5]);
158
22.8k
    }
159
22.8k
}
160
161
static int tgq_decode_mb(TgqContext *s, GetByteContext *gbyte,
162
                         AVFrame *frame, int mb_y, int mb_x)
163
132k
{
164
132k
    int mode;
165
132k
    int i;
166
167
132k
    mode = bytestream2_get_byte(gbyte);
168
132k
    if (mode > 12) {
169
102k
        GetBitContext gb;
170
102k
        int ret = init_get_bits8(&gb, gbyte->buffer, FFMIN(bytestream2_get_bytes_left(gbyte), mode));
171
102k
        if (ret < 0)
172
0
            return ret;
173
174
711k
        for (i = 0; i < 6; i++) {
175
610k
            ret = tgq_decode_block(s, s->block[i], &gb);
176
610k
            if (ret < 0)
177
1.13k
                return ret;
178
610k
        }
179
101k
        tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
180
101k
        bytestream2_skip(gbyte, mode);
181
101k
    } else {
182
29.4k
        int8_t dc[6];
183
29.4k
        if (mode == 1) {
184
4.68k
            int x, y;
185
4.68k
            int mv = bytestream2_get_byte(gbyte);
186
4.68k
            int mv_x = mv >> 4;
187
4.68k
            int mv_y = mv & 0x0F;
188
4.68k
            if (!s->last_frame->data[0]) {
189
523
                av_log(s->avctx, AV_LOG_ERROR, "missing reference frame\n");
190
523
                return -1;
191
523
            }
192
4.16k
            if (mv_x >= 8) mv_x -= 16;
193
4.16k
            if (mv_y >= 8) mv_y -= 16;
194
4.16k
            x = mb_x * 16 - mv_x;
195
4.16k
            y = mb_y * 16 - mv_y;
196
4.16k
            if (x < 0 || x + 16 > s->width || y < 0 || y + 16 > s->height) {
197
1.18k
                av_log(s->avctx, AV_LOG_ERROR, "invalid motion vector\n");
198
1.18k
                return -1;
199
1.18k
            }
200
2.97k
            copy_block16(frame->data[0] + (mb_y * 16 * frame->linesize[0]) + mb_x * 16,
201
2.97k
                         s->last_frame->data[0] + y * s->last_frame->linesize[0] + x,
202
2.97k
                         frame->linesize[0], s->last_frame->linesize[0], 16);
203
8.93k
            for (int p = 1; p < 3; p++)
204
5.95k
                copy_block8(frame->data[p] + (mb_y * 8 * frame->linesize[p]) + mb_x * 8,
205
5.95k
                            s->last_frame->data[p] + (y >> 1) * s->last_frame->linesize[p] + (x >> 1),
206
5.95k
                            frame->linesize[p], s->last_frame->linesize[p], 8);
207
2.97k
            frame->flags &= ~AV_FRAME_FLAG_KEY;
208
2.97k
            return 0;
209
24.7k
        } else if (mode == 3) {
210
9.75k
            memset(dc, bytestream2_get_byte(gbyte), 4);
211
9.75k
            dc[4] = bytestream2_get_byte(gbyte);
212
9.75k
            dc[5] = bytestream2_get_byte(gbyte);
213
14.9k
        } else if (mode == 6) {
214
8.61k
            if (bytestream2_get_buffer(gbyte, dc, 6) != 6)
215
201
                return AVERROR_INVALIDDATA;
216
8.61k
        } else if (mode == 12) {
217
32.9k
            for (i = 0; i < 6; i++) {
218
28.2k
                dc[i] = bytestream2_get_byte(gbyte);
219
28.2k
                bytestream2_skip(gbyte, 1);
220
28.2k
            }
221
4.71k
        } else {
222
1.63k
            av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode);
223
1.63k
            return -1;
224
1.63k
        }
225
22.8k
        tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc);
226
22.8k
    }
227
124k
    return 0;
228
132k
}
229
230
static void tgq_calculate_qtable(TgqContext *s, int quant)
231
120k
{
232
120k
    int i, j;
233
120k
    const int a = (14 * (100 - quant)) / 100 + 1;
234
120k
    const int b = (11 * (100 - quant)) / 100 + 4;
235
1.08M
    for (j = 0; j < 8; j++)
236
8.64M
        for (i = 0; i < 8; i++)
237
7.68M
            s->qtable[j * 8 + i] = ((a * (j + i) / (7 + 7) + b) *
238
7.68M
                                    ff_inv_aanscales[j * 8 + i]) >> (14 - 4);
239
120k
}
240
241
static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame,
242
                            int *got_frame, AVPacket *avpkt)
243
211k
{
244
211k
    const uint8_t *buf = avpkt->data;
245
211k
    int buf_size       = avpkt->size;
246
211k
    TgqContext *s      = avctx->priv_data;
247
211k
    GetByteContext gbyte;
248
211k
    int x, y, ret;
249
211k
    int big_endian;
250
251
211k
    if (buf_size < 16) {
252
87.6k
        av_log(avctx, AV_LOG_WARNING, "truncated header\n");
253
87.6k
        return AVERROR_INVALIDDATA;
254
87.6k
    }
255
123k
    big_endian = AV_RL32(&buf[4]) > 0x000FFFFF;
256
123k
    bytestream2_init(&gbyte, buf + 8, buf_size - 8);
257
123k
    if (big_endian) {
258
120k
        s->width  = bytestream2_get_be16u(&gbyte);
259
120k
        s->height = bytestream2_get_be16u(&gbyte);
260
120k
    } else {
261
3.34k
        s->width  = bytestream2_get_le16u(&gbyte);
262
3.34k
        s->height = bytestream2_get_le16u(&gbyte);
263
3.34k
    }
264
265
123k
    if (s->avctx->width != s->width || s->avctx->height != s->height) {
266
32.8k
        av_frame_unref(s->last_frame);
267
32.8k
        ret = ff_set_dimensions(s->avctx, s->width, s->height);
268
32.8k
        if (ret < 0)
269
3.84k
            return ret;
270
32.8k
    }
271
272
120k
    tgq_calculate_qtable(s, bytestream2_get_byteu(&gbyte));
273
120k
    bytestream2_skipu(&gbyte, 3);
274
275
120k
    int mb_width  = FFALIGN(avctx->width,  16) >> 4;
276
120k
    int mb_height = FFALIGN(avctx->height, 16) >> 4;
277
120k
    if (bytestream2_get_bytes_left(&gbyte) < mb_width * mb_height)
278
14.8k
        return AVERROR_INVALIDDATA;
279
280
105k
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
281
337
        return ret;
282
283
104k
    frame->flags |= AV_FRAME_FLAG_KEY;
284
212k
    for (y = 0; y < mb_height; y++)
285
239k
        for (x = 0; x < mb_width; x++)
286
132k
            if (tgq_decode_mb(s, &gbyte, frame, y, x) < 0)
287
4.67k
                return AVERROR_INVALIDDATA;
288
289
100k
    if ((ret = av_frame_replace(s->last_frame, frame)) < 0)
290
0
        return ret;
291
292
100k
    *got_frame = 1;
293
294
100k
    return avpkt->size;
295
100k
}
296
297
static av_cold int tgq_decode_close(AVCodecContext *avctx)
298
1.49k
{
299
1.49k
    TgqContext *s = avctx->priv_data;
300
1.49k
    av_frame_free(&s->last_frame);
301
1.49k
    return 0;
302
1.49k
}
303
304
const FFCodec ff_eatgq_decoder = {
305
    .p.name         = "eatgq",
306
    CODEC_LONG_NAME("Electronic Arts TGQ video"),
307
    .p.type         = AVMEDIA_TYPE_VIDEO,
308
    .p.id           = AV_CODEC_ID_TGQ,
309
    .priv_data_size = sizeof(TgqContext),
310
    .init           = tgq_decode_init,
311
    .close          = tgq_decode_close,
312
    FF_CODEC_DECODE_CB(tgq_decode_frame),
313
    .p.capabilities = AV_CODEC_CAP_DR1,
314
};