From patchwork Sat Jun 17 13:08:33 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: 4006 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.22.4 with SMTP id 4csp107607vsw; Sat, 17 Jun 2017 06:08:46 -0700 (PDT) X-Received: by 10.223.134.117 with SMTP id 50mr2146083wrw.62.1497704926862; Sat, 17 Jun 2017 06:08:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1497704926; cv=none; d=google.com; s=arc-20160816; b=GNwtkLBlO+qQrSHtoLlmPvAIuf954ASqIP4CzI00Y6GFzlPc2kN0rIQxZ0ec3jCKqY FxPIovNtVIjCRlAR9RAJrl9OdanYu4BywdyYW5wiARRgY94ZSw2eBqoWxch2DJdPBzsD SJ99WEbzamjl20ih/RUFr415W6xEdU6aenM14ZKXf+Wx3vpvz8+vhXT8KYYB/v5aMbMX QoRLaXs/CvPl7pyUPH9QEQT+T0RunIWchb2aIQW216mbgxbQoCQomc5Ilg2gUT1aWUY2 1AvTIS91HuI/TMplA3B23g1YLfsEkbCTKvjBNzIg/JWbLlQ/X6pEruu+wK84RVNBwCRR piiw== 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:date:to:from:message-id:dkim-signature:dkim-filter :delivered-to:arc-authentication-results; bh=qvCb7nhuTjanJEUH8h+BmBxFWexXpeh3vnmVRLvMHv4=; b=hUzZVaioUTbiOGowl0qwqPJpXR0gUdzr6tIJ1PzEJwOql5dSavJkuFiu66STVJzpaw XwJnZ3IJnDfjRXT9q676bcNwv4WFmeleJC7m4l9wTIHf3DrvlM600zdh/InxAko31Eer 9EthzImyF+cpEYh84CQyJ9MRckhxK+PiqSB1rqB5dxbGaulmVU/2xLj4Kh1UqdGGC0l0 RA4QB1YuQUzeV1SpybsT7cdeOJcNmsO35wRHI88FZONR8Qeyg3RR7Esn6GmChZPubacj T7DmDc1LXaWocwqwo6+N83wFtu14+eKq747On+2ol96tmhGYVu1Qpj1/hAe/qAixVs+/ uZmQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@tmm.cx header.b=VKObw/uA; 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 28si5066629wrz.309.2017.06.17.06.08.46; Sat, 17 Jun 2017 06:08:46 -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=VKObw/uA; 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 9510768A1D0; Sat, 17 Jun 2017 16:08:38 +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 E8C97689FDF for ; Sat, 17 Jun 2017 16:08:31 +0300 (EEST) Received: from lola (unknown [92.110.172.3]) by eva.tmm.cx (Postfix) with ESMTPSA id 2AB7E17CAED6 for ; Sat, 17 Jun 2017 13:08:34 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 eva.tmm.cx 2AB7E17CAED6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tmm.cx; s=mail; t=1497704915; bh=mGokVQBdnEULzvrbYO7vW7Rr3lAHRO25Jj/TOz5RVuY=; h=Subject:From:To:Date:From; b=VKObw/uA8VI8thZwHW54ouamtZof0My/iDWah3qJD94Tf0ugIqNM0U5MazkybtDYY 71+WCK2PN1IE6RT6CDIgYWAhL8IHYAl79lGNVaI9i0fJH5qvPIeKj0Iz6nIgnoQ5m7 vX0o7//ZDK3ZQBvz5vm5kjBLOL/csKcZjfB9CKKA= Message-ID: <1497704913.3919.12.camel@tmm.cx> From: Hein-Pieter van Braam To: ffmpeg-devel@ffmpeg.org Date: Sat, 17 Jun 2017 15:08:33 +0200 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: [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, 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 From 1f6d7a95748bb9f567c9cb97f2be3ff5c43140ea 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 | 279 +++++++++++++++++++++++++++++++++++++++++--- libavformat/ipmovie.c | 101 ++++++++++++---- 2 files changed, 341 insertions(+), 39 deletions(-) diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index df3314d..d82dc0e 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,189 @@ 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*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*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) % cur_decode_frame->linesize[0]; + off_y = ((unsigned short)opcode - 0xC000) / 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) % cur_decode_frame->linesize[0]; + off_y = ((unsigned short)opcode - 0x4000) / 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 { + 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 +1163,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 +1204,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 +1266,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 +1293,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