Commit c293ef25 authored by Paul B Mahol's avatar Paul B Mahol

avformat/ipmovie: put video decoding_map_size into packet and use it in decoder

The size of decoding map can differ from one calculated
internally, producing artifacts while decoding video.
Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent dee74405
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "libavutil/intreadwrite.h"
#include "avcodec.h" #include "avcodec.h"
#include "bytestream.h" #include "bytestream.h"
#include "hpeldsp.h" #include "hpeldsp.h"
...@@ -949,7 +950,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame) ...@@ -949,7 +950,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame)
} }
} }
if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) { 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", "decode finished with %d bytes left over\n",
bytestream2_get_bytes_left(&s->stream_ptr)); bytestream2_get_bytes_left(&s->stream_ptr));
} }
...@@ -987,12 +988,15 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, ...@@ -987,12 +988,15 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
AVFrame *frame = data; AVFrame *frame = data;
int ret; int ret;
if (buf_size < 2)
return AVERROR_INVALIDDATA;
/* decoding map contains 4 bits of information per 8x8 block */ /* 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 /* compressed buffer needs to be large enough to at least hold an entire
* decoding map */ * decoding map */
if (buf_size < s->decoding_map_size) if (buf_size < s->decoding_map_size + 2)
return buf_size; return buf_size;
if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) { if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
...@@ -1000,8 +1004,8 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, ...@@ -1000,8 +1004,8 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
av_frame_unref(s->second_last_frame); av_frame_unref(s->second_last_frame);
} }
s->decoding_map = buf; s->decoding_map = buf + 2;
bytestream2_init(&s->stream_ptr, buf + s->decoding_map_size, bytestream2_init(&s->stream_ptr, buf + 2 + s->decoding_map_size,
buf_size - s->decoding_map_size); buf_size - s->decoding_map_size);
if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
......
...@@ -156,7 +156,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -156,7 +156,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
/* send both the decode map and the video data together */ /* 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; return CHUNK_NOMEM;
if (s->has_palette) { if (s->has_palette) {
...@@ -178,7 +178,8 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -178,7 +178,8 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET); avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
s->decode_map_chunk_offset = 0; 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) { s->decode_map_chunk_size) {
av_packet_unref(pkt); av_packet_unref(pkt);
return CHUNK_EOF; return CHUNK_EOF;
...@@ -187,7 +188,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -187,7 +188,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
avio_seek(pb, s->video_chunk_offset, SEEK_SET); avio_seek(pb, s->video_chunk_offset, SEEK_SET);
s->video_chunk_offset = 0; 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) { s->video_chunk_size) != s->video_chunk_size) {
av_packet_unref(pkt); av_packet_unref(pkt);
return CHUNK_EOF; return CHUNK_EOF;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment