avformat/ipmovie: put video decoding_map_size into packet and use it in decoder
authorPaul B Mahol <onemda@gmail.com>
Sun, 1 Nov 2015 16:02:26 +0000 (17:02 +0100)
committerAndreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
Thu, 28 Jan 2016 00:50:33 +0000 (01:50 +0100)
The size of decoding map can differ from one calculated
internally, producing artifacts while decoding video.

Signed-off-by: Paul B Mahol <onemda@gmail.com>
(cherry picked from commit c293ef258cbb2c058e23651a26edf46e3bc05050)
Signed-off-by: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
libavcodec/interplayvideo.c
libavformat/ipmovie.c

index 96c0cd1..f9e74b0 100644 (file)
@@ -38,6 +38,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "libavutil/intreadwrite.h"
 #include "avcodec.h"
 #include "bytestream.h"
 #include "hpeldsp.h"
@@ -949,7 +950,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame)
         }
     }
     if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) {
-        av_log(s->avctx, AV_LOG_ERROR,
+        av_log(s->avctx, AV_LOG_DEBUG,
                "decode finished with %d bytes left over\n",
                bytestream2_get_bytes_left(&s->stream_ptr));
     }
@@ -987,12 +988,15 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
     AVFrame *frame = data;
     int ret;
 
+    if (buf_size < 2)
+        return AVERROR_INVALIDDATA;
+
     /* decoding map contains 4 bits of information per 8x8 block */
-    s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
+    s->decoding_map_size = AV_RL16(avpkt->data);
 
     /* compressed buffer needs to be large enough to at least hold an entire
      * decoding map */
-    if (buf_size < s->decoding_map_size)
+    if (buf_size < s->decoding_map_size + 2)
         return buf_size;
 
     if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
@@ -1000,8 +1004,8 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
         av_frame_unref(s->second_last_frame);
     }
 
-    s->decoding_map = buf;
-    bytestream2_init(&s->stream_ptr, buf + s->decoding_map_size,
+    s->decoding_map = buf + 2;
+    bytestream2_init(&s->stream_ptr, buf + 2 + s->decoding_map_size,
                      buf_size - s->decoding_map_size);
 
     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
index 01e70e8..0112009 100644 (file)
@@ -156,7 +156,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
 
         /* send both the decode map and the video data together */
 
-        if (av_new_packet(pkt, s->decode_map_chunk_size + s->video_chunk_size))
+        if (av_new_packet(pkt, 2 + s->decode_map_chunk_size + s->video_chunk_size))
             return CHUNK_NOMEM;
 
         if (s->has_palette) {
@@ -178,7 +178,8 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
         avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
         s->decode_map_chunk_offset = 0;
 
-        if (avio_read(pb, pkt->data, s->decode_map_chunk_size) !=
+        AV_WL16(pkt->data, s->decode_map_chunk_size);
+        if (avio_read(pb, pkt->data + 2, s->decode_map_chunk_size) !=
             s->decode_map_chunk_size) {
             av_free_packet(pkt);
             return CHUNK_EOF;
@@ -187,7 +188,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
         avio_seek(pb, s->video_chunk_offset, SEEK_SET);
         s->video_chunk_offset = 0;
 
-        if (avio_read(pb, pkt->data + s->decode_map_chunk_size,
+        if (avio_read(pb, pkt->data + 2 + s->decode_map_chunk_size,
             s->video_chunk_size) != s->video_chunk_size) {
             av_free_packet(pkt);
             return CHUNK_EOF;