| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Flash Screen Video decoder | ||
| 3 | * Copyright (C) 2004 Alex Beregszaszi | ||
| 4 | * Copyright (C) 2006 Benjamin Larsson | ||
| 5 | * | ||
| 6 | * This file is part of FFmpeg. | ||
| 7 | * | ||
| 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. | ||
| 12 | * | ||
| 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. | ||
| 17 | * | ||
| 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 | ||
| 21 | */ | ||
| 22 | |||
| 23 | /** | ||
| 24 | * @file | ||
| 25 | * Flash Screen Video decoder | ||
| 26 | * @author Alex Beregszaszi | ||
| 27 | * @author Benjamin Larsson | ||
| 28 | * @author Daniel Verkamp | ||
| 29 | * @author Konstantin Shishkov | ||
| 30 | * | ||
| 31 | * A description of the bitstream format for Flash Screen Video version 1/2 | ||
| 32 | * is part of the SWF File Format Specification (version 10), which can be | ||
| 33 | * downloaded from http://www.adobe.com/devnet/swf.html. | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include "config_components.h" | ||
| 37 | |||
| 38 | #include <stddef.h> | ||
| 39 | #include <zlib.h> | ||
| 40 | |||
| 41 | #include "libavutil/intreadwrite.h" | ||
| 42 | #include "libavutil/mem.h" | ||
| 43 | #include "avcodec.h" | ||
| 44 | #include "bytestream.h" | ||
| 45 | #include "codec_internal.h" | ||
| 46 | #include "decode.h" | ||
| 47 | #include "get_bits.h" | ||
| 48 | #include "zlib_wrapper.h" | ||
| 49 | |||
| 50 | typedef struct BlockInfo { | ||
| 51 | const uint8_t *pos; | ||
| 52 | int size; | ||
| 53 | } BlockInfo; | ||
| 54 | |||
| 55 | typedef struct FlashSVContext { | ||
| 56 | AVCodecContext *avctx; | ||
| 57 | AVFrame *frame; | ||
| 58 | int image_width, image_height; | ||
| 59 | int block_width, block_height; | ||
| 60 | uint8_t *tmpblock; | ||
| 61 | int block_size; | ||
| 62 | int ver; | ||
| 63 | const uint32_t *pal; | ||
| 64 | int is_keyframe; | ||
| 65 | const uint8_t *keyframedata; | ||
| 66 | AVBufferRef *keyframedata_buf; | ||
| 67 | uint8_t *keyframe; | ||
| 68 | BlockInfo *blocks; | ||
| 69 | int color_depth; | ||
| 70 | int zlibprime_curr, zlibprime_prev; | ||
| 71 | int diff_start, diff_height; | ||
| 72 | FFZStream zstream; | ||
| 73 | uint8_t tmp[UINT16_MAX]; | ||
| 74 | } FlashSVContext; | ||
| 75 | |||
| 76 | 4641 | static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy, | |
| 77 | int h, int w, int stride, const uint32_t *pal) | ||
| 78 | { | ||
| 79 | int x, y; | ||
| 80 | 4641 | const uint8_t *orig_src = sptr; | |
| 81 | |||
| 82 |
2/2✓ Branch 0 taken 266118 times.
✓ Branch 1 taken 4641 times.
|
270759 | for (y = dx + h; y > dx; y--) { |
| 83 | 266118 | uint8_t *dst = dptr + (y * stride) + dy * 3; | |
| 84 |
2/2✓ Branch 0 taken 15569484 times.
✓ Branch 1 taken 266118 times.
|
15835602 | for (x = 0; x < w; x++) { |
| 85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15569484 times.
|
15569484 | if (sptr >= sptr_end) |
| 86 | ✗ | return AVERROR_INVALIDDATA; | |
| 87 |
2/2✓ Branch 0 taken 12342661 times.
✓ Branch 1 taken 3226823 times.
|
15569484 | if (*sptr & 0x80) { |
| 88 | /* 15-bit color */ | ||
| 89 | 12342661 | unsigned c = AV_RB16(sptr) & ~0x8000; | |
| 90 | 12342661 | unsigned b = c & 0x1F; | |
| 91 | 12342661 | unsigned g = (c >> 5) & 0x1F; | |
| 92 | 12342661 | unsigned r = c >> 10; | |
| 93 | /* 000aaabb -> aaabbaaa */ | ||
| 94 | 12342661 | *dst++ = (b << 3) | (b >> 2); | |
| 95 | 12342661 | *dst++ = (g << 3) | (g >> 2); | |
| 96 | 12342661 | *dst++ = (r << 3) | (r >> 2); | |
| 97 | 12342661 | sptr += 2; | |
| 98 | } else { | ||
| 99 | /* palette index */ | ||
| 100 | 3226823 | uint32_t c = pal[*sptr++]; | |
| 101 | 3226823 | bytestream_put_le24(&dst, c); | |
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | 4641 | return sptr - orig_src; | |
| 106 | } | ||
| 107 | |||
| 108 | 17 | static av_cold int flashsv_decode_end(AVCodecContext *avctx) | |
| 109 | { | ||
| 110 | 17 | FlashSVContext *s = avctx->priv_data; | |
| 111 | |||
| 112 | 17 | ff_inflate_end(&s->zstream); | |
| 113 | /* release the frame if needed */ | ||
| 114 | 17 | av_frame_free(&s->frame); | |
| 115 | |||
| 116 | /* free the tmpblock */ | ||
| 117 | 17 | av_freep(&s->tmpblock); | |
| 118 | |||
| 119 | 17 | return 0; | |
| 120 | } | ||
| 121 | |||
| 122 | 17 | static av_cold int flashsv_decode_init(AVCodecContext *avctx) | |
| 123 | { | ||
| 124 | 17 | FlashSVContext *s = avctx->priv_data; | |
| 125 | |||
| 126 | 17 | s->avctx = avctx; | |
| 127 | 17 | avctx->pix_fmt = AV_PIX_FMT_BGR24; | |
| 128 | |||
| 129 | 17 | s->frame = av_frame_alloc(); | |
| 130 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!s->frame) { |
| 131 | ✗ | return AVERROR(ENOMEM); | |
| 132 | } | ||
| 133 | |||
| 134 | 17 | return ff_inflate_init(&s->zstream, avctx); | |
| 135 | } | ||
| 136 | |||
| 137 | 4095 | static int flashsv2_prime(FlashSVContext *s, const uint8_t *src, int size) | |
| 138 | { | ||
| 139 | int zret; // Zlib return code | ||
| 140 | static const uint8_t zlib_header[] = { 0x78, 0x01 }; | ||
| 141 | 4095 | z_stream *const zstream = &s->zstream.zstream; | |
| 142 | 4095 | uint8_t *data = s->tmpblock; | |
| 143 | unsigned remaining; | ||
| 144 | |||
| 145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (!src) |
| 146 | ✗ | return AVERROR_INVALIDDATA; | |
| 147 | |||
| 148 | 4095 | zstream->next_in = src; | |
| 149 | 4095 | zstream->avail_in = size; | |
| 150 | 4095 | zstream->next_out = data; | |
| 151 | 4095 | zstream->avail_out = s->block_size * 3; | |
| 152 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
| 153 |
2/4✓ Branch 0 taken 4095 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4095 times.
|
4095 | if (zret != Z_OK && zret != Z_STREAM_END) |
| 154 | ✗ | return AVERROR_UNKNOWN; | |
| 155 | 4095 | remaining = s->block_size * 3 - zstream->avail_out; | |
| 156 | |||
| 157 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4095 times.
|
4095 | if ((zret = inflateReset(zstream)) != Z_OK) { |
| 158 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); | |
| 159 | ✗ | return AVERROR_UNKNOWN; | |
| 160 | } | ||
| 161 | |||
| 162 | /* Create input for zlib that is equivalent to encoding the output | ||
| 163 | * from above and decoding it again (the net result of this is that | ||
| 164 | * the dictionary of past decoded data is correctly primed and | ||
| 165 | * the adler32 checksum is correctly initialized). | ||
| 166 | * This is accomplished by synthetizing blocks of uncompressed data | ||
| 167 | * out of the output from above. See section 3.2.4 of RFC 1951. */ | ||
| 168 | 4095 | zstream->next_in = zlib_header; | |
| 169 | 4095 | zstream->avail_in = sizeof(zlib_header); | |
| 170 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
| 171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (zret != Z_OK) |
| 172 | ✗ | return AVERROR_UNKNOWN; | |
| 173 |
2/2✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 4095 times.
|
8190 | while (remaining > 0) { |
| 174 | 4095 | unsigned block_size = FFMIN(UINT16_MAX, remaining); | |
| 175 | uint8_t header[5]; | ||
| 176 | /* Bit 0: Non-last-block, bits 1-2: BTYPE for uncompressed block */ | ||
| 177 | 4095 | header[0] = 0; | |
| 178 | /* Block size */ | ||
| 179 | 4095 | AV_WL16(header + 1, block_size); | |
| 180 | /* Block size (one's complement) */ | ||
| 181 | 4095 | AV_WL16(header + 3, block_size ^ 0xFFFF); | |
| 182 | 4095 | zstream->next_in = header; | |
| 183 | 4095 | zstream->avail_in = sizeof(header); | |
| 184 | 4095 | zstream->next_out = s->tmp; | |
| 185 | 4095 | zstream->avail_out = sizeof(s->tmp); | |
| 186 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
| 187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (zret != Z_OK) |
| 188 | ✗ | return AVERROR_UNKNOWN; | |
| 189 | 4095 | zstream->next_in = data; | |
| 190 | 4095 | zstream->avail_in = block_size; | |
| 191 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
| 192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (zret != Z_OK) |
| 193 | ✗ | return AVERROR_UNKNOWN; | |
| 194 | 4095 | data += block_size; | |
| 195 | 4095 | remaining -= block_size; | |
| 196 | } | ||
| 197 | |||
| 198 | 4095 | return 0; | |
| 199 | } | ||
| 200 | |||
| 201 | 9312 | static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, | |
| 202 | GetBitContext *gb, int block_size, | ||
| 203 | int width, int height, int x_pos, int y_pos, | ||
| 204 | int blk_idx) | ||
| 205 | { | ||
| 206 | 9312 | struct FlashSVContext *s = avctx->priv_data; | |
| 207 | 9312 | z_stream *const zstream = &s->zstream.zstream; | |
| 208 | 9312 | uint8_t *line = s->tmpblock; | |
| 209 | int k; | ||
| 210 | 9312 | int ret = inflateReset(zstream); | |
| 211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (ret != Z_OK) { |
| 212 | ✗ | av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); | |
| 213 | ✗ | return AVERROR_UNKNOWN; | |
| 214 | } | ||
| 215 |
3/4✓ Branch 0 taken 9312 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4095 times.
✓ Branch 3 taken 5217 times.
|
9312 | if (s->zlibprime_curr || s->zlibprime_prev) { |
| 216 | 4095 | ret = flashsv2_prime(s, | |
| 217 | 4095 | s->blocks[blk_idx].pos, | |
| 218 | 4095 | s->blocks[blk_idx].size); | |
| 219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (ret < 0) |
| 220 | ✗ | return ret; | |
| 221 | } | ||
| 222 | 9312 | zstream->next_in = avpkt->data + get_bits_count(gb) / 8; | |
| 223 | 9312 | zstream->avail_in = block_size; | |
| 224 | 9312 | zstream->next_out = s->tmpblock; | |
| 225 | 9312 | zstream->avail_out = s->block_size * 3; | |
| 226 | 9312 | ret = inflate(zstream, Z_FINISH); | |
| 227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (ret == Z_DATA_ERROR) { |
| 228 | ✗ | av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); | |
| 229 | ✗ | inflateSync(zstream); | |
| 230 | ✗ | ret = inflate(zstream, Z_FINISH); | |
| 231 | } | ||
| 232 | |||
| 233 | if (ret != Z_OK && ret != Z_STREAM_END) { | ||
| 234 | //return -1; | ||
| 235 | } | ||
| 236 | |||
| 237 |
2/2✓ Branch 0 taken 546 times.
✓ Branch 1 taken 8766 times.
|
9312 | if (s->is_keyframe) { |
| 238 | 546 | s->blocks[blk_idx].pos = s->keyframedata + (get_bits_count(gb) / 8); | |
| 239 | 546 | s->blocks[blk_idx].size = block_size; | |
| 240 | } | ||
| 241 | |||
| 242 | 9312 | y_pos += s->diff_start; | |
| 243 | |||
| 244 |
2/2✓ Branch 0 taken 4671 times.
✓ Branch 1 taken 4641 times.
|
9312 | if (!s->color_depth) { |
| 245 | /* Flash Screen Video stores the image upside down, so copy | ||
| 246 | * lines to destination in reverse order. */ | ||
| 247 |
2/2✓ Branch 0 taken 267846 times.
✓ Branch 1 taken 4671 times.
|
272517 | for (k = 1; k <= s->diff_height; k++) { |
| 248 | 267846 | memcpy(s->frame->data[0] + x_pos * 3 + | |
| 249 | 267846 | (s->image_height - y_pos - k) * s->frame->linesize[0], | |
| 250 | 267846 | line, width * 3); | |
| 251 | /* advance source pointer to next line */ | ||
| 252 | 267846 | line += width * 3; | |
| 253 | } | ||
| 254 | } else { | ||
| 255 | /* hybrid 15-bit/palette mode */ | ||
| 256 | 4641 | ret = decode_hybrid(s->tmpblock, zstream->next_out, | |
| 257 | 4641 | s->frame->data[0], | |
| 258 | 4641 | s->image_height - (y_pos + 1 + s->diff_height), | |
| 259 | x_pos, s->diff_height, width, | ||
| 260 | 4641 | s->frame->linesize[0], s->pal); | |
| 261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
|
4641 | if (ret < 0) { |
| 262 | ✗ | av_log(avctx, AV_LOG_ERROR, "decode_hybrid failed\n"); | |
| 263 | ✗ | return ret; | |
| 264 | } | ||
| 265 | } | ||
| 266 | 9312 | skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */ | |
| 267 | 9312 | return 0; | |
| 268 | } | ||
| 269 | |||
| 270 | 409 | static int flashsv_decode_frame(AVCodecContext *avctx, AVFrame *rframe, | |
| 271 | int *got_frame, AVPacket *avpkt) | ||
| 272 | { | ||
| 273 | 409 | int buf_size = avpkt->size; | |
| 274 | 409 | FlashSVContext *s = avctx->priv_data; | |
| 275 | int h_blocks, v_blocks, h_part, v_part, i, j, ret; | ||
| 276 | GetBitContext gb; | ||
| 277 | 409 | int last_blockwidth = s->block_width; | |
| 278 | 409 | int last_blockheight= s->block_height; | |
| 279 | |||
| 280 | /* no supplementary picture */ | ||
| 281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409 times.
|
409 | if (buf_size == 0) |
| 282 | ✗ | return 0; | |
| 283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409 times.
|
409 | if (buf_size < 4) |
| 284 | ✗ | return -1; | |
| 285 | |||
| 286 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((ret = init_get_bits8(&gb, avpkt->data, buf_size)) < 0) |
| 287 | ✗ | return ret; | |
| 288 | |||
| 289 | /* start to parse the bitstream */ | ||
| 290 | 409 | s->block_width = 16 * (get_bits(&gb, 4) + 1); | |
| 291 | 409 | s->image_width = get_bits(&gb, 12); | |
| 292 | 409 | s->block_height = 16 * (get_bits(&gb, 4) + 1); | |
| 293 | 409 | s->image_height = get_bits(&gb, 12); | |
| 294 | |||
| 295 |
2/2✓ Branch 0 taken 392 times.
✓ Branch 1 taken 17 times.
|
409 | if ( last_blockwidth != s->block_width |
| 296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | || last_blockheight!= s->block_height) |
| 297 | 17 | av_freep(&s->blocks); | |
| 298 | |||
| 299 |
2/2✓ Branch 0 taken 204 times.
✓ Branch 1 taken 205 times.
|
409 | if (s->ver == 2) { |
| 300 | 204 | skip_bits(&gb, 6); | |
| 301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
|
204 | if (get_bits1(&gb)) { |
| 302 | ✗ | avpriv_request_sample(avctx, "iframe"); | |
| 303 | ✗ | return AVERROR_PATCHWELCOME; | |
| 304 | } | ||
| 305 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
|
204 | if (get_bits1(&gb)) { |
| 306 | ✗ | avpriv_request_sample(avctx, "Custom palette"); | |
| 307 | ✗ | return AVERROR_PATCHWELCOME; | |
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | /* calculate number of blocks and size of border (partial) blocks */ | ||
| 312 | 409 | h_blocks = s->image_width / s->block_width; | |
| 313 | 409 | h_part = s->image_width % s->block_width; | |
| 314 | 409 | v_blocks = s->image_height / s->block_height; | |
| 315 | 409 | v_part = s->image_height % s->block_height; | |
| 316 | |||
| 317 | /* the block size could change between frames, make sure the buffer | ||
| 318 | * is large enough, if not, get a larger one */ | ||
| 319 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 392 times.
|
409 | if (s->block_size < s->block_width * s->block_height) { |
| 320 | 17 | int tmpblock_size = 3 * s->block_width * s->block_height, err; | |
| 321 | |||
| 322 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
|
17 | if ((err = av_reallocp(&s->tmpblock, tmpblock_size)) < 0) { |
| 323 | ✗ | s->block_size = 0; | |
| 324 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 325 | "Cannot allocate decompression buffer.\n"); | ||
| 326 | ✗ | return err; | |
| 327 | } | ||
| 328 | } | ||
| 329 | 409 | s->block_size = s->block_width * s->block_height; | |
| 330 | |||
| 331 | /* initialize the image size once */ | ||
| 332 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 400 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
409 | if (avctx->width == 0 && avctx->height == 0) { |
| 333 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | if ((ret = ff_set_dimensions(avctx, s->image_width, s->image_height)) < 0) |
| 334 | ✗ | return ret; | |
| 335 | } | ||
| 336 | |||
| 337 | /* check for changes of image width and image height */ | ||
| 338 |
2/4✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 409 times.
|
409 | if (avctx->width != s->image_width || avctx->height != s->image_height) { |
| 339 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 340 | "Frame width or height differs from first frame!\n"); | ||
| 341 | ✗ | av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n", | |
| 342 | avctx->height, avctx->width, s->image_height, s->image_width); | ||
| 343 | ✗ | return AVERROR_INVALIDDATA; | |
| 344 | } | ||
| 345 | |||
| 346 | /* we care for keyframes only in Screen Video v2 */ | ||
| 347 |
4/4✓ Branch 0 taken 229 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 205 times.
|
409 | s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); |
| 348 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 385 times.
|
409 | if (s->is_keyframe) { |
| 349 | 24 | int err = av_buffer_replace(&s->keyframedata_buf, avpkt->buf); | |
| 350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (err < 0) |
| 351 | ✗ | return err; | |
| 352 | 24 | s->keyframedata = avpkt->data; | |
| 353 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
|
24 | if (s->blocks) |
| 354 | 16 | memset(s->blocks, 0, (v_blocks + !!v_part) * (h_blocks + !!h_part) * | |
| 355 | sizeof(s->blocks[0])); | ||
| 356 | } | ||
| 357 |
4/4✓ Branch 0 taken 204 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 196 times.
|
409 | if(s->ver == 2 && !s->blocks) |
| 358 | 8 | s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) * | |
| 359 | sizeof(s->blocks[0])); | ||
| 360 | |||
| 361 | ff_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", | ||
| 362 | s->image_width, s->image_height, s->block_width, s->block_height, | ||
| 363 | h_blocks, v_blocks, h_part, v_part); | ||
| 364 | |||
| 365 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
| 366 | ✗ | return ret; | |
| 367 | |||
| 368 | /* loop over all block columns */ | ||
| 369 |
2/2✓ Branch 0 taken 1637 times.
✓ Branch 1 taken 409 times.
|
2046 | for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) { |
| 370 | |||
| 371 | 1637 | int y_pos = j * s->block_height; // vertical position in frame | |
| 372 |
2/2✓ Branch 0 taken 1228 times.
✓ Branch 1 taken 409 times.
|
1637 | int cur_blk_height = (j < v_blocks) ? s->block_height : v_part; |
| 373 | |||
| 374 | /* loop over all block rows */ | ||
| 375 |
2/2✓ Branch 0 taken 9312 times.
✓ Branch 1 taken 1637 times.
|
10949 | for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) { |
| 376 | 9312 | int x_pos = i * s->block_width; // horizontal position in frame | |
| 377 |
2/2✓ Branch 0 taken 7675 times.
✓ Branch 1 taken 1637 times.
|
9312 | int cur_blk_width = (i < h_blocks) ? s->block_width : h_part; |
| 378 | 9312 | int has_diff = 0; | |
| 379 | |||
| 380 | /* get the size of the compressed zlib chunk */ | ||
| 381 | 9312 | int size = get_bits(&gb, 16); | |
| 382 | |||
| 383 | 9312 | s->color_depth = 0; | |
| 384 | 9312 | s->zlibprime_curr = 0; | |
| 385 | 9312 | s->zlibprime_prev = 0; | |
| 386 | 9312 | s->diff_start = 0; | |
| 387 | 9312 | s->diff_height = cur_blk_height; | |
| 388 | |||
| 389 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9312 times.
|
9312 | if (8 * size > get_bits_left(&gb)) { |
| 390 | ✗ | av_frame_unref(s->frame); | |
| 391 | ✗ | return AVERROR_INVALIDDATA; | |
| 392 | } | ||
| 393 | |||
| 394 |
3/4✓ Branch 0 taken 4641 times.
✓ Branch 1 taken 4671 times.
✓ Branch 2 taken 4641 times.
✗ Branch 3 not taken.
|
9312 | if (s->ver == 2 && size) { |
| 395 | 4641 | skip_bits(&gb, 3); | |
| 396 | 4641 | s->color_depth = get_bits(&gb, 2); | |
| 397 | 4641 | has_diff = get_bits1(&gb); | |
| 398 | 4641 | s->zlibprime_curr = get_bits1(&gb); | |
| 399 | 4641 | s->zlibprime_prev = get_bits1(&gb); | |
| 400 | |||
| 401 |
2/4✓ Branch 0 taken 4641 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4641 times.
|
4641 | if (s->color_depth != 0 && s->color_depth != 2) { |
| 402 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 403 | "%dx%d invalid color depth %d\n", | ||
| 404 | i, j, s->color_depth); | ||
| 405 | ✗ | return AVERROR_INVALIDDATA; | |
| 406 | } | ||
| 407 | |||
| 408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
|
4641 | if (has_diff) { |
| 409 | ✗ | if (size < 3) { | |
| 410 | ✗ | av_log(avctx, AV_LOG_ERROR, "size too small for diff\n"); | |
| 411 | ✗ | return AVERROR_INVALIDDATA; | |
| 412 | } | ||
| 413 | ✗ | if (!s->keyframe) { | |
| 414 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 415 | "Inter frame without keyframe\n"); | ||
| 416 | ✗ | return AVERROR_INVALIDDATA; | |
| 417 | } | ||
| 418 | ✗ | s->diff_start = get_bits(&gb, 8); | |
| 419 | ✗ | s->diff_height = get_bits(&gb, 8); | |
| 420 | ✗ | if (s->diff_start + s->diff_height > cur_blk_height) { | |
| 421 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 422 | "Block parameters invalid: %d + %d > %d\n", | ||
| 423 | s->diff_start, s->diff_height, cur_blk_height); | ||
| 424 | ✗ | return AVERROR_INVALIDDATA; | |
| 425 | } | ||
| 426 | ✗ | av_log(avctx, AV_LOG_DEBUG, | |
| 427 | "%dx%d diff start %d height %d\n", | ||
| 428 | i, j, s->diff_start, s->diff_height); | ||
| 429 | ✗ | size -= 2; | |
| 430 | } | ||
| 431 | |||
| 432 |
2/2✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 546 times.
|
4641 | if (s->zlibprime_prev) |
| 433 | 4095 | av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j); | |
| 434 | |||
| 435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
|
4641 | if (s->zlibprime_curr) { |
| 436 | ✗ | int col = get_bits(&gb, 8); | |
| 437 | ✗ | int row = get_bits(&gb, 8); | |
| 438 | ✗ | av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", | |
| 439 | i, j, col, row); | ||
| 440 | ✗ | if (size < 3) { | |
| 441 | ✗ | av_log(avctx, AV_LOG_ERROR, "size too small for zlibprime_curr\n"); | |
| 442 | ✗ | return AVERROR_INVALIDDATA; | |
| 443 | } | ||
| 444 | ✗ | size -= 2; | |
| 445 | ✗ | avpriv_request_sample(avctx, "zlibprime_curr"); | |
| 446 | ✗ | return AVERROR_PATCHWELCOME; | |
| 447 | } | ||
| 448 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4641 | if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) { |
| 449 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 450 | "no data available for zlib priming\n"); | ||
| 451 | ✗ | return AVERROR_INVALIDDATA; | |
| 452 | } | ||
| 453 | 4641 | size--; // account for flags byte | |
| 454 | } | ||
| 455 | |||
| 456 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (has_diff) { |
| 457 | int k; | ||
| 458 | ✗ | int off = (s->image_height - y_pos - 1) * s->frame->linesize[0]; | |
| 459 | |||
| 460 | ✗ | for (k = 0; k < cur_blk_height; k++) { | |
| 461 | ✗ | int x = off - k * s->frame->linesize[0] + x_pos * 3; | |
| 462 | ✗ | memcpy(s->frame->data[0] + x, s->keyframe + x, | |
| 463 | ✗ | cur_blk_width * 3); | |
| 464 | } | ||
| 465 | } | ||
| 466 | |||
| 467 | /* skip unchanged blocks, which have size 0 */ | ||
| 468 |
1/2✓ Branch 0 taken 9312 times.
✗ Branch 1 not taken.
|
9312 | if (size) { |
| 469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (flashsv_decode_block(avctx, avpkt, &gb, size, |
| 470 | cur_blk_width, cur_blk_height, | ||
| 471 | x_pos, y_pos, | ||
| 472 | 9312 | i + j * (h_blocks + !!h_part))) | |
| 473 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
| 474 | "error in decompression of block %dx%d\n", i, j); | ||
| 475 | } | ||
| 476 | } | ||
| 477 | } | ||
| 478 |
3/4✓ Branch 0 taken 24 times.
✓ Branch 1 taken 385 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
409 | if (s->is_keyframe && s->ver == 2) { |
| 479 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
|
24 | if (!s->keyframe) { |
| 480 | 8 | s->keyframe = av_malloc(s->frame->linesize[0] * avctx->height); | |
| 481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!s->keyframe) { |
| 482 | ✗ | av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n"); | |
| 483 | ✗ | return AVERROR(ENOMEM); | |
| 484 | } | ||
| 485 | } | ||
| 486 | 24 | memcpy(s->keyframe, s->frame->data[0], | |
| 487 | 24 | s->frame->linesize[0] * avctx->height); | |
| 488 | } | ||
| 489 | |||
| 490 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((ret = av_frame_ref(rframe, s->frame)) < 0) |
| 491 | ✗ | return ret; | |
| 492 | |||
| 493 | 409 | *got_frame = 1; | |
| 494 | |||
| 495 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((get_bits_count(&gb) / 8) != buf_size) |
| 496 | ✗ | av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", | |
| 497 | ✗ | buf_size, (get_bits_count(&gb) / 8)); | |
| 498 | |||
| 499 | /* report that the buffer was completely consumed */ | ||
| 500 | 409 | return buf_size; | |
| 501 | } | ||
| 502 | |||
| 503 | #if CONFIG_FLASHSV_DECODER | ||
| 504 | const FFCodec ff_flashsv_decoder = { | ||
| 505 | .p.name = "flashsv", | ||
| 506 | CODEC_LONG_NAME("Flash Screen Video v1"), | ||
| 507 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
| 508 | .p.id = AV_CODEC_ID_FLASHSV, | ||
| 509 | .priv_data_size = sizeof(FlashSVContext), | ||
| 510 | .init = flashsv_decode_init, | ||
| 511 | .close = flashsv_decode_end, | ||
| 512 | FF_CODEC_DECODE_CB(flashsv_decode_frame), | ||
| 513 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
| 514 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
| 515 | }; | ||
| 516 | #endif /* CONFIG_FLASHSV_DECODER */ | ||
| 517 | |||
| 518 | #if CONFIG_FLASHSV2_DECODER | ||
| 519 | static const uint32_t ff_flashsv2_default_palette[128] = { | ||
| 520 | 0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF, | ||
| 521 | 0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300, | ||
| 522 | 0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066, | ||
| 523 | 0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900, | ||
| 524 | 0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC, | ||
| 525 | 0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF, | ||
| 526 | 0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF, | ||
| 527 | 0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF, | ||
| 528 | 0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC, | ||
| 529 | 0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC, | ||
| 530 | 0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699, | ||
| 531 | 0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999, | ||
| 532 | 0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966, | ||
| 533 | 0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666, | ||
| 534 | 0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933, | ||
| 535 | 0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333, | ||
| 536 | 0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300, | ||
| 537 | 0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633, | ||
| 538 | 0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966, | ||
| 539 | 0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99, | ||
| 540 | 0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB, | ||
| 541 | 0xDDDDDD, 0xEEEEEE | ||
| 542 | }; | ||
| 543 | |||
| 544 | 8 | static av_cold int flashsv2_decode_init(AVCodecContext *avctx) | |
| 545 | { | ||
| 546 | 8 | FlashSVContext *s = avctx->priv_data; | |
| 547 | int ret; | ||
| 548 | |||
| 549 | 8 | ret = flashsv_decode_init(avctx); | |
| 550 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (ret < 0) |
| 551 | ✗ | return ret; | |
| 552 | 8 | s->pal = ff_flashsv2_default_palette; | |
| 553 | 8 | s->ver = 2; | |
| 554 | |||
| 555 | 8 | return 0; | |
| 556 | } | ||
| 557 | |||
| 558 | 8 | static av_cold int flashsv2_decode_end(AVCodecContext *avctx) | |
| 559 | { | ||
| 560 | 8 | FlashSVContext *s = avctx->priv_data; | |
| 561 | |||
| 562 | 8 | av_buffer_unref(&s->keyframedata_buf); | |
| 563 | 8 | s->keyframedata = NULL; | |
| 564 | 8 | av_freep(&s->blocks); | |
| 565 | 8 | av_freep(&s->keyframe); | |
| 566 | 8 | flashsv_decode_end(avctx); | |
| 567 | |||
| 568 | 8 | return 0; | |
| 569 | } | ||
| 570 | |||
| 571 | const FFCodec ff_flashsv2_decoder = { | ||
| 572 | .p.name = "flashsv2", | ||
| 573 | CODEC_LONG_NAME("Flash Screen Video v2"), | ||
| 574 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
| 575 | .p.id = AV_CODEC_ID_FLASHSV2, | ||
| 576 | .priv_data_size = sizeof(FlashSVContext), | ||
| 577 | .init = flashsv2_decode_init, | ||
| 578 | .close = flashsv2_decode_end, | ||
| 579 | FF_CODEC_DECODE_CB(flashsv_decode_frame), | ||
| 580 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
| 581 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
| 582 | }; | ||
| 583 | #endif /* CONFIG_FLASHSV2_DECODER */ | ||
| 584 |