Libav 0.7.1
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
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav 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  * Libav 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 Libav; 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 "get_bits.h"
00028 #include "bytestream.h"
00029 #include "dsputil.h"
00030 #include "thread.h"
00031 
00032 #define MIMIC_HEADER_SIZE   20
00033 
00034 typedef struct {
00035     AVCodecContext *avctx;
00036 
00037     int             num_vblocks[3];
00038     int             num_hblocks[3];
00039 
00040     void           *swap_buf;
00041     int             swap_buf_size;
00042 
00043     int             cur_index;
00044     int             prev_index;
00045 
00046     AVFrame         buf_ptrs    [16];
00047     AVPicture       flipped_ptrs[16];
00048 
00049     DECLARE_ALIGNED(16, DCTELEM, dct_block)[64];
00050 
00051     GetBitContext   gb;
00052     ScanTable       scantable;
00053     DSPContext      dsp;
00054     VLC             vlc;
00055 
00056     /* Kept in the context so multithreading can have a constant to read from */
00057     int             next_cur_index;
00058     int             next_prev_index;
00059 } MimicContext;
00060 
00061 static const uint32_t huffcodes[] = {
00062     0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
00063     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
00064     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b,
00065     0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9,
00066     0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb,
00067     0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb,
00068     0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9,
00069     0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000,
00070     0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9,
00071     0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb,
00072     0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8,
00073     0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb,
00074     0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9,
00075     0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8,
00076     0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa,
00077     0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000,
00078     0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb,
00079     0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9,
00080     0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9,
00081     0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb,
00082     0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9,
00083     0x3ffffffa,
00084 };
00085 
00086 static const uint8_t huffbits[] = {
00087      4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00088      0,  0,  0,  0,  2,  4,  5,  6,  7,  7,  7,  8,
00089      8, 10, 11, 11, 11, 11, 12, 12,  2,  6,  7,  8,
00090      9,  9, 12, 12, 13, 13, 13, 13, 14, 14, 14,  0,
00091      3,  6,  9, 14, 15, 15, 15, 15, 16, 16, 16, 16,
00092     17, 17, 17,  0,  4,  8,  9, 17, 18, 18, 18, 18,
00093     19, 19, 19, 19, 20, 20, 20,  0,  5, 10, 20, 21,
00094     21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,  0,
00095      6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26,
00096     26, 26, 27,  0, 10, 27, 27, 27, 28, 28, 28, 28,
00097     29, 29, 29, 29, 30, 30, 30,
00098 };
00099 
00100 static const uint8_t col_zag[64] = {
00101      0,  8,  1,  2,  9, 16, 24, 17,
00102     10,  3,  4, 11, 18, 25, 32, 40,
00103     33, 26, 19, 12,  5,  6, 13, 20,
00104     27, 34, 41, 48, 56, 49, 42, 35,
00105     28, 21, 14,  7, 15, 22, 29, 36,
00106     43, 50, 57, 58, 51, 44, 37, 30,
00107     23, 31, 38, 45, 52, 59, 39, 46,
00108     53, 60, 61, 54, 47, 55, 62, 63,
00109 };
00110 
00111 static av_cold int mimic_decode_init(AVCodecContext *avctx)
00112 {
00113     MimicContext *ctx = avctx->priv_data;
00114 
00115     ctx->prev_index = 0;
00116     ctx->cur_index = 15;
00117 
00118     if(init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits),
00119                  huffbits, 1, 1, huffcodes, 4, 4, 0)) {
00120         av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n");
00121         return -1;
00122     }
00123     dsputil_init(&ctx->dsp, avctx);
00124     ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag);
00125 
00126     return 0;
00127 }
00128 
00129 static int mimic_decode_update_thread_context(AVCodecContext *avctx, const AVCodecContext *avctx_from)
00130 {
00131     MimicContext *dst = avctx->priv_data, *src = avctx_from->priv_data;
00132 
00133     if (avctx == avctx_from) return 0;
00134 
00135     dst->cur_index  = src->next_cur_index;
00136     dst->prev_index = src->next_prev_index;
00137 
00138     memcpy(dst->buf_ptrs, src->buf_ptrs, sizeof(src->buf_ptrs));
00139     memcpy(dst->flipped_ptrs, src->flipped_ptrs, sizeof(src->flipped_ptrs));
00140 
00141     memset(&dst->buf_ptrs[dst->cur_index], 0, sizeof(AVFrame));
00142 
00143     return 0;
00144 }
00145 
00146 static const int8_t vlcdec_lookup[9][64] = {
00147     {    0, },
00148     {   -1,   1, },
00149     {   -3,   3,   -2,   2, },
00150     {   -7,   7,   -6,   6,   -5,   5,   -4,   4, },
00151     {  -15,  15,  -14,  14,  -13,  13,  -12,  12,
00152        -11,  11,  -10,  10,   -9,   9,   -8,   8, },
00153     {  -31,  31,  -30,  30,  -29,  29,  -28,  28,
00154        -27,  27,  -26,  26,  -25,  25,  -24,  24,
00155        -23,  23,  -22,  22,  -21,  21,  -20,  20,
00156        -19,  19,  -18,  18,  -17,  17,  -16,  16, },
00157     {  -63,  63,  -62,  62,  -61,  61,  -60,  60,
00158        -59,  59,  -58,  58,  -57,  57,  -56,  56,
00159        -55,  55,  -54,  54,  -53,  53,  -52,  52,
00160        -51,  51,  -50,  50,  -49,  49,  -48,  48,
00161        -47,  47,  -46,  46,  -45,  45,  -44,  44,
00162        -43,  43,  -42,  42,  -41,  41,  -40,  40,
00163        -39,  39,  -38,  38,  -37,  37,  -36,  36,
00164        -35,  35,  -34,  34,  -33,  33,  -32,  32, },
00165     { -127, 127, -126, 126, -125, 125, -124, 124,
00166       -123, 123, -122, 122, -121, 121, -120, 120,
00167       -119, 119, -118, 118, -117, 117, -116, 116,
00168       -115, 115, -114, 114, -113, 113, -112, 112,
00169       -111, 111, -110, 110, -109, 109, -108, 108,
00170       -107, 107, -106, 106, -105, 105, -104, 104,
00171       -103, 103, -102, 102, -101, 101, -100, 100,
00172        -99,  99,  -98,  98,  -97,  97,  -96,  96, },
00173     {  -95,  95,  -94,  94,  -93,  93,  -92,  92,
00174        -91,  91,  -90,  90,  -89,  89,  -88,  88,
00175        -87,  87,  -86,  86,  -85,  85,  -84,  84,
00176        -83,  83,  -82,  82,  -81,  81,  -80,  80,
00177        -79,  79,  -78,  78,  -77,  77,  -76,  76,
00178        -75,  75,  -74,  74,  -73,  73,  -72,  72,
00179        -71,  71,  -70,  70,  -69,  69,  -68,  68,
00180        -67,  67,  -66,  66,  -65,  65,  -64,  64, },
00181 };
00182 
00183 static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale)
00184 {
00185     DCTELEM *block = ctx->dct_block;
00186     unsigned int pos;
00187 
00188     ctx->dsp.clear_block(block);
00189 
00190     block[0] = get_bits(&ctx->gb, 8) << 3;
00191 
00192     for(pos = 1; pos < num_coeffs; pos++) {
00193         uint32_t vlc, num_bits;
00194         int value;
00195         int coeff;
00196 
00197         vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3);
00198         if(!vlc) /* end-of-block code */
00199             return 1;
00200         if(vlc == -1)
00201             return 0;
00202 
00203         /* pos_add and num_bits are coded in the vlc code */
00204         pos +=     vlc&15; // pos_add
00205         num_bits = vlc>>4; // num_bits
00206 
00207         if(pos >= 64)
00208             return 0;
00209 
00210         value = get_bits(&ctx->gb, num_bits);
00211 
00212         /* Libav's IDCT behaves somewhat different from the original code, so
00213          * a factor of 4 was added to the input */
00214 
00215         coeff = vlcdec_lookup[num_bits][value];
00216         if(pos<3)
00217             coeff <<= 4;
00218         else /* TODO Use >> 10 instead of / 1001 */
00219             coeff = (coeff * qscale) / 1001;
00220 
00221         block[ctx->scantable.permutated[pos]] = coeff;
00222     }
00223 
00224     return 1;
00225 }
00226 
00227 static int decode(MimicContext *ctx, int quality, int num_coeffs,
00228                   int is_iframe)
00229 {
00230     int y, x, plane, cur_row = 0;
00231 
00232     for(plane = 0; plane < 3; plane++) {
00233         const int is_chroma = !!plane;
00234         const int qscale = av_clip(10000-quality,is_chroma?1000:2000,10000)<<2;
00235         const int stride = ctx->flipped_ptrs[ctx->cur_index].linesize[plane];
00236         const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane];
00237         uint8_t       *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane];
00238 
00239         for(y = 0; y < ctx->num_vblocks[plane]; y++) {
00240             for(x = 0; x < ctx->num_hblocks[plane]; x++) {
00241 
00242                 /* Check for a change condition in the current block.
00243                  * - iframes always change.
00244                  * - Luma plane changes on get_bits1 == 0
00245                  * - Chroma planes change on get_bits1 == 1 */
00246                 if(is_iframe || get_bits1(&ctx->gb) == is_chroma) {
00247 
00248                     /* Luma planes may use a backreference from the 15 last
00249                      * frames preceding the previous. (get_bits1 == 1)
00250                      * Chroma planes don't use backreferences. */
00251                     if(is_chroma || is_iframe || !get_bits1(&ctx->gb)) {
00252 
00253                         if(!vlc_decode_block(ctx, num_coeffs, qscale))
00254                             return 0;
00255                         ctx->dsp.idct_put(dst, stride, ctx->dct_block);
00256                     } else {
00257                         unsigned int backref = get_bits(&ctx->gb, 4);
00258                         int index = (ctx->cur_index+backref)&15;
00259                         uint8_t *p = ctx->flipped_ptrs[index].data[0];
00260 
00261                         ff_thread_await_progress(&ctx->buf_ptrs[index], cur_row, 0);
00262                         if(p) {
00263                             p += src -
00264                                 ctx->flipped_ptrs[ctx->prev_index].data[plane];
00265                             ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8);
00266                         } else {
00267                             av_log(ctx->avctx, AV_LOG_ERROR,
00268                                      "No such backreference! Buggy sample.\n");
00269                         }
00270                     }
00271                 } else {
00272                     ff_thread_await_progress(&ctx->buf_ptrs[ctx->prev_index], cur_row, 0);
00273                     ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
00274                 }
00275                 src += 8;
00276                 dst += 8;
00277             }
00278             src += (stride - ctx->num_hblocks[plane])<<3;
00279             dst += (stride - ctx->num_hblocks[plane])<<3;
00280 
00281             ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], cur_row++, 0);
00282         }
00283     }
00284 
00285     return 1;
00286 }
00287 
00292 static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVPicture *src)
00293 {
00294     int i;
00295     dst->data[0] = src->data[0]+( ctx->avctx->height    -1)*src->linesize[0];
00296     dst->data[1] = src->data[2]+((ctx->avctx->height>>1)-1)*src->linesize[2];
00297     dst->data[2] = src->data[1]+((ctx->avctx->height>>1)-1)*src->linesize[1];
00298     for(i = 0; i < 3; i++)
00299         dst->linesize[i] = -src->linesize[i];
00300 }
00301 
00302 static int mimic_decode_frame(AVCodecContext *avctx, void *data,
00303                               int *data_size, AVPacket *avpkt)
00304 {
00305     const uint8_t *buf = avpkt->data;
00306     int buf_size = avpkt->size;
00307     MimicContext *ctx = avctx->priv_data;
00308     int is_pframe;
00309     int width, height;
00310     int quality, num_coeffs;
00311     int swap_buf_size = buf_size - MIMIC_HEADER_SIZE;
00312 
00313     if(buf_size < MIMIC_HEADER_SIZE) {
00314         av_log(avctx, AV_LOG_ERROR, "insufficient data\n");
00315         return -1;
00316     }
00317 
00318     buf       += 2; /* some constant (always 256) */
00319     quality    = bytestream_get_le16(&buf);
00320     width      = bytestream_get_le16(&buf);
00321     height     = bytestream_get_le16(&buf);
00322     buf       += 4; /* some constant */
00323     is_pframe  = bytestream_get_le32(&buf);
00324     num_coeffs = bytestream_get_byte(&buf);
00325     buf       += 3; /* some constant */
00326 
00327     if(!ctx->avctx) {
00328         int i;
00329 
00330         if(!(width == 160 && height == 120) &&
00331            !(width == 320 && height == 240)) {
00332             av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n");
00333             return -1;
00334         }
00335 
00336         ctx->avctx     = avctx;
00337         avctx->width   = width;
00338         avctx->height  = height;
00339         avctx->pix_fmt = PIX_FMT_YUV420P;
00340         for(i = 0; i < 3; i++) {
00341             ctx->num_vblocks[i] = -((-height) >> (3 + !!i));
00342             ctx->num_hblocks[i] =     width   >> (3 + !!i) ;
00343         }
00344     } else if(width != ctx->avctx->width || height != ctx->avctx->height) {
00345         av_log(avctx, AV_LOG_ERROR, "resolution changing is not supported\n");
00346         return -1;
00347     }
00348 
00349     if(is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) {
00350         av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n");
00351         return -1;
00352     }
00353 
00354     ctx->buf_ptrs[ctx->cur_index].reference = 1;
00355     ctx->buf_ptrs[ctx->cur_index].pict_type = is_pframe ? AV_PICTURE_TYPE_P:AV_PICTURE_TYPE_I;
00356     if(ff_thread_get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index])) {
00357         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00358         return -1;
00359     }
00360 
00361     ctx->next_prev_index = ctx->cur_index;
00362     ctx->next_cur_index  = (ctx->cur_index - 1) & 15;
00363 
00364     prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
00365                   (AVPicture*) &ctx->buf_ptrs[ctx->cur_index]);
00366 
00367     ff_thread_finish_setup(avctx);
00368 
00369     av_fast_malloc(&ctx->swap_buf, &ctx->swap_buf_size,
00370                                  swap_buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
00371     if(!ctx->swap_buf)
00372         return AVERROR(ENOMEM);
00373 
00374     ctx->dsp.bswap_buf(ctx->swap_buf,
00375                         (const uint32_t*) buf,
00376                         swap_buf_size>>2);
00377     init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
00378 
00379     if(!decode(ctx, quality, num_coeffs, !is_pframe)) {
00380         if (avctx->active_thread_type&FF_THREAD_FRAME)
00381             ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], INT_MAX, 0);
00382         else {
00383             ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
00384             return -1;
00385         }
00386     }
00387 
00388     *(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index];
00389     *data_size = sizeof(AVFrame);
00390 
00391     ctx->prev_index = ctx->next_prev_index;
00392     ctx->cur_index  = ctx->next_cur_index;
00393 
00394     /* Only release frames that aren't used for backreferences anymore */
00395     if(ctx->buf_ptrs[ctx->cur_index].data[0])
00396         ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
00397 
00398     return buf_size;
00399 }
00400 
00401 static av_cold int mimic_decode_end(AVCodecContext *avctx)
00402 {
00403     MimicContext *ctx = avctx->priv_data;
00404     int i;
00405 
00406     av_free(ctx->swap_buf);
00407 
00408     if(avctx->is_copy) return 0;
00409 
00410     for(i = 0; i < 16; i++)
00411         if(ctx->buf_ptrs[i].data[0])
00412             ff_thread_release_buffer(avctx, &ctx->buf_ptrs[i]);
00413     free_vlc(&ctx->vlc);
00414 
00415     return 0;
00416 }
00417 
00418 AVCodec ff_mimic_decoder = {
00419     "mimic",
00420     AVMEDIA_TYPE_VIDEO,
00421     CODEC_ID_MIMIC,
00422     sizeof(MimicContext),
00423     mimic_decode_init,
00424     NULL,
00425     mimic_decode_end,
00426     mimic_decode_frame,
00427     CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
00428     .long_name = NULL_IF_CONFIG_SMALL("Mimic"),
00429     .update_thread_context = ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context)
00430 };