From patchwork Sun Jun 30 12:04:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Novikov X-Patchwork-Id: 13767 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 09B14447849 for ; Sun, 30 Jun 2019 15:05:57 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DE9AE68A976; Sun, 30 Jun 2019 15:05:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f172.google.com (mail-oi1-f172.google.com [209.85.167.172]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8471968A2FA for ; Sun, 30 Jun 2019 15:05:49 +0300 (EEST) Received: by mail-oi1-f172.google.com with SMTP id l12so7757689oil.1 for ; Sun, 30 Jun 2019 05:05:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=ab+bGT6tmJOLfIcvYIKYjg0y8dmzCxqqjZVmhQvK6ZU=; b=c5NHsVOa5bng3Vp+gX6YEioIi6drUoDTuHXizXZdgop2JVSFDKcjKACfiJwrsvKMuQ YI6pk/1HeMHbM82XeOxkisMmgm9KQHGLpIReiyeD+7Y9EBPI4sBkVvOc2NKwFXydc3aA zW3QPSL2kLd5i3a2ICyPWTVeYcUQkcfL6PQHZm+aXXSosVAhU/IyrEQ+f6FvBzU8vHfX bOnn4m4K/aF+wehNIi/0ZSJBC71B9anYhZq8JVCJGd9YfB5n8HbunSMf1o4jj31rPxbr OnSZJeH6D1wn+oV6/w0YKAoMv+5FtrAvHZFy0aHLpD3uFmgESEEKi+QCaJGcQ3BKEMFM aq9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=ab+bGT6tmJOLfIcvYIKYjg0y8dmzCxqqjZVmhQvK6ZU=; b=QdBeK+k3tOyRRqiDscDVMQm9u3iQIErgqkiB47kt8Bfq6r2TeWY6nHjJdVTjQnkj4J EcR6Q/Hw1dunkKLvqvr+ZTSMVQQdgKkTOU2f4azQp5gcpQbgr32950KrwTpFjpOSl/DV 7z+z/ANhfGQ5GrAdE3Wy8o5I5SgFFtq+T+ss+hYUt+x6+6T1BB7tDTGkP6zYJd37JpZH tPPitR2WrOlKcHcPFf9cNmK1+mhl2jlb7hQX5c2WUBDvv4kyLbnsQ4n3qxFM9W+yFm2d NxN65ak+BOwfjJSO/5Bnmv+iz8wg2QNAhri/SxrNFL/XIaeBRijD3Vo69VAttrH9QM95 3ElA== X-Gm-Message-State: APjAAAXQdJ/mtmYdVqqC2IGY8ezsFNYBdnVU5DYk0ixIx0ftY3k4xMfP E3tOjiWU3HiNxkHox33Yw2iWcjPnDbA2Hlv4yOz/jJSJ X-Google-Smtp-Source: APXvYqzuIcz3lwmzpgx0tS3U/VCpNIiEJQgproG4QCqjcMjwWuoswnciCDP6l8a/Y1SmFFBTn5gdmFq7jnhMOkecWz4= X-Received: by 2002:aca:c084:: with SMTP id q126mr3628565oif.124.1561896347731; Sun, 30 Jun 2019 05:05:47 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Anton Novikov Date: Sun, 30 Jun 2019 17:04:38 +0500 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: Re: [FFmpeg-devel] JPEG2000 multiple SOC and SIZ 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" When I truncate the packet at next SOC, I get: [jpeg2000 @ 0x55ce0298aa40] SIZ [jpeg2000 @ 0x55ce0298aa40] SIZ width=2056 height=2168 tile_width=2056 tile_height=2168 tile_offset_x=0 tile_offset_y=0 xtiles=1 ytiles=1 [jpeg2000 @ 0x55ce0298aa40] SIZ Rsiz=0x8040 2056 2168 [jpeg2000 @ 0x55ce0298aa40] POC [jpeg2000 @ 0x55ce0298aa40] unsupported marker 0xFF79 at pos 0x70 [jpeg2000 @ 0x55ce0298aa40] COD [jpeg2000 @ 0x55ce0298aa40] extra cblk styles E [jpeg2000 @ 0x55ce0298aa40] QCD [jpeg2000 @ 0x55ce0298aa40] SOT Last message repeated 3 times [jpeg2000 @ 0x55ce0298aa40] Psot 1451180 too big [jpeg2000 @ 0x55ce0298aa40] error during processing marker segment ff90 Moreover, in both SIZes, tile offsets are 0, I can't get the idea how the file should be handled correctly. file: https://www.file-up.org/niuxrl31dyij fmpeg commits are attached вс, 30 июн. 2019 г. в 15:17, Paul B Mahol : > On 6/30/19, Anton Novikov wrote: > > Hi everyone, > > I'm reversing the recent version of r3d file format, and have > encountered a > > JPEG2000-related thing. > > I've got a memory dump of something that seems to be JPEG2000, and > modified > > ffmpeg to consume it. The log follows: > > [r3d @ 0x558d304077c0] test > > [r3d @ 0x558d304077c0] error reading end atom > > Input #0, r3d, from '/home/anek/src/red/frame2.without0.r3d': > > Duration: N/A, bitrate: N/A > > Stream #0:0: Video: jpeg2000, bayer_rggb16le, 8192x4320, 24 fps, 24 > > tbr, 134286336 tbn, 134286336 tbc > > Metadata: > > filename : ? > > File 'frame.jpg' already exists. Overwrite ? [y/N] y > > Stream mapping: > > Stream #0:0 -> #0:0 (jpeg2000 (native) -> mjpeg (native)) > > Press [q] to stop, [?] for help > > Truncating packet of size 9496960 to 7595371 > > /home/anek/src/red/frame2.without0.r3d: corrupt input packet in stream 0 > > /home/anek/src/red/frame2.without0.r3d: Operation not permitted > > [jpeg2000 @ 0x558d3041c280] SIZ > > [jpeg2000 @ 0x558d3041c280] SIZ Rsiz=0x8040 2056 2168 > > [jpeg2000 @ 0x558d3041c280] POC > > [jpeg2000 @ 0x558d3041c280] unsupported marker 0xFF79 at pos 0x70 > > [jpeg2000 @ 0x558d3041c280] COD > > [jpeg2000 @ 0x558d3041c280] extra cblk styles E > > [jpeg2000 @ 0x558d3041c280] QCD > > [jpeg2000 @ 0x558d3041c280] SOT > > Last message repeated 3 times > > [jpeg2000 @ 0x558d3041c280] Duplicate SOC at 3821997=0x3A51AD > > [jpeg2000 @ 0x558d3041c280] SIZ > > [jpeg2000 @ 0x558d3041c280] SIZ Rsiz=0x8040 2056 2168 > > [jpeg2000 @ 0x558d3041c280] POC > > [jpeg2000 @ 0x558d3041c280] unsupported marker 0xFF79 at pos 0x3A5203 > > [jpeg2000 @ 0x558d3041c280] COD > > [jpeg2000 @ 0x558d3041c280] extra cblk styles E > > [jpeg2000 @ 0x558d3041c280] QCD > > [jpeg2000 @ 0x558d3041c280] SOT > > Last message repeated 3 times > > [jpeg2000 @ 0x558d3041c280] Progression order RPCL > > Last message repeated 3 times > > [swscaler @ 0x558d30425900] deprecated pixel format used, make sure you > did > > set range correctly > > [mjpeg @ 0x558d3040e780] removing common factors from framerate > > Output #0, image2, to 'frame.jpg': > > Metadata: > > encoder : Lavf58.27.103 > > Stream #0:0: Video: mjpeg, yuvj444p(pc), 2056x2168, q=2-31, 200 kb/s, > > 24 fps, 24 tbn, 24 tbc > > Metadata: > > filename : ? > > encoder : Lavc58.52.102 mjpeg > > Side data: > > cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1 > > [image2 @ 0x558d3040abc0] Application provided invalid, non monotonically > > increasing dts to muxer in stream 0: 101000 >= 0 > > /home/anek/src/red/frame2.without0.r3d: Operation not permitted > > frame= 1 fps=0.4 q=2.9 Lsize=N/A time=00:00:00.00 bitrate=N/A speed= > > 0x > > video:96kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB > > muxing overhead: unknown > > > > picture dimensions are 8192x4320, but in JPEG2000 bytestream there are 2 > > SOC and SIZ markers with SIZ mentioning 2056x2168. The image is decoded, > > but colors and area are wrong. What can I do? > > Make sure it uses tiles (each jpeg2000 is special tile) and that your > packet is trimmed. > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". From 5acc9762c553dd3302dc9da537bab817f98ba2a0 Mon Sep 17 00:00:00 2001 From: Anek Date: Sat, 29 Jun 2019 19:20:22 +0500 Subject: [PATCH 1/2] some_picture --- fftools/ffmpeg.c | 5 +- libavcodec/jpeg2000.h | 1 + libavcodec/jpeg2000dec.c | 16 +++++- libavformat/r3d.c | 116 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 129 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 01f04103cf..9e6dac6439 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3874,10 +3874,13 @@ static OutputStream *choose_output(void) int64_t opts = ost->st->cur_dts == AV_NOPTS_VALUE ? INT64_MIN : av_rescale_q(ost->st->cur_dts, ost->st->time_base, AV_TIME_BASE_Q); - if (ost->st->cur_dts == AV_NOPTS_VALUE) + if (ost->st->cur_dts == AV_NOPTS_VALUE) { + static int nondts = 100000; + ost->st->cur_dts = nondts += 1000; av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished); + } if (!ost->initialized && !ost->inputs_done) return ost; diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index c429ca5996..0e8608f4d7 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -51,6 +51,7 @@ enum Jpeg2000Markers { JPEG2000_PPT, // packed packet headers, main header JPEG2000_CRG = 0xff63, // component registration JPEG2000_COM, // comment + JPEG2000_ATK = 0xff79, // arbitrary transformation kernel JPEG2000_SOT = 0xff90, // start of tile-part JPEG2000_SOP, // start of packet JPEG2000_EPH, // end of packet header diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 019dc81f56..a40726f4b8 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -1903,10 +1903,13 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) break; } +next_marker: marker = bytestream2_get_be16u(&s->g); oldpos = bytestream2_tell(&s->g); - if (marker == JPEG2000_SOD) { + if (marker == JPEG2000_SOC) + goto next_marker; + else if (marker == JPEG2000_SOD) { Jpeg2000Tile *tile; Jpeg2000TilePart *tp; @@ -1935,13 +1938,17 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) len = bytestream2_get_be16(&s->g); if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d left=%d\n", len, bytestream2_get_bytes_left(&s->g)); + if (bytestream2_get_bytes_left(&s->g) == 0) + break; + av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d pos=%d left=%d\n", len, bytestream2_tell(&s->g), bytestream2_get_bytes_left(&s->g)); return AVERROR_INVALIDDATA; } switch (marker) { + case JPEG2000_SOC: + return 0xdeadbeef; case JPEG2000_SIZ: - if (s->ncomponents) { + if (0 && s->ncomponents) { av_log(s->avctx, AV_LOG_ERROR, "Duplicate SIZ\n"); return AVERROR_INVALIDDATA; } @@ -2217,6 +2224,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, bytestream2_seek(&s->g, 0, SEEK_SET); } +next_codestream: while (bytestream2_get_bytes_left(&s->g) >= 3 && bytestream2_peek_be16(&s->g) != JPEG2000_SOC) bytestream2_skip(&s->g, 1); @@ -2252,6 +2260,8 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, return bytestream2_tell(&s->g); end: + if (ret == 0xdeadbeef) + ret = 0; jpeg2000_dec_cleanup(s); return ret; } diff --git a/libavformat/r3d.c b/libavformat/r3d.c index 934cebefa8..862c51f295 100644 --- a/libavformat/r3d.c +++ b/libavformat/r3d.c @@ -29,6 +29,7 @@ typedef struct R3DContext { unsigned video_offsets_count; unsigned *video_offsets; unsigned rdvo_offset; + unsigned rdvs_offset; int audio_channels; } R3DContext; @@ -48,6 +49,11 @@ static int read_atom(AVFormatContext *s, Atom *atom) if (atom->size < 8) return -1; atom->tag = avio_rl32(s->pb); + if (atom->tag == MKTAG('R','E','D','2')) + format2 = 1; + if (format2) + if (atom->size % 0x1000 > 0) + atom->size += 0x1000 - atom->size % 0x1000; av_log(s, AV_LOG_TRACE, "atom %u %.4s offset %#"PRIx64"\n", atom->size, (char*)&atom->tag, atom->offset); return atom->size; @@ -84,6 +90,7 @@ static int r3d_read_red1(AVFormatContext *s) st->codecpar->width = avio_rb32(s->pb); st->codecpar->height = avio_rb32(s->pb); + st->codecpar->format = AV_PIX_FMT_BAYER_BGGR16LE; tmp = avio_rb16(s->pb); // unknown av_log(s, AV_LOG_TRACE, "unknown2 %d\n", tmp); @@ -143,14 +150,17 @@ static int r3d_read_red2(AVFormatContext *s) avio_skip(s->pb, 32); // unknown + avio_seek(s->pb, 0x4C, SEEK_SET); st->codecpar->width = avio_rb32(s->pb); st->codecpar->height = avio_rb32(s->pb); + st->codecpar->format = AV_PIX_FMT_BAYER_RGGB16; tmp = avio_rb16(s->pb); // unknown av_log(s, AV_LOG_TRACE, "unknown2 %d\n", tmp); - framerate.num = avio_rb16(s->pb); framerate.den = avio_rb16(s->pb); + tmp = avio_rb16(s->pb); // unknown + framerate.num = avio_rb16(s->pb); if (framerate.num > 0 && framerate.den > 0) { #if FF_API_R_FRAME_RATE st->r_frame_rate = @@ -158,6 +168,10 @@ static int r3d_read_red2(AVFormatContext *s) st->avg_frame_rate = framerate; } + r3d->video_offsets_count = 1; + r3d->video_offsets = av_malloc(4); + r3d->video_offsets[0] = 0x12680; + r3d->audio_channels = avio_r8(s->pb); // audio channels av_log(s, AV_LOG_TRACE, "audio channels %d\n", tmp); @@ -203,13 +217,43 @@ static int r3d_read_rdvo(AVFormatContext *s, Atom *atom) return 0; } +static int r3d_read_rdvs(AVFormatContext *s, Atom *atom) +{ + R3DContext *r3d = s->priv_data; + AVStream *st = s->streams[0]; + int i; + + r3d->video_offsets_count = (atom->size - 8) / 4; + r3d->video_offsets = av_malloc(atom->size); + if (!r3d->video_offsets) + return AVERROR(ENOMEM); + + for (i = 0; i < r3d->video_offsets_count; i++) { + r3d->video_offsets[i] = avio_rb32(s->pb); + if (!r3d->video_offsets[i]) { + r3d->video_offsets_count = i; + break; + } + av_log(s, AV_LOG_TRACE, "video offset %d: %#x\n", i, r3d->video_offsets[i]); + } + + if (st->avg_frame_rate.num) + st->duration = av_rescale_q(r3d->video_offsets_count, + av_inv_q(st->avg_frame_rate), + st->time_base); + av_log(s, AV_LOG_TRACE, "duration %"PRId64"\n", st->duration); + avio_seek(s->pb, s->internal->data_offset, SEEK_SET); + + return 0; +} + static void r3d_read_reos(AVFormatContext *s) { R3DContext *r3d = s->priv_data; int av_unused tmp; r3d->rdvo_offset = avio_rb32(s->pb); - avio_rb32(s->pb); // rdvs offset + r3d->rdvs_offset = avio_rb32(s->pb); avio_rb32(s->pb); // rdao offset avio_rb32(s->pb); // rdas offset @@ -261,17 +305,25 @@ static int r3d_read_header(AVFormatContext *s) if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) return 0; // find REOB/REOF/REOS to load index - avio_seek(s->pb, avio_size(s->pb)-48-8, SEEK_SET); - if (read_atom(s, &atom) < 0) + avio_seek(s->pb, atom.offset + atom.size, SEEK_SET); +next: + av_log(s, AV_LOG_TRACE, "at %x\n", avio_tell(s->pb)); + if (read_atom(s, &atom) < 0) { av_log(s, AV_LOG_ERROR, "error reading end atom\n"); + goto out; + } + + avio_seek(s->pb, atom.offset + atom.size, SEEK_SET); if (atom.tag != MKTAG('R','E','O','B') && atom.tag != MKTAG('R','E','O','F') && atom.tag != MKTAG('R','E','O','S')) - goto out; + goto next; + avio_seek(s->pb, atom.offset + 8, SEEK_SET); r3d_read_reos(s); + avio_seek(s->pb, s->internal->data_offset, SEEK_SET); if (r3d->rdvo_offset) { avio_seek(s->pb, r3d->rdvo_offset, SEEK_SET); if (read_atom(s, &atom) < 0) @@ -281,9 +333,22 @@ static int r3d_read_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "error parsing 'rdvo' atom\n"); } } + /* + if (r3d->rdvs_offset) { + av_log(s, AV_LOG_ERROR, "rdvs"); + avio_seek(s->pb, r3d->rdvs_offset, SEEK_SET); + if (read_atom(s, &atom) < 0) + av_log(s, AV_LOG_ERROR, "error reading 'rdvs' atom\n"); + if (atom.tag == MKTAG('R','D','V','S')) { + if (r3d_read_rdvs(s, &atom) < 0) + av_log(s, AV_LOG_ERROR, "error parsing 'rdvs' atom\n"); + } + } + */ out: avio_seek(s->pb, s->internal->data_offset, SEEK_SET); + //avio_seek(s->pb, 0x12680, SEEK_SET); return 0; } @@ -342,6 +407,38 @@ static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) return 0; } +static int r3d_read_redv2(AVFormatContext *s, AVPacket *pkt, Atom *atom) +{ + AVStream *st = s->streams[0]; + int tmp; + int av_unused tmp2; + int64_t pos = avio_tell(s->pb); + unsigned dts; + int ret; + + static nondts = 100000; + dts = nondts++; + + tmp = atom->size; + tmp = 9496960; + if (tmp < 0) + return -1; + ret = av_get_packet(s->pb, pkt, tmp); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "error reading video packet\n"); + return -1; + } + + pkt->stream_index = 0; + pkt->dts = dts; + if (st->avg_frame_rate.num) + pkt->duration = (uint64_t)st->time_base.den* + st->avg_frame_rate.den/st->avg_frame_rate.num; + av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64"\n", pkt->dts, pkt->duration); + + return 0; +} + static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) { R3DContext *r3d = s->priv_data; @@ -433,6 +530,13 @@ static int r3d_read_packet(AVFormatContext *s, AVPacket *pkt) return 0; break; default: + avio_seek(s->pb, 0x12680, SEEK_SET); + av_log(s, AV_LOG_TRACE, "packet atom %u", atom.tag); + if (s->streams[0]->discard == AVDISCARD_ALL) + goto skip; + if (!(err = r3d_read_redv2(s, pkt, &atom))) + return 0; + break; skip: avio_skip(s->pb, atom.size-8); } @@ -444,6 +548,8 @@ static int r3d_probe(const AVProbeData *p) { if (AV_RL32(p->buf + 4) == MKTAG('R','E','D','1')) return AVPROBE_SCORE_MAX; + if (AV_RL32(p->buf + 4) == MKTAG('R','E','D','2')) + return AVPROBE_SCORE_MAX; return 0; } -- 2.22.0