2 * Flash Screen Video decoder
3 * Copyright (C) 2004 Alex Beregszaszi
4 * Copyright (C) 2006 Benjamin Larsson
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * @file libavcodec/flashsv.c
25 * Flash Screen Video decoder
26 * @author Alex Beregszaszi
27 * @author Benjamin Larsson
30 /* Bitstream description
31 * The picture is divided into blocks that are zlib compressed.
33 * The decoder is fed complete frames, the frameheader contains:
34 * 4bits of block width
35 * 12bits of frame width
36 * 4bits of block height
37 * 12bits of frame height
39 * Directly after the header are the compressed blocks. The blocks
40 * have their compressed size represented with 16bits in the beginnig.
41 * If the size = 0 then the block is unchanged from the previous frame.
42 * All blocks are decompressed until the buffer is consumed.
44 * Encoding ideas, a basic encoder would just use a fixed block size.
45 * Block sizes can be multipels of 16, from 16 to 256. The blocks don't
46 * have to be quadratic. A brute force search with a set of diffrent
47 * block sizes should give a better result then to just use a fixed size.
58 typedef struct FlashSVContext
{
59 AVCodecContext
*avctx
;
61 int image_width
, image_height
;
62 int block_width
, block_height
;
69 static void copy_region(uint8_t *sptr
, uint8_t *dptr
,
70 int dx
, int dy
, int h
, int w
, int stride
)
74 for (i
= dx
+h
; i
> dx
; i
--)
76 memcpy(dptr
+(i
*stride
)+dy
*3, sptr
, w
*3);
82 static av_cold
int flashsv_decode_init(AVCodecContext
*avctx
)
84 FlashSVContext
*s
= avctx
->priv_data
;
85 int zret
; // Zlib return code
88 s
->zstream
.zalloc
= Z_NULL
;
89 s
->zstream
.zfree
= Z_NULL
;
90 s
->zstream
.opaque
= Z_NULL
;
91 zret
= inflateInit(&(s
->zstream
));
93 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
96 avctx
->pix_fmt
= PIX_FMT_BGR24
;
97 s
->frame
.data
[0] = NULL
;
103 static int flashsv_decode_frame(AVCodecContext
*avctx
,
104 void *data
, int *data_size
,
107 const uint8_t *buf
= avpkt
->data
;
108 int buf_size
= avpkt
->size
;
109 FlashSVContext
*s
= avctx
->priv_data
;
110 int h_blocks
, v_blocks
, h_part
, v_part
, i
, j
;
113 /* no supplementary picture */
118 avctx
->release_buffer(avctx
, &s
->frame
);
120 init_get_bits(&gb
, buf
, buf_size
* 8);
122 /* start to parse the bitstream */
123 s
->block_width
= 16* (get_bits(&gb
, 4)+1);
124 s
->image_width
= get_bits(&gb
,12);
125 s
->block_height
= 16* (get_bits(&gb
, 4)+1);
126 s
->image_height
= get_bits(&gb
,12);
128 /* calculate amount of blocks and the size of the border blocks */
129 h_blocks
= s
->image_width
/ s
->block_width
;
130 h_part
= s
->image_width
% s
->block_width
;
131 v_blocks
= s
->image_height
/ s
->block_height
;
132 v_part
= s
->image_height
% s
->block_height
;
134 /* the block size could change between frames, make sure the buffer
135 * is large enough, if not, get a larger one */
136 if(s
->block_size
< s
->block_width
*s
->block_height
) {
137 if (s
->tmpblock
!= NULL
)
138 av_free(s
->tmpblock
);
139 if ((s
->tmpblock
= av_malloc(3*s
->block_width
*s
->block_height
)) == NULL
) {
140 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
144 s
->block_size
= s
->block_width
*s
->block_height
;
146 /* init the image size once */
147 if((avctx
->width
==0) && (avctx
->height
==0)){
148 avctx
->width
= s
->image_width
;
149 avctx
->height
= s
->image_height
;
152 /* check for changes of image width and image height */
153 if ((avctx
->width
!= s
->image_width
) || (avctx
->height
!= s
->image_height
)) {
154 av_log(avctx
, AV_LOG_ERROR
, "Frame width or height differs from first frames!\n");
155 av_log(avctx
, AV_LOG_ERROR
, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx
->height
,
156 avctx
->width
,s
->image_height
,s
->image_width
);
160 av_log(avctx
, AV_LOG_DEBUG
, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
161 s
->image_width
, s
->image_height
, s
->block_width
, s
->block_height
,
162 h_blocks
, v_blocks
, h_part
, v_part
);
164 s
->frame
.reference
= 1;
165 s
->frame
.buffer_hints
= FF_BUFFER_HINTS_VALID
| FF_BUFFER_HINTS_PRESERVE
| FF_BUFFER_HINTS_REUSABLE
;
166 if(avctx
->reget_buffer(avctx
, &s
->frame
) < 0){
167 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
171 /* loop over all block columns */
172 for (j
= 0; j
< v_blocks
+ (v_part
?1:0); j
++)
175 int hp
= j
*s
->block_height
; // horiz position in frame
176 int hs
= (j
<v_blocks
)?s
->block_height
:v_part
; // size of block
179 /* loop over all block rows */
180 for (i
= 0; i
< h_blocks
+ (h_part
?1:0); i
++)
182 int wp
= i
*s
->block_width
; // vert position in frame
183 int ws
= (i
<h_blocks
)?s
->block_width
:h_part
; // size of block
185 /* get the size of the compressed zlib chunk */
186 int size
= get_bits(&gb
, 16);
189 /* no change, don't do anything */
191 /* decompress block */
192 int ret
= inflateReset(&(s
->zstream
));
195 av_log(avctx
, AV_LOG_ERROR
, "error in decompression (reset) of block %dx%d\n", i
, j
);
198 s
->zstream
.next_in
= buf
+(get_bits_count(&gb
)/8);
199 s
->zstream
.avail_in
= size
;
200 s
->zstream
.next_out
= s
->tmpblock
;
201 s
->zstream
.avail_out
= s
->block_size
*3;
202 ret
= inflate(&(s
->zstream
), Z_FINISH
);
203 if (ret
== Z_DATA_ERROR
)
205 av_log(avctx
, AV_LOG_ERROR
, "Zlib resync occurred\n");
206 inflateSync(&(s
->zstream
));
207 ret
= inflate(&(s
->zstream
), Z_FINISH
);
210 if ((ret
!= Z_OK
) && (ret
!= Z_STREAM_END
))
212 av_log(avctx
, AV_LOG_ERROR
, "error in decompression of block %dx%d: %d\n", i
, j
, ret
);
215 copy_region(s
->tmpblock
, s
->frame
.data
[0], s
->image_height
-(hp
+hs
+1), wp
, hs
, ws
, s
->frame
.linesize
[0]);
216 skip_bits_long(&gb
, 8*size
); /* skip the consumed bits */
221 *data_size
= sizeof(AVFrame
);
222 *(AVFrame
*)data
= s
->frame
;
224 if ((get_bits_count(&gb
)/8) != buf_size
)
225 av_log(avctx
, AV_LOG_ERROR
, "buffer not fully consumed (%d != %d)\n",
226 buf_size
, (get_bits_count(&gb
)/8));
228 /* report that the buffer was completely consumed */
233 static av_cold
int flashsv_decode_end(AVCodecContext
*avctx
)
235 FlashSVContext
*s
= avctx
->priv_data
;
236 inflateEnd(&(s
->zstream
));
237 /* release the frame if needed */
238 if (s
->frame
.data
[0])
239 avctx
->release_buffer(avctx
, &s
->frame
);
241 /* free the tmpblock */
242 if (s
->tmpblock
!= NULL
)
243 av_free(s
->tmpblock
);
249 AVCodec flashsv_decoder
= {
253 sizeof(FlashSVContext
),
257 flashsv_decode_frame
,
259 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_BGR24
, PIX_FMT_NONE
},
260 .long_name
= NULL_IF_CONFIG_SMALL("Flash Screen Video v1"),