FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 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 <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, int16_t, 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  int ret;
116 
117  ctx->prev_index = 0;
118  ctx->cur_index = 15;
119 
120  if ((ret = init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits),
121  huffbits, 1, 1, huffcodes, 4, 4, 0)) < 0) {
122  av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n");
123  return ret;
124  }
125  ff_dsputil_init(&ctx->dsp, avctx);
127 
128  return 0;
129 }
130 
132 {
133  MimicContext *dst = avctx->priv_data, *src = avctx_from->priv_data;
134 
135  if (avctx == avctx_from)
136  return 0;
137 
138  dst->cur_index = src->next_cur_index;
139  dst->prev_index = src->next_prev_index;
140 
141  memcpy(dst->buf_ptrs, src->buf_ptrs, sizeof(src->buf_ptrs));
142  memcpy(dst->flipped_ptrs, src->flipped_ptrs, sizeof(src->flipped_ptrs));
143 
144  memset(&dst->buf_ptrs[dst->cur_index], 0, sizeof(AVFrame));
145 
146  return 0;
147 }
148 
149 static const int8_t vlcdec_lookup[9][64] = {
150  { 0, },
151  { -1, 1, },
152  { -3, 3, -2, 2, },
153  { -7, 7, -6, 6, -5, 5, -4, 4, },
154  { -15, 15, -14, 14, -13, 13, -12, 12,
155  -11, 11, -10, 10, -9, 9, -8, 8, },
156  { -31, 31, -30, 30, -29, 29, -28, 28,
157  -27, 27, -26, 26, -25, 25, -24, 24,
158  -23, 23, -22, 22, -21, 21, -20, 20,
159  -19, 19, -18, 18, -17, 17, -16, 16, },
160  { -63, 63, -62, 62, -61, 61, -60, 60,
161  -59, 59, -58, 58, -57, 57, -56, 56,
162  -55, 55, -54, 54, -53, 53, -52, 52,
163  -51, 51, -50, 50, -49, 49, -48, 48,
164  -47, 47, -46, 46, -45, 45, -44, 44,
165  -43, 43, -42, 42, -41, 41, -40, 40,
166  -39, 39, -38, 38, -37, 37, -36, 36,
167  -35, 35, -34, 34, -33, 33, -32, 32, },
168  { -127, 127, -126, 126, -125, 125, -124, 124,
169  -123, 123, -122, 122, -121, 121, -120, 120,
170  -119, 119, -118, 118, -117, 117, -116, 116,
171  -115, 115, -114, 114, -113, 113, -112, 112,
172  -111, 111, -110, 110, -109, 109, -108, 108,
173  -107, 107, -106, 106, -105, 105, -104, 104,
174  -103, 103, -102, 102, -101, 101, -100, 100,
175  -99, 99, -98, 98, -97, 97, -96, 96, },
176  { -95, 95, -94, 94, -93, 93, -92, 92,
177  -91, 91, -90, 90, -89, 89, -88, 88,
178  -87, 87, -86, 86, -85, 85, -84, 84,
179  -83, 83, -82, 82, -81, 81, -80, 80,
180  -79, 79, -78, 78, -77, 77, -76, 76,
181  -75, 75, -74, 74, -73, 73, -72, 72,
182  -71, 71, -70, 70, -69, 69, -68, 68,
183  -67, 67, -66, 66, -65, 65, -64, 64, },
184 };
185 
186 static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale)
187 {
188  int16_t *block = ctx->dct_block;
189  unsigned int pos;
190 
191  ctx->dsp.clear_block(block);
192 
193  block[0] = get_bits(&ctx->gb, 8) << 3;
194 
195  for (pos = 1; pos < num_coeffs; pos++) {
196  uint32_t vlc, num_bits;
197  int value;
198  int coeff;
199 
200  vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3);
201  if (!vlc) /* end-of-block code */
202  return 0;
203  if (vlc == -1)
204  return AVERROR_INVALIDDATA;
205 
206  /* pos_add and num_bits are coded in the vlc code */
207  pos += vlc & 15; // pos_add
208  num_bits = vlc >> 4; // num_bits
209 
210  if (pos >= 64)
211  return AVERROR_INVALIDDATA;
212 
213  value = get_bits(&ctx->gb, num_bits);
214 
215  /* FFmpeg's IDCT behaves somewhat different from the original code, so
216  * a factor of 4 was added to the input */
217 
218  coeff = vlcdec_lookup[num_bits][value];
219  if (pos < 3)
220  coeff <<= 4;
221  else /* TODO Use >> 10 instead of / 1001 */
222  coeff = (coeff * qscale) / 1001;
223 
224  block[ctx->scantable.permutated[pos]] = coeff;
225  }
226 
227  return 0;
228 }
229 
230 static int decode(MimicContext *ctx, int quality, int num_coeffs,
231  int is_iframe)
232 {
233  int ret, y, x, plane, cur_row = 0;
234 
235  for (plane = 0; plane < 3; plane++) {
236  const int is_chroma = !!plane;
237  const int qscale = av_clip(10000 - quality, is_chroma ? 1000 : 2000,
238  10000) << 2;
239  const int stride = ctx->flipped_ptrs[ctx->cur_index ].linesize[plane];
240  const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane];
241  uint8_t *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane];
242 
243  for (y = 0; y < ctx->num_vblocks[plane]; y++) {
244  for (x = 0; x < ctx->num_hblocks[plane]; x++) {
245  /* Check for a change condition in the current block.
246  * - iframes always change.
247  * - Luma plane changes on get_bits1 == 0
248  * - Chroma planes change on get_bits1 == 1 */
249  if (is_iframe || get_bits1(&ctx->gb) == is_chroma) {
250  /* Luma planes may use a backreference from the 15 last
251  * frames preceding the previous. (get_bits1 == 1)
252  * Chroma planes don't use backreferences. */
253  if (is_chroma || is_iframe || !get_bits1(&ctx->gb)) {
254  if ((ret = vlc_decode_block(ctx, num_coeffs,
255  qscale)) < 0) {
256  av_log(ctx->avctx, AV_LOG_ERROR, "Error decoding "
257  "block.\n");
258  return ret;
259  }
260  ctx->dsp.idct_put(dst, stride, ctx->dct_block);
261  } else {
262  unsigned int backref = get_bits(&ctx->gb, 4);
263  int index = (ctx->cur_index + backref) & 15;
264  uint8_t *p = ctx->flipped_ptrs[index].data[0];
265 
266  if (index != ctx->cur_index && p) {
267  ff_thread_await_progress(&ctx->buf_ptrs[index],
268  cur_row, 0);
269  p += src -
270  ctx->flipped_ptrs[ctx->prev_index].data[plane];
271  ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8);
272  } else {
273  av_log(ctx->avctx, AV_LOG_ERROR,
274  "No such backreference! Buggy sample.\n");
275  }
276  }
277  } else {
279  cur_row, 0);
280  ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
281  }
282  src += 8;
283  dst += 8;
284  }
285  src += (stride - ctx->num_hblocks[plane]) << 3;
286  dst += (stride - ctx->num_hblocks[plane]) << 3;
287 
289  cur_row++, 0);
290  }
291  }
292 
293  return 0;
294 }
295 
296 /**
297  * Flip the buffer upside-down and put it in the YVU order to match the
298  * way Mimic encodes frames.
299  */
300 static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVFrame *src)
301 {
302  int i;
303  dst->data[0] = src->data[0] + ( ctx->avctx->height - 1) * src->linesize[0];
304  dst->data[1] = src->data[2] + ((ctx->avctx->height >> 1) - 1) * src->linesize[2];
305  dst->data[2] = src->data[1] + ((ctx->avctx->height >> 1) - 1) * src->linesize[1];
306  for (i = 0; i < 3; i++)
307  dst->linesize[i] = -src->linesize[i];
308 }
309 
310 static int mimic_decode_frame(AVCodecContext *avctx, void *data,
311  int *got_frame, AVPacket *avpkt)
312 {
313  const uint8_t *buf = avpkt->data;
314  int buf_size = avpkt->size;
315  int swap_buf_size = buf_size - MIMIC_HEADER_SIZE;
316  MimicContext *ctx = avctx->priv_data;
317  GetByteContext gb;
318  int is_pframe;
319  int width, height;
320  int quality, num_coeffs;
321  int res;
322 
323  if (buf_size <= MIMIC_HEADER_SIZE) {
324  av_log(avctx, AV_LOG_ERROR, "insufficient data\n");
325  return AVERROR_INVALIDDATA;
326  }
327 
328  bytestream2_init(&gb, buf, MIMIC_HEADER_SIZE);
329  bytestream2_skip(&gb, 2); /* some constant (always 256) */
330  quality = bytestream2_get_le16u(&gb);
331  width = bytestream2_get_le16u(&gb);
332  height = bytestream2_get_le16u(&gb);
333  bytestream2_skip(&gb, 4); /* some constant */
334  is_pframe = bytestream2_get_le32u(&gb);
335  num_coeffs = bytestream2_get_byteu(&gb);
336  bytestream2_skip(&gb, 3); /* some constant */
337 
338  if (!ctx->avctx) {
339  int i;
340 
341  if (!(width == 160 && height == 120) &&
342  !(width == 320 && height == 240)) {
343  av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n");
344  return AVERROR_INVALIDDATA;
345  }
346 
347  ctx->avctx = avctx;
348  avctx->width = width;
349  avctx->height = height;
350  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
351  for (i = 0; i < 3; i++) {
352  ctx->num_vblocks[i] = -((-height) >> (3 + !!i));
353  ctx->num_hblocks[i] = width >> (3 + !!i);
354  }
355  } else if (width != ctx->avctx->width || height != ctx->avctx->height) {
356  av_log_missing_feature(avctx, "resolution changing", 1);
357  return AVERROR_PATCHWELCOME;
358  }
359 
360  if (is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) {
361  av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n");
362  return AVERROR_INVALIDDATA;
363  }
364 
365  ctx->buf_ptrs[ctx->cur_index].reference = 3;
366  ctx->buf_ptrs[ctx->cur_index].pict_type = is_pframe ? AV_PICTURE_TYPE_P :
368  if ((res = ff_thread_get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index])) < 0) {
369  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
370  return res;
371  }
372 
373  ctx->next_prev_index = ctx->cur_index;
374  ctx->next_cur_index = (ctx->cur_index - 1) & 15;
375 
376  prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
377  &ctx->buf_ptrs[ctx->cur_index]);
378 
379  ff_thread_finish_setup(avctx);
380 
381  av_fast_padded_malloc(&ctx->swap_buf, &ctx->swap_buf_size, swap_buf_size);
382  if (!ctx->swap_buf)
383  return AVERROR(ENOMEM);
384 
385  ctx->dsp.bswap_buf(ctx->swap_buf,
386  (const uint32_t*) (buf + MIMIC_HEADER_SIZE),
387  swap_buf_size >> 2);
388  init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
389 
390  res = decode(ctx, quality, num_coeffs, !is_pframe);
391  ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], INT_MAX, 0);
392  if (res < 0) {
393  if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
394  ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
395  return res;
396  }
397  }
398 
399  *(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index];
400  *got_frame = 1;
401 
402  ctx->prev_index = ctx->next_prev_index;
403  ctx->cur_index = ctx->next_cur_index;
404 
405  /* Only release frames that aren't used for backreferences anymore */
406  if (ctx->buf_ptrs[ctx->cur_index].data[0])
407  ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
408 
409  return buf_size;
410 }
411 
413 {
414  MimicContext *ctx = avctx->priv_data;
415  int i;
416 
417  av_free(ctx->swap_buf);
418 
419  if (avctx->internal->is_copy)
420  return 0;
421 
422  for (i = 0; i < 16; i++)
423  if (ctx->buf_ptrs[i].data[0])
424  ff_thread_release_buffer(avctx, &ctx->buf_ptrs[i]);
425  ff_free_vlc(&ctx->vlc);
426 
427  return 0;
428 }
429 
431  .name = "mimic",
432  .type = AVMEDIA_TYPE_VIDEO,
433  .id = AV_CODEC_ID_MIMIC,
434  .priv_data_size = sizeof(MimicContext),
438  .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
439  .long_name = NULL_IF_CONFIG_SMALL("Mimic"),
441 };