On 2/4/23, Paul B Mahol wrote:
> Hi,
>
> Patches attached, decoder is not bit by bit exact yet for lossless
> mode because some samples are not properly rounded.
>
Now lossless mode is bit exact.
From 232125e5bbbd6ac0b8049cc32e5ca61c484d1bd8 Mon Sep 17 00:00:00 2001
From: Paul B Mahol
Date: Tue, 31 Jan 2023 19:27:09 +0100
Subject: [PATCH 1/2] avformat: add RKA demuxer
Signed-off-by: Paul B Mahol
---
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/rka.c| 173 +++
3 files changed, 175 insertions(+)
create mode 100644 libavformat/rka.c
diff --git a/libavformat/Makefile b/libavformat/Makefile
index f0408a58b1..cd9c7a36a8 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -482,6 +482,7 @@ OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
OBJS-$(CONFIG_RAWVIDEO_MUXER)+= rawenc.o
OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
+OBJS-$(CONFIG_RKA_DEMUXER) += rka.o apetag.o img2.o
OBJS-$(CONFIG_RL2_DEMUXER) += rl2.o
OBJS-$(CONFIG_RM_DEMUXER)+= rmdec.o rm.o rmsipr.o
OBJS-$(CONFIG_RM_MUXER) += rmenc.o rm.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 9ca8d2692f..4903bf7f9d 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -380,6 +380,7 @@ extern const AVInputFormat ff_rawvideo_demuxer;
extern const AVOutputFormat ff_rawvideo_muxer;
extern const AVInputFormat ff_realtext_demuxer;
extern const AVInputFormat ff_redspark_demuxer;
+extern const AVInputFormat ff_rka_demuxer;
extern const AVInputFormat ff_rl2_demuxer;
extern const AVInputFormat ff_rm_demuxer;
extern const AVOutputFormat ff_rm_muxer;
diff --git a/libavformat/rka.c b/libavformat/rka.c
new file mode 100644
index 00..c1e64ebcb3
--- /dev/null
+++ b/libavformat/rka.c
@@ -0,0 +1,173 @@
+/*
+ * RKA demuxer
+ * Copyright (c) 2023 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/dict.h"
+#include "libavutil/intreadwrite.h"
+
+#include "apetag.h"
+#include "avformat.h"
+#include "avio_internal.h"
+#include "demux.h"
+#include "internal.h"
+
+typedef struct RKAContext {
+int total_frames, currentframe;
+int frame_size;
+int last_frame_size;
+} RKAContext;
+
+static int rka_probe(const AVProbeData *p)
+{
+if (AV_RL32(>buf[0]) == MKTAG('R', 'K', 'A', '7') &&
+AV_RL32(>buf[4]) > 0 &&
+AV_RL32(>buf[8]) > 0 &&
+p->buf[12] > 0 &&
+p->buf[12] <= 2 &&
+(p->buf[13] == 8 || p->buf[13] == 16) &&
+p->buf[15] & 2 != 0)
+return AVPROBE_SCORE_EXTENSION + 30;
+return 0;
+}
+
+static int rka_read_header(AVFormatContext *s)
+{
+int64_t nb_samples, size_offset;
+RKAContext *c = s->priv_data;
+int channels, bps, samplerate;
+AVCodecParameters *par;
+int64_t framepos;
+AVStream *st;
+int ret;
+
+st = avformat_new_stream(s, NULL);
+if (!st)
+return AVERROR(ENOMEM);
+
+par = st->codecpar;
+ret = ff_get_extradata(s, par, s->pb, 16);
+if (ret < 0)
+return ret;
+
+nb_samples = AV_RL32(par->extradata + 4);
+samplerate = AV_RL32(par->extradata + 8);
+channels = par->extradata[12];
+if (channels == 0)
+return AVERROR_INVALIDDATA;
+bps = par->extradata[13];
+if (bps == 0)
+return AVERROR_INVALIDDATA;
+size_offset = avio_rl32(s->pb);
+framepos = avio_tell(s->pb);
+c->frame_size = 131072;
+
+avpriv_set_pts_info(st, 64, 1, samplerate);
+st->start_time = 0;
+
+avio_seek(s->pb, size_offset, SEEK_SET);
+c->total_frames = (nb_samples + c->frame_size - 1) / c->frame_size;
+c->last_frame_size = nb_samples % c->frame_size;
+
+for (int i = 0; i < c->total_frames; i++) {
+int r, end = 0;
+int64_t size;
+
+if (avio_feof(s->pb))
+break;
+
+size = avio_rl24(s->pb);
+if (size == 0) {
+end = 1;
+size = size_offset - framepos;
+if (size <= 0)
+break;
+}
+
+if ((r = av_add_index_entry(st, framepos, (i *