Libav 0.7.1
libavcodec/jvdec.c
Go to the documentation of this file.
00001 /*
00002  * Bitmap Brothers JV video decoder
00003  * Copyright (c) 2011 Peter Ross <pross@xvid.org>
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 
00028 #include "avcodec.h"
00029 #include "dsputil.h"
00030 #include "get_bits.h"
00031 #include "libavutil/intreadwrite.h"
00032 
00033 typedef struct JvContext {
00034     DSPContext dsp;
00035     AVFrame    frame;
00036     uint32_t   palette[AVPALETTE_COUNT];
00037     int        palette_has_changed;
00038 } JvContext;
00039 
00040 static av_cold int decode_init(AVCodecContext *avctx)
00041 {
00042     JvContext *s = avctx->priv_data;
00043     avctx->pix_fmt = PIX_FMT_PAL8;
00044     dsputil_init(&s->dsp, avctx);
00045     return 0;
00046 }
00047 
00051 static inline void decode2x2(GetBitContext *gb, uint8_t *dst, int linesize)
00052 {
00053     int i, j, v[2];
00054 
00055     switch (get_bits(gb, 2)) {
00056     case 1:
00057         v[0] = get_bits(gb, 8);
00058         for (j = 0; j < 2; j++)
00059             memset(dst + j*linesize, v[0], 2);
00060         break;
00061     case 2:
00062         v[0] = get_bits(gb, 8);
00063         v[1] = get_bits(gb, 8);
00064         for (j = 0; j < 2; j++)
00065             for (i = 0; i < 2; i++)
00066                 dst[j*linesize + i] = v[get_bits1(gb)];
00067         break;
00068     case 3:
00069         for (j = 0; j < 2; j++)
00070             for (i = 0; i < 2; i++)
00071                 dst[j*linesize + i] = get_bits(gb, 8);
00072     }
00073 }
00074 
00078 static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize)
00079 {
00080     int i, j, v[2];
00081 
00082     switch (get_bits(gb, 2)) {
00083     case 1:
00084         v[0] = get_bits(gb, 8);
00085         for (j = 0; j < 4; j++)
00086             memset(dst + j*linesize, v[0], 4);
00087         break;
00088     case 2:
00089         v[0] = get_bits(gb, 8);
00090         v[1] = get_bits(gb, 8);
00091         for (j = 2; j >= 0; j -= 2) {
00092             for (i = 0; i < 4; i++)
00093                 dst[j*linesize + i]     = v[get_bits1(gb)];
00094             for (i = 0; i < 4; i++)
00095                 dst[(j+1)*linesize + i] = v[get_bits1(gb)];
00096         }
00097         break;
00098     case 3:
00099         for (j = 0; j < 4; j += 2)
00100             for (i = 0; i < 4; i += 2)
00101                 decode2x2(gb, dst + j*linesize + i, linesize);
00102     }
00103 }
00104 
00108 static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize, DSPContext *dsp)
00109 {
00110     int i, j, v[2];
00111 
00112     switch (get_bits(gb, 2)) {
00113     case 1:
00114         v[0] = get_bits(gb, 8);
00115         dsp->fill_block_tab[1](dst, v[0], linesize, 8);
00116         break;
00117     case 2:
00118         v[0] = get_bits(gb, 8);
00119         v[1] = get_bits(gb, 8);
00120         for (j = 7; j >= 0; j--)
00121             for (i = 0; i <  8; i++)
00122                 dst[j*linesize + i] = v[get_bits1(gb)];
00123         break;
00124     case 3:
00125         for (j = 0; j < 8; j += 4)
00126             for (i = 0; i < 8; i += 4)
00127                 decode4x4(gb, dst + j*linesize + i, linesize);
00128     }
00129 }
00130 
00131 static int decode_frame(AVCodecContext *avctx,
00132                         void *data, int *data_size,
00133                         AVPacket *avpkt)
00134 {
00135     JvContext *s           = avctx->priv_data;
00136     int buf_size           = avpkt->size;
00137     const uint8_t *buf     = avpkt->data;
00138     const uint8_t *buf_end = buf + buf_size;
00139     int video_size, video_type, i, j;
00140 
00141     video_size = AV_RL32(buf);
00142     video_type = buf[4];
00143     buf += 5;
00144 
00145     if (video_size) {
00146         if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00147             av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00148             return -1;
00149         }
00150 
00151         if (video_type == 0 || video_type == 1) {
00152             GetBitContext gb;
00153             init_get_bits(&gb, buf, 8 * FFMIN(video_size, buf_end - buf));
00154 
00155             for (j = 0; j < avctx->height; j += 8)
00156                 for (i = 0; i < avctx->width; i += 8)
00157                     decode8x8(&gb, s->frame.data[0] + j*s->frame.linesize[0] + i,
00158                               s->frame.linesize[0], &s->dsp);
00159 
00160             buf += video_size;
00161         } else if (video_type == 2) {
00162             if (buf + 1 <= buf_end) {
00163                 int v = *buf++;
00164                 for (j = 0; j < avctx->height; j++)
00165                     memset(s->frame.data[0] + j*s->frame.linesize[0], v, avctx->width);
00166             }
00167         } else {
00168             av_log(avctx, AV_LOG_WARNING, "unsupported frame type %i\n", video_type);
00169             return AVERROR_INVALIDDATA;
00170         }
00171     }
00172 
00173     if (buf < buf_end) {
00174         for (i = 0; i < AVPALETTE_COUNT && buf + 3 <= buf_end; i++) {
00175             s->palette[i] = AV_RB24(buf) << 2;
00176             buf += 3;
00177         }
00178         s->palette_has_changed = 1;
00179     }
00180 
00181     if (video_size) {
00182         s->frame.key_frame           = 1;
00183         s->frame.pict_type           = AV_PICTURE_TYPE_I;
00184         s->frame.palette_has_changed = s->palette_has_changed;
00185         s->palette_has_changed       = 0;
00186         memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
00187 
00188         *data_size      = sizeof(AVFrame);
00189         *(AVFrame*)data = s->frame;
00190     }
00191 
00192     return buf_size;
00193 }
00194 
00195 static av_cold int decode_close(AVCodecContext *avctx)
00196 {
00197     JvContext *s = avctx->priv_data;
00198 
00199     if(s->frame.data[0])
00200         avctx->release_buffer(avctx, &s->frame);
00201 
00202     return 0;
00203 }
00204 
00205 AVCodec ff_jv_decoder = {
00206     .name           = "jv",
00207     .long_name      = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"),
00208     .type           = AVMEDIA_TYPE_VIDEO,
00209     .id             = CODEC_ID_JV,
00210     .priv_data_size = sizeof(JvContext),
00211     .init           = decode_init,
00212     .close          = decode_close,
00213     .decode         = decode_frame,
00214     .capabilities   = CODEC_CAP_DR1,
00215 };