mimic.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005 Ole André Vadla Ravnås <oleavr@gmail.com>
3  * Copyright (C) 2008 Ramiro Polla
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 <stdlib.h>
23 #include <string.h>
24 #include <stdint.h>
25 
26 #include "avcodec.h"
27 #include "internal.h"
28 #include "get_bits.h"
29 #include "bytestream.h"
30 #include "dsputil.h"
31 #include "thread.h"
32 
33 #define MIMIC_HEADER_SIZE 20
34 
35 typedef struct {
37 
38  int num_vblocks[3];
39  int num_hblocks[3];
40 
41  void *swap_buf;
43 
44  int cur_index;
46 
47  AVFrame buf_ptrs [16];
48  AVPicture flipped_ptrs[16];
49 
50  DECLARE_ALIGNED(16, DCTELEM, dct_block)[64];
51 
56 
57  /* Kept in the context so multithreading can have a constant to read from */
60 } MimicContext;
61 
62 static const uint32_t huffcodes[] = {
63  0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
64  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
65  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b,
66  0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9,
67  0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb,
68  0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb,
69  0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9,
70  0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000,
71  0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9,
72  0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb,
73  0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8,
74  0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb,
75  0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9,
76  0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8,
77  0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa,
78  0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000,
79  0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb,
80  0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9,
81  0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9,
82  0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb,
83  0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9,
84  0x3ffffffa,
85 };
86 
87 static const uint8_t huffbits[] = {
88  4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89  0, 0, 0, 0, 2, 4, 5, 6, 7, 7, 7, 8,
90  8, 10, 11, 11, 11, 11, 12, 12, 2, 6, 7, 8,
91  9, 9, 12, 12, 13, 13, 13, 13, 14, 14, 14, 0,
92  3, 6, 9, 14, 15, 15, 15, 15, 16, 16, 16, 16,
93  17, 17, 17, 0, 4, 8, 9, 17, 18, 18, 18, 18,
94  19, 19, 19, 19, 20, 20, 20, 0, 5, 10, 20, 21,
95  21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 0,
96  6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26,
97  26, 26, 27, 0, 10, 27, 27, 27, 28, 28, 28, 28,
98  29, 29, 29, 29, 30, 30, 30,
99 };
100 
101 static const uint8_t col_zag[64] = {
102  0, 8, 1, 2, 9, 16, 24, 17,
103  10, 3, 4, 11, 18, 25, 32, 40,
104  33, 26, 19, 12, 5, 6, 13, 20,
105  27, 34, 41, 48, 56, 49, 42, 35,
106  28, 21, 14, 7, 15, 22, 29, 36,
107  43, 50, 57, 58, 51, 44, 37, 30,
108  23, 31, 38, 45, 52, 59, 39, 46,
109  53, 60, 61, 54, 47, 55, 62, 63,
110 };
111 
113 {
114  MimicContext *ctx = avctx->priv_data;
115 
116  ctx->prev_index = 0;
117  ctx->cur_index = 15;
118 
119  if(init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits),
120  huffbits, 1, 1, huffcodes, 4, 4, 0)) {
121  av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n");
122  return -1;
123  }
124  dsputil_init(&ctx->dsp, avctx);
126 
127  return 0;
128 }
129 
131 {
132  MimicContext *dst = avctx->priv_data, *src = avctx_from->priv_data;
133 
134  if (avctx == avctx_from) return 0;
135 
136  dst->cur_index = src->next_cur_index;
137  dst->prev_index = src->next_prev_index;
138 
139  memcpy(dst->buf_ptrs, src->buf_ptrs, sizeof(src->buf_ptrs));
140  memcpy(dst->flipped_ptrs, src->flipped_ptrs, sizeof(src->flipped_ptrs));
141 
142  memset(&dst->buf_ptrs[dst->cur_index], 0, sizeof(AVFrame));
143 
144  return 0;
145 }
146 
147 static const int8_t vlcdec_lookup[9][64] = {
148  { 0, },
149  { -1, 1, },
150  { -3, 3, -2, 2, },
151  { -7, 7, -6, 6, -5, 5, -4, 4, },
152  { -15, 15, -14, 14, -13, 13, -12, 12,
153  -11, 11, -10, 10, -9, 9, -8, 8, },
154  { -31, 31, -30, 30, -29, 29, -28, 28,
155  -27, 27, -26, 26, -25, 25, -24, 24,
156  -23, 23, -22, 22, -21, 21, -20, 20,
157  -19, 19, -18, 18, -17, 17, -16, 16, },
158  { -63, 63, -62, 62, -61, 61, -60, 60,
159  -59, 59, -58, 58, -57, 57, -56, 56,
160  -55, 55, -54, 54, -53, 53, -52, 52,
161  -51, 51, -50, 50, -49, 49, -48, 48,
162  -47, 47, -46, 46, -45, 45, -44, 44,
163  -43, 43, -42, 42, -41, 41, -40, 40,
164  -39, 39, -38, 38, -37, 37, -36, 36,
165  -35, 35, -34, 34, -33, 33, -32, 32, },
166  { -127, 127, -126, 126, -125, 125, -124, 124,
167  -123, 123, -122, 122, -121, 121, -120, 120,
168  -119, 119, -118, 118, -117, 117, -116, 116,
169  -115, 115, -114, 114, -113, 113, -112, 112,
170  -111, 111, -110, 110, -109, 109, -108, 108,
171  -107, 107, -106, 106, -105, 105, -104, 104,
172  -103, 103, -102, 102, -101, 101, -100, 100,
173  -99, 99, -98, 98, -97, 97, -96, 96, },
174  { -95, 95, -94, 94, -93, 93, -92, 92,
175  -91, 91, -90, 90, -89, 89, -88, 88,
176  -87, 87, -86, 86, -85, 85, -84, 84,
177  -83, 83, -82, 82, -81, 81, -80, 80,
178  -79, 79, -78, 78, -77, 77, -76, 76,
179  -75, 75, -74, 74, -73, 73, -72, 72,
180  -71, 71, -70, 70, -69, 69, -68, 68,
181  -67, 67, -66, 66, -65, 65, -64, 64, },
182 };
183 
184 static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale)
185 {
186  DCTELEM *block = ctx->dct_block;
187  unsigned int pos;
188 
189  ctx->dsp.clear_block(block);
190 
191  block[0] = get_bits(&ctx->gb, 8) << 3;
192 
193  for(pos = 1; pos < num_coeffs; pos++) {
194  uint32_t vlc, num_bits;
195  int value;
196  int coeff;
197 
198  vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3);
199  if(!vlc) /* end-of-block code */
200  return 1;
201  if(vlc == -1)
202  return 0;
203 
204  /* pos_add and num_bits are coded in the vlc code */
205  pos += vlc&15; // pos_add
206  num_bits = vlc>>4; // num_bits
207 
208  if(pos >= 64)
209  return 0;
210 
211  value = get_bits(&ctx->gb, num_bits);
212 
213  /* Libav's IDCT behaves somewhat different from the original code, so
214  * a factor of 4 was added to the input */
215 
216  coeff = vlcdec_lookup[num_bits][value];
217  if(pos<3)
218  coeff <<= 4;
219  else /* TODO Use >> 10 instead of / 1001 */
220  coeff = (coeff * qscale) / 1001;
221 
222  block[ctx->scantable.permutated[pos]] = coeff;
223  }
224 
225  return 1;
226 }
227 
228 static int decode(MimicContext *ctx, int quality, int num_coeffs,
229  int is_iframe)
230 {
231  int y, x, plane, cur_row = 0;
232 
233  for(plane = 0; plane < 3; plane++) {
234  const int is_chroma = !!plane;
235  const int qscale = av_clip(10000-quality,is_chroma?1000:2000,10000)<<2;
236  const int stride = ctx->flipped_ptrs[ctx->cur_index].linesize[plane];
237  const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane];
238  uint8_t *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane];
239 
240  for(y = 0; y < ctx->num_vblocks[plane]; y++) {
241  for(x = 0; x < ctx->num_hblocks[plane]; x++) {
242 
243  /* Check for a change condition in the current block.
244  * - iframes always change.
245  * - Luma plane changes on get_bits1 == 0
246  * - Chroma planes change on get_bits1 == 1 */
247  if(is_iframe || get_bits1(&ctx->gb) == is_chroma) {
248 
249  /* Luma planes may use a backreference from the 15 last
250  * frames preceding the previous. (get_bits1 == 1)
251  * Chroma planes don't use backreferences. */
252  if(is_chroma || is_iframe || !get_bits1(&ctx->gb)) {
253 
254  if(!vlc_decode_block(ctx, num_coeffs, qscale))
255  return 0;
256  ctx->dsp.idct_put(dst, stride, ctx->dct_block);
257  } else {
258  unsigned int backref = get_bits(&ctx->gb, 4);
259  int index = (ctx->cur_index+backref)&15;
260  uint8_t *p = ctx->flipped_ptrs[index].data[0];
261 
262  if (index != ctx->cur_index && p) {
263  ff_thread_await_progress(&ctx->buf_ptrs[index], cur_row, 0);
264  p += src -
265  ctx->flipped_ptrs[ctx->prev_index].data[plane];
266  ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8);
267  } else {
268  av_log(ctx->avctx, AV_LOG_ERROR,
269  "No such backreference! Buggy sample.\n");
270  }
271  }
272  } else {
273  ff_thread_await_progress(&ctx->buf_ptrs[ctx->prev_index], cur_row, 0);
274  ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
275  }
276  src += 8;
277  dst += 8;
278  }
279  src += (stride - ctx->num_hblocks[plane])<<3;
280  dst += (stride - ctx->num_hblocks[plane])<<3;
281 
282  ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], cur_row++, 0);
283  }
284  }
285 
286  return 1;
287 }
288 
293 static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVPicture *src)
294 {
295  int i;
296  dst->data[0] = src->data[0]+( ctx->avctx->height -1)*src->linesize[0];
297  dst->data[1] = src->data[2]+((ctx->avctx->height>>1)-1)*src->linesize[2];
298  dst->data[2] = src->data[1]+((ctx->avctx->height>>1)-1)*src->linesize[1];
299  for(i = 0; i < 3; i++)
300  dst->linesize[i] = -src->linesize[i];
301 }
302 
303 static int mimic_decode_frame(AVCodecContext *avctx, void *data,
304  int *data_size, AVPacket *avpkt)
305 {
306  const uint8_t *buf = avpkt->data;
307  int buf_size = avpkt->size;
308  MimicContext *ctx = avctx->priv_data;
309  int is_pframe;
310  int width, height;
311  int quality, num_coeffs;
312  int swap_buf_size = buf_size - MIMIC_HEADER_SIZE;
313  int res;
314 
315  if(buf_size < MIMIC_HEADER_SIZE) {
316  av_log(avctx, AV_LOG_ERROR, "insufficient data\n");
317  return -1;
318  }
319 
320  buf += 2; /* some constant (always 256) */
321  quality = bytestream_get_le16(&buf);
322  width = bytestream_get_le16(&buf);
323  height = bytestream_get_le16(&buf);
324  buf += 4; /* some constant */
325  is_pframe = bytestream_get_le32(&buf);
326  num_coeffs = bytestream_get_byte(&buf);
327  buf += 3; /* some constant */
328 
329  if(!ctx->avctx) {
330  int i;
331 
332  if(!(width == 160 && height == 120) &&
333  !(width == 320 && height == 240)) {
334  av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n");
335  return -1;
336  }
337 
338  ctx->avctx = avctx;
339  avctx->width = width;
340  avctx->height = height;
341  avctx->pix_fmt = PIX_FMT_YUV420P;
342  for(i = 0; i < 3; i++) {
343  ctx->num_vblocks[i] = -((-height) >> (3 + !!i));
344  ctx->num_hblocks[i] = width >> (3 + !!i) ;
345  }
346  } else if(width != ctx->avctx->width || height != ctx->avctx->height) {
347  av_log(avctx, AV_LOG_ERROR, "resolution changing is not supported\n");
348  return -1;
349  }
350 
351  if(is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) {
352  av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n");
353  return -1;
354  }
355 
356  ctx->buf_ptrs[ctx->cur_index].reference = 1;
358  if(ff_thread_get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index])) {
359  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
360  return -1;
361  }
362 
363  ctx->next_prev_index = ctx->cur_index;
364  ctx->next_cur_index = (ctx->cur_index - 1) & 15;
365 
366  prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
367  (AVPicture*) &ctx->buf_ptrs[ctx->cur_index]);
368 
369  ff_thread_finish_setup(avctx);
370 
372  swap_buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
373  if(!ctx->swap_buf)
374  return AVERROR(ENOMEM);
375 
376  ctx->dsp.bswap_buf(ctx->swap_buf,
377  (const uint32_t*) buf,
378  swap_buf_size>>2);
379  init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
380 
381  res = decode(ctx, quality, num_coeffs, !is_pframe);
382  ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], INT_MAX, 0);
383  if (!res) {
384  if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
385  ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
386  return -1;
387  }
388  }
389 
390  *(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index];
391  *data_size = sizeof(AVFrame);
392 
393  ctx->prev_index = ctx->next_prev_index;
394  ctx->cur_index = ctx->next_cur_index;
395 
396  /* Only release frames that aren't used for backreferences anymore */
397  if(ctx->buf_ptrs[ctx->cur_index].data[0])
398  ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
399 
400  return buf_size;
401 }
402 
404 {
405  MimicContext *ctx = avctx->priv_data;
406  int i;
407 
408  av_free(ctx->swap_buf);
409 
410  if (avctx->internal->is_copy)
411  return 0;
412 
413  for(i = 0; i < 16; i++)
414  if(ctx->buf_ptrs[i].data[0])
415  ff_thread_release_buffer(avctx, &ctx->buf_ptrs[i]);
416  ff_free_vlc(&ctx->vlc);
417 
418  return 0;
419 }
420 
422  .name = "mimic",
423  .type = AVMEDIA_TYPE_VIDEO,
424  .id = CODEC_ID_MIMIC,
425  .priv_data_size = sizeof(MimicContext),
429  .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
430  .long_name = NULL_IF_CONFIG_SMALL("Mimic"),
432 };