Libav
|
00001 /* 00002 * Flash Screen Video decoder 00003 * Copyright (C) 2004 Alex Beregszaszi 00004 * Copyright (C) 2006 Benjamin Larsson 00005 * 00006 * This file is part of FFmpeg. 00007 * 00008 * FFmpeg is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * FFmpeg is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with FFmpeg; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00030 /* Bitstream description 00031 * The picture is divided into blocks that are zlib compressed. 00032 * 00033 * The decoder is fed complete frames, the frameheader contains: 00034 * 4bits of block width 00035 * 12bits of frame width 00036 * 4bits of block height 00037 * 12bits of frame height 00038 * 00039 * Directly after the header are the compressed blocks. The blocks 00040 * have their compressed size represented with 16bits in the beginnig. 00041 * If the size = 0 then the block is unchanged from the previous frame. 00042 * All blocks are decompressed until the buffer is consumed. 00043 * 00044 * Encoding ideas, a basic encoder would just use a fixed block size. 00045 * Block sizes can be multipels of 16, from 16 to 256. The blocks don't 00046 * have to be quadratic. A brute force search with a set of diffrent 00047 * block sizes should give a better result then to just use a fixed size. 00048 */ 00049 00050 #include <stdio.h> 00051 #include <stdlib.h> 00052 00053 #include "avcodec.h" 00054 #include "get_bits.h" 00055 00056 #include <zlib.h> 00057 00058 typedef struct FlashSVContext { 00059 AVCodecContext *avctx; 00060 AVFrame frame; 00061 int image_width, image_height; 00062 int block_width, block_height; 00063 uint8_t* tmpblock; 00064 int block_size; 00065 z_stream zstream; 00066 } FlashSVContext; 00067 00068 00069 static void copy_region(uint8_t *sptr, uint8_t *dptr, 00070 int dx, int dy, int h, int w, int stride) 00071 { 00072 int i; 00073 00074 for (i = dx+h; i > dx; i--) 00075 { 00076 memcpy(dptr+(i*stride)+dy*3, sptr, w*3); 00077 sptr += w*3; 00078 } 00079 } 00080 00081 00082 static av_cold int flashsv_decode_init(AVCodecContext *avctx) 00083 { 00084 FlashSVContext *s = avctx->priv_data; 00085 int zret; // Zlib return code 00086 00087 s->avctx = avctx; 00088 s->zstream.zalloc = Z_NULL; 00089 s->zstream.zfree = Z_NULL; 00090 s->zstream.opaque = Z_NULL; 00091 zret = inflateInit(&(s->zstream)); 00092 if (zret != Z_OK) { 00093 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); 00094 return 1; 00095 } 00096 avctx->pix_fmt = PIX_FMT_BGR24; 00097 s->frame.data[0] = NULL; 00098 00099 return 0; 00100 } 00101 00102 00103 static int flashsv_decode_frame(AVCodecContext *avctx, 00104 void *data, int *data_size, 00105 AVPacket *avpkt) 00106 { 00107 const uint8_t *buf = avpkt->data; 00108 int buf_size = avpkt->size; 00109 FlashSVContext *s = avctx->priv_data; 00110 int h_blocks, v_blocks, h_part, v_part, i, j; 00111 GetBitContext gb; 00112 00113 /* no supplementary picture */ 00114 if (buf_size == 0) 00115 return 0; 00116 if (buf_size < 4) 00117 return -1; 00118 00119 init_get_bits(&gb, buf, buf_size * 8); 00120 00121 /* start to parse the bitstream */ 00122 s->block_width = 16* (get_bits(&gb, 4)+1); 00123 s->image_width = get_bits(&gb,12); 00124 s->block_height= 16* (get_bits(&gb, 4)+1); 00125 s->image_height= get_bits(&gb,12); 00126 00127 /* calculate amount of blocks and the size of the border blocks */ 00128 h_blocks = s->image_width / s->block_width; 00129 h_part = s->image_width % s->block_width; 00130 v_blocks = s->image_height / s->block_height; 00131 v_part = s->image_height % s->block_height; 00132 00133 /* the block size could change between frames, make sure the buffer 00134 * is large enough, if not, get a larger one */ 00135 if(s->block_size < s->block_width*s->block_height) { 00136 if (s->tmpblock != NULL) 00137 av_free(s->tmpblock); 00138 if ((s->tmpblock = av_malloc(3*s->block_width*s->block_height)) == NULL) { 00139 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); 00140 return -1; 00141 } 00142 } 00143 s->block_size = s->block_width*s->block_height; 00144 00145 /* init the image size once */ 00146 if((avctx->width==0) && (avctx->height==0)){ 00147 avctx->width = s->image_width; 00148 avctx->height = s->image_height; 00149 } 00150 00151 /* check for changes of image width and image height */ 00152 if ((avctx->width != s->image_width) || (avctx->height != s->image_height)) { 00153 av_log(avctx, AV_LOG_ERROR, "Frame width or height differs from first frames!\n"); 00154 av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx->height, 00155 avctx->width,s->image_height,s->image_width); 00156 return -1; 00157 } 00158 00159 av_log(avctx, AV_LOG_DEBUG, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", 00160 s->image_width, s->image_height, s->block_width, s->block_height, 00161 h_blocks, v_blocks, h_part, v_part); 00162 00163 s->frame.reference = 1; 00164 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00165 if(avctx->reget_buffer(avctx, &s->frame) < 0){ 00166 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 00167 return -1; 00168 } 00169 00170 /* loop over all block columns */ 00171 for (j = 0; j < v_blocks + (v_part?1:0); j++) 00172 { 00173 00174 int hp = j*s->block_height; // horiz position in frame 00175 int hs = (j<v_blocks)?s->block_height:v_part; // size of block 00176 00177 00178 /* loop over all block rows */ 00179 for (i = 0; i < h_blocks + (h_part?1:0); i++) 00180 { 00181 int wp = i*s->block_width; // vert position in frame 00182 int ws = (i<h_blocks)?s->block_width:h_part; // size of block 00183 00184 /* get the size of the compressed zlib chunk */ 00185 int size = get_bits(&gb, 16); 00186 if (8 * size > get_bits_left(&gb)) { 00187 avctx->release_buffer(avctx, &s->frame); 00188 s->frame.data[0] = NULL; 00189 return -1; 00190 } 00191 00192 if (size == 0) { 00193 /* no change, don't do anything */ 00194 } else { 00195 /* decompress block */ 00196 int ret = inflateReset(&(s->zstream)); 00197 if (ret != Z_OK) 00198 { 00199 av_log(avctx, AV_LOG_ERROR, "error in decompression (reset) of block %dx%d\n", i, j); 00200 /* return -1; */ 00201 } 00202 s->zstream.next_in = buf+(get_bits_count(&gb)/8); 00203 s->zstream.avail_in = size; 00204 s->zstream.next_out = s->tmpblock; 00205 s->zstream.avail_out = s->block_size*3; 00206 ret = inflate(&(s->zstream), Z_FINISH); 00207 if (ret == Z_DATA_ERROR) 00208 { 00209 av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); 00210 inflateSync(&(s->zstream)); 00211 ret = inflate(&(s->zstream), Z_FINISH); 00212 } 00213 00214 if ((ret != Z_OK) && (ret != Z_STREAM_END)) 00215 { 00216 av_log(avctx, AV_LOG_ERROR, "error in decompression of block %dx%d: %d\n", i, j, ret); 00217 /* return -1; */ 00218 } 00219 copy_region(s->tmpblock, s->frame.data[0], s->image_height-(hp+hs+1), wp, hs, ws, s->frame.linesize[0]); 00220 skip_bits_long(&gb, 8*size); /* skip the consumed bits */ 00221 } 00222 } 00223 } 00224 00225 *data_size = sizeof(AVFrame); 00226 *(AVFrame*)data = s->frame; 00227 00228 if ((get_bits_count(&gb)/8) != buf_size) 00229 av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", 00230 buf_size, (get_bits_count(&gb)/8)); 00231 00232 /* report that the buffer was completely consumed */ 00233 return buf_size; 00234 } 00235 00236 00237 static av_cold int flashsv_decode_end(AVCodecContext *avctx) 00238 { 00239 FlashSVContext *s = avctx->priv_data; 00240 inflateEnd(&(s->zstream)); 00241 /* release the frame if needed */ 00242 if (s->frame.data[0]) 00243 avctx->release_buffer(avctx, &s->frame); 00244 00245 /* free the tmpblock */ 00246 if (s->tmpblock != NULL) 00247 av_free(s->tmpblock); 00248 00249 return 0; 00250 } 00251 00252 00253 AVCodec flashsv_decoder = { 00254 "flashsv", 00255 AVMEDIA_TYPE_VIDEO, 00256 CODEC_ID_FLASHSV, 00257 sizeof(FlashSVContext), 00258 flashsv_decode_init, 00259 NULL, 00260 flashsv_decode_end, 00261 flashsv_decode_frame, 00262 CODEC_CAP_DR1, 00263 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE}, 00264 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), 00265 };