This also fixes the FATE test if frame data is not initialized in get_buffer(). --- avconv.c | 2 +- libavcodec/bethsoftvideo.c | 14 +++++++++++--- libavformat/bethsoftvid.c | 35 +++++++++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/avconv.c b/avconv.c index e2cc4b0..10785bc 100644 --- a/avconv.c +++ b/avconv.c @@ -444,7 +444,7 @@ static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf) /* XXX this shouldn't be needed, but some tests break without this line * those decoders are buggy and need to be fixed. * the following tests fail: - * bethsoft-vid, cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit + * cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit */ memset(buf->base[0], 128, ret); diff --git a/libavcodec/bethsoftvideo.c b/libavcodec/bethsoftvideo.c index 743e387..c57aa9f 100644 --- a/libavcodec/bethsoftvideo.c +++ b/libavcodec/bethsoftvideo.c @@ -71,14 +71,23 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, uint8_t * dst; uint8_t * frame_end; int remaining = avctx->width; // number of bytes remaining on a line - const int wrap_to_next_line = vid->frame.linesize[0] - avctx->width; - int code; + int wrap_to_next_line; + int code, ret; int yoffset; if (avctx->reget_buffer(avctx, &vid->frame)) { av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return -1; } + wrap_to_next_line = vid->frame.linesize[0] - avctx->width; + + if (avpkt->side_data_elems > 0 && + avpkt->side_data[0].type == AV_PKT_DATA_PALETTE) { + bytestream2_init(&vid->g, avpkt->side_data[0].data, + avpkt->side_data[0].size); + if ((ret = set_palette(vid)) < 0) + return ret; + } bytestream2_init(&vid->g, avpkt->data, avpkt->size); dst = vid->frame.data[0]; @@ -86,7 +95,6 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, switch(block_type = bytestream2_get_byte(&vid->g)){ case PALETTE_BLOCK: { - int ret; *data_size = 0; if ((ret = set_palette(vid)) < 0) { av_log(avctx, AV_LOG_ERROR, "error reading palette\n"); diff --git a/libavformat/bethsoftvid.c b/libavformat/bethsoftvid.c index 7705fcb..a949c4d 100644 --- a/libavformat/bethsoftvid.c +++ b/libavformat/bethsoftvid.c @@ -32,6 +32,8 @@ #include "internal.h" #include "libavcodec/bethsoftvideo.h" +#define BVID_PALETTE_SIZE 3 * 256 + typedef struct BVID_DemuxContext { int nframes; @@ -43,6 +45,7 @@ typedef struct BVID_DemuxContext /** video presentation time stamp. * delay = 16 milliseconds * (global_delay + per_frame_delay) */ int video_pts; + uint8_t *palette; int is_finished; @@ -164,6 +167,14 @@ static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt, pkt->stream_index = 0; // use the video decoder, which was initialized as the first stream pkt->pts = vid->video_pts; + /* if there is a new palette available, add it to packet side data */ + if (vid->palette) { + uint8_t *pdata = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, + BVID_PALETTE_SIZE); + memcpy(pdata, vid->palette, BVID_PALETTE_SIZE); + av_freep(&vid->palette); + } + vid->nframes--; // used to check if all the frames were read return vidbuf_nbytes; fail: @@ -186,14 +197,18 @@ static int vid_read_packet(AVFormatContext *s, block_type = avio_r8(pb); switch(block_type){ case PALETTE_BLOCK: - avio_seek(pb, -1, SEEK_CUR); // include block type - ret_value = av_get_packet(pb, pkt, 3 * 256 + 1); - if(ret_value != 3 * 256 + 1){ - av_free_packet(pkt); + if (vid->palette) { + av_log(s, AV_LOG_WARNING, "discarding unused palette\n"); + av_freep(&vid->palette); + } + vid->palette = av_malloc(BVID_PALETTE_SIZE); + if (!vid->palette) + return AVERROR(ENOMEM); + if (avio_read(pb, vid->palette, BVID_PALETTE_SIZE) != BVID_PALETTE_SIZE) { + av_freep(&vid->palette); return AVERROR(EIO); } - pkt->stream_index = 0; - return ret_value; + return vid_read_packet(s, pkt); case FIRST_AUDIO_BLOCK: avio_rl16(pb); @@ -223,6 +238,13 @@ static int vid_read_packet(AVFormatContext *s, } } +static int vid_read_close(AVFormatContext *s) +{ + BVID_DemuxContext *vid = s->priv_data; + av_freep(&vid->palette); + return 0; +} + AVInputFormat ff_bethsoftvid_demuxer = { .name = "bethsoftvid", .long_name = NULL_IF_CONFIG_SMALL("Bethesda Softworks VID format"), @@ -230,4 +252,5 @@ AVInputFormat ff_bethsoftvid_demuxer = { .read_probe = vid_probe, .read_header = vid_read_header, .read_packet = vid_read_packet, + .read_close = vid_read_close, }; -- 1.7.1 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel