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 #include "avcodec.h"
25 #define BITSTREAM_READER_LE
26 #include "get_bits.h"
27 #include "internal.h"
28 
29 typedef struct Escape130Context {
31 
35 
37  int linesize[3];
39 
40 static const uint8_t offset_table[] = { 2, 4, 10, 20 };
41 static const int8_t sign_table[64][4] = {
42  { 0, 0, 0, 0 },
43  { -1, 1, 0, 0 },
44  { 1, -1, 0, 0 },
45  { -1, 0, 1, 0 },
46  { -1, 1, 1, 0 },
47  { 0, -1, 1, 0 },
48  { 1, -1, 1, 0 },
49  { -1, -1, 1, 0 },
50  { 1, 0, -1, 0 },
51  { 0, 1, -1, 0 },
52  { 1, 1, -1, 0 },
53  { -1, 1, -1, 0 },
54  { 1, -1, -1, 0 },
55  { -1, 0, 0, 1 },
56  { -1, 1, 0, 1 },
57  { 0, -1, 0, 1 },
58 
59  { 0, 0, 0, 0 },
60  { 1, -1, 0, 1 },
61  { -1, -1, 0, 1 },
62  { -1, 0, 1, 1 },
63  { -1, 1, 1, 1 },
64  { 0, -1, 1, 1 },
65  { 1, -1, 1, 1 },
66  { -1, -1, 1, 1 },
67  { 0, 0, -1, 1 },
68  { 1, 0, -1, 1 },
69  { -1, 0, -1, 1 },
70  { 0, 1, -1, 1 },
71  { 1, 1, -1, 1 },
72  { -1, 1, -1, 1 },
73  { 0, -1, -1, 1 },
74  { 1, -1, -1, 1 },
75 
76  { 0, 0, 0, 0 },
77  { -1, -1, -1, 1 },
78  { 1, 0, 0, -1 },
79  { 0, 1, 0, -1 },
80  { 1, 1, 0, -1 },
81  { -1, 1, 0, -1 },
82  { 1, -1, 0, -1 },
83  { 0, 0, 1, -1 },
84  { 1, 0, 1, -1 },
85  { -1, 0, 1, -1 },
86  { 0, 1, 1, -1 },
87  { 1, 1, 1, -1 },
88  { -1, 1, 1, -1 },
89  { 0, -1, 1, -1 },
90  { 1, -1, 1, -1 },
91  { -1, -1, 1, -1 },
92 
93  { 0, 0, 0, 0 },
94  { 1, 0, -1, -1 },
95  { 0, 1, -1, -1 },
96  { 1, 1, -1, -1 },
97  { -1, 1, -1, -1 },
98  { 1, -1, -1, -1 }
99 };
100 
101 static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
102 
103 static const int8_t chroma_adjust[2][8] = {
104  { 1, 1, 0, -1, -1, -1, 0, 1 },
105  { 0, 1, 1, 1, 0, -1, -1, -1 }
106 };
107 
108 const uint8_t chroma_vals[] = {
109  20, 28, 36, 44, 52, 60, 68, 76,
110  84, 92, 100, 106, 112, 116, 120, 124,
111  128, 132, 136, 140, 144, 150, 156, 164,
112  172, 180, 188, 196, 204, 212, 220, 228
113 };
114 
116 {
117  Escape130Context *s = avctx->priv_data;
118  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
119 
120  if ((avctx->width & 1) || (avctx->height & 1)) {
121  av_log(avctx, AV_LOG_ERROR,
122  "Dimensions should be a multiple of two.\n");
123  return AVERROR_INVALIDDATA;
124  }
125 
126  s->old_y_avg = av_malloc(avctx->width * avctx->height / 4);
127  s->buf1 = av_malloc(avctx->width * avctx->height * 3 / 2);
128  s->buf2 = av_malloc(avctx->width * avctx->height * 3 / 2);
129  if (!s->old_y_avg || !s->buf1 || !s->buf2) {
130  av_freep(&s->old_y_avg);
131  av_freep(&s->buf1);
132  av_freep(&s->buf2);
133  av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
134  return AVERROR(ENOMEM);
135  }
136 
137  s->linesize[0] = avctx->width;
138  s->linesize[1] =
139  s->linesize[2] = avctx->width / 2;
140 
141  s->new_y = s->buf1;
142  s->new_u = s->new_y + avctx->width * avctx->height;
143  s->new_v = s->new_u + avctx->width * avctx->height / 4;
144  s->old_y = s->buf2;
145  s->old_u = s->old_y + avctx->width * avctx->height;
146  s->old_v = s->old_u + avctx->width * avctx->height / 4;
147  memset(s->old_y, 0, avctx->width * avctx->height);
148  memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
149  memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
150 
151  return 0;
152 }
153 
155 {
156  Escape130Context *s = avctx->priv_data;
157 
158  av_freep(&s->old_y_avg);
159  av_freep(&s->buf1);
160  av_freep(&s->buf2);
161 
162  return 0;
163 }
164 
166 {
167  int value;
168 
169  value = get_bits1(gb);
170  if (value)
171  return 0;
172 
173  value = get_bits(gb, 3);
174  if (value)
175  return value;
176 
177  value = get_bits(gb, 8);
178  if (value)
179  return value + 7;
180 
181  value = get_bits(gb, 15);
182  if (value)
183  return value + 262;
184 
185  return -1;
186 }
187 
188 static int escape130_decode_frame(AVCodecContext *avctx, void *data,
189  int *got_frame, AVPacket *avpkt)
190 {
191  const uint8_t *buf = avpkt->data;
192  int buf_size = avpkt->size;
193  Escape130Context *s = avctx->priv_data;
194  AVFrame *pic = 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 = ff_get_buffer(avctx, pic, 0)) < 0)
216  return ret;
217 
218  init_get_bits(&gb, buf + 16, (buf_size - 16) * 8);
219 
220  new_y = s->new_y;
221  new_cb = s->new_u;
222  new_cr = s->new_v;
223  new_y_stride = s->linesize[0];
224  new_cb_stride = s->linesize[1];
225  new_cr_stride = s->linesize[2];
226  old_y = s->old_y;
227  old_cb = s->old_u;
228  old_cr = s->old_v;
229  old_y_stride = s->linesize[0];
230  old_cb_stride = s->linesize[1];
231  old_cr_stride = s->linesize[2];
232 
233  for (block_index = 0; block_index < total_blocks; block_index++) {
234  // Note that this call will make us skip the rest of the blocks
235  // if the frame ends prematurely.
236  if (skip == -1)
237  skip = decode_skip_count(&gb);
238  if (skip == -1) {
239  av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
240  return AVERROR_INVALIDDATA;
241  }
242 
243  if (skip) {
244  y[0] = old_y[0];
245  y[1] = old_y[1];
246  y[2] = old_y[old_y_stride];
247  y[3] = old_y[old_y_stride + 1];
248  y_avg = ya[0];
249  cb = old_cb[0];
250  cr = old_cr[0];
251  } else {
252  if (get_bits1(&gb)) {
253  unsigned sign_selector = get_bits(&gb, 6);
254  unsigned difference_selector = get_bits(&gb, 2);
255  y_avg = 2 * get_bits(&gb, 5);
256  for (i = 0; i < 4; i++) {
257  y[i] = av_clip(y_avg + offset_table[difference_selector] *
258  sign_table[sign_selector][i], 0, 63);
259  }
260  } else if (get_bits1(&gb)) {
261  if (get_bits1(&gb)) {
262  y_avg = get_bits(&gb, 6);
263  } else {
264  unsigned adjust_index = get_bits(&gb, 3);
265  y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
266  }
267  for (i = 0; i < 4; i++)
268  y[i] = y_avg;
269  }
270 
271  if (get_bits1(&gb)) {
272  if (get_bits1(&gb)) {
273  cb = get_bits(&gb, 5);
274  cr = get_bits(&gb, 5);
275  } else {
276  unsigned adjust_index = get_bits(&gb, 3);
277  cb = (cb + chroma_adjust[0][adjust_index]) & 31;
278  cr = (cr + chroma_adjust[1][adjust_index]) & 31;
279  }
280  }
281  }
282  *ya++ = y_avg;
283 
284  new_y[0] = y[0];
285  new_y[1] = y[1];
286  new_y[new_y_stride] = y[2];
287  new_y[new_y_stride + 1] = y[3];
288  *new_cb = cb;
289  *new_cr = cr;
290 
291  old_y += 2;
292  old_cb++;
293  old_cr++;
294  new_y += 2;
295  new_cb++;
296  new_cr++;
297  block_x++;
298  if (block_x * 2 == avctx->width) {
299  block_x = 0;
300  old_y += old_y_stride * 2 - avctx->width;
301  old_cb += old_cb_stride - avctx->width / 2;
302  old_cr += old_cr_stride - avctx->width / 2;
303  new_y += new_y_stride * 2 - avctx->width;
304  new_cb += new_cb_stride - avctx->width / 2;
305  new_cr += new_cr_stride - avctx->width / 2;
306  }
307 
308  skip--;
309  }
310 
311  new_y = s->new_y;
312  new_cb = s->new_u;
313  new_cr = s->new_v;
314  dstY = pic->data[0];
315  dstU = pic->data[1];
316  dstV = pic->data[2];
317  for (j = 0; j < avctx->height; j++) {
318  for (i = 0; i < avctx->width; i++)
319  dstY[i] = new_y[i] << 2;
320  dstY += pic->linesize[0];
321  new_y += new_y_stride;
322  }
323  for (j = 0; j < avctx->height / 2; j++) {
324  for (i = 0; i < avctx->width / 2; i++) {
325  dstU[i] = chroma_vals[new_cb[i]];
326  dstV[i] = chroma_vals[new_cr[i]];
327  }
328  dstU += pic->linesize[1];
329  dstV += pic->linesize[2];
330  new_cb += new_cb_stride;
331  new_cr += new_cr_stride;
332  }
333 
334  av_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
335  buf_size, get_bits_count(&gb) >> 3);
336 
337  FFSWAP(uint8_t*, s->old_y, s->new_y);
338  FFSWAP(uint8_t*, s->old_u, s->new_u);
339  FFSWAP(uint8_t*, s->old_v, s->new_v);
340 
341  *got_frame = 1;
342 
343  return buf_size;
344 }
345 
347  .name = "escape130",
348  .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
349  .type = AVMEDIA_TYPE_VIDEO,
350  .id = AV_CODEC_ID_ESCAPE130,
351  .priv_data_size = sizeof(Escape130Context),
355  .capabilities = CODEC_CAP_DR1,
356 };
const uint8_t chroma_vals[]
Definition: escape130.c:108
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:135
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:240
memory handling functions
int size
Definition: avcodec.h:968
uint8_t * old_v
Definition: escape130.c:34
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1248
av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (%s)\n", 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)
AVCodec.
Definition: avcodec.h:2790
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:198
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:275
static av_cold int escape130_decode_close(AVCodecContext *avctx)
Definition: escape130.c:154
uint8_t
#define av_cold
Definition: attributes.h:66
uint8_t * old_u
Definition: escape130.c:33
uint8_t * new_v
Definition: escape130.c:34
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:684
uint8_t * new_y
Definition: escape130.c:32
const char data[16]
Definition: mxf.c:70
uint8_t * data
Definition: avcodec.h:967
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:194
bitstream reader API header.
static const int8_t chroma_adjust[2][8]
Definition: escape130.c:103
static const int8_t sign_table[64][4]
Definition: escape130.c:41
static int escape130_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: escape130.c:188
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
#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:150
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:168
const char * name
Name of the codec implementation.
Definition: avcodec.h:2797
int width
picture width / height.
Definition: avcodec.h:1218
uint8_t * buf1
Definition: escape130.c:36
static int decode_skip_count(GetBitContext *gb)
Definition: escape130.c:165
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:153
static const int8_t luma_adjust[]
Definition: escape130.c:101
main external API structure.
Definition: avcodec.h:1044
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:490
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:603
AVCodec ff_escape130_decoder
Definition: escape130.c:346
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:271
uint8_t * old_y
Definition: escape130.c:32
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:375
uint8_t * buf2
Definition: escape130.c:36
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:141
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:65
common internal api header.
static av_cold int init(AVCodecParserContext *s)
Definition: h264_parser.c:499
void * priv_data
Definition: avcodec.h:1086
static const uint8_t offset_table[]
Definition: escape130.c:40
static av_cold int escape130_decode_init(AVCodecContext *avctx)
Definition: escape130.c:115
int linesize[3]
Definition: escape130.c:37
uint8_t * old_y_avg
Definition: escape130.c:30
#define FFSWAP(type, a, b)
Definition: common.h:60
This structure stores compressed data.
Definition: avcodec.h:944
uint8_t * new_u
Definition: escape130.c:33