Mercurial > libavcodec.hg
annotate flashsv.c @ 3990:746a60ba3177 libavcodec
enable CMOV_IS_FAST as its faster or equal speed on every cpu (duron, athlon, PM, P3) from which ive seen benchmarks, it might be slower on P4 but noone has posted benchmarks ...
author | michael |
---|---|
date | Wed, 11 Oct 2006 12:23:40 +0000 |
parents | c8c591fe26f8 |
children | b885917fbfef |
rev | line source |
---|---|
3329 | 1 /* |
2 * Flash Screen Video decoder | |
3 * Copyright (C) 2004 Alex Beregszaszi | |
4 * Copyright (C) 2006 Benjamin Larsson | |
5 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3329
diff
changeset
|
6 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3329
diff
changeset
|
7 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3329
diff
changeset
|
8 * FFmpeg is free software; you can redistribute it and/or |
3329 | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3329
diff
changeset
|
11 * version 2.1 of the License, or (at your option) any later version. |
3329 | 12 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3329
diff
changeset
|
13 * FFmpeg is distributed in the hope that it will be useful, |
3329 | 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. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3329
diff
changeset
|
19 * License along with FFmpeg; if not, write to the Free Software |
3329 | 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 */ | |
22 | |
23 /** | |
24 * @file flashsv.c | |
25 * Flash Screen Video decoder | |
26 * @author Alex Beregszaszi | |
27 * @author Benjamin Larsson | |
28 */ | |
29 | |
30 /* Bitstream description | |
31 * The picture is divided into blocks that are zlib compressed. | |
32 * | |
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 | |
38 * | |
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. | |
43 * | |
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. | |
48 */ | |
49 | |
50 #include <stdio.h> | |
51 #include <stdlib.h> | |
52 | |
53 #include "common.h" | |
54 #include "avcodec.h" | |
55 #include "bitstream.h" | |
56 | |
57 #ifdef CONFIG_ZLIB | |
58 #include <zlib.h> | |
59 #endif | |
60 | |
61 typedef struct FlashSVContext { | |
62 AVCodecContext *avctx; | |
63 AVFrame frame; | |
64 int image_width, image_height; | |
65 int block_width, block_height; | |
66 uint8_t* tmpblock; | |
67 int block_size; | |
68 #ifdef CONFIG_ZLIB | |
69 z_stream zstream; | |
70 #endif | |
71 } FlashSVContext; | |
72 | |
73 | |
74 static void copy_region(uint8_t *sptr, uint8_t *dptr, | |
75 int dx, int dy, int h, int w, int stride) | |
76 { | |
77 int i; | |
78 | |
79 for (i = dx+h; i > dx; i--) | |
80 { | |
81 memcpy(dptr+(i*stride)+dy*3, sptr, w*3); | |
82 sptr += w*3; | |
83 } | |
84 } | |
85 | |
86 | |
87 static int flashsv_decode_init(AVCodecContext *avctx) | |
88 { | |
89 FlashSVContext *s = (FlashSVContext *)avctx->priv_data; | |
90 int zret; // Zlib return code | |
91 | |
92 s->avctx = avctx; | |
93 #ifdef CONFIG_ZLIB | |
94 s->zstream.zalloc = Z_NULL; | |
95 s->zstream.zfree = Z_NULL; | |
96 s->zstream.opaque = Z_NULL; | |
97 zret = inflateInit(&(s->zstream)); | |
98 if (zret != Z_OK) { | |
99 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); | |
100 return 1; | |
101 } | |
102 #else | |
103 av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled. Needed for the decoder.\n"); | |
104 return 1; | |
105 #endif | |
106 avctx->pix_fmt = PIX_FMT_BGR24; | |
107 avctx->has_b_frames = 0; | |
108 s->frame.data[0] = NULL; | |
109 | |
110 return 0; | |
111 } | |
112 | |
113 | |
114 static int flashsv_decode_frame(AVCodecContext *avctx, | |
115 void *data, int *data_size, | |
116 uint8_t *buf, int buf_size) | |
117 { | |
118 FlashSVContext *s = (FlashSVContext *)avctx->priv_data; | |
119 int h_blocks, v_blocks, h_part, v_part, i, j; | |
120 GetBitContext gb; | |
121 | |
122 /* no supplementary picture */ | |
123 if (buf_size == 0) | |
124 return 0; | |
125 | |
126 if(s->frame.data[0]) | |
127 avctx->release_buffer(avctx, &s->frame); | |
128 | |
129 init_get_bits(&gb, buf, buf_size * 8); | |
130 | |
131 /* start to parse the bitstream */ | |
132 s->block_width = 16* (get_bits(&gb, 4)+1); | |
133 s->image_width = get_bits(&gb,12); | |
134 s->block_height= 16* (get_bits(&gb, 4)+1); | |
135 s->image_height= get_bits(&gb,12); | |
136 | |
137 /* calculate amount of blocks and the size of the border blocks */ | |
138 h_blocks = s->image_width / s->block_width; | |
139 h_part = s->image_width % s->block_width; | |
140 v_blocks = s->image_height / s->block_height; | |
141 v_part = s->image_height % s->block_height; | |
142 | |
143 /* the block size could change between frames, make sure the buffer | |
144 * is large enough, if not, get a larger one */ | |
145 if(s->block_size < s->block_width*s->block_height) { | |
146 if (s->tmpblock != NULL) | |
147 av_free(s->tmpblock); | |
148 s->block_size = s->block_width*s->block_height; | |
149 if ((s->tmpblock = av_malloc(3*s->block_size)) == NULL) { | |
150 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); | |
151 return -1; | |
152 } | |
153 } | |
154 | |
155 /* init the image size once */ | |
156 if((avctx->width==0) && (avctx->height==0)){ | |
157 avctx->width = s->image_width; | |
158 avctx->height = s->image_height; | |
159 } | |
160 | |
161 /* check for changes of image width and image height */ | |
162 if ((avctx->width != s->image_width) || (avctx->height != s->image_height)) { | |
163 av_log(avctx, AV_LOG_ERROR, "Frame width or height differs from first frames!\n"); | |
164 av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx->height, | |
165 avctx->width,s->image_height,s->image_width); | |
166 return -1; | |
167 } | |
168 | |
169 av_log(avctx, AV_LOG_DEBUG, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", | |
170 s->image_width, s->image_height, s->block_width, s->block_height, | |
171 h_blocks, v_blocks, h_part, v_part); | |
172 | |
173 s->frame.reference = 1; | |
174 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID; | |
175 if (avctx->get_buffer(avctx, &s->frame) < 0) { | |
176 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
177 return -1; | |
178 } | |
179 | |
180 /* loop over all block columns */ | |
181 for (j = 0; j < v_blocks + (v_part?1:0); j++) | |
182 { | |
183 | |
184 int hp = j*s->block_height; // horiz position in frame | |
185 int hs = (j<v_blocks)?s->block_height:v_part; // size of block | |
186 | |
187 | |
188 /* loop over all block rows */ | |
189 for (i = 0; i < h_blocks + (h_part?1:0); i++) | |
190 { | |
191 int wp = i*s->block_width; // vert position in frame | |
192 int ws = (i<h_blocks)?s->block_width:h_part; // size of block | |
193 | |
194 /* get the size of the compressed zlib chunk */ | |
195 int size = get_bits(&gb, 16); | |
196 | |
197 if (size == 0) { | |
198 /* no change, don't do anything */ | |
199 } else { | |
200 /* decompress block */ | |
201 #ifdef CONFIG_ZLIB | |
202 int ret = inflateReset(&(s->zstream)); | |
203 if (ret != Z_OK) | |
204 { | |
205 av_log(avctx, AV_LOG_ERROR, "error in decompression (reset) of block %dx%d\n", i, j); | |
206 /* return -1; */ | |
207 } | |
208 s->zstream.next_in = buf+(get_bits_count(&gb)/8); | |
209 s->zstream.avail_in = size; | |
210 s->zstream.next_out = s->tmpblock; | |
211 s->zstream.avail_out = s->block_size*3; | |
212 ret = inflate(&(s->zstream), Z_FINISH); | |
213 if (ret == Z_DATA_ERROR) | |
214 { | |
215 av_log(avctx, AV_LOG_ERROR, "Zlib resync occured\n"); | |
216 inflateSync(&(s->zstream)); | |
217 ret = inflate(&(s->zstream), Z_FINISH); | |
218 } | |
219 | |
220 if ((ret != Z_OK) && (ret != Z_STREAM_END)) | |
221 { | |
222 av_log(avctx, AV_LOG_ERROR, "error in decompression of block %dx%d: %d\n", i, j, ret); | |
223 /* return -1; */ | |
224 } | |
225 #else | |
226 av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled in.\n"); | |
227 return -1; | |
228 #endif | |
229 copy_region(s->tmpblock, s->frame.data[0], s->image_height-(hp+hs+1), wp, hs, ws, s->frame.linesize[0]); | |
230 skip_bits(&gb, 8*size); /* skip the consumed bits */ | |
231 } | |
232 } | |
233 } | |
234 | |
235 *data_size = sizeof(AVFrame); | |
236 *(AVFrame*)data = s->frame; | |
237 | |
238 if ((get_bits_count(&gb)/8) != buf_size) | |
239 av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", | |
240 buf_size, (get_bits_count(&gb)/8)); | |
241 | |
242 /* report that the buffer was completely consumed */ | |
243 return buf_size; | |
244 } | |
245 | |
246 | |
247 static int flashsv_decode_end(AVCodecContext *avctx) | |
248 { | |
249 FlashSVContext *s = (FlashSVContext *)avctx->priv_data; | |
250 #ifdef CONFIG_ZLIB | |
251 inflateEnd(&(s->zstream)); | |
252 #endif | |
253 /* release the frame if needed */ | |
254 if (s->frame.data[0]) | |
255 avctx->release_buffer(avctx, &s->frame); | |
256 | |
257 /* free the tmpblock */ | |
258 if (s->tmpblock != NULL) | |
259 av_free(s->tmpblock); | |
260 | |
261 return 0; | |
262 } | |
263 | |
264 | |
265 AVCodec flashsv_decoder = { | |
266 "flashsv", | |
267 CODEC_TYPE_VIDEO, | |
268 CODEC_ID_FLASHSV, | |
269 sizeof(FlashSVContext), | |
270 flashsv_decode_init, | |
271 NULL, | |
272 flashsv_decode_end, | |
273 flashsv_decode_frame, | |
274 CODEC_CAP_DR1, | |
275 .pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, -1}, | |
276 }; |