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