X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Finterplayvideo.c;h=bd1d7c74ba8380d80a235c3b65ccc1386a227eca;hb=1c7f252783aec37e4ff8049476386f63afe91756;hp=deaa09cba60ff4e9319bb121c794b1ab8717be20;hpb=fda424b300c1a0b991296aa585691609d01196bd;p=ffmpeg diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index deaa09cba60..bd1d7c74ba8 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -43,6 +43,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "decode.h" #include "get_bits.h" #include "hpeldsp.h" #include "internal.h" @@ -77,9 +78,14 @@ typedef struct IpvideoContext { static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y) { + int width = dst->width; int current_offset = s->pixel_ptr - dst->data[0]; - int motion_offset = current_offset + delta_y * dst->linesize[0] - + delta_x * (1 + s->is_16bpp); + int x = (current_offset % dst->linesize[0]) / (1 + s->is_16bpp); + int y = current_offset / dst->linesize[0]; + int dx = delta_x + x - ((delta_x + x >= width) - (delta_x + x < 0)) * width; + int dy = delta_y + y + (delta_x + x >= width) - (delta_x + x < 0); + int motion_offset = dy * src->linesize[0] + dx * (1 + s->is_16bpp); + if (motion_offset < 0) { av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset); return AVERROR_INVALIDDATA; @@ -931,12 +937,12 @@ static void ipvideo_format_06_secondpass(IpvideoContext *s, AVFrame *frame, int1 int off_x, off_y; if (opcode < 0) { - off_x = ((uint16_t)opcode - 0xC000) % frame->linesize[0]; - off_y = ((uint16_t)opcode - 0xC000) / frame->linesize[0]; + off_x = ((uint16_t)opcode - 0xC000) % frame->width; + off_y = ((uint16_t)opcode - 0xC000) / frame->width; copy_from(s, s->last_frame, frame, off_x, off_y); } else if (opcode > 0) { - off_x = ((uint16_t)opcode - 0x4000) % frame->linesize[0]; - off_y = ((uint16_t)opcode - 0x4000) / frame->linesize[0]; + off_x = ((uint16_t)opcode - 0x4000) % frame->width; + off_y = ((uint16_t)opcode - 0x4000) / frame->width; copy_from(s, frame, frame, off_x, off_y); } } @@ -1001,12 +1007,12 @@ static void ipvideo_format_10_secondpass(IpvideoContext *s, AVFrame *frame, int1 int off_x, off_y; if (opcode < 0) { - off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->linesize[0]; - off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->linesize[0]; + off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->width; + off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->width; copy_from(s, s->prev_decode_frame, s->cur_decode_frame, off_x, off_y); } else if (opcode > 0) { - off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->linesize[0]; - off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->linesize[0]; + off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->width; + off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->width; copy_from(s, s->cur_decode_frame, s->cur_decode_frame, off_x, off_y); } } @@ -1155,7 +1161,6 @@ static void ipvideo_decode_format_11_opcodes(IpvideoContext *s, AVFrame *frame) static av_cold int ipvideo_decode_init(AVCodecContext *avctx) { IpvideoContext *s = avctx->priv_data; - int ret; s->avctx = avctx; @@ -1170,8 +1175,7 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx) s->prev_decode_frame = av_frame_alloc(); if (!s->last_frame || !s->second_last_frame || !s->cur_decode_frame || !s->prev_decode_frame) { - ret = AVERROR(ENOMEM); - goto error; + return AVERROR(ENOMEM); } s->cur_decode_frame->width = avctx->width; @@ -1181,21 +1185,7 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx) s->cur_decode_frame->format = avctx->pix_fmt; s->prev_decode_frame->format = avctx->pix_fmt; - ret = ff_get_buffer(avctx, s->cur_decode_frame, 0); - if (ret < 0) - goto error; - - ret = ff_get_buffer(avctx, s->prev_decode_frame, 0); - if (ret < 0) - goto error; - return 0; -error: - av_frame_free(&s->last_frame); - av_frame_free(&s->second_last_frame); - av_frame_free(&s->cur_decode_frame); - av_frame_free(&s->prev_decode_frame); - return ret; } static int ipvideo_decode_frame(AVCodecContext *avctx, @@ -1239,83 +1229,83 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, s->decoding_map_size = AV_RL16(buf + 4); s->skip_map_size = AV_RL16(buf + 6); - switch(frame_format) { - case 0x06: - if (s->decoding_map_size) { - av_log(avctx, AV_LOG_ERROR, "Decoding map for format 0x06\n"); - return AVERROR_INVALIDDATA; - } + switch (frame_format) { + case 0x06: + if (s->decoding_map_size) { + av_log(avctx, AV_LOG_ERROR, "Decoding map for format 0x06\n"); + return AVERROR_INVALIDDATA; + } - if (s->skip_map_size) { - av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x06\n"); - return AVERROR_INVALIDDATA; - } + if (s->skip_map_size) { + av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x06\n"); + return AVERROR_INVALIDDATA; + } - if (s->is_16bpp) { - av_log(avctx, AV_LOG_ERROR, "Video format 0x06 does not support 16bpp movies\n"); - return AVERROR_INVALIDDATA; - } + if (s->is_16bpp) { + av_log(avctx, AV_LOG_ERROR, "Video format 0x06 does not support 16bpp movies\n"); + return AVERROR_INVALIDDATA; + } - /* Decoding map for 0x06 frame format is at the top of pixeldata */ - s->decoding_map_size = ((s->avctx->width / 8) * (s->avctx->height / 8)) * 2; - s->decoding_map = buf + 8 + 14; /* 14 bits of op data */ - video_data_size -= s->decoding_map_size + 14; - if (video_data_size <= 0) - return AVERROR_INVALIDDATA; + /* Decoding map for 0x06 frame format is at the top of pixeldata */ + s->decoding_map_size = ((s->avctx->width / 8) * (s->avctx->height / 8)) * 2; + s->decoding_map = buf + 8 + 14; /* 14 bits of op data */ + video_data_size -= s->decoding_map_size + 14; + if (video_data_size <= 0 || s->decoding_map_size == 0) + return AVERROR_INVALIDDATA; - if (buf_size < 8 + s->decoding_map_size + 14 + video_data_size) - return AVERROR_INVALIDDATA; + if (buf_size < 8 + s->decoding_map_size + 14 + video_data_size) + return AVERROR_INVALIDDATA; - bytestream2_init(&s->stream_ptr, buf + 8 + s->decoding_map_size + 14, video_data_size); + bytestream2_init(&s->stream_ptr, buf + 8 + s->decoding_map_size + 14, video_data_size); - break; + break; - case 0x10: - if (! s->decoding_map_size) { - av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x10\n"); - return AVERROR_INVALIDDATA; - } + case 0x10: + if (! s->decoding_map_size) { + av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x10\n"); + return AVERROR_INVALIDDATA; + } - if (! s->skip_map_size) { - av_log(avctx, AV_LOG_ERROR, "Empty skip map for format 0x10\n"); - return AVERROR_INVALIDDATA; - } + if (! s->skip_map_size) { + av_log(avctx, AV_LOG_ERROR, "Empty skip map for format 0x10\n"); + return AVERROR_INVALIDDATA; + } - if (s->is_16bpp) { - av_log(avctx, AV_LOG_ERROR, "Video format 0x10 does not support 16bpp movies\n"); - return AVERROR_INVALIDDATA; - } + if (s->is_16bpp) { + av_log(avctx, AV_LOG_ERROR, "Video format 0x10 does not support 16bpp movies\n"); + return AVERROR_INVALIDDATA; + } - if (buf_size < 8 + video_data_size + s->decoding_map_size + s->skip_map_size) - return AVERROR_INVALIDDATA; + if (buf_size < 8 + video_data_size + s->decoding_map_size + s->skip_map_size) + return AVERROR_INVALIDDATA; - bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); - s->decoding_map = buf + 8 + video_data_size; - s->skip_map = buf + 8 + video_data_size + s->decoding_map_size; + bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); + s->decoding_map = buf + 8 + video_data_size; + s->skip_map = buf + 8 + video_data_size + s->decoding_map_size; - break; + break; - case 0x11: - if (! s->decoding_map_size) { - av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x11\n"); - return AVERROR_INVALIDDATA; - } + case 0x11: + if (! s->decoding_map_size) { + av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x11\n"); + return AVERROR_INVALIDDATA; + } - if (s->skip_map_size) { - av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x11\n"); - return AVERROR_INVALIDDATA; - } + if (s->skip_map_size) { + av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x11\n"); + return AVERROR_INVALIDDATA; + } - if (buf_size < 8 + video_data_size + s->decoding_map_size) - return AVERROR_INVALIDDATA; + if (buf_size < 8 + video_data_size + s->decoding_map_size) + return AVERROR_INVALIDDATA; - bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); - s->decoding_map = buf + 8 + video_data_size; + bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); + s->decoding_map = buf + 8 + video_data_size; - break; + break; - default: - av_log(avctx, AV_LOG_ERROR, "Frame type 0x%02X unsupported\n", frame_format); + default: + av_log(avctx, AV_LOG_ERROR, "Frame type 0x%02X unsupported\n", frame_format); } /* ensure we can't overread the packet */ @@ -1328,26 +1318,19 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, return ret; if (!s->is_16bpp) { - int size; - const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); - if (pal && size == AVPALETTE_SIZE) { - frame->palette_has_changed = 1; - memcpy(s->pal, pal, AVPALETTE_SIZE); - } else if (pal) { - av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size); - } + frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); } - switch(frame_format) { - case 0x06: - ipvideo_decode_format_06_opcodes(s, frame); - break; - case 0x10: - ipvideo_decode_format_10_opcodes(s, frame); - break; - case 0x11: - ipvideo_decode_format_11_opcodes(s, frame); - break; + switch (frame_format) { + case 0x06: + ipvideo_decode_format_06_opcodes(s, frame); + break; + case 0x10: + ipvideo_decode_format_10_opcodes(s, frame); + break; + case 0x11: + ipvideo_decode_format_11_opcodes(s, frame); + break; } *got_frame = send_buffer; @@ -1374,7 +1357,7 @@ static av_cold int ipvideo_decode_end(AVCodecContext *avctx) return 0; } -AVCodec ff_interplay_video_decoder = { +const AVCodec ff_interplay_video_decoder = { .name = "interplayvideo", .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"), .type = AVMEDIA_TYPE_VIDEO, @@ -1384,4 +1367,5 @@ AVCodec ff_interplay_video_decoder = { .close = ipvideo_decode_end, .decode = ipvideo_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, };