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