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(-)
@@ -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;
@@ -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
@@ -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;
}
@@ -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