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.
54 #include "bitstream.h"
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
,
105 const uint8_t *buf
, int buf_size
)
107 FlashSVContext
*s
= avctx
->priv_data
;
108 int h_blocks
, v_blocks
, h_part
, v_part
, i
, j
;
111 /* no supplementary picture */
116 avctx
->release_buffer(avctx
, &s
->frame
);
118 init_get_bits(&gb
, buf
, buf_size
* 8);
120 /* start to parse the bitstream */
121 s
->block_width
= 16* (get_bits(&gb
, 4)+1);
122 s
->image_width
= get_bits(&gb
,12);
123 s
->block_height
= 16* (get_bits(&gb
, 4)+1);
124 s
->image_height
= get_bits(&gb
,12);
126 /* calculate amount of blocks and the size of the border blocks */
127 h_blocks
= s
->image_width
/ s
->block_width
;
128 h_part
= s
->image_width
% s
->block_width
;
129 v_blocks
= s
->image_height
/ s
->block_height
;
130 v_part
= s
->image_height
% s
->block_height
;
132 /* the block size could change between frames, make sure the buffer
133 * is large enough, if not, get a larger one */
134 if(s
->block_size
< s
->block_width
*s
->block_height
) {
135 if (s
->tmpblock
!= NULL
)
136 av_free(s
->tmpblock
);
137 if ((s
->tmpblock
= av_malloc(3*s
->block_width
*s
->block_height
)) == NULL
) {
138 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
142 s
->block_size
= s
->block_width
*s
->block_height
;
144 /* init the image size once */
145 if((avctx
->width
==0) && (avctx
->height
==0)){
146 avctx
->width
= s
->image_width
;
147 avctx
->height
= s
->image_height
;
150 /* check for changes of image width and image height */
151 if ((avctx
->width
!= s
->image_width
) || (avctx
->height
!= s
->image_height
)) {
152 av_log(avctx
, AV_LOG_ERROR
, "Frame width or height differs from first frames!\n");
153 av_log(avctx
, AV_LOG_ERROR
, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx
->height
,
154 avctx
->width
,s
->image_height
,s
->image_width
);
158 av_log(avctx
, AV_LOG_DEBUG
, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
159 s
->image_width
, s
->image_height
, s
->block_width
, s
->block_height
,
160 h_blocks
, v_blocks
, h_part
, v_part
);
162 s
->frame
.reference
= 1;
163 s
->frame
.buffer_hints
= FF_BUFFER_HINTS_VALID
;
164 if (avctx
->get_buffer(avctx
, &s
->frame
) < 0) {
165 av_log(s
->avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
169 /* loop over all block columns */
170 for (j
= 0; j
< v_blocks
+ (v_part
?1:0); j
++)
173 int hp
= j
*s
->block_height
; // horiz position in frame
174 int hs
= (j
<v_blocks
)?s
->block_height
:v_part
; // size of block
177 /* loop over all block rows */
178 for (i
= 0; i
< h_blocks
+ (h_part
?1:0); i
++)
180 int wp
= i
*s
->block_width
; // vert position in frame
181 int ws
= (i
<h_blocks
)?s
->block_width
:h_part
; // size of block
183 /* get the size of the compressed zlib chunk */
184 int size
= get_bits(&gb
, 16);
187 /* no change, don't do anything */
189 /* decompress block */
190 int ret
= inflateReset(&(s
->zstream
));
193 av_log(avctx
, AV_LOG_ERROR
, "error in decompression (reset) of block %dx%d\n", i
, j
);
196 s
->zstream
.next_in
= buf
+(get_bits_count(&gb
)/8);
197 s
->zstream
.avail_in
= size
;
198 s
->zstream
.next_out
= s
->tmpblock
;
199 s
->zstream
.avail_out
= s
->block_size
*3;
200 ret
= inflate(&(s
->zstream
), Z_FINISH
);
201 if (ret
== Z_DATA_ERROR
)
203 av_log(avctx
, AV_LOG_ERROR
, "Zlib resync occurred\n");
204 inflateSync(&(s
->zstream
));
205 ret
= inflate(&(s
->zstream
), Z_FINISH
);
208 if ((ret
!= Z_OK
) && (ret
!= Z_STREAM_END
))
210 av_log(avctx
, AV_LOG_ERROR
, "error in decompression of block %dx%d: %d\n", i
, j
, ret
);
213 copy_region(s
->tmpblock
, s
->frame
.data
[0], s
->image_height
-(hp
+hs
+1), wp
, hs
, ws
, s
->frame
.linesize
[0]);
214 skip_bits_long(&gb
, 8*size
); /* skip the consumed bits */
219 *data_size
= sizeof(AVFrame
);
220 *(AVFrame
*)data
= s
->frame
;
222 if ((get_bits_count(&gb
)/8) != buf_size
)
223 av_log(avctx
, AV_LOG_ERROR
, "buffer not fully consumed (%d != %d)\n",
224 buf_size
, (get_bits_count(&gb
)/8));
226 /* report that the buffer was completely consumed */
231 static av_cold
int flashsv_decode_end(AVCodecContext
*avctx
)
233 FlashSVContext
*s
= avctx
->priv_data
;
234 inflateEnd(&(s
->zstream
));
235 /* release the frame if needed */
236 if (s
->frame
.data
[0])
237 avctx
->release_buffer(avctx
, &s
->frame
);
239 /* free the tmpblock */
240 if (s
->tmpblock
!= NULL
)
241 av_free(s
->tmpblock
);
247 AVCodec flashsv_decoder
= {
251 sizeof(FlashSVContext
),
255 flashsv_decode_frame
,
257 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_BGR24
, PIX_FMT_NONE
},
258 .long_name
= NULL_IF_CONFIG_SMALL("Flash Screen Video v1"),