From patchwork Sat Jun 17 14:13:16 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: 4007 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.22.4 with SMTP id 4csp129607vsw; Sat, 17 Jun 2017 07:13:29 -0700 (PDT) X-Received: by 10.28.198.3 with SMTP id w3mr10701216wmf.112.1497708809409; Sat, 17 Jun 2017 07:13:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1497708809; cv=none; d=google.com; s=arc-20160816; b=MZg6dAuDxUAWLYIeWQZgDAsOEOt4D4/3NE1x6ZnBaJEa2QVue2sSIyJgZjXH/BtAlB zh2oEzmpvbFPXRDmkhduIRRKd491VuBMfxHLhmytqnEgLWE5DKXyMXuEUnC/S4a4v4Cr +fIvP9HMoDayq02VC786EJPUkiNujhTqKVUjtp8ZbOm5wYEvGsH8MnVAEs41Z6M4N/iD ahJ8pDH3YLLJUJ1GDrQf1L9opyEWAZvfFn2jwOGiMPOMP5+CJ6MbGnBGgMd6DToMpg9J jeINAqYwpJMq7maBBqJi0TRUToEL4mHZ3E2nwyZG9ZqoMzwUpsc/0ygozKiu7Wpfl3O0 PwQA== 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=lhmMLhX7odhrf4XfXcQtNEv7z6FIrcm5IVUbaubTmhc=; b=Nbe9vCGKiaxOMSMN8PM+0Gs1xpYUV+YZgn8VOOvc+tgAsT1DSSrJx6QGPPZ0szTw2r QxsQGIqMu7IMx0nagXKD3mxXapNrbF55Yyw2eBc2qfqFhJqFV6hjhOQ9qPuXF/tdBJKC bPlhOh4IrriH7ZPN0TtRc3+VEq0uq3h0a0/3diF2Gxkj7Ra4LY8uhoS8RXSIgbWjWTVV uCxLY2BY7ndRSAkXvX4byP42t7eRbOnDhnjVG6oR0u4K/GyvwZ+Bi1nUgJTlKoHy8FOG U7AenYktTPasVeZzJPa6XPbZi7IrL8S8Nh7t1KlT7B7OS//PiTsANTzK5MKOMu4c3z/7 uaYA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@tmm.cx header.b=HI0r7Ul5; 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 y123si1781503wmd.16.2017.06.17.07.13.27; Sat, 17 Jun 2017 07:13:29 -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=HI0r7Ul5; 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 5F3C3689F73; Sat, 17 Jun 2017 17:13:20 +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 6832A689F2C for ; Sat, 17 Jun 2017 17:13:14 +0300 (EEST) Received: from lola (unknown [92.110.172.3]) by eva.tmm.cx (Postfix) with ESMTPSA id C450217CB698 for ; Sat, 17 Jun 2017 14:13:16 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 eva.tmm.cx C450217CB698 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tmm.cx; s=mail; t=1497708798; bh=wCALONCWMQsG4HO03PhvCyzmVBWSIn8rock8gUErbfw=; h=Subject:From:To:Date:In-Reply-To:References:From; b=HI0r7Ul5MJhLH0+h71BhMr/7pWIZ/qOzCC/y4Bus8L++gCxsY7Rn8qXxr260D9Lod DXPvyLZ4xVnBGBWq24I+2m/wYrs8tQmdMGkuOJuBKs1QFxr1wReVUxV+l3joXrBbtk KyH+PqVC9qtZ/VLYk4VcKEihfM2gY7FIua2iZiRg= Message-ID: <1497708796.3919.14.camel@tmm.cx> From: Hein-Pieter van Braam To: FFmpeg development discussions and patches Date: Sat, 17 Jun 2017 16:13:16 +0200 In-Reply-To: <1497704913.3919.12.camel@tmm.cx> References: <1497704913.3919.12.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" Hi all, I seemed to have done something wrong when fixing the patchcheck problems originally. Apparently I didn't build between making my 'fixes' and creating the patch. The previous patch doesn't compile. I fixed this in this version, my apologies for the noise. I've also fixed reading garbage data from the 'last frame' on the very first frame. - HP On Sat, 2017-06-17 at 15:08 +0200, Hein-Pieter van Braam wrote: > Hi all, > > This patch implements support for 3 previously unknown Interplay MVE > opcodes. These opcodes together implement support for 2 additional > video frame formats. > > This is my first time trying to contribute to ffmpeg so I expect this > code to not be entirely up to snuff, I'm interested in getting this > merged so any comments are welcome and I'll make any necessary > changes. > I have ran patchcheck over it and fix most of the issues it found. > > I'm working with Multimedia Mike to get these opcodes documented on > the > multimedia.cx wiki. > > You may notice something strange going on with decoding opcode 10 > movies, the reason for that is that the codec appears to need access > to > a block since before the last time it was changed, this is not > necessarily the last displayed frame. To implement this I decode to > two > extra AVFrame's, swapping them after each decode, and copying only > changed blocks from the current decoding frame to the final display > frame. I think that my implementation is probably more convoluted > than > it needs to be, any suggestions on that front would be most welcome > also. > > There's a bug in FFmpeg master currently that prevents the MVE > decoder > from signaling that the end of the file has been reached. I've made > no > attempt to fix that in this patch. I'll create a separate patch to > fix > this issue. > > - HP > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel From 1e1cde69e5728f937d79815bea8b9661fb69a8dd 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 | 281 +++++++++++++++++++++++++++++++++++++++++--- libavformat/ipmovie.c | 101 ++++++++++++---- 2 files changed, 343 insertions(+), 39 deletions(-) diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index df3314d..9542e5f 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -55,8 +55,17 @@ 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; @@ -903,7 +912,191 @@ 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; + const unsigned char* decode_map_p; + 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); + + decode_map_p = s->decoding_map; + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + opcode = AV_RL16(decode_map_p); + + 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 { + copy_from(s, s->second_last_frame, frame, 0, 0); + } + decode_map_p += 2; + } + } + + decode_map_p = s->decoding_map; + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + opcode = AV_RL16(decode_map_p); + + 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); + } + decode_map_p += 2; + } + } + + 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; + const unsigned char* decode_map_p; + const unsigned char* skip_map_p; + 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); + + decode_map_p = s->decoding_map; + skip_map_p = s->skip_map; + skip = AV_RL16(skip_map_p); + 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 = AV_RL16(decode_map_p); + 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; + } + } + decode_map_p += 2; + break; + } + skip_map_p += 2; + skip = AV_RL16(skip_map_p); + } + skip *= 2; + } + } + + decode_map_p = s->decoding_map; + skip_map_p = s->skip_map; + skip = AV_RL16(skip_map_p); + 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 = AV_RL16(decode_map_p); + 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); + } + decode_map_p += 2; + break; + } + skip_map_p += 2; + skip = AV_RL16(skip_map_p); + } + skip *= 2; + } + } + + skip_map_p = s->skip_map; + skip = AV_RL16(skip_map_p); + 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_map_p += 2; + skip = AV_RL16(skip_map_p); + } + 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 +1165,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 +1206,53 @@ 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); + + 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; + + /* 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; + 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 +1268,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 +1295,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