FFmpeg
Loading...
Searching...
No Matches
escape130.c
Go to the documentation of this file.
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
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
31typedef 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];
41
42static const uint8_t offset_table[] = { 2, 4, 10, 20 };
43static 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
103static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
104
105static 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
110static 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
118{
119 Escape130Context *s = avctx->priv_data;
121
122 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 s->old_y_avg = av_mallocz(avctx->width * avctx->height / 4);
129 s->buf1 = av_malloc(avctx->width * avctx->height * 3 / 2);
130 s->buf2 = av_malloc(avctx->width * avctx->height * 3 / 2);
131 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 s->linesize[0] = avctx->width;
137 s->linesize[1] =
138 s->linesize[2] = avctx->width / 2;
139
140 s->new_y = s->buf1;
141 s->new_u = s->new_y + avctx->width * avctx->height;
142 s->new_v = s->new_u + avctx->width * avctx->height / 4;
143 s->old_y = s->buf2;
144 s->old_u = s->old_y + avctx->width * avctx->height;
145 s->old_v = s->old_u + avctx->width * avctx->height / 4;
146 memset(s->old_y, 0, avctx->width * avctx->height);
147 memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
148 memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
149
150 return 0;
151}
152
154{
155 Escape130Context *s = avctx->priv_data;
156
157 av_freep(&s->old_y_avg);
158 av_freep(&s->buf1);
159 av_freep(&s->buf2);
160
161 return 0;
162}
163
165{
166 int value;
167
168 if (get_bits_left(gb) < 1+3)
169 return -1;
170
171 value = get_bits1(gb);
172 if (value)
173 return 0;
174
175 value = get_bits(gb, 3);
176 if (value)
177 return value;
178
179 value = get_bits(gb, 8);
180 if (value)
181 return value + 7;
182
183 value = get_bits(gb, 15);
184 if (value)
185 return value + 262;
186
187 return -1;
188}
189
191 int *got_frame, AVPacket *avpkt)
192{
193 int buf_size = avpkt->size;
194 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 unsigned total_blocks = avctx->width * avctx->height / 4,
204 block_index, block_x = 0;
205 unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
206 int skip = -1, y_avg = 0, i, j;
207 uint8_t *ya = s->old_y_avg;
208
209 // first 16 bytes are header; no useful information in here
210 if (buf_size <= 16) {
211 av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
212 return AVERROR_INVALIDDATA;
213 }
214
215 if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
216 return ret;
217 skip_bits_long(&gb, 16 * 8);
218
219 new_y = s->new_y;
220 new_cb = s->new_u;
221 new_cr = s->new_v;
222 new_y_stride = s->linesize[0];
223 new_cb_stride = s->linesize[1];
224 new_cr_stride = s->linesize[2];
225 old_y = s->old_y;
226 old_cb = s->old_u;
227 old_cr = s->old_v;
228 old_y_stride = s->linesize[0];
229 old_cb_stride = s->linesize[1];
230 old_cr_stride = s->linesize[2];
231
232 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 if (skip == -1)
236 skip = decode_skip_count(&gb);
237 if (skip == -1) {
238 av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
239 return AVERROR_INVALIDDATA;
240 }
241
242 if (skip) {
243 y[0] = old_y[0];
244 y[1] = old_y[1];
245 y[2] = old_y[old_y_stride];
246 y[3] = old_y[old_y_stride + 1];
247 y_avg = ya[0];
248 cb = old_cb[0];
249 cr = old_cr[0];
250 } else {
251 if (get_bits1(&gb)) {
252 unsigned sign_selector = get_bits(&gb, 6);
253 unsigned difference_selector = get_bits(&gb, 2);
254 y_avg = 2 * get_bits(&gb, 5);
255 for (i = 0; i < 4; i++) {
256 y[i] = av_clip(y_avg + offset_table[difference_selector] *
257 sign_table[sign_selector][i], 0, 63);
258 }
259 } else if (get_bits1(&gb)) {
260 if (get_bits1(&gb)) {
261 y_avg = get_bits(&gb, 6);
262 } else {
263 unsigned adjust_index = get_bits(&gb, 3);
264 y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
265 }
266 for (i = 0; i < 4; i++)
267 y[i] = y_avg;
268 }
269
270 if (get_bits1(&gb)) {
271 if (get_bits1(&gb)) {
272 cb = get_bits(&gb, 5);
273 cr = get_bits(&gb, 5);
274 } else {
275 unsigned adjust_index = get_bits(&gb, 3);
276 cb = (cb + chroma_adjust[0][adjust_index]) & 31;
277 cr = (cr + chroma_adjust[1][adjust_index]) & 31;
278 }
279 }
280 }
281 *ya++ = y_avg;
282
283 new_y[0] = y[0];
284 new_y[1] = y[1];
285 new_y[new_y_stride] = y[2];
286 new_y[new_y_stride + 1] = y[3];
287 *new_cb = cb;
288 *new_cr = cr;
289
290 old_y += 2;
291 old_cb++;
292 old_cr++;
293 new_y += 2;
294 new_cb++;
295 new_cr++;
296 block_x++;
297 if (block_x * 2 == avctx->width) {
298 block_x = 0;
299 old_y += old_y_stride * 2 - avctx->width;
300 old_cb += old_cb_stride - avctx->width / 2;
301 old_cr += old_cr_stride - avctx->width / 2;
302 new_y += new_y_stride * 2 - avctx->width;
303 new_cb += new_cb_stride - avctx->width / 2;
304 new_cr += new_cr_stride - avctx->width / 2;
305 }
306
307 skip--;
308 }
309
310 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
311 return ret;
312
313 new_y = s->new_y;
314 new_cb = s->new_u;
315 new_cr = s->new_v;
316 dstY = pic->data[0];
317 dstU = pic->data[1];
318 dstV = pic->data[2];
319 for (j = 0; j < avctx->height; j++) {
320 for (i = 0; i < avctx->width; i++)
321 dstY[i] = new_y[i] << 2;
322 dstY += pic->linesize[0];
323 new_y += new_y_stride;
324 }
325 for (j = 0; j < avctx->height / 2; j++) {
326 for (i = 0; i < avctx->width / 2; i++) {
327 dstU[i] = chroma_vals[new_cb[i]];
328 dstV[i] = chroma_vals[new_cr[i]];
329 }
330 dstU += pic->linesize[1];
331 dstV += pic->linesize[2];
332 new_cb += new_cb_stride;
333 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 FFSWAP(uint8_t*, s->old_y, s->new_y);
340 FFSWAP(uint8_t*, s->old_u, s->new_u);
341 FFSWAP(uint8_t*, s->old_v, s->new_v);
342
343 *got_frame = 1;
344
345 return buf_size;
346}
347
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),
357 .p.capabilities = AV_CODEC_CAP_DR1,
358 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
359};
const FFCodec ff_escape130_decoder
Definition escape130.c:348
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
Libavcodec external API header.
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define av_clip
Definition common.h:100
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static const int8_t sign_table[64][4]
Definition escape130.c:43
static const int8_t chroma_adjust[2][8]
Definition escape130.c:105
static const uint8_t offset_table[]
Definition escape130.c:42
static const uint8_t chroma_vals[]
Definition escape130.c:110
static int decode_skip_count(GetBitContext *gb)
Definition escape130.c:164
static int escape130_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt)
Definition escape130.c:190
static av_cold int escape130_decode_init(AVCodecContext *avctx)
Definition escape130.c:117
static const int8_t luma_adjust[]
Definition escape130.c:103
static av_cold int escape130_decode_close(AVCodecContext *avctx)
Definition escape130.c:153
double value
Definition eval.c:102
bitstream reader API header.
static int get_bits_left(GetBitContext *gb)
Definition get_bits.h:688
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition get_bits.h:280
static unsigned int get_bits1(GetBitContext *s)
Definition get_bits.h:391
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition get_bits.h:544
static int get_bits_count(const GetBitContext *s)
Definition get_bits.h:254
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_ESCAPE130
Definition codec_id.h:219
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
Macro definitions for various function/variable attributes.
#define av_cold
Definition attributes.h:117
#define FFSWAP(type, a, b)
Definition macros.h:52
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
uint8_t * old_u
Definition escape130.c:35
uint8_t * new_u
Definition escape130.c:35
uint8_t * new_y
Definition escape130.c:34
uint8_t * buf1
Definition escape130.c:38
uint8_t * old_y_avg
Definition escape130.c:32
uint8_t * old_y
Definition escape130.c:34
uint8_t * old_v
Definition escape130.c:36
uint8_t * new_v
Definition escape130.c:36
uint8_t * buf2
Definition escape130.c:38
#define av_mallocz(s)
#define ff_dlog(a,...)
#define av_freep(p)
#define av_log(a,...)
static double cr(void *priv, double x, double y)
Definition vf_geq.c:248
static double cb(void *priv, double x, double y)
Definition vf_geq.c:247