summaryrefslogtreecommitdiff
path: root/libavcodec/escape130.c (plain)
blob: 1dd7eedd74bcd2fb1f911a94c0c74a5b937be489
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 "get_bits.h"
28#include "internal.h"
29
30typedef struct Escape130Context {
31 uint8_t *old_y_avg;
32
33 uint8_t *new_y, *old_y;
34 uint8_t *new_u, *old_u;
35 uint8_t *new_v, *old_v;
36
37 uint8_t *buf1, *buf2;
38 int linesize[3];
39} Escape130Context;
40
41static const uint8_t offset_table[] = { 2, 4, 10, 20 };
42static const int8_t sign_table[64][4] = {
43 { 0, 0, 0, 0 },
44 { -1, 1, 0, 0 },
45 { 1, -1, 0, 0 },
46 { -1, 0, 1, 0 },
47 { -1, 1, 1, 0 },
48 { 0, -1, 1, 0 },
49 { 1, -1, 1, 0 },
50 { -1, -1, 1, 0 },
51 { 1, 0, -1, 0 },
52 { 0, 1, -1, 0 },
53 { 1, 1, -1, 0 },
54 { -1, 1, -1, 0 },
55 { 1, -1, -1, 0 },
56 { -1, 0, 0, 1 },
57 { -1, 1, 0, 1 },
58 { 0, -1, 0, 1 },
59
60 { 0, 0, 0, 0 },
61 { 1, -1, 0, 1 },
62 { -1, -1, 0, 1 },
63 { -1, 0, 1, 1 },
64 { -1, 1, 1, 1 },
65 { 0, -1, 1, 1 },
66 { 1, -1, 1, 1 },
67 { -1, -1, 1, 1 },
68 { 0, 0, -1, 1 },
69 { 1, 0, -1, 1 },
70 { -1, 0, -1, 1 },
71 { 0, 1, -1, 1 },
72 { 1, 1, -1, 1 },
73 { -1, 1, -1, 1 },
74 { 0, -1, -1, 1 },
75 { 1, -1, -1, 1 },
76
77 { 0, 0, 0, 0 },
78 { -1, -1, -1, 1 },
79 { 1, 0, 0, -1 },
80 { 0, 1, 0, -1 },
81 { 1, 1, 0, -1 },
82 { -1, 1, 0, -1 },
83 { 1, -1, 0, -1 },
84 { 0, 0, 1, -1 },
85 { 1, 0, 1, -1 },
86 { -1, 0, 1, -1 },
87 { 0, 1, 1, -1 },
88 { 1, 1, 1, -1 },
89 { -1, 1, 1, -1 },
90 { 0, -1, 1, -1 },
91 { 1, -1, 1, -1 },
92 { -1, -1, 1, -1 },
93
94 { 0, 0, 0, 0 },
95 { 1, 0, -1, -1 },
96 { 0, 1, -1, -1 },
97 { 1, 1, -1, -1 },
98 { -1, 1, -1, -1 },
99 { 1, -1, -1, -1 }
100};
101
102static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
103
104static const int8_t chroma_adjust[2][8] = {
105 { 1, 1, 0, -1, -1, -1, 0, 1 },
106 { 0, 1, 1, 1, 0, -1, -1, -1 }
107};
108
109static const uint8_t chroma_vals[] = {
110 20, 28, 36, 44, 52, 60, 68, 76,
111 84, 92, 100, 106, 112, 116, 120, 124,
112 128, 132, 136, 140, 144, 150, 156, 164,
113 172, 180, 188, 196, 204, 212, 220, 228
114};
115
116static av_cold int escape130_decode_init(AVCodecContext *avctx)
117{
118 Escape130Context *s = avctx->priv_data;
119 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
120
121 if ((avctx->width & 1) || (avctx->height & 1)) {
122 av_log(avctx, AV_LOG_ERROR,
123 "Dimensions should be a multiple of two.\n");
124 return AVERROR_INVALIDDATA;
125 }
126
127 s->old_y_avg = av_malloc(avctx->width * avctx->height / 4);
128 s->buf1 = av_malloc(avctx->width * avctx->height * 3 / 2);
129 s->buf2 = av_malloc(avctx->width * avctx->height * 3 / 2);
130 if (!s->old_y_avg || !s->buf1 || !s->buf2) {
131 av_freep(&s->old_y_avg);
132 av_freep(&s->buf1);
133 av_freep(&s->buf2);
134 av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
135 return AVERROR(ENOMEM);
136 }
137
138 s->linesize[0] = avctx->width;
139 s->linesize[1] =
140 s->linesize[2] = avctx->width / 2;
141
142 s->new_y = s->buf1;
143 s->new_u = s->new_y + avctx->width * avctx->height;
144 s->new_v = s->new_u + avctx->width * avctx->height / 4;
145 s->old_y = s->buf2;
146 s->old_u = s->old_y + avctx->width * avctx->height;
147 s->old_v = s->old_u + avctx->width * avctx->height / 4;
148 memset(s->old_y, 0, avctx->width * avctx->height);
149 memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
150 memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
151
152 return 0;
153}
154
155static av_cold int escape130_decode_close(AVCodecContext *avctx)
156{
157 Escape130Context *s = avctx->priv_data;
158
159 av_freep(&s->old_y_avg);
160 av_freep(&s->buf1);
161 av_freep(&s->buf2);
162
163 return 0;
164}
165
166static int decode_skip_count(GetBitContext* gb)
167{
168 int value;
169
170 if (get_bits_left(gb) < 1+3)
171 return -1;
172
173 value = get_bits1(gb);
174 if (value)
175 return 0;
176
177 value = get_bits(gb, 3);
178 if (value)
179 return value;
180
181 value = get_bits(gb, 8);
182 if (value)
183 return value + 7;
184
185 value = get_bits(gb, 15);
186 if (value)
187 return value + 262;
188
189 return -1;
190}
191
192static int escape130_decode_frame(AVCodecContext *avctx, void *data,
193 int *got_frame, AVPacket *avpkt)
194{
195 int buf_size = avpkt->size;
196 Escape130Context *s = avctx->priv_data;
197 AVFrame *pic = data;
198 GetBitContext gb;
199 int ret;
200
201 uint8_t *old_y, *old_cb, *old_cr,
202 *new_y, *new_cb, *new_cr;
203 uint8_t *dstY, *dstU, *dstV;
204 unsigned old_y_stride, old_cb_stride, old_cr_stride,
205 new_y_stride, new_cb_stride, new_cr_stride;
206 unsigned total_blocks = avctx->width * avctx->height / 4,
207 block_index, block_x = 0;
208 unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
209 int skip = -1, y_avg = 0, i, j;
210 uint8_t *ya = s->old_y_avg;
211
212 // first 16 bytes are header; no useful information in here
213 if (buf_size <= 16) {
214 av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
215 return AVERROR_INVALIDDATA;
216 }
217
218 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
219 return ret;
220
221 if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
222 return ret;
223 skip_bits_long(&gb, 16 * 8);
224
225 new_y = s->new_y;
226 new_cb = s->new_u;
227 new_cr = s->new_v;
228 new_y_stride = s->linesize[0];
229 new_cb_stride = s->linesize[1];
230 new_cr_stride = s->linesize[2];
231 old_y = s->old_y;
232 old_cb = s->old_u;
233 old_cr = s->old_v;
234 old_y_stride = s->linesize[0];
235 old_cb_stride = s->linesize[1];
236 old_cr_stride = s->linesize[2];
237
238 for (block_index = 0; block_index < total_blocks; block_index++) {
239 // Note that this call will make us skip the rest of the blocks
240 // if the frame ends prematurely.
241 if (skip == -1)
242 skip = decode_skip_count(&gb);
243 if (skip == -1) {
244 av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
245 return AVERROR_INVALIDDATA;
246 }
247
248 if (skip) {
249 y[0] = old_y[0];
250 y[1] = old_y[1];
251 y[2] = old_y[old_y_stride];
252 y[3] = old_y[old_y_stride + 1];
253 y_avg = ya[0];
254 cb = old_cb[0];
255 cr = old_cr[0];
256 } else {
257 if (get_bits1(&gb)) {
258 unsigned sign_selector = get_bits(&gb, 6);
259 unsigned difference_selector = get_bits(&gb, 2);
260 y_avg = 2 * get_bits(&gb, 5);
261 for (i = 0; i < 4; i++) {
262 y[i] = av_clip(y_avg + offset_table[difference_selector] *
263 sign_table[sign_selector][i], 0, 63);
264 }
265 } else if (get_bits1(&gb)) {
266 if (get_bits1(&gb)) {
267 y_avg = get_bits(&gb, 6);
268 } else {
269 unsigned adjust_index = get_bits(&gb, 3);
270 y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
271 }
272 for (i = 0; i < 4; i++)
273 y[i] = y_avg;
274 }
275
276 if (get_bits1(&gb)) {
277 if (get_bits1(&gb)) {
278 cb = get_bits(&gb, 5);
279 cr = get_bits(&gb, 5);
280 } else {
281 unsigned adjust_index = get_bits(&gb, 3);
282 cb = (cb + chroma_adjust[0][adjust_index]) & 31;
283 cr = (cr + chroma_adjust[1][adjust_index]) & 31;
284 }
285 }
286 }
287 *ya++ = y_avg;
288
289 new_y[0] = y[0];
290 new_y[1] = y[1];
291 new_y[new_y_stride] = y[2];
292 new_y[new_y_stride + 1] = y[3];
293 *new_cb = cb;
294 *new_cr = cr;
295
296 old_y += 2;
297 old_cb++;
298 old_cr++;
299 new_y += 2;
300 new_cb++;
301 new_cr++;
302 block_x++;
303 if (block_x * 2 == avctx->width) {
304 block_x = 0;
305 old_y += old_y_stride * 2 - avctx->width;
306 old_cb += old_cb_stride - avctx->width / 2;
307 old_cr += old_cr_stride - avctx->width / 2;
308 new_y += new_y_stride * 2 - avctx->width;
309 new_cb += new_cb_stride - avctx->width / 2;
310 new_cr += new_cr_stride - avctx->width / 2;
311 }
312
313 skip--;
314 }
315
316 new_y = s->new_y;
317 new_cb = s->new_u;
318 new_cr = s->new_v;
319 dstY = pic->data[0];
320 dstU = pic->data[1];
321 dstV = pic->data[2];
322 for (j = 0; j < avctx->height; j++) {
323 for (i = 0; i < avctx->width; i++)
324 dstY[i] = new_y[i] << 2;
325 dstY += pic->linesize[0];
326 new_y += new_y_stride;
327 }
328 for (j = 0; j < avctx->height / 2; j++) {
329 for (i = 0; i < avctx->width / 2; i++) {
330 dstU[i] = chroma_vals[new_cb[i]];
331 dstV[i] = chroma_vals[new_cr[i]];
332 }
333 dstU += pic->linesize[1];
334 dstV += pic->linesize[2];
335 new_cb += new_cb_stride;
336 new_cr += new_cr_stride;
337 }
338
339 ff_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
340 buf_size, get_bits_count(&gb) >> 3);
341
342 FFSWAP(uint8_t*, s->old_y, s->new_y);
343 FFSWAP(uint8_t*, s->old_u, s->new_u);
344 FFSWAP(uint8_t*, s->old_v, s->new_v);
345
346 *got_frame = 1;
347
348 return buf_size;
349}
350
351AVCodec ff_escape130_decoder = {
352 .name = "escape130",
353 .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
354 .type = AVMEDIA_TYPE_VIDEO,
355 .id = AV_CODEC_ID_ESCAPE130,
356 .priv_data_size = sizeof(Escape130Context),
357 .init = escape130_decode_init,
358 .close = escape130_decode_close,
359 .decode = escape130_decode_frame,
360 .capabilities = AV_CODEC_CAP_DR1,
361};
362