Mercurial > libavcodec.hg
annotate flashsv.c @ 12197:fbf4d5b1b664 libavcodec
Remove FF_MM_SSE2/3 flags for CPUs where this is generally not faster than
regular MMX code. Examples of this are the Core1 CPU. Instead, set a new flag,
FF_MM_SSE2/3SLOW, which can be checked for particular SSE2/3 functions that
have been checked specifically on such CPUs and are actually faster than
their MMX counterparts.
In addition, use this flag to enable particular VP8 and LPC SSE2 functions
that are faster than their MMX counterparts.
Based on a patch by Loren Merritt <lorenm AT u washington edu>.
author | rbultje |
---|---|
date | Mon, 19 Jul 2010 22:38:23 +0000 |
parents | 7dd2a45249a9 |
children |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
24 * @file |
3329 | 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 "avcodec.h" | |
9428 | 54 #include "get_bits.h" |
3329 | 55 |
4372 | 56 #include <zlib.h> |
57 | |
3329 | 58 typedef struct FlashSVContext { |
59 AVCodecContext *avctx; | |
60 AVFrame frame; | |
61 int image_width, image_height; | |
62 int block_width, block_height; | |
63 uint8_t* tmpblock; | |
64 int block_size; | |
65 z_stream zstream; | |
66 } FlashSVContext; | |
67 | |
68 | |
69 static void copy_region(uint8_t *sptr, uint8_t *dptr, | |
70 int dx, int dy, int h, int w, int stride) | |
71 { | |
72 int i; | |
73 | |
74 for (i = dx+h; i > dx; i--) | |
75 { | |
76 memcpy(dptr+(i*stride)+dy*3, sptr, w*3); | |
77 sptr += w*3; | |
78 } | |
79 } | |
80 | |
81 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6236
diff
changeset
|
82 static av_cold int flashsv_decode_init(AVCodecContext *avctx) |
3329 | 83 { |
4827 | 84 FlashSVContext *s = avctx->priv_data; |
3329 | 85 int zret; // Zlib return code |
86 | |
87 s->avctx = avctx; | |
88 s->zstream.zalloc = Z_NULL; | |
89 s->zstream.zfree = Z_NULL; | |
90 s->zstream.opaque = Z_NULL; | |
91 zret = inflateInit(&(s->zstream)); | |
92 if (zret != Z_OK) { | |
93 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); | |
94 return 1; | |
95 } | |
96 avctx->pix_fmt = PIX_FMT_BGR24; | |
97 s->frame.data[0] = NULL; | |
98 | |
99 return 0; | |
100 } | |
101 | |
102 | |
103 static int flashsv_decode_frame(AVCodecContext *avctx, | |
104 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
105 AVPacket *avpkt) |
3329 | 106 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
107 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
108 int buf_size = avpkt->size; |
4827 | 109 FlashSVContext *s = avctx->priv_data; |
3329 | 110 int h_blocks, v_blocks, h_part, v_part, i, j; |
111 GetBitContext gb; | |
112 | |
113 /* no supplementary picture */ | |
114 if (buf_size == 0) | |
115 return 0; | |
11363 | 116 if (buf_size < 4) |
117 return -1; | |
3329 | 118 |
119 init_get_bits(&gb, buf, buf_size * 8); | |
120 | |
121 /* start to parse the bitstream */ | |
122 s->block_width = 16* (get_bits(&gb, 4)+1); | |
123 s->image_width = get_bits(&gb,12); | |
124 s->block_height= 16* (get_bits(&gb, 4)+1); | |
125 s->image_height= get_bits(&gb,12); | |
126 | |
127 /* calculate amount of blocks and the size of the border blocks */ | |
128 h_blocks = s->image_width / s->block_width; | |
129 h_part = s->image_width % s->block_width; | |
130 v_blocks = s->image_height / s->block_height; | |
131 v_part = s->image_height % s->block_height; | |
132 | |
133 /* the block size could change between frames, make sure the buffer | |
134 * is large enough, if not, get a larger one */ | |
135 if(s->block_size < s->block_width*s->block_height) { | |
136 if (s->tmpblock != NULL) | |
137 av_free(s->tmpblock); | |
4370
e6eb67453d94
The block_size might be used incorrectly if it is not updated.
banan
parents:
4367
diff
changeset
|
138 if ((s->tmpblock = av_malloc(3*s->block_width*s->block_height)) == NULL) { |
3329 | 139 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); |
140 return -1; | |
141 } | |
142 } | |
4370
e6eb67453d94
The block_size might be used incorrectly if it is not updated.
banan
parents:
4367
diff
changeset
|
143 s->block_size = s->block_width*s->block_height; |
3329 | 144 |
145 /* init the image size once */ | |
146 if((avctx->width==0) && (avctx->height==0)){ | |
147 avctx->width = s->image_width; | |
148 avctx->height = s->image_height; | |
149 } | |
150 | |
151 /* check for changes of image width and image height */ | |
152 if ((avctx->width != s->image_width) || (avctx->height != s->image_height)) { | |
153 av_log(avctx, AV_LOG_ERROR, "Frame width or height differs from first frames!\n"); | |
154 av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx->height, | |
155 avctx->width,s->image_height,s->image_width); | |
156 return -1; | |
157 } | |
158 | |
159 av_log(avctx, AV_LOG_DEBUG, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", | |
160 s->image_width, s->image_height, s->block_width, s->block_height, | |
161 h_blocks, v_blocks, h_part, v_part); | |
162 | |
163 s->frame.reference = 1; | |
10159
6110cd97dc8e
Use reget_buffer instead of get_buffer. Fixes issue1367.
banan
parents:
10146
diff
changeset
|
164 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
6110cd97dc8e
Use reget_buffer instead of get_buffer. Fixes issue1367.
banan
parents:
10146
diff
changeset
|
165 if(avctx->reget_buffer(avctx, &s->frame) < 0){ |
6110cd97dc8e
Use reget_buffer instead of get_buffer. Fixes issue1367.
banan
parents:
10146
diff
changeset
|
166 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); |
6110cd97dc8e
Use reget_buffer instead of get_buffer. Fixes issue1367.
banan
parents:
10146
diff
changeset
|
167 return -1; |
3329 | 168 } |
169 | |
170 /* loop over all block columns */ | |
171 for (j = 0; j < v_blocks + (v_part?1:0); j++) | |
172 { | |
173 | |
174 int hp = j*s->block_height; // horiz position in frame | |
175 int hs = (j<v_blocks)?s->block_height:v_part; // size of block | |
176 | |
177 | |
178 /* loop over all block rows */ | |
179 for (i = 0; i < h_blocks + (h_part?1:0); i++) | |
180 { | |
181 int wp = i*s->block_width; // vert position in frame | |
182 int ws = (i<h_blocks)?s->block_width:h_part; // size of block | |
183 | |
184 /* get the size of the compressed zlib chunk */ | |
185 int size = get_bits(&gb, 16); | |
11363 | 186 if (8 * size > get_bits_left(&gb)) { |
187 avctx->release_buffer(avctx, &s->frame); | |
188 s->frame.data[0] = NULL; | |
189 return -1; | |
190 } | |
3329 | 191 |
192 if (size == 0) { | |
193 /* no change, don't do anything */ | |
194 } else { | |
195 /* decompress block */ | |
196 int ret = inflateReset(&(s->zstream)); | |
197 if (ret != Z_OK) | |
198 { | |
199 av_log(avctx, AV_LOG_ERROR, "error in decompression (reset) of block %dx%d\n", i, j); | |
200 /* return -1; */ | |
201 } | |
202 s->zstream.next_in = buf+(get_bits_count(&gb)/8); | |
203 s->zstream.avail_in = size; | |
204 s->zstream.next_out = s->tmpblock; | |
205 s->zstream.avail_out = s->block_size*3; | |
206 ret = inflate(&(s->zstream), Z_FINISH); | |
207 if (ret == Z_DATA_ERROR) | |
208 { | |
6524 | 209 av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); |
3329 | 210 inflateSync(&(s->zstream)); |
211 ret = inflate(&(s->zstream), Z_FINISH); | |
212 } | |
213 | |
214 if ((ret != Z_OK) && (ret != Z_STREAM_END)) | |
215 { | |
216 av_log(avctx, AV_LOG_ERROR, "error in decompression of block %dx%d: %d\n", i, j, ret); | |
217 /* return -1; */ | |
218 } | |
219 copy_region(s->tmpblock, s->frame.data[0], s->image_height-(hp+hs+1), wp, hs, ws, s->frame.linesize[0]); | |
8210 | 220 skip_bits_long(&gb, 8*size); /* skip the consumed bits */ |
3329 | 221 } |
222 } | |
223 } | |
224 | |
225 *data_size = sizeof(AVFrame); | |
226 *(AVFrame*)data = s->frame; | |
227 | |
228 if ((get_bits_count(&gb)/8) != buf_size) | |
229 av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", | |
230 buf_size, (get_bits_count(&gb)/8)); | |
231 | |
232 /* report that the buffer was completely consumed */ | |
233 return buf_size; | |
234 } | |
235 | |
236 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6236
diff
changeset
|
237 static av_cold int flashsv_decode_end(AVCodecContext *avctx) |
3329 | 238 { |
4827 | 239 FlashSVContext *s = avctx->priv_data; |
3329 | 240 inflateEnd(&(s->zstream)); |
241 /* release the frame if needed */ | |
242 if (s->frame.data[0]) | |
243 avctx->release_buffer(avctx, &s->frame); | |
244 | |
245 /* free the tmpblock */ | |
246 if (s->tmpblock != NULL) | |
247 av_free(s->tmpblock); | |
248 | |
249 return 0; | |
250 } | |
251 | |
252 | |
253 AVCodec flashsv_decoder = { | |
254 "flashsv", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11363
diff
changeset
|
255 AVMEDIA_TYPE_VIDEO, |
3329 | 256 CODEC_ID_FLASHSV, |
257 sizeof(FlashSVContext), | |
258 flashsv_decode_init, | |
259 NULL, | |
260 flashsv_decode_end, | |
261 flashsv_decode_frame, | |
262 CODEC_CAP_DR1, | |
10146
38cfe222e1a4
Mark all pix_fmts and supported_framerates compound literals as const.
reimar
parents:
9428
diff
changeset
|
263 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE}, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6788
diff
changeset
|
264 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), |
3329 | 265 }; |