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

Reply via email to