Mercurial > libavcodec.hg
annotate flashsv.c @ 11060:daff45175333 libavcodec
Make the jump-table section-relative for x86_64 with PIC enabled.
This allows to get rid of the macho64 specific hack that moves them
to rodata (with worse cache behaviour) and avoids textrels which
e.g. Gentoo does not allow for x86_64 libraries.
author | reimar |
---|---|
date | Sat, 30 Jan 2010 19:26:47 +0000 |
parents | 39a7bdbf0d40 |
children | a4596f842e18 |
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 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8210
diff
changeset
|
24 * @file libavcodec/flashsv.c |
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; | |
116 | |
117 init_get_bits(&gb, buf, buf_size * 8); | |
118 | |
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); | |
124 | |
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; | |
130 | |
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); | |
4370
e6eb67453d94
The block_size might be used incorrectly if it is not updated.
banan
parents:
4367
diff
changeset
|
136 if ((s->tmpblock = av_malloc(3*s->block_width*s->block_height)) == NULL) { |
3329 | 137 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); |
138 return -1; | |
139 } | |
140 } | |
4370
e6eb67453d94
The block_size might be used incorrectly if it is not updated.
banan
parents:
4367
diff
changeset
|
141 s->block_size = s->block_width*s->block_height; |
3329 | 142 |
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; | |
147 } | |
148 | |
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); | |
154 return -1; | |
155 } | |
156 | |
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); | |
160 | |
161 s->frame.reference = 1; | |
10159
6110cd97dc8e
Use reget_buffer instead of get_buffer. Fixes issue1367.
banan
parents:
10146
diff
changeset
|
162 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
|
163 if(avctx->reget_buffer(avctx, &s->frame) < 0){ |
6110cd97dc8e
Use reget_buffer instead of get_buffer. Fixes issue1367.
banan
parents:
10146
diff
changeset
|
164 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
|
165 return -1; |
3329 | 166 } |
167 | |
168 /* loop over all block columns */ | |
169 for (j = 0; j < v_blocks + (v_part?1:0); j++) | |
170 { | |
171 | |
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 | |
174 | |
175 | |
176 /* loop over all block rows */ | |
177 for (i = 0; i < h_blocks + (h_part?1:0); i++) | |
178 { | |
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 | |
181 | |
182 /* get the size of the compressed zlib chunk */ | |
183 int size = get_bits(&gb, 16); | |
184 | |
185 if (size == 0) { | |
186 /* no change, don't do anything */ | |
187 } else { | |
188 /* decompress block */ | |
189 int ret = inflateReset(&(s->zstream)); | |
190 if (ret != Z_OK) | |
191 { | |
192 av_log(avctx, AV_LOG_ERROR, "error in decompression (reset) of block %dx%d\n", i, j); | |
193 /* return -1; */ | |
194 } | |
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) | |
201 { | |
6524 | 202 av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); |
3329 | 203 inflateSync(&(s->zstream)); |
204 ret = inflate(&(s->zstream), Z_FINISH); | |
205 } | |
206 | |
207 if ((ret != Z_OK) && (ret != Z_STREAM_END)) | |
208 { | |
209 av_log(avctx, AV_LOG_ERROR, "error in decompression of block %dx%d: %d\n", i, j, ret); | |
210 /* return -1; */ | |
211 } | |
212 copy_region(s->tmpblock, s->frame.data[0], s->image_height-(hp+hs+1), wp, hs, ws, s->frame.linesize[0]); | |
8210 | 213 skip_bits_long(&gb, 8*size); /* skip the consumed bits */ |
3329 | 214 } |
215 } | |
216 } | |
217 | |
218 *data_size = sizeof(AVFrame); | |
219 *(AVFrame*)data = s->frame; | |
220 | |
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)); | |
224 | |
225 /* report that the buffer was completely consumed */ | |
226 return buf_size; | |
227 } | |
228 | |
229 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6236
diff
changeset
|
230 static av_cold int flashsv_decode_end(AVCodecContext *avctx) |
3329 | 231 { |
4827 | 232 FlashSVContext *s = avctx->priv_data; |
3329 | 233 inflateEnd(&(s->zstream)); |
234 /* release the frame if needed */ | |
235 if (s->frame.data[0]) | |
236 avctx->release_buffer(avctx, &s->frame); | |
237 | |
238 /* free the tmpblock */ | |
239 if (s->tmpblock != NULL) | |
240 av_free(s->tmpblock); | |
241 | |
242 return 0; | |
243 } | |
244 | |
245 | |
246 AVCodec flashsv_decoder = { | |
247 "flashsv", | |
248 CODEC_TYPE_VIDEO, | |
249 CODEC_ID_FLASHSV, | |
250 sizeof(FlashSVContext), | |
251 flashsv_decode_init, | |
252 NULL, | |
253 flashsv_decode_end, | |
254 flashsv_decode_frame, | |
255 CODEC_CAP_DR1, | |
10146
38cfe222e1a4
Mark all pix_fmts and supported_framerates compound literals as const.
reimar
parents:
9428
diff
changeset
|
256 .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
|
257 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), |
3329 | 258 }; |