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 <[email protected]>:
> On 6/30/19, Anton Novikov <[email protected]> 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
> [email protected]
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> [email protected] 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
[email protected]
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
[email protected] with subject "unsubscribe".