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 <one...@gmail.com>: > On 6/30/19, Anton Novikov <random.pl...@gmail.com> 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-requ...@ffmpeg.org with subject "unsubscribe".
From ce21789b0da6e7f16c21ea33dcf67586b32630bd Mon Sep 17 00:00:00 2001 From: Anek <anek@archlinuxi> Date: Sun, 30 Jun 2019 16:32:21 +0500 Subject: [PATCH 2/2] jpeg2000 decoding dbginfo --- libavcodec/jpeg2000dec.c | 43 +++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index a40726f4b8..5de7e042c6 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -1907,9 +1907,10 @@ next_marker: marker = bytestream2_get_be16u(&s->g); oldpos = bytestream2_tell(&s->g); - if (marker == JPEG2000_SOC) - goto next_marker; - else if (marker == JPEG2000_SOD) { + if (marker == JPEG2000_SOC) { + av_log(s->avctx, AV_LOG_WARNING, "Duplicate SOC at %i=0x%X\n", oldpos - 2, oldpos - 2); + continue; + } else if (marker == JPEG2000_SOD) { Jpeg2000Tile *tile; Jpeg2000TilePart *tp; @@ -1946,32 +1947,53 @@ next_marker: switch (marker) { case JPEG2000_SOC: + av_log(s->avctx, AV_LOG_WARNING, "SOC\n"); return 0xdeadbeef; case JPEG2000_SIZ: + av_log(s->avctx, AV_LOG_WARNING, "SIZ\n"); if (0 && s->ncomponents) { - av_log(s->avctx, AV_LOG_ERROR, "Duplicate SIZ\n"); - return AVERROR_INVALIDDATA; - } - ret = get_siz(s); - if (!s->tile) - s->numXtiles = s->numYtiles = 0; + av_log(s->avctx, AV_LOG_WARNING, "Duplicate SIZ\n"); + bytestream2_skip(&s->g, len - 2); + ret = 0; + return 0; + return 0xdeadbeef; + //return AVERROR_INVALIDDATA; + } else { + if (s->ncomponents && s->tile) { + ret = get_siz(s); + av_log(s->avctx, AV_LOG_WARNING, "SIZ xtiles=%i ytiles=%i\n", s->numXtiles, s->numYtiles); + } else { + ret = get_siz(s); + av_log(s->avctx, AV_LOG_WARNING, "SIZ xtiles=%i ytiles=%i\n", s->numXtiles, s->numYtiles); + if (!s->tile) + s->numXtiles = s->numYtiles = 0; + av_log(s->avctx, AV_LOG_WARNING, "SIZ xtiles=%i ytiles=%i\n", s->numXtiles, s->numYtiles); + } + av_log(s->avctx, AV_LOG_WARNING, "SIZ Rsiz=0x%x %i %i\n", s->avctx->profile, s->width, s->height); + } break; case JPEG2000_COC: + av_log(s->avctx, AV_LOG_WARNING, "COC\n"); ret = get_coc(s, codsty, properties); break; case JPEG2000_COD: + av_log(s->avctx, AV_LOG_WARNING, "COD\n"); ret = get_cod(s, codsty, properties); break; case JPEG2000_QCC: + av_log(s->avctx, AV_LOG_WARNING, "QCC\n"); ret = get_qcc(s, len, qntsty, properties); break; case JPEG2000_QCD: + av_log(s->avctx, AV_LOG_WARNING, "QCD\n"); ret = get_qcd(s, len, qntsty, properties); break; case JPEG2000_POC: + av_log(s->avctx, AV_LOG_WARNING, "POC\n"); ret = get_poc(s, len, poc); break; case JPEG2000_SOT: + av_log(s->avctx, AV_LOG_WARNING, "SOT\n"); if (!(ret = get_sot(s, len))) { av_assert1(s->curtileno >= 0); codsty = s->tile[s->curtileno].codsty; @@ -1984,14 +2006,17 @@ next_marker: // the PLM marker is ignored case JPEG2000_COM: // the comment is ignored + av_log(s->avctx, AV_LOG_WARNING, "ignored marker\n"); bytestream2_skip(&s->g, len - 2); break; case JPEG2000_TLM: // Tile-part lengths + av_log(s->avctx, AV_LOG_WARNING, "TLM\n"); ret = get_tlm(s, len); break; case JPEG2000_PLT: // Packet length, tile-part header + av_log(s->avctx, AV_LOG_WARNING, "PLT\n"); ret = get_plt(s, len); break; default: -- 2.22.0
From 5acc9762c553dd3302dc9da537bab817f98ba2a0 Mon Sep 17 00:00:00 2001 From: Anek <anek@archlinuxi> 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
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".