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 */
117 init_get_bits(&gb
, buf
, buf_size
* 8);
119 /* start to parse the bitstream */
120 s
->block_width
= 16* (get_bits(&gb
, 4)+1);
121 s
->image_width
= get_bits(&gb
,12);
122 s
->block_height
= 16* (get_bits(&gb
, 4)+1);
123 s
->image_height
= get_bits(&gb
,12);
125 /* calculate amount of blocks and the size of the border blocks */
126 h_blocks
= s
->image_width
/ s
->block_width
;
127 h_part
= s
->image_width
% s
->block_width
;
128 v_blocks
= s
->image_height
/ s
->block_height
;
129 v_part
= s
->image_height
% s
->block_height
;
131 /* the block size could change between frames, make sure the buffer
132 * is large enough, if not, get a larger one */
133 if(s
->block_size
< s
->block_width
*s
->block_height
) {
134 if (s
->tmpblock
!= NULL
)
135 av_free(s
->tmpblock
);
136 if ((s
->tmpblock
= av_malloc(3*s
->block_width
*s
->block_height
)) == NULL
) {
137 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
141 s
->block_size
= s
->block_width
*s
->block_height
;
143 /* init the image size once */
144 if((avctx
->width
==0) && (avctx
->height
==0)){
145 avctx
->width
= s
->image_width
;
146 avctx
->height
= s
->image_height
;
149 /* check for changes of image width and image height */
150 if ((avctx
->width
!= s
->image_width
) || (avctx
->height
!= s
->image_height
)) {
151 av_log(avctx
, AV_LOG_ERROR
, "Frame width or height differs from first frames!\n");
152 av_log(avctx
, AV_LOG_ERROR
, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx
->height
,
153 avctx
->width
,s
->image_height
,s
->image_width
);
157 av_log(avctx
, AV_LOG_DEBUG
, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
158 s
->image_width
, s
->image_height
, s
->block_width
, s
->block_height
,
159 h_blocks
, v_blocks
, h_part
, v_part
);
161 s
->frame
.reference
= 1;
162 s
->frame
.buffer_hints
= FF_BUFFER_HINTS_VALID
| FF_BUFFER_HINTS_PRESERVE
| FF_BUFFER_HINTS_REUSABLE
;
163 if(avctx
->reget_buffer(avctx
, &s
->frame
) < 0){
164 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
168 /* loop over all block columns */
169 for (j
= 0; j
< v_blocks
+ (v_part
?1:0); j
++)
172 int hp
= j
*s
->block_height
; // horiz position in frame
173 int hs
= (j
<v_blocks
)?s
->block_height
:v_part
; // size of block
176 /* loop over all block rows */
177 for (i
= 0; i
< h_blocks
+ (h_part
?1:0); i
++)
179 int wp
= i
*s
->block_width
; // vert position in frame
180 int ws
= (i
<h_blocks
)?s
->block_width
:h_part
; // size of block
182 /* get the size of the compressed zlib chunk */
183 int size
= get_bits(&gb
, 16);
186 /* no change, don't do anything */
188 /* decompress block */
189 int ret
= inflateReset(&(s
->zstream
));
192 av_log(avctx
, AV_LOG_ERROR
, "error in decompression (reset) of block %dx%d\n", i
, j
);
195 s
->zstream
.next_in
= buf
+(get_bits_count(&gb
)/8);
196 s
->zstream
.avail_in
= size
;
197 s
->zstream
.next_out
= s
->tmpblock
;
198 s
->zstream
.avail_out
= s
->block_size
*3;
199 ret
= inflate(&(s
->zstream
), Z_FINISH
);
200 if (ret
== Z_DATA_ERROR
)
202 av_log(avctx
, AV_LOG_ERROR
, "Zlib resync occurred\n");
203 inflateSync(&(s
->zstream
));
204 ret
= inflate(&(s
->zstream
), Z_FINISH
);
207 if ((ret
!= Z_OK
) && (ret
!= Z_STREAM_END
))
209 av_log(avctx
, AV_LOG_ERROR
, "error in decompression of block %dx%d: %d\n", i
, j
, ret
);
212 copy_region(s
->tmpblock
, s
->frame
.data
[0], s
->image_height
-(hp
+hs
+1), wp
, hs
, ws
, s
->frame
.linesize
[0]);
213 skip_bits_long(&gb
, 8*size
); /* skip the consumed bits */
218 *data_size
= sizeof(AVFrame
);
219 *(AVFrame
*)data
= s
->frame
;
221 if ((get_bits_count(&gb
)/8) != buf_size
)
222 av_log(avctx
, AV_LOG_ERROR
, "buffer not fully consumed (%d != %d)\n",
223 buf_size
, (get_bits_count(&gb
)/8));
225 /* report that the buffer was completely consumed */
230 static av_cold
int flashsv_decode_end(AVCodecContext
*avctx
)
232 FlashSVContext
*s
= avctx
->priv_data
;
233 inflateEnd(&(s
->zstream
));
234 /* release the frame if needed */
235 if (s
->frame
.data
[0])
236 avctx
->release_buffer(avctx
, &s
->frame
);
238 /* free the tmpblock */
239 if (s
->tmpblock
!= NULL
)
240 av_free(s
->tmpblock
);
246 AVCodec flashsv_decoder
= {
250 sizeof(FlashSVContext
),
254 flashsv_decode_frame
,
256 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_BGR24
, PIX_FMT_NONE
},
257 .long_name
= NULL_IF_CONFIG_SMALL("Flash Screen Video v1"),