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 
00046     if (!avctx->width || !avctx->height ||
00047         (avctx->width & 7) || (avctx->height & 7)) {
00048         av_log(avctx, AV_LOG_ERROR, "Invalid video dimensions: %dx%d\n",
00049                avctx->width, avctx->height);
00050         return AVERROR(EINVAL);
00051     }
00052 
00053     return 0;
00054 }
00055 
00059 static inline void decode2x2(GetBitContext *gb, uint8_t *dst, int linesize)
00060 {
00061     int i, j, v[2];
00062 
00063     switch (get_bits(gb, 2)) {
00064     case 1:
00065         v[0] = get_bits(gb, 8);
00066         for (j = 0; j < 2; j++)
00067             memset(dst + j*linesize, v[0], 2);
00068         break;
00069     case 2:
00070         v[0] = get_bits(gb, 8);
00071         v[1] = get_bits(gb, 8);
00072         for (j = 0; j < 2; j++)
00073             for (i = 0; i < 2; i++)
00074                 dst[j*linesize + i] = v[get_bits1(gb)];
00075         break;
00076     case 3:
00077         for (j = 0; j < 2; j++)
00078             for (i = 0; i < 2; i++)
00079                 dst[j*linesize + i] = get_bits(gb, 8);
00080     }
00081 }
00082 
00086 static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize)
00087 {
00088     int i, j, v[2];
00089 
00090     switch (get_bits(gb, 2)) {
00091     case 1:
00092         v[0] = get_bits(gb, 8);
00093         for (j = 0; j < 4; j++)
00094             memset(dst + j*linesize, v[0], 4);
00095         break;
00096     case 2:
00097         v[0] = get_bits(gb, 8);
00098         v[1] = get_bits(gb, 8);
00099         for (j = 2; j >= 0; j -= 2) {
00100             for (i = 0; i < 4; i++)
00101                 dst[j*linesize + i]     = v[get_bits1(gb)];
00102             for (i = 0; i < 4; i++)
00103                 dst[(j+1)*linesize + i] = v[get_bits1(gb)];
00104         }
00105         break;
00106     case 3:
00107         for (j = 0; j < 4; j += 2)
00108             for (i = 0; i < 4; i += 2)
00109                 decode2x2(gb, dst + j*linesize + i, linesize);
00110     }
00111 }
00112 
00116 static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize, DSPContext *dsp)
00117 {
00118     int i, j, v[2];
00119 
00120     switch (get_bits(gb, 2)) {
00121     case 1:
00122         v[0] = get_bits(gb, 8);
00123         dsp->fill_block_tab[1](dst, v[0], linesize, 8);
00124         break;
00125     case 2:
00126         v[0] = get_bits(gb, 8);
00127         v[1] = get_bits(gb, 8);
00128         for (j = 7; j >= 0; j--)
00129             for (i = 0; i <  8; i++)
00130                 dst[j*linesize + i] = v[get_bits1(gb)];
00131         break;
00132     case 3:
00133         for (j = 0; j < 8; j += 4)
00134             for (i = 0; i < 8; i += 4)
00135                 decode4x4(gb, dst + j*linesize + i, linesize);
00136     }
00137 }
00138 
00139 static int decode_frame(AVCodecContext *avctx,
00140                         void *data, int *data_size,
00141                         AVPacket *avpkt)
00142 {
00143     JvContext *s           = avctx->priv_data;
00144     int buf_size           = avpkt->size;
00145     const uint8_t *buf     = avpkt->data;
00146     const uint8_t *buf_end = buf + buf_size;
00147     int video_size, video_type, i, j;
00148 
00149     video_size = AV_RL32(buf);
00150     video_type = buf[4];
00151     buf += 5;
00152 
00153     if (video_size) {
00154         if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00155             av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00156             return -1;
00157         }
00158 
00159         if (video_type == 0 || video_type == 1) {
00160             GetBitContext gb;
00161             init_get_bits(&gb, buf, 8 * FFMIN(video_size, buf_end - buf));
00162 
00163             for (j = 0; j < avctx->height; j += 8)
00164                 for (i = 0; i < avctx->width; i += 8)
00165                     decode8x8(&gb, s->frame.data[0] + j*s->frame.linesize[0] + i,
00166                               s->frame.linesize[0], &s->dsp);
00167 
00168             buf += video_size;
00169         } else if (video_type == 2) {
00170             if (buf + 1 <= buf_end) {
00171                 int v = *buf++;
00172                 for (j = 0; j < avctx->height; j++)
00173                     memset(s->frame.data[0] + j*s->frame.linesize[0], v, avctx->width);
00174             }
00175         } else {
00176             av_log(avctx, AV_LOG_WARNING, "unsupported frame type %i\n", video_type);
00177             return AVERROR_INVALIDDATA;
00178         }
00179     }
00180 
00181     if (buf < buf_end) {
00182         for (i = 0; i < AVPALETTE_COUNT && buf + 3 <= buf_end; i++) {
00183             s->palette[i] = AV_RB24(buf) << 2;
00184             buf += 3;
00185         }
00186         s->palette_has_changed = 1;
00187     }
00188 
00189     if (video_size) {
00190         s->frame.key_frame           = 1;
00191         s->frame.pict_type           = AV_PICTURE_TYPE_I;
00192         s->frame.palette_has_changed = s->palette_has_changed;
00193         s->palette_has_changed       = 0;
00194         memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
00195 
00196         *data_size      = sizeof(AVFrame);
00197         *(AVFrame*)data = s->frame;
00198     }
00199 
00200     return buf_size;
00201 }
00202 
00203 static av_cold int decode_close(AVCodecContext *avctx)
00204 {
00205     JvContext *s = avctx->priv_data;
00206 
00207     if(s->frame.data[0])
00208         avctx->release_buffer(avctx, &s->frame);
00209 
00210     return 0;
00211 }
00212 
00213 AVCodec ff_jv_decoder = {
00214     .name           = "jv",
00215     .long_name      = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"),
00216     .type           = AVMEDIA_TYPE_VIDEO,
00217     .id             = CODEC_ID_JV,
00218     .priv_data_size = sizeof(JvContext),
00219     .init           = decode_init,
00220     .close          = decode_close,
00221     .decode         = decode_frame,
00222     .capabilities   = CODEC_CAP_DR1,
00223 };