FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/escape130.c
Date: 2024-04-19 17:50:32
Exec Total Coverage
Lines: 145 157 92.4%
Functions: 4 4 100.0%
Branches: 47 58 81.0%

Line Branch Exec 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 2 static av_cold int escape130_decode_init(AVCodecContext *avctx)
118 {
119 2 Escape130Context *s = avctx->priv_data;
120 2 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
121
122
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if ((avctx->width & 1) || (avctx->height & 1)) {
123 av_log(avctx, AV_LOG_ERROR,
124 "Dimensions should be a multiple of two.\n");
125 return AVERROR_INVALIDDATA;
126 }
127
128 2 s->old_y_avg = av_malloc(avctx->width * avctx->height / 4);
129 2 s->buf1 = av_malloc(avctx->width * avctx->height * 3 / 2);
130 2 s->buf2 = av_malloc(avctx->width * avctx->height * 3 / 2);
131
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (!s->old_y_avg || !s->buf1 || !s->buf2) {
132 av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
133 return AVERROR(ENOMEM);
134 }
135
136 2 s->linesize[0] = avctx->width;
137 2 s->linesize[1] =
138 2 s->linesize[2] = avctx->width / 2;
139
140 2 s->new_y = s->buf1;
141 2 s->new_u = s->new_y + avctx->width * avctx->height;
142 2 s->new_v = s->new_u + avctx->width * avctx->height / 4;
143 2 s->old_y = s->buf2;
144 2 s->old_u = s->old_y + avctx->width * avctx->height;
145 2 s->old_v = s->old_u + avctx->width * avctx->height / 4;
146 2 memset(s->old_y, 0, avctx->width * avctx->height);
147 2 memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
148 2 memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
149
150 2 return 0;
151 }
152
153 2 static av_cold int escape130_decode_close(AVCodecContext *avctx)
154 {
155 2 Escape130Context *s = avctx->priv_data;
156
157 2 av_freep(&s->old_y_avg);
158 2 av_freep(&s->buf1);
159 2 av_freep(&s->buf2);
160
161 2 return 0;
162 }
163
164 1642909 static int decode_skip_count(GetBitContext* gb)
165 {
166 int value;
167
168
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1642909 times.
1642909 if (get_bits_left(gb) < 1+3)
169 return -1;
170
171 1642909 value = get_bits1(gb);
172
2/2
✓ Branch 0 taken 1274799 times.
✓ Branch 1 taken 368110 times.
1642909 if (value)
173 1274799 return 0;
174
175 368110 value = get_bits(gb, 3);
176
2/2
✓ Branch 0 taken 296591 times.
✓ Branch 1 taken 71519 times.
368110 if (value)
177 296591 return value;
178
179 71519 value = get_bits(gb, 8);
180
2/2
✓ Branch 0 taken 70932 times.
✓ Branch 1 taken 587 times.
71519 if (value)
181 70932 return value + 7;
182
183 587 value = get_bits(gb, 15);
184
1/2
✓ Branch 0 taken 587 times.
✗ Branch 1 not taken.
587 if (value)
185 587 return value + 262;
186
187 return -1;
188 }
189
190 359 static int escape130_decode_frame(AVCodecContext *avctx, AVFrame *pic,
191 int *got_frame, AVPacket *avpkt)
192 {
193 359 int buf_size = avpkt->size;
194 359 Escape130Context *s = avctx->priv_data;
195 GetBitContext gb;
196 int ret;
197
198 uint8_t *old_y, *old_cb, *old_cr,
199 *new_y, *new_cb, *new_cr;
200 uint8_t *dstY, *dstU, *dstV;
201 unsigned old_y_stride, old_cb_stride, old_cr_stride,
202 new_y_stride, new_cb_stride, new_cr_stride;
203 359 unsigned total_blocks = avctx->width * avctx->height / 4,
204 359 block_index, block_x = 0;
205 359 unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
206 359 int skip = -1, y_avg = 0, i, j;
207 359 uint8_t *ya = s->old_y_avg;
208
209 // first 16 bytes are header; no useful information in here
210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 if (buf_size <= 16) {
211 av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
212 return AVERROR_INVALIDDATA;
213 }
214
215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 359 times.
359 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
216 return ret;
217
218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 359 times.
359 if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
219 return ret;
220 359 skip_bits_long(&gb, 16 * 8);
221
222 359 new_y = s->new_y;
223 359 new_cb = s->new_u;
224 359 new_cr = s->new_v;
225 359 new_y_stride = s->linesize[0];
226 359 new_cb_stride = s->linesize[1];
227 359 new_cr_stride = s->linesize[2];
228 359 old_y = s->old_y;
229 359 old_cb = s->old_u;
230 359 old_cr = s->old_v;
231 359 old_y_stride = s->linesize[0];
232 359 old_cb_stride = s->linesize[1];
233 359 old_cr_stride = s->linesize[2];
234
235
2/2
✓ Branch 0 taken 4595200 times.
✓ Branch 1 taken 359 times.
4595559 for (block_index = 0; block_index < total_blocks; block_index++) {
236 // Note that this call will make us skip the rest of the blocks
237 // if the frame ends prematurely.
238
2/2
✓ Branch 0 taken 1642909 times.
✓ Branch 1 taken 2952291 times.
4595200 if (skip == -1)
239 1642909 skip = decode_skip_count(&gb);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4595200 times.
4595200 if (skip == -1) {
241 av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
242 return AVERROR_INVALIDDATA;
243 }
244
245
2/2
✓ Branch 0 taken 2952495 times.
✓ Branch 1 taken 1642705 times.
4595200 if (skip) {
246 2952495 y[0] = old_y[0];
247 2952495 y[1] = old_y[1];
248 2952495 y[2] = old_y[old_y_stride];
249 2952495 y[3] = old_y[old_y_stride + 1];
250 2952495 y_avg = ya[0];
251 2952495 cb = old_cb[0];
252 2952495 cr = old_cr[0];
253 } else {
254
2/2
✓ Branch 1 taken 506697 times.
✓ Branch 2 taken 1136008 times.
1642705 if (get_bits1(&gb)) {
255 506697 unsigned sign_selector = get_bits(&gb, 6);
256 506697 unsigned difference_selector = get_bits(&gb, 2);
257 506697 y_avg = 2 * get_bits(&gb, 5);
258
2/2
✓ Branch 0 taken 2026788 times.
✓ Branch 1 taken 506697 times.
2533485 for (i = 0; i < 4; i++) {
259 2026788 y[i] = av_clip(y_avg + offset_table[difference_selector] *
260 2026788 sign_table[sign_selector][i], 0, 63);
261 }
262
2/2
✓ Branch 1 taken 686938 times.
✓ Branch 2 taken 449070 times.
1136008 } else if (get_bits1(&gb)) {
263
2/2
✓ Branch 1 taken 35948 times.
✓ Branch 2 taken 650990 times.
686938 if (get_bits1(&gb)) {
264 35948 y_avg = get_bits(&gb, 6);
265 } else {
266 650990 unsigned adjust_index = get_bits(&gb, 3);
267 650990 y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
268 }
269
2/2
✓ Branch 0 taken 2747752 times.
✓ Branch 1 taken 686938 times.
3434690 for (i = 0; i < 4; i++)
270 2747752 y[i] = y_avg;
271 }
272
273
2/2
✓ Branch 1 taken 340030 times.
✓ Branch 2 taken 1302675 times.
1642705 if (get_bits1(&gb)) {
274
2/2
✓ Branch 1 taken 9871 times.
✓ Branch 2 taken 330159 times.
340030 if (get_bits1(&gb)) {
275 9871 cb = get_bits(&gb, 5);
276 9871 cr = get_bits(&gb, 5);
277 } else {
278 330159 unsigned adjust_index = get_bits(&gb, 3);
279 330159 cb = (cb + chroma_adjust[0][adjust_index]) & 31;
280 330159 cr = (cr + chroma_adjust[1][adjust_index]) & 31;
281 }
282 }
283 }
284 4595200 *ya++ = y_avg;
285
286 4595200 new_y[0] = y[0];
287 4595200 new_y[1] = y[1];
288 4595200 new_y[new_y_stride] = y[2];
289 4595200 new_y[new_y_stride + 1] = y[3];
290 4595200 *new_cb = cb;
291 4595200 *new_cr = cr;
292
293 4595200 old_y += 2;
294 4595200 old_cb++;
295 4595200 old_cr++;
296 4595200 new_y += 2;
297 4595200 new_cb++;
298 4595200 new_cr++;
299 4595200 block_x++;
300
2/2
✓ Branch 0 taken 28720 times.
✓ Branch 1 taken 4566480 times.
4595200 if (block_x * 2 == avctx->width) {
301 28720 block_x = 0;
302 28720 old_y += old_y_stride * 2 - avctx->width;
303 28720 old_cb += old_cb_stride - avctx->width / 2;
304 28720 old_cr += old_cr_stride - avctx->width / 2;
305 28720 new_y += new_y_stride * 2 - avctx->width;
306 28720 new_cb += new_cb_stride - avctx->width / 2;
307 28720 new_cr += new_cr_stride - avctx->width / 2;
308 }
309
310 4595200 skip--;
311 }
312
313 359 new_y = s->new_y;
314 359 new_cb = s->new_u;
315 359 new_cr = s->new_v;
316 359 dstY = pic->data[0];
317 359 dstU = pic->data[1];
318 359 dstV = pic->data[2];
319
2/2
✓ Branch 0 taken 57440 times.
✓ Branch 1 taken 359 times.
57799 for (j = 0; j < avctx->height; j++) {
320
2/2
✓ Branch 0 taken 18380800 times.
✓ Branch 1 taken 57440 times.
18438240 for (i = 0; i < avctx->width; i++)
321 18380800 dstY[i] = new_y[i] << 2;
322 57440 dstY += pic->linesize[0];
323 57440 new_y += new_y_stride;
324 }
325
2/2
✓ Branch 0 taken 28720 times.
✓ Branch 1 taken 359 times.
29079 for (j = 0; j < avctx->height / 2; j++) {
326
2/2
✓ Branch 0 taken 4595200 times.
✓ Branch 1 taken 28720 times.
4623920 for (i = 0; i < avctx->width / 2; i++) {
327 4595200 dstU[i] = chroma_vals[new_cb[i]];
328 4595200 dstV[i] = chroma_vals[new_cr[i]];
329 }
330 28720 dstU += pic->linesize[1];
331 28720 dstV += pic->linesize[2];
332 28720 new_cb += new_cb_stride;
333 28720 new_cr += new_cr_stride;
334 }
335
336 ff_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
337 buf_size, get_bits_count(&gb) >> 3);
338
339 359 FFSWAP(uint8_t*, s->old_y, s->new_y);
340 359 FFSWAP(uint8_t*, s->old_u, s->new_u);
341 359 FFSWAP(uint8_t*, s->old_v, s->new_v);
342
343 359 *got_frame = 1;
344
345 359 return buf_size;
346 }
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 };
360