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 |