Libav
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 Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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 
30 typedef struct Escape130Context {
32 
36 
38  int linesize[3];
40 
41 static const uint8_t offset_table[] = { 2, 4, 10, 20 };
42 static 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 
102 static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
103 
104 static 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 
109 static 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 
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 
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 
167 {
168  int value;
169 
170  value = get_bits1(gb);
171  if (value)
172  return 0;
173 
174  value = get_bits(gb, 3);
175  if (value)
176  return value;
177 
178  value = get_bits(gb, 8);
179  if (value)
180  return value + 7;
181 
182  value = get_bits(gb, 15);
183  if (value)
184  return value + 262;
185 
186  return -1;
187 }
188 
189 static int escape130_decode_frame(AVCodecContext *avctx, void *data,
190  int *got_frame, AVPacket *avpkt)
191 {
192  const uint8_t *buf = avpkt->data;
193  int buf_size = avpkt->size;
194  Escape130Context *s = avctx->priv_data;
195  AVFrame *pic = data;
196  GetBitContext gb;
197  int ret;
198 
199  uint8_t *old_y, *old_cb, *old_cr,
200  *new_y, *new_cb, *new_cr;
201  uint8_t *dstY, *dstU, *dstV;
202  unsigned old_y_stride, old_cb_stride, old_cr_stride,
203  new_y_stride, new_cb_stride, new_cr_stride;
204  unsigned total_blocks = avctx->width * avctx->height / 4,
205  block_index, block_x = 0;
206  unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
207  int skip = -1, y_avg = 0, i, j;
208  uint8_t *ya = s->old_y_avg;
209 
210  // first 16 bytes are header; no useful information in here
211  if (buf_size <= 16) {
212  av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
213  return AVERROR_INVALIDDATA;
214  }
215 
216  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
217  return ret;
218 
219  init_get_bits(&gb, buf + 16, (buf_size - 16) * 8);
220 
221  new_y = s->new_y;
222  new_cb = s->new_u;
223  new_cr = s->new_v;
224  new_y_stride = s->linesize[0];
225  new_cb_stride = s->linesize[1];
226  new_cr_stride = s->linesize[2];
227  old_y = s->old_y;
228  old_cb = s->old_u;
229  old_cr = s->old_v;
230  old_y_stride = s->linesize[0];
231  old_cb_stride = s->linesize[1];
232  old_cr_stride = s->linesize[2];
233 
234  for (block_index = 0; block_index < total_blocks; block_index++) {
235  // Note that this call will make us skip the rest of the blocks
236  // if the frame ends prematurely.
237  if (skip == -1)
238  skip = decode_skip_count(&gb);
239  if (skip == -1) {
240  av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
241  return AVERROR_INVALIDDATA;
242  }
243 
244  if (skip) {
245  y[0] = old_y[0];
246  y[1] = old_y[1];
247  y[2] = old_y[old_y_stride];
248  y[3] = old_y[old_y_stride + 1];
249  y_avg = ya[0];
250  cb = old_cb[0];
251  cr = old_cr[0];
252  } else {
253  if (get_bits1(&gb)) {
254  unsigned sign_selector = get_bits(&gb, 6);
255  unsigned difference_selector = get_bits(&gb, 2);
256  y_avg = 2 * get_bits(&gb, 5);
257  for (i = 0; i < 4; i++) {
258  y[i] = av_clip(y_avg + offset_table[difference_selector] *
259  sign_table[sign_selector][i], 0, 63);
260  }
261  } else if (get_bits1(&gb)) {
262  if (get_bits1(&gb)) {
263  y_avg = get_bits(&gb, 6);
264  } else {
265  unsigned adjust_index = get_bits(&gb, 3);
266  y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
267  }
268  for (i = 0; i < 4; i++)
269  y[i] = y_avg;
270  }
271 
272  if (get_bits1(&gb)) {
273  if (get_bits1(&gb)) {
274  cb = get_bits(&gb, 5);
275  cr = get_bits(&gb, 5);
276  } else {
277  unsigned adjust_index = get_bits(&gb, 3);
278  cb = (cb + chroma_adjust[0][adjust_index]) & 31;
279  cr = (cr + chroma_adjust[1][adjust_index]) & 31;
280  }
281  }
282  }
283  *ya++ = y_avg;
284 
285  new_y[0] = y[0];
286  new_y[1] = y[1];
287  new_y[new_y_stride] = y[2];
288  new_y[new_y_stride + 1] = y[3];
289  *new_cb = cb;
290  *new_cr = cr;
291 
292  old_y += 2;
293  old_cb++;
294  old_cr++;
295  new_y += 2;
296  new_cb++;
297  new_cr++;
298  block_x++;
299  if (block_x * 2 == avctx->width) {
300  block_x = 0;
301  old_y += old_y_stride * 2 - avctx->width;
302  old_cb += old_cb_stride - avctx->width / 2;
303  old_cr += old_cr_stride - avctx->width / 2;
304  new_y += new_y_stride * 2 - avctx->width;
305  new_cb += new_cb_stride - avctx->width / 2;
306  new_cr += new_cr_stride - avctx->width / 2;
307  }
308 
309  skip--;
310  }
311 
312  new_y = s->new_y;
313  new_cb = s->new_u;
314  new_cr = s->new_v;
315  dstY = pic->data[0];
316  dstU = pic->data[1];
317  dstV = pic->data[2];
318  for (j = 0; j < avctx->height; j++) {
319  for (i = 0; i < avctx->width; i++)
320  dstY[i] = new_y[i] << 2;
321  dstY += pic->linesize[0];
322  new_y += new_y_stride;
323  }
324  for (j = 0; j < avctx->height / 2; j++) {
325  for (i = 0; i < avctx->width / 2; i++) {
326  dstU[i] = chroma_vals[new_cb[i]];
327  dstV[i] = chroma_vals[new_cr[i]];
328  }
329  dstU += pic->linesize[1];
330  dstV += pic->linesize[2];
331  new_cb += new_cb_stride;
332  new_cr += new_cr_stride;
333  }
334 
335  ff_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
336  buf_size, get_bits_count(&gb) >> 3);
337 
338  FFSWAP(uint8_t*, s->old_y, s->new_y);
339  FFSWAP(uint8_t*, s->old_u, s->new_u);
340  FFSWAP(uint8_t*, s->old_v, s->new_v);
341 
342  *got_frame = 1;
343 
344  return buf_size;
345 }
346 
348  .name = "escape130",
349  .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
350  .type = AVMEDIA_TYPE_VIDEO,
351  .id = AV_CODEC_ID_ESCAPE130,
352  .priv_data_size = sizeof(Escape130Context),
354  .close = escape130_decode_close,
356  .capabilities = AV_CODEC_CAP_DR1,
357 };
static const uint8_t chroma_vals[]
Definition: escape130.c:109
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:62
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
This structure describes decoded (raw) audio or video data.
Definition: frame.h:140
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:228
memory handling functions
int size
Definition: avcodec.h:1347
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
uint8_t * old_v
Definition: escape130.c:35
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1621
AVCodec.
Definition: avcodec.h:3120
Macro definitions for various function/variable attributes.
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
static av_cold int escape130_decode_close(AVCodecContext *avctx)
Definition: escape130.c:155
uint8_t
#define av_cold
Definition: attributes.h:66
uint8_t * old_u
Definition: escape130.c:34
uint8_t * new_v
Definition: escape130.c:35
uint8_t * new_y
Definition: escape130.c:33
const char data[16]
Definition: mxf.c:70
uint8_t * data
Definition: avcodec.h:1346
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:182
bitstream reader API header.
static const int8_t chroma_adjust[2][8]
Definition: escape130.c:104
static const int8_t sign_table[64][4]
Definition: escape130.c:42
static int escape130_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: escape130.c:189
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:148
const char * name
Name of the codec implementation.
Definition: avcodec.h:3127
int width
picture width / height.
Definition: avcodec.h:1580
static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
Definition: avconv.c:1288
uint8_t * buf1
Definition: escape130.c:37
static int decode_skip_count(GetBitContext *gb)
Definition: escape130.c:166
Libavcodec external API header.
#define ff_dlog(ctx,...)
Definition: internal.h:60
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:158
static const int8_t luma_adjust[]
Definition: escape130.c:102
main external API structure.
Definition: avcodec.h:1409
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:589
AVCodec ff_escape130_decoder
Definition: escape130.c:347
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:267
uint8_t * old_y
Definition: escape130.c:33
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:362
uint8_t * buf2
Definition: escape130.c:37
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:146
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:59
common internal api header.
static av_cold int init(AVCodecParserContext *s)
Definition: h264_parser.c:582
void * priv_data
Definition: avcodec.h:1451
static const uint8_t offset_table[]
Definition: escape130.c:41
static av_cold int escape130_decode_init(AVCodecContext *avctx)
Definition: escape130.c:116
int linesize[3]
Definition: escape130.c:38
uint8_t * old_y_avg
Definition: escape130.c:31
#define FFSWAP(type, a, b)
Definition: common.h:69
This structure stores compressed data.
Definition: avcodec.h:1323
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:838
uint8_t * new_u
Definition: escape130.c:34