| @@ -20,6 +20,8 @@ | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "libavutil/avassert.h" | |||
| #include "libavutil/imgutils.h" | |||
| #include "libavutil/intreadwrite.h" | |||
| #include "swf.h" | |||
| @@ -253,6 +255,127 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) | |||
| return pkt->size; | |||
| } | |||
| } | |||
| } else if (tag == TAG_DEFINEBITSLOSSLESS || tag == TAG_DEFINEBITSLOSSLESS2) { | |||
| #if CONFIG_ZLIB | |||
| long out_len; | |||
| uint8_t *buf = NULL, *zbuf = NULL, *pal; | |||
| uint32_t colormap[AVPALETTE_COUNT] = {0}; | |||
| const int alpha_bmp = tag == TAG_DEFINEBITSLOSSLESS2; | |||
| const int colormapbpp = 3 + alpha_bmp; | |||
| int linesize, colormapsize = 0; | |||
| const int ch_id = avio_rl16(pb); | |||
| const int bmp_fmt = avio_r8(pb); | |||
| const int width = avio_rl16(pb); | |||
| const int height = avio_rl16(pb); | |||
| len -= 2+1+2+2; | |||
| switch (bmp_fmt) { | |||
| case 3: // PAL-8 | |||
| linesize = width; | |||
| colormapsize = avio_r8(pb) + 1; | |||
| len--; | |||
| break; | |||
| case 4: // RGB15 | |||
| linesize = width * 2; | |||
| break; | |||
| case 5: // RGB24 (0RGB) | |||
| linesize = width * 4; | |||
| break; | |||
| default: | |||
| av_log(s, AV_LOG_ERROR, "invalid bitmap format %d, skipped\n", bmp_fmt); | |||
| goto bitmap_end_skip; | |||
| } | |||
| linesize = FFALIGN(linesize, 4); | |||
| if (av_image_check_size(width, height, 0, s) < 0 || | |||
| linesize >= INT_MAX / height || | |||
| linesize * height >= INT_MAX - colormapsize * colormapbpp) { | |||
| av_log(s, AV_LOG_ERROR, "invalid frame size %dx%d\n", width, height); | |||
| goto bitmap_end_skip; | |||
| } | |||
| out_len = colormapsize * colormapbpp + linesize * height; | |||
| av_dlog(s, "bitmap: ch=%d fmt=%d %dx%d (linesize=%d) len=%d->%ld pal=%d\n", | |||
| ch_id, bmp_fmt, width, height, linesize, len, out_len, colormapsize); | |||
| zbuf = av_malloc(len); | |||
| buf = av_malloc(out_len); | |||
| if (!zbuf || !buf) { | |||
| res = AVERROR(ENOMEM); | |||
| goto bitmap_end; | |||
| } | |||
| len = avio_read(pb, zbuf, len); | |||
| if (len < 0 || (res = uncompress(buf, &out_len, zbuf, len)) != Z_OK) { | |||
| av_log(s, AV_LOG_WARNING, "Failed to uncompress one bitmap\n"); | |||
| goto bitmap_end_skip; | |||
| } | |||
| for (i = 0; i < s->nb_streams; i++) { | |||
| st = s->streams[i]; | |||
| if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && st->id == -3) | |||
| break; | |||
| } | |||
| if (i == s->nb_streams) { | |||
| vst = avformat_new_stream(s, NULL); | |||
| if (!vst) { | |||
| res = AVERROR(ENOMEM); | |||
| goto bitmap_end; | |||
| } | |||
| vst->id = -3; /* -3 to avoid clash with video stream and audio stream */ | |||
| vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |||
| vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO; | |||
| avpriv_set_pts_info(vst, 64, 256, swf->frame_rate); | |||
| st = vst; | |||
| } | |||
| st->codec->width = width; | |||
| st->codec->height = height; | |||
| if ((res = av_new_packet(pkt, out_len - colormapsize * colormapbpp)) < 0) | |||
| goto bitmap_end; | |||
| pkt->pos = pos; | |||
| pkt->stream_index = st->index; | |||
| switch (bmp_fmt) { | |||
| case 3: | |||
| st->codec->pix_fmt = AV_PIX_FMT_PAL8; | |||
| for (i = 0; i < colormapsize; i++) | |||
| if (alpha_bmp) colormap[i] = buf[3]<<24 | AV_RB24(buf + 4*i); | |||
| else colormap[i] = 0xffU <<24 | AV_RB24(buf + 3*i); | |||
| pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); | |||
| if (!pal) { | |||
| res = AVERROR(ENOMEM); | |||
| goto bitmap_end; | |||
| } | |||
| memcpy(pal, colormap, AVPALETTE_SIZE); | |||
| break; | |||
| case 4: | |||
| st->codec->pix_fmt = AV_PIX_FMT_RGB555; | |||
| break; | |||
| case 5: | |||
| st->codec->pix_fmt = alpha_bmp ? AV_PIX_FMT_ARGB : AV_PIX_FMT_0RGB; | |||
| break; | |||
| default: | |||
| av_assert0(0); | |||
| } | |||
| memcpy(pkt->data, buf + colormapsize*colormapbpp, linesize * height); | |||
| res = pkt->size; | |||
| bitmap_end: | |||
| av_freep(&zbuf); | |||
| av_freep(&buf); | |||
| return res; | |||
| bitmap_end_skip: | |||
| av_freep(&zbuf); | |||
| av_freep(&buf); | |||
| #else | |||
| av_log(s, AV_LOG_ERROR, "this file requires zlib support compiled in\n"); | |||
| #endif | |||
| } else if (tag == TAG_STREAMBLOCK) { | |||
| for (i = 0; i < s->nb_streams; i++) { | |||
| st = s->streams[i]; | |||