FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 
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  if (get_bits_left(gb) < 1+3)
170  return -1;
171 
172  value = get_bits1(gb);
173  if (value)
174  return 0;
175 
176  value = get_bits(gb, 3);
177  if (value)
178  return value;
179 
180  value = get_bits(gb, 8);
181  if (value)
182  return value + 7;
183 
184  value = get_bits(gb, 15);
185  if (value)
186  return value + 262;
187 
188  return -1;
189 }
190 
191 static int escape130_decode_frame(AVCodecContext *avctx, void *data,
192  int *got_frame, AVPacket *avpkt)
193 {
194  const uint8_t *buf = avpkt->data;
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  init_get_bits(&gb, buf + 16, (buf_size - 16) * 8);
222 
223  new_y = s->new_y;
224  new_cb = s->new_u;
225  new_cr = s->new_v;
226  new_y_stride = s->linesize[0];
227  new_cb_stride = s->linesize[1];
228  new_cr_stride = s->linesize[2];
229  old_y = s->old_y;
230  old_cb = s->old_u;
231  old_cr = s->old_v;
232  old_y_stride = s->linesize[0];
233  old_cb_stride = s->linesize[1];
234  old_cr_stride = s->linesize[2];
235 
236  for (block_index = 0; block_index < total_blocks; block_index++) {
237  // Note that this call will make us skip the rest of the blocks
238  // if the frame ends prematurely.
239  if (skip == -1)
240  skip = decode_skip_count(&gb);
241  if (skip == -1) {
242  av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
243  return AVERROR_INVALIDDATA;
244  }
245 
246  if (skip) {
247  y[0] = old_y[0];
248  y[1] = old_y[1];
249  y[2] = old_y[old_y_stride];
250  y[3] = old_y[old_y_stride + 1];
251  y_avg = ya[0];
252  cb = old_cb[0];
253  cr = old_cr[0];
254  } else {
255  if (get_bits1(&gb)) {
256  unsigned sign_selector = get_bits(&gb, 6);
257  unsigned difference_selector = get_bits(&gb, 2);
258  y_avg = 2 * get_bits(&gb, 5);
259  for (i = 0; i < 4; i++) {
260  y[i] = av_clip(y_avg + offset_table[difference_selector] *
261  sign_table[sign_selector][i], 0, 63);
262  }
263  } else if (get_bits1(&gb)) {
264  if (get_bits1(&gb)) {
265  y_avg = get_bits(&gb, 6);
266  } else {
267  unsigned adjust_index = get_bits(&gb, 3);
268  y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
269  }
270  for (i = 0; i < 4; i++)
271  y[i] = y_avg;
272  }
273 
274  if (get_bits1(&gb)) {
275  if (get_bits1(&gb)) {
276  cb = get_bits(&gb, 5);
277  cr = get_bits(&gb, 5);
278  } else {
279  unsigned adjust_index = get_bits(&gb, 3);
280  cb = (cb + chroma_adjust[0][adjust_index]) & 31;
281  cr = (cr + chroma_adjust[1][adjust_index]) & 31;
282  }
283  }
284  }
285  *ya++ = y_avg;
286 
287  new_y[0] = y[0];
288  new_y[1] = y[1];
289  new_y[new_y_stride] = y[2];
290  new_y[new_y_stride + 1] = y[3];
291  *new_cb = cb;
292  *new_cr = cr;
293 
294  old_y += 2;
295  old_cb++;
296  old_cr++;
297  new_y += 2;
298  new_cb++;
299  new_cr++;
300  block_x++;
301  if (block_x * 2 == avctx->width) {
302  block_x = 0;
303  old_y += old_y_stride * 2 - avctx->width;
304  old_cb += old_cb_stride - avctx->width / 2;
305  old_cr += old_cr_stride - avctx->width / 2;
306  new_y += new_y_stride * 2 - avctx->width;
307  new_cb += new_cb_stride - avctx->width / 2;
308  new_cr += new_cr_stride - avctx->width / 2;
309  }
310 
311  skip--;
312  }
313 
314  new_y = s->new_y;
315  new_cb = s->new_u;
316  new_cr = s->new_v;
317  dstY = pic->data[0];
318  dstU = pic->data[1];
319  dstV = pic->data[2];
320  for (j = 0; j < avctx->height; j++) {
321  for (i = 0; i < avctx->width; i++)
322  dstY[i] = new_y[i] << 2;
323  dstY += pic->linesize[0];
324  new_y += new_y_stride;
325  }
326  for (j = 0; j < avctx->height / 2; j++) {
327  for (i = 0; i < avctx->width / 2; i++) {
328  dstU[i] = chroma_vals[new_cb[i]];
329  dstV[i] = chroma_vals[new_cr[i]];
330  }
331  dstU += pic->linesize[1];
332  dstV += pic->linesize[2];
333  new_cb += new_cb_stride;
334  new_cr += new_cr_stride;
335  }
336 
337  av_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
338  buf_size, get_bits_count(&gb) >> 3);
339 
340  FFSWAP(uint8_t*, s->old_y, s->new_y);
341  FFSWAP(uint8_t*, s->old_u, s->new_u);
342  FFSWAP(uint8_t*, s->old_v, s->new_v);
343 
344  *got_frame = 1;
345 
346  return buf_size;
347 }
348 
350  .name = "escape130",
351  .type = AVMEDIA_TYPE_VIDEO,
352  .id = AV_CODEC_ID_ESCAPE130,
353  .priv_data_size = sizeof(Escape130Context),
357  .capabilities = CODEC_CAP_DR1,
358  .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
359 };