• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/mimic.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005  Ole André Vadla Ravnås <oleavr@gmail.com>
00003  * Copyright (C) 2008  Ramiro Polla <ramiro@lisha.ufsc.br>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <stdint.h>
00025 
00026 #include "avcodec.h"
00027 #include "bitstream.h"
00028 #include "bytestream.h"
00029 #include "dsputil.h"
00030 
00031 #define MIMIC_HEADER_SIZE   20
00032 
00033 typedef struct {
00034     AVCodecContext *avctx;
00035 
00036     int             num_vblocks[3];
00037     int             num_hblocks[3];
00038 
00039     uint8_t        *swap_buf;
00040     int             swap_buf_size;
00041 
00042     int             cur_index;
00043     int             prev_index;
00044 
00045     AVFrame         buf_ptrs    [16];
00046     AVPicture       flipped_ptrs[16];
00047 
00048     DECLARE_ALIGNED_16(DCTELEM, dct_block[64]);
00049 
00050     GetBitContext   gb;
00051     ScanTable       scantable;
00052     DSPContext      dsp;
00053     VLC             vlc;
00054 } MimicContext;
00055 
00056 static const uint32_t huffcodes[] = {
00057     0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
00058     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
00059     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b,
00060     0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9,
00061     0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb,
00062     0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb,
00063     0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9,
00064     0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000,
00065     0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9,
00066     0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb,
00067     0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8,
00068     0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb,
00069     0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9,
00070     0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8,
00071     0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa,
00072     0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000,
00073     0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb,
00074     0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9,
00075     0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9,
00076     0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb,
00077     0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9,
00078     0x3ffffffa,
00079 };
00080 
00081 static const uint8_t huffbits[] = {
00082      4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00083      0,  0,  0,  0,  2,  4,  5,  6,  7,  7,  7,  8,
00084      8, 10, 11, 11, 11, 11, 12, 12,  2,  6,  7,  8,
00085      9,  9, 12, 12, 13, 13, 13, 13, 14, 14, 14,  0,
00086      3,  6,  9, 14, 15, 15, 15, 15, 16, 16, 16, 16,
00087     17, 17, 17,  0,  4,  8,  9, 17, 18, 18, 18, 18,
00088     19, 19, 19, 19, 20, 20, 20,  0,  5, 10, 20, 21,
00089     21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,  0,
00090      6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26,
00091     26, 26, 27,  0, 10, 27, 27, 27, 28, 28, 28, 28,
00092     29, 29, 29, 29, 30, 30, 30,
00093 };
00094 
00095 static const uint8_t col_zag[64] = {
00096      0,  8,  1,  2,  9, 16, 24, 17,
00097     10,  3,  4, 11, 18, 25, 32, 40,
00098     33, 26, 19, 12,  5,  6, 13, 20,
00099     27, 34, 41, 48, 56, 49, 42, 35,
00100     28, 21, 14,  7, 15, 22, 29, 36,
00101     43, 50, 57, 58, 51, 44, 37, 30,
00102     23, 31, 38, 45, 52, 59, 39, 46,
00103     53, 60, 61, 54, 47, 55, 62, 63,
00104 };
00105 
00106 static av_cold int mimic_decode_init(AVCodecContext *avctx)
00107 {
00108     MimicContext *ctx = avctx->priv_data;
00109 
00110     ctx->prev_index = 0;
00111     ctx->cur_index = 15;
00112 
00113     if(init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits),
00114                  huffbits, 1, 1, huffcodes, 4, 4, 0)) {
00115         av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n");
00116         return -1;
00117     }
00118     dsputil_init(&ctx->dsp, avctx);
00119     ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag);
00120 
00121     return 0;
00122 }
00123 
00124 static const int8_t vlcdec_lookup[9][64] = {
00125     {    0, },
00126     {   -1,   1, },
00127     {   -3,   3,   -2,   2, },
00128     {   -7,   7,   -6,   6,   -5,   5,   -4,   4, },
00129     {  -15,  15,  -14,  14,  -13,  13,  -12,  12,
00130        -11,  11,  -10,  10,   -9,   9,   -8,   8, },
00131     {  -31,  31,  -30,  30,  -29,  29,  -28,  28,
00132        -27,  27,  -26,  26,  -25,  25,  -24,  24,
00133        -23,  23,  -22,  22,  -21,  21,  -20,  20,
00134        -19,  19,  -18,  18,  -17,  17,  -16,  16, },
00135     {  -63,  63,  -62,  62,  -61,  61,  -60,  60,
00136        -59,  59,  -58,  58,  -57,  57,  -56,  56,
00137        -55,  55,  -54,  54,  -53,  53,  -52,  52,
00138        -51,  51,  -50,  50,  -49,  49,  -48,  48,
00139        -47,  47,  -46,  46,  -45,  45,  -44,  44,
00140        -43,  43,  -42,  42,  -41,  41,  -40,  40,
00141        -39,  39,  -38,  38,  -37,  37,  -36,  36,
00142        -35,  35,  -34,  34,  -33,  33,  -32,  32, },
00143     { -127, 127, -126, 126, -125, 125, -124, 124,
00144       -123, 123, -122, 122, -121, 121, -120, 120,
00145       -119, 119, -118, 118, -117, 117, -116, 116,
00146       -115, 115, -114, 114, -113, 113, -112, 112,
00147       -111, 111, -110, 110, -109, 109, -108, 108,
00148       -107, 107, -106, 106, -105, 105, -104, 104,
00149       -103, 103, -102, 102, -101, 101, -100, 100,
00150        -99,  99,  -98,  98,  -97,  97,  -96,  96, },
00151     {  -95,  95,  -94,  94,  -93,  93,  -92,  92,
00152        -91,  91,  -90,  90,  -89,  89,  -88,  88,
00153        -87,  87,  -86,  86,  -85,  85,  -84,  84,
00154        -83,  83,  -82,  82,  -81,  81,  -80,  80,
00155        -79,  79,  -78,  78,  -77,  77,  -76,  76,
00156        -75,  75,  -74,  74,  -73,  73,  -72,  72,
00157        -71,  71,  -70,  70,  -69,  69,  -68,  68,
00158        -67,  67,  -66,  66,  -65,  65,  -64,  64, },
00159 };
00160 
00161 static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale)
00162 {
00163     DCTELEM *block = ctx->dct_block;
00164     unsigned int pos;
00165 
00166     ctx->dsp.clear_block(block);
00167 
00168     block[0] = get_bits(&ctx->gb, 8) << 3;
00169 
00170     for(pos = 1; pos < num_coeffs; pos++) {
00171         uint32_t vlc, num_bits;
00172         int value;
00173         int coeff;
00174 
00175         vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3);
00176         if(!vlc) /* end-of-block code */
00177             return 1;
00178         if(vlc == -1)
00179             return 0;
00180 
00181         /* pos_add and num_bits are coded in the vlc code */
00182         pos +=     vlc&15; // pos_add
00183         num_bits = vlc>>4; // num_bits
00184 
00185         if(pos >= 64)
00186             return 0;
00187 
00188         value = get_bits(&ctx->gb, num_bits);
00189 
00190         /* FFmpeg's IDCT behaves somewhat different from the original code, so
00191          * a factor of 4 was added to the input */
00192 
00193         coeff = vlcdec_lookup[num_bits][value];
00194         if(pos<3)
00195             coeff <<= 4;
00196         else /* TODO Use >> 10 instead of / 1001 */
00197             coeff = (coeff * qscale) / 1001;
00198 
00199         block[ctx->scantable.permutated[pos]] = coeff;
00200     }
00201 
00202     return 1;
00203 }
00204 
00205 static int decode(MimicContext *ctx, int quality, int num_coeffs,
00206                   int is_iframe)
00207 {
00208     int y, x, plane;
00209 
00210     for(plane = 0; plane < 3; plane++) {
00211         const int is_chroma = !!plane;
00212         const int qscale = av_clip(10000-quality,is_chroma?1000:2000,10000)<<2;
00213         const int stride = ctx->flipped_ptrs[ctx->cur_index].linesize[plane];
00214         const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane];
00215         uint8_t       *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane];
00216 
00217         for(y = 0; y < ctx->num_vblocks[plane]; y++) {
00218             for(x = 0; x < ctx->num_hblocks[plane]; x++) {
00219 
00220                 /* Check for a change condition in the current block.
00221                  * - iframes always change.
00222                  * - Luma plane changes on get_bits1 == 0
00223                  * - Chroma planes change on get_bits1 == 1 */
00224                 if(is_iframe || get_bits1(&ctx->gb) == is_chroma) {
00225 
00226                     /* Luma planes may use a backreference from the 15 last
00227                      * frames preceding the previous. (get_bits1 == 1)
00228                      * Chroma planes don't use backreferences. */
00229                     if(is_chroma || is_iframe || !get_bits1(&ctx->gb)) {
00230 
00231                         if(!vlc_decode_block(ctx, num_coeffs, qscale))
00232                             return 0;
00233                         ctx->dsp.idct_put(dst, stride, ctx->dct_block);
00234                     } else {
00235                         unsigned int backref = get_bits(&ctx->gb, 4);
00236                         int index = (ctx->cur_index+backref)&15;
00237                         uint8_t *p = ctx->flipped_ptrs[index].data[0];
00238 
00239                         if(p) {
00240                             p += src -
00241                                 ctx->flipped_ptrs[ctx->prev_index].data[plane];
00242                             ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8);
00243                         } else {
00244                             av_log(ctx->avctx, AV_LOG_ERROR,
00245                                      "No such backreference! Buggy sample.\n");
00246                         }
00247                     }
00248                 } else {
00249                     ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
00250                 }
00251                 src += 8;
00252                 dst += 8;
00253             }
00254             src += (stride - ctx->num_hblocks[plane])<<3;
00255             dst += (stride - ctx->num_hblocks[plane])<<3;
00256         }
00257     }
00258 
00259     return 1;
00260 }
00261 
00266 static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVPicture *src)
00267 {
00268     int i;
00269     dst->data[0] = src->data[0]+( ctx->avctx->height    -1)*src->linesize[0];
00270     dst->data[1] = src->data[2]+((ctx->avctx->height>>1)-1)*src->linesize[2];
00271     dst->data[2] = src->data[1]+((ctx->avctx->height>>1)-1)*src->linesize[1];
00272     for(i = 0; i < 3; i++)
00273         dst->linesize[i] = -src->linesize[i];
00274 }
00275 
00276 static int mimic_decode_frame(AVCodecContext *avctx, void *data,
00277                               int *data_size, const uint8_t *buf, int buf_size)
00278 {
00279     MimicContext *ctx = avctx->priv_data;
00280     int is_pframe;
00281     int width, height;
00282     int quality, num_coeffs;
00283     int swap_buf_size = buf_size - MIMIC_HEADER_SIZE;
00284 
00285     if(buf_size < MIMIC_HEADER_SIZE) {
00286         av_log(avctx, AV_LOG_ERROR, "insufficient data\n");
00287         return -1;
00288     }
00289 
00290     buf       += 2; /* some constant (always 256) */
00291     quality    = bytestream_get_le16(&buf);
00292     width      = bytestream_get_le16(&buf);
00293     height     = bytestream_get_le16(&buf);
00294     buf       += 4; /* some constant */
00295     is_pframe  = bytestream_get_le32(&buf);
00296     num_coeffs = bytestream_get_byte(&buf);
00297     buf       += 3; /* some constant */
00298 
00299     if(!ctx->avctx) {
00300         int i;
00301 
00302         if(!(width == 160 && height == 120) &&
00303            !(width == 320 && height == 240)) {
00304             av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n");
00305             return -1;
00306         }
00307 
00308         ctx->avctx     = avctx;
00309         avctx->width   = width;
00310         avctx->height  = height;
00311         avctx->pix_fmt = PIX_FMT_YUV420P;
00312         for(i = 0; i < 3; i++) {
00313             ctx->num_vblocks[i] = -((-height) >> (3 + !!i));
00314             ctx->num_hblocks[i] =     width   >> (3 + !!i) ;
00315         }
00316     } else if(width != ctx->avctx->width || height != ctx->avctx->height) {
00317         av_log(avctx, AV_LOG_ERROR, "resolution changing is not supported\n");
00318         return -1;
00319     }
00320 
00321     if(is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) {
00322         av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n");
00323         return -1;
00324     }
00325 
00326     ctx->buf_ptrs[ctx->cur_index].reference = 1;
00327     if(avctx->get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index])) {
00328         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00329         return -1;
00330     }
00331 
00332     prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
00333                   (AVPicture*) &ctx->buf_ptrs[ctx->cur_index]);
00334 
00335     ctx->swap_buf = av_fast_realloc(ctx->swap_buf, &ctx->swap_buf_size,
00336                                  swap_buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
00337     if(!ctx->swap_buf)
00338         return AVERROR_NOMEM;
00339 
00340     ctx->dsp.bswap_buf((uint32_t*)ctx->swap_buf,
00341                         (const uint32_t*) buf,
00342                         swap_buf_size>>2);
00343     init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
00344 
00345     if(!decode(ctx, quality, num_coeffs, !is_pframe)) {
00346         avctx->release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
00347         return -1;
00348     }
00349 
00350     ctx->buf_ptrs[ctx->cur_index].pict_type = is_pframe ? FF_P_TYPE:FF_I_TYPE;
00351     *(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index];
00352     *data_size = sizeof(AVFrame);
00353 
00354     ctx->prev_index = ctx->cur_index;
00355     ctx->cur_index--;
00356     ctx->cur_index &= 15;
00357 
00358     /* Only release frames that aren't used for backreferences anymore */
00359     if(ctx->buf_ptrs[ctx->cur_index].data[0])
00360         avctx->release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
00361 
00362     return buf_size;
00363 }
00364 
00365 static av_cold int mimic_decode_end(AVCodecContext *avctx)
00366 {
00367     MimicContext *ctx = avctx->priv_data;
00368     int i;
00369 
00370     av_free(ctx->swap_buf);
00371     for(i = 0; i < 16; i++)
00372         if(ctx->buf_ptrs[i].data[0])
00373             avctx->release_buffer(avctx, &ctx->buf_ptrs[i]);
00374     free_vlc(&ctx->vlc);
00375 
00376     return 0;
00377 }
00378 
00379 AVCodec mimic_decoder = {
00380     "mimic",
00381     CODEC_TYPE_VIDEO,
00382     CODEC_ID_MIMIC,
00383     sizeof(MimicContext),
00384     mimic_decode_init,
00385     NULL,
00386     mimic_decode_end,
00387     mimic_decode_frame,
00388     CODEC_CAP_DR1,
00389     .long_name = NULL_IF_CONFIG_SMALL("Mimic"),
00390 };

Generated on Sat Feb 16 2013 09:23:12 for ffmpeg by  doxygen 1.7.1