diff options
Diffstat (limited to 'libavcodec/interplayvideo.c')
-rw-r--r-- | libavcodec/interplayvideo.c | 80 |
1 files changed, 56 insertions, 24 deletions
diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index f0a770a519..1460741a53 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -1,21 +1,21 @@ /* * Interplay MVE Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg Project * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -38,6 +38,7 @@ #include <stdlib.h> #include <string.h> +#include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" #include "hpeldsp.h" @@ -72,10 +73,10 @@ static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int motion_offset = current_offset + delta_y * dst->linesize[0] + delta_x * (1 + s->is_16bpp); if (motion_offset < 0) { - av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset); + av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset); return AVERROR_INVALIDDATA; } else if (motion_offset > s->upper_motion_limit_offset) { - av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n", + av_log(s->avctx, AV_LOG_ERROR, "motion offset above limit (%d >= %d)\n", motion_offset, s->upper_motion_limit_offset); return AVERROR_INVALIDDATA; } @@ -118,7 +119,7 @@ static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s, AVFrame *frame) y = 8 + ((B - 56) / 29); } - ff_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + ff_tlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); return copy_from(s, s->second_last_frame, frame, x, y); } @@ -144,7 +145,7 @@ static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s, AVFrame *frame) y = -( 8 + ((B - 56) / 29)); } - ff_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + ff_tlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); return copy_from(s, frame, frame, x, y); } @@ -165,7 +166,7 @@ static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s, AVFrame *frame) x = -8 + BL; y = -8 + BH; - ff_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + ff_tlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); return copy_from(s, s->last_frame, frame, x, y); } @@ -178,14 +179,14 @@ static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s, AVFrame *frame) x = bytestream2_get_byte(&s->stream_ptr); y = bytestream2_get_byte(&s->stream_ptr); - ff_dlog(NULL, " motion bytes = %d, %d\n", x, y); + ff_tlog(s->avctx, "motion bytes = %d, %d\n", x, y); return copy_from(s, s->last_frame, frame, x, y); } static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s, AVFrame *frame) { /* mystery opcode? skip multiple blocks? */ - av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n"); + av_log(s->avctx, AV_LOG_ERROR, "Help! Mystery opcode 0x6 seen\n"); /* report success */ return 0; @@ -197,6 +198,11 @@ static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s, AVFrame *frame) unsigned char P[2]; unsigned int flags; + if (bytestream2_get_bytes_left(&s->stream_ptr) < 4) { + av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0x7\n"); + return AVERROR_INVALIDDATA; + } + /* 2-color encoding */ P[0] = bytestream2_get_byte(&s->stream_ptr); P[1] = bytestream2_get_byte(&s->stream_ptr); @@ -236,6 +242,11 @@ static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s, AVFrame *frame) unsigned char P[4]; unsigned int flags = 0; + if (bytestream2_get_bytes_left(&s->stream_ptr) < 12) { + av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0x8\n"); + return AVERROR_INVALIDDATA; + } + /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on * either top and bottom or left and right halves */ P[0] = bytestream2_get_byte(&s->stream_ptr); @@ -308,6 +319,11 @@ static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s, AVFrame *frame) int x, y; unsigned char P[4]; + if (bytestream2_get_bytes_left(&s->stream_ptr) < 8) { + av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0x9\n"); + return AVERROR_INVALIDDATA; + } + /* 4-color encoding */ bytestream2_get_buffer(&s->stream_ptr, P, 4); @@ -374,6 +390,11 @@ static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s, AVFrame *frame) unsigned char P[8]; int flags = 0; + if (bytestream2_get_bytes_left(&s->stream_ptr) < 16) { + av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0xA\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_get_buffer(&s->stream_ptr, P, 4); /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on @@ -467,6 +488,11 @@ static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s, AVFrame *frame) int y; unsigned char P[2]; + if (bytestream2_get_bytes_left(&s->stream_ptr) < 4) { + av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0xD\n"); + return AVERROR_INVALIDDATA; + } + /* 4-color block encoding: each 4x4 block is a different color */ for (y = 0; y < 8; y++) { if (!(y & 3)) { @@ -528,7 +554,7 @@ static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s, AVFrame *frame) x = bytestream2_get_byte(&s->stream_ptr); y = bytestream2_get_byte(&s->stream_ptr); - ff_dlog(NULL, " motion bytes = %d, %d\n", x, y); + ff_tlog(s->avctx, "motion bytes = %d, %d\n", x, y); return copy_from(s, s->second_last_frame, frame, x, y); } @@ -903,7 +929,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame) for (x = 0; x < s->avctx->width; x += 8) { opcode = get_bits(&gb, 4); - ff_dlog(s->avctx, + ff_tlog(s->avctx, " block @ (%3d, %3d): encoding 0x%X, data ptr offset %d\n", x, y, opcode, bytestream2_tell(&s->stream_ptr)); @@ -917,15 +943,15 @@ static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame) ret = ipvideo_decode_block16[opcode](s, frame); } if (ret != 0) { - av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n", + av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n", s->avctx->frame_number, x, y); return; } } } if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) { - av_log(s->avctx, AV_LOG_ERROR, - "Interplay video: decode finished with %d bytes left over\n", + av_log(s->avctx, AV_LOG_DEBUG, + "decode finished with %d bytes left over\n", bytestream2_get_bytes_left(&s->stream_ptr)); } } @@ -962,22 +988,28 @@ 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; - s->decoding_map = buf; - bytestream2_init(&s->stream_ptr, buf + s->decoding_map_size, + if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) { + av_frame_unref(s->last_frame); + av_frame_unref(s->second_last_frame); + } + + 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) { - av_log(avctx, AV_LOG_ERROR, " Interplay Video: get_buffer() failed\n"); + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - } if (!s->is_16bpp) { const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); |