From patchwork Sat Jun 17 17:13:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hein-Pieter van Braam X-Patchwork-Id: 4009 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.22.4 with SMTP id 4csp184683vsw; Sat, 17 Jun 2017 10:14:06 -0700 (PDT) X-Received: by 10.223.161.89 with SMTP id r25mr11202848wrr.153.1497719646066; Sat, 17 Jun 2017 10:14:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1497719646; cv=none; d=google.com; s=arc-20160816; b=jiRPbEt/3b7y3Slq1I39aXuGbluRGd/Pgr8laNR8PS7QsSy8oIo4HVvgw7il0qRn/l ku2A8FX6bNj8FUsRbbbe/m9tgRXqkbYJsf+s87vcBfAvBm4mbCmATnzPjGoUONFpU+2s 4VBaGcZ/W/FZpOhiTBvcYAXtAnQ2a8o9AVB+mpq6xTnqf9Z1CtgiSRF5Rsb0HRIw8n6Q gLlv/hYIfUguxAsZkpSxa0e5zBPrwKIpDenmjkvBKKB3Ptsm0s/ASXADaXn8bL+eTozm XqWiDGL6tJCt1rFCHVyMWTTMAr/nH9wb1CK8z45a4ty/W17LH+Cz9WdXFeiQfB8gwCRc gKJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:date:to:from:message-id :dkim-signature:dkim-filter:delivered-to:arc-authentication-results; bh=lU7ugE2BqaSf7GLohb5p23XUBogFD0cK+GAQPhRrHKQ=; b=VSFQqYHzqeewYkIMmtA6kdl6LvS1VpJHsihXnah2aDhsGJteyhhSF/Nu/D2tlOHZ0G MhSaRMYLgki1llQ6c0y5PSM34RInrITCA/1HiFf95Ka4J0ZL1duDReuz4ygzWwMBkBc+ /giso3ymihwELuxwCZLjKuBIqQu5Mi0wk5LF0QvRYGiURXXZI2Da6BRBEYLkLfDYaAmj jlOk8QJWQBnxPXs/El1upKVCO5KboRK1LuYuvEcvKTXBO7tRmGCNcL0sOWS3iI8yo9EZ fHN3EK/NenIPu4kd1xP1bE5PoWSIcMnO5INJtWCoez9nFzKvQoI2L/Srwj0HPIlDcUfj WzYA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@tmm.cx header.b=O/ZUjVrL; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=REJECT dis=NONE) header.from=tmm.cx Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id u74si5613201wrb.292.2017.06.17.10.14.05; Sat, 17 Jun 2017 10:14:06 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@tmm.cx header.b=O/ZUjVrL; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=REJECT dis=NONE) header.from=tmm.cx Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6729968A1EA; Sat, 17 Jun 2017 20:13:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from eva.tmm.cx (eva.tmm.cx [5.9.73.21]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8603668A16C for ; Sat, 17 Jun 2017 20:13:51 +0300 (EEST) Received: from lola (unknown [92.110.172.3]) by eva.tmm.cx (Postfix) with ESMTPSA id 272C117CC474 for ; Sat, 17 Jun 2017 17:13:54 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 eva.tmm.cx 272C117CC474 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tmm.cx; s=mail; t=1497719635; bh=Uptjdf0R+Bnr/px93lJZ6COC+raXnC+OipuGnfuLSIA=; h=Subject:From:To:Date:In-Reply-To:References:From; b=O/ZUjVrLeq0w6aSdMzMePpAAbkaixC3827yE+sKK0L6itElq/Yz/NJgb1gNV0u5iT o7M6KnO/IMHyD4qGCUvuIDKAKv0MZmiAfLF6FSlpbXJNAdjImAI05SLRbFCcq4egh6 mBmTvW7a6QiKle9wx+G/mYulQq5ipk3vA6fextw8= Message-ID: <1497719632.3919.15.camel@tmm.cx> From: Hein-Pieter van Braam To: FFmpeg development discussions and patches Date: Sat, 17 Jun 2017 19:13:52 +0200 In-Reply-To: References: <1497704913.3919.12.camel@tmm.cx> <1497708796.3919.14.camel@tmm.cx> X-Mailer: Evolution 3.22.6 (3.22.6-2.fc25) Mime-Version: 1.0 X-Spam-Status: No, score=0.0 required=2.4 tests=UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on eva.tmm.cx Subject: Re: [FFmpeg-devel] [RFC] Implement support for interplay MVE 0x06, 0x0F and 0x10 X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" On Sat, 2017-06-17 at 18:45 +0200, Paul B Mahol wrote: > Have you made sure that new code does not cause overreads? > > Use bytestream2* for that. > I have made that change, thanks, the code actually looks better now too! Attached is a new version of the patch. Thanks! - HP From e8a45ce4748e395e829c664c61b57e3c2e9d9fc8 Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Fri, 16 Jun 2017 22:02:43 +0200 Subject: [PATCH] Implement support for interplay MVE 0x06 and 0x10 --- libavcodec/interplayvideo.c | 276 +++++++++++++++++++++++++++++++++++++++++--- libavformat/ipmovie.c | 101 ++++++++++++---- 2 files changed, 338 insertions(+), 39 deletions(-) diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index df3314d..d8c6543 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -55,11 +55,21 @@ typedef struct IpvideoContext { HpelDSPContext hdsp; AVFrame *second_last_frame; AVFrame *last_frame; + + /* For format 0x10 */ + AVFrame *cur_decode_frame; + AVFrame *prev_decode_frame; + + uint8_t frame_format; + const unsigned char *skip_map; + int skip_map_size; const unsigned char *decoding_map; int decoding_map_size; + int video_data_size; int is_16bpp; GetByteContext stream_ptr, mv_ptr; + GetByteContext decoding_map_ptr, skip_map_ptr; unsigned char *pixel_ptr; int line_inc; int stride; @@ -903,7 +913,182 @@ static int (* const ipvideo_decode_block16[])(IpvideoContext *s, AVFrame *frame) ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1, }; -static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame) + +static void ipvideo_decode_format_06_opcodes(IpvideoContext *s, AVFrame *frame) +{ + int x, y, off_x, off_y; + short opcode; + + if (!s->is_16bpp) { + /* this is PAL8, so make the palette available */ + memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); + + s->stride = frame->linesize[0]; + } + + s->line_inc = s->stride - 8; + s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0] + + (s->avctx->width - 8) * (1 + s->is_16bpp); + + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + opcode = bytestream2_get_le16(&s->decoding_map_ptr); + + ff_tlog(s->avctx, + " block @ (%3d, %3d): opcode 0x%X, data ptr offset %d\n", + x, y, opcode, bytestream2_tell(&s->stream_ptr)); + + s->pixel_ptr = frame->data[0] + x + y*frame->linesize[0]; + if (! opcode) { + int k; + for (k = 0; k < 8; k++) { + bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8); + s->pixel_ptr += s->stride; + } + } else { + /* Don't try to copy second_last_frame data on the first frame */ + if (s->avctx->frame_number > 2) + copy_from(s, s->second_last_frame, frame, 0, 0); + } + } + } + + bytestream2_seek(&s->decoding_map_ptr, 0, SEEK_SET); + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + opcode = bytestream2_get_le16(&s->decoding_map_ptr); + + ff_tlog(s->avctx, + " block @ (%3d, %3d): opcode 0x%X, data ptr offset %d\n", + x, y, opcode, bytestream2_tell(&s->stream_ptr)); + + s->pixel_ptr = frame->data[0] + x + y*frame->linesize[0]; + if (opcode < 0) { + off_x = ((unsigned short)opcode - 0xC000) % frame->linesize[0]; + off_y = ((unsigned short)opcode - 0xC000) / frame->linesize[0]; + copy_from(s, s->last_frame, frame, off_x, off_y); + } + if (opcode > 0) { + off_x = ((unsigned short)opcode - 0x4000) % frame->linesize[0]; + off_y = ((unsigned short)opcode - 0x4000) / frame->linesize[0]; + copy_from(s, frame, frame, off_x, off_y); + } + } + } + + if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) { + av_log(s->avctx, AV_LOG_DEBUG, + "decode finished with %d bytes left over\n", + bytestream2_get_bytes_left(&s->stream_ptr)); + } +} + +static void ipvideo_decode_format_10_opcodes(IpvideoContext *s, AVFrame *frame) +{ + int x, y, off_x, off_y; + short opcode, skip; + int changed_block = 0; + + if (!s->is_16bpp) { + /* this is PAL8, so make the palette available */ + memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); + + s->stride = frame->linesize[0]; + } + + bytestream2_skip(&s->stream_ptr, 14); /* data starts 14 bytes in */ + + s->line_inc = s->stride - 8; + s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0] + + (s->avctx->width - 8) * (1 + s->is_16bpp); + + skip = bytestream2_get_le16(&s->skip_map_ptr); + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + s->pixel_ptr = s->cur_decode_frame->data[0] + x + y*s->cur_decode_frame->linesize[0]; + + while (skip <= 0) { + if (skip != -0x8000 && skip) { + opcode = bytestream2_get_le16(&s->decoding_map_ptr); + if (! opcode) { + int k; + for (k = 0; k < 8; k++) { + bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8); + s->pixel_ptr += s->stride; + } + } + break; + } + skip = bytestream2_get_le16(&s->skip_map_ptr); + } + skip *= 2; + } + } + + bytestream2_seek(&s->decoding_map_ptr, 0, SEEK_SET); + bytestream2_seek(&s->skip_map_ptr, 0, SEEK_SET); + skip = bytestream2_get_le16(&s->skip_map_ptr); + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + s->pixel_ptr = s->cur_decode_frame->data[0] + x + y*s->cur_decode_frame->linesize[0]; + + while (skip <= 0) { + if (skip != -0x8000 && skip) { + opcode = bytestream2_get_le16(&s->decoding_map_ptr); + if (opcode < 0) { + off_x = ((unsigned short)opcode - 0xC000) % s->cur_decode_frame->linesize[0]; + off_y = ((unsigned short)opcode - 0xC000) / s->cur_decode_frame->linesize[0]; + copy_from(s, s->prev_decode_frame, s->cur_decode_frame, off_x, off_y); + } + if (opcode > 0) { + off_x = ((unsigned short)opcode - 0x4000) % s->cur_decode_frame->linesize[0]; + off_y = ((unsigned short)opcode - 0x4000) / s->cur_decode_frame->linesize[0]; + copy_from(s, s->cur_decode_frame, s->cur_decode_frame, off_x, off_y); + } + break; + } + skip = bytestream2_get_le16(&s->skip_map_ptr); + } + skip *= 2; + } + } + + bytestream2_seek(&s->skip_map_ptr, 0, SEEK_SET); + skip = bytestream2_get_le16(&s->skip_map_ptr); + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + changed_block = 0; + s->pixel_ptr = frame->data[0] + x + y*frame->linesize[0]; + + while (skip <= 0) { + if (skip != -0x8000 && skip) { + changed_block = 1; + break; + } + skip = bytestream2_get_le16(&s->skip_map_ptr); + } + + if (changed_block) { + copy_from(s, s->cur_decode_frame, frame, 0, 0); + } else { + /* Don't try to copy last_frame data on the first frame */ + if (s->avctx->frame_number) + copy_from(s, s->last_frame, frame, 0, 0); + } + skip *= 2; + } + } + + FFSWAP(AVFrame*, s->prev_decode_frame, s->cur_decode_frame); + + if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) { + av_log(s->avctx, AV_LOG_DEBUG, + "decode finished with %d bytes left over\n", + bytestream2_get_bytes_left(&s->stream_ptr)); + } +} + +static void ipvideo_decode_format_11_opcodes(IpvideoContext *s, AVFrame *frame) { int x, y; unsigned char opcode; @@ -972,12 +1157,26 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx) s->last_frame = av_frame_alloc(); s->second_last_frame = av_frame_alloc(); - if (!s->last_frame || !s->second_last_frame) { + s->cur_decode_frame = av_frame_alloc(); + s->prev_decode_frame = av_frame_alloc(); + if (!s->last_frame || !s->second_last_frame || + !s->cur_decode_frame || !s->prev_decode_frame) { 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 AVERROR(ENOMEM); } + s->cur_decode_frame->width = avctx->width; + s->prev_decode_frame->width = avctx->width; + s->cur_decode_frame->height = avctx->height; + s->prev_decode_frame->height = avctx->height; + s->cur_decode_frame->format = avctx->pix_fmt; + s->prev_decode_frame->format = avctx->pix_fmt; + + ff_get_buffer(avctx, s->cur_decode_frame, 0); + ff_get_buffer(avctx, s->prev_decode_frame, 0); return 0; } @@ -999,18 +1198,56 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, if (buf_size < 2) return AVERROR_INVALIDDATA; - /* decoding map contains 4 bits of information per 8x8 block */ - 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 + 2) - return buf_size; - - - s->decoding_map = buf + 2; - bytestream2_init(&s->stream_ptr, buf + 2 + s->decoding_map_size, - buf_size - s->decoding_map_size); + s->frame_format = AV_RB8(avpkt->data); + switch (s->frame_format) { + case 0x06: + /* Format 0x06 has decoding map appended to the top of pixel data */ + /* decoding map contains 16 bits of information per 8x8 block */ + s->decoding_map_size = ((s->avctx->width / 8) * (s->avctx->height / 8)) * 2; + s->decoding_map = buf + 3 + 14; /* 14 bits of op data */ + + s->video_data_size = AV_RL16(avpkt->data + 1) - s->decoding_map_size - 14; + bytestream2_init(&s->stream_ptr, buf + 3 + s->decoding_map_size + 14, s->video_data_size); + bytestream2_init(&s->decoding_map_ptr, s->decoding_map, s->decoding_map_size); + + if (buf_size < s->decoding_map_size + 2) + return buf_size; + break; + + case 0x10: + /* Format 0x10 has a decoding map, pixel data, and a skip map */ + s->video_data_size = AV_RL16(avpkt->data + 1); + bytestream2_init(&s->stream_ptr, buf + 3, s->video_data_size); + + /* decoding map contains 16 bits of information per 8x8 block */ + s->decoding_map_size = AV_RL16(avpkt->data + 3 + s->video_data_size); + s->decoding_map = buf + 3 + s->video_data_size + 2; + bytestream2_init(&s->decoding_map_ptr, s->decoding_map, s->decoding_map_size); + + /* skip map contains 16 bits of information per 15 blocks, ish */ + s->skip_map_size = AV_RL16(avpkt->data + 3 + s->video_data_size + 2 + s->decoding_map_size); + s->skip_map = buf + 3 + s->video_data_size + 2 + s->decoding_map_size + 2; + bytestream2_init(&s->skip_map_ptr, s->skip_map, s->skip_map_size); + break; + + case 0x11: + /* Format 0x11 has a decoding map and pixel data */ + s->video_data_size = AV_RL16(avpkt->data + 1); + bytestream2_init(&s->stream_ptr, buf + 3, s->video_data_size); + + /* decoding map contains 4 bits of information per 8x8 block */ + s->decoding_map_size = AV_RL16(avpkt->data + 3 + s->video_data_size); + s->decoding_map = buf + 3 + s->video_data_size + 2; + + /* compressed buffer needs to be large enough to at least hold an entire + * decoding map */ + if (buf_size < s->decoding_map_size + 2) + return buf_size; + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Frame type 0x%02X unsupported\n", s->frame_format); + } if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; @@ -1026,7 +1263,14 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, } } - ipvideo_decode_opcodes(s, frame); + if (s->frame_format == 0x06) + ipvideo_decode_format_06_opcodes(s, frame); + + if (s->frame_format == 0x10) + ipvideo_decode_format_10_opcodes(s, frame); + + if (s->frame_format == 0x11) + ipvideo_decode_format_11_opcodes(s, frame); *got_frame = 1; @@ -1046,6 +1290,8 @@ static av_cold int ipvideo_decode_end(AVCodecContext *avctx) 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 0; } diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c index a83909f..3c4d85c 100644 --- a/libavformat/ipmovie.c +++ b/libavformat/ipmovie.c @@ -58,7 +58,7 @@ #define OPCODE_INIT_AUDIO_BUFFERS 0x03 #define OPCODE_START_STOP_AUDIO 0x04 #define OPCODE_INIT_VIDEO_BUFFERS 0x05 -#define OPCODE_UNKNOWN_06 0x06 +#define OPCODE_VIDEO_DATA_06 0x06 #define OPCODE_SEND_BUFFER 0x07 #define OPCODE_AUDIO_FRAME 0x08 #define OPCODE_SILENCE_FRAME 0x09 @@ -66,10 +66,10 @@ #define OPCODE_CREATE_GRADIENT 0x0B #define OPCODE_SET_PALETTE 0x0C #define OPCODE_SET_PALETTE_COMPRESSED 0x0D -#define OPCODE_UNKNOWN_0E 0x0E +#define OPCODE_SET_SKIP_MAP 0x0E #define OPCODE_SET_DECODING_MAP 0x0F -#define OPCODE_UNKNOWN_10 0x10 -#define OPCODE_VIDEO_DATA 0x11 +#define OPCODE_VIDEO_DATA_10 0x10 +#define OPCODE_VIDEO_DATA_11 0x11 #define OPCODE_UNKNOWN_12 0x12 #define OPCODE_UNKNOWN_13 0x13 #define OPCODE_UNKNOWN_14 0x14 @@ -91,6 +91,7 @@ typedef struct IPMVEContext { uint32_t palette[256]; int has_palette; int changed; + uint8_t frame_format; unsigned int audio_bits; unsigned int audio_channels; @@ -105,6 +106,8 @@ typedef struct IPMVEContext { int audio_chunk_size; int64_t video_chunk_offset; int video_chunk_size; + int64_t skip_map_chunk_offset; + int skip_map_chunk_size; int64_t decode_map_chunk_offset; int decode_map_chunk_size; @@ -152,11 +155,11 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, chunk_type = CHUNK_VIDEO; - } else if (s->decode_map_chunk_offset) { + } else if (s->frame_format) { + av_log(s->avf, AV_LOG_TRACE, "frame format 0x%02X\n", s->frame_format); - /* send both the decode map and the video data together */ - - if (av_new_packet(pkt, 2 + s->decode_map_chunk_size + s->video_chunk_size)) + /* send video data, skip map, and decode map together */ + if (av_new_packet(pkt, 1 + 2 + s->video_chunk_size + 2 + s->decode_map_chunk_size + 2 + s->skip_map_chunk_size)) return CHUNK_NOMEM; if (s->has_palette) { @@ -174,26 +177,47 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height); s->changed = 0; } - pkt->pos= s->decode_map_chunk_offset; - avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET); - s->decode_map_chunk_offset = 0; - 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_packet_unref(pkt); - return CHUNK_EOF; - } + AV_WB8(pkt->data, s->frame_format); + s->frame_format = 0; + pkt->pos= s->video_chunk_offset; avio_seek(pb, s->video_chunk_offset, SEEK_SET); s->video_chunk_offset = 0; - if (avio_read(pb, pkt->data + 2 + s->decode_map_chunk_size, - s->video_chunk_size) != s->video_chunk_size) { + AV_WL16(pkt->data + 1, s->video_chunk_size); + if (avio_read(pb, pkt->data + 3, s->video_chunk_size) != + s->video_chunk_size) { av_packet_unref(pkt); return CHUNK_EOF; } + if (s->decode_map_chunk_size) { + pkt->pos= s->decode_map_chunk_offset; + avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET); + s->decode_map_chunk_offset = 0; + + AV_WL16(pkt->data + 3 + s->video_chunk_size, s->decode_map_chunk_size); + if (avio_read(pb, pkt->data + 3 + s->video_chunk_size + 2, s->decode_map_chunk_size) != + s->decode_map_chunk_size) { + av_packet_unref(pkt); + return CHUNK_EOF; + } + } + + if (s->skip_map_chunk_size) { + pkt->pos= s->skip_map_chunk_offset; + avio_seek(pb, s->skip_map_chunk_offset, SEEK_SET); + s->skip_map_chunk_offset = 0; + + AV_WL16(pkt->data + 3 + s->video_chunk_size + 2 + s->decode_map_chunk_size, s->skip_map_chunk_size); + if (avio_read(pb, pkt->data + 3 + s->video_chunk_size + 2 + s->decode_map_chunk_size + 2, s->skip_map_chunk_size) != + s->skip_map_chunk_size) { + av_packet_unref(pkt); + return CHUNK_EOF; + } + } + pkt->stream_index = s->video_stream_index; pkt->pts = s->video_pts; @@ -430,9 +454,6 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, s->video_width, s->video_height); break; - case OPCODE_UNKNOWN_06: - case OPCODE_UNKNOWN_0E: - case OPCODE_UNKNOWN_10: case OPCODE_UNKNOWN_12: case OPCODE_UNKNOWN_13: case OPCODE_UNKNOWN_14: @@ -513,6 +534,15 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, avio_skip(pb, opcode_size); break; + case OPCODE_SET_SKIP_MAP: + av_log(s->avf, AV_LOG_TRACE, "set skip map\n"); + + /* log position and move on for now */ + s->skip_map_chunk_offset = avio_tell(pb); + s->skip_map_chunk_size = opcode_size; + avio_skip(pb, opcode_size); + break; + case OPCODE_SET_DECODING_MAP: av_log(s->avf, AV_LOG_TRACE, "set decoding map\n"); @@ -522,8 +552,29 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, avio_skip(pb, opcode_size); break; - case OPCODE_VIDEO_DATA: - av_log(s->avf, AV_LOG_TRACE, "set video data\n"); + case OPCODE_VIDEO_DATA_06: + av_log(s->avf, AV_LOG_TRACE, "set video data type 0x06\n"); + s->frame_format = 0x06; + + /* log position and move on for now */ + s->video_chunk_offset = avio_tell(pb); + s->video_chunk_size = opcode_size; + avio_skip(pb, opcode_size); + break; + + case OPCODE_VIDEO_DATA_10: + av_log(s->avf, AV_LOG_TRACE, "set video data type 0x10\n"); + s->frame_format = 0x10; + + /* log position and move on for now */ + s->video_chunk_offset = avio_tell(pb); + s->video_chunk_size = opcode_size; + avio_skip(pb, opcode_size); + break; + + case OPCODE_VIDEO_DATA_11: + av_log(s->avf, AV_LOG_TRACE, "set video data type 0x11\n"); + s->frame_format = 0x11; /* log position and move on for now */ s->video_chunk_offset = avio_tell(pb); @@ -587,8 +638,10 @@ static int ipmovie_read_header(AVFormatContext *s) return AVERROR_EOF; } /* initialize private context members */ + ipmovie->frame_format = 0; ipmovie->video_pts = ipmovie->audio_frame_count = 0; ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset = + ipmovie->skip_map_chunk_offset = 0; ipmovie->decode_map_chunk_offset = 0; /* on the first read, this will position the stream at the first chunk */ -- 2.9.4