[FFmpeg-devel] [PATCH 3/7] avformat/s337m: switch to two rawdec for 16- and 24-bit
ffnicolasg at sfr.fr
ffnicolasg at sfr.fr
Wed Dec 4 16:14:05 EET 2024
From: Nicolas Gaullier <nicolas.gaullier at cji.paris>
Add support for variable or unknown 'offset':
- phase change or jitter
- Dolby E D2
Fix sync in several cases:
- Dolby E integer rounded sample_rate
- Missing frames (replaced by silence)
Signed-off-by: Nicolas Gaullier <nicolas.gaullier at cji.paris>
---
libavformat/Makefile | 3 +-
libavformat/allformats.c | 3 +-
libavformat/s337m.c | 216 +++++++++++--------------------------
tests/fate/audio.mak | 5 +-
tests/fate/demux.mak | 2 +-
tests/ref/fate/s337m-demux | 56 +++++-----
6 files changed, 99 insertions(+), 186 deletions(-)
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 52aa64d43b..9caf205b61 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -531,7 +531,8 @@ OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o \
urldecode.o
OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o \
urldecode.o
-OBJS-$(CONFIG_S337M_DEMUXER) += s337m.o
+OBJS-$(CONFIG_S337M_16_DEMUXER) += s337m.o rawdec.o
+OBJS-$(CONFIG_S337M_24_DEMUXER) += s337m.o rawdec.o
OBJS-$(CONFIG_SAMI_DEMUXER) += samidec.o subtitles.o
OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o
OBJS-$(CONFIG_SAP_MUXER) += sapenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 445f13f42a..b16c93a80f 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -413,7 +413,8 @@ extern const FFOutputFormat ff_rtp_muxer;
extern const FFOutputFormat ff_rtp_mpegts_muxer;
extern const FFInputFormat ff_rtsp_demuxer;
extern const FFOutputFormat ff_rtsp_muxer;
-extern const FFInputFormat ff_s337m_demuxer;
+extern const FFInputFormat ff_s337m_16_demuxer;
+extern const FFInputFormat ff_s337m_24_demuxer;
extern const FFInputFormat ff_sami_demuxer;
extern const FFInputFormat ff_sap_demuxer;
extern const FFOutputFormat ff_sap_muxer;
diff --git a/libavformat/s337m.c b/libavformat/s337m.c
index feb0f66cb3..16733bc095 100644
--- a/libavformat/s337m.c
+++ b/libavformat/s337m.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 foo86
+ * S337M demuxer
*
* This file is part of FFmpeg.
*
@@ -18,182 +18,92 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+#include "libavcodec/codec_id.h"
#include "libavcodec/spdif_s337m_parser_internal.h"
+
#include "avformat.h"
-#include "demux.h"
#include "internal.h"
-#include "spdif.h"
-
-#define MARKER_16LE 0x72F81F4E
-#define MARKER_20LE 0x20876FF0E154
-#define MARKER_24LE 0x72F8961F4EA5
-
-#define IS_16LE_MARKER(state) ((state & 0xFFFFFFFF) == MARKER_16LE)
-#define IS_20LE_MARKER(state) ((state & 0xF0FFFFF0FFFF) == MARKER_20LE)
-#define IS_24LE_MARKER(state) ((state & 0xFFFFFFFFFFFF) == MARKER_24LE)
-#define IS_LE_MARKER(state) (IS_16LE_MARKER(state) || IS_20LE_MARKER(state) || IS_24LE_MARKER(state))
-
-static int s337m_get_offset_and_codec(void *avc,
- uint64_t state,
- int data_type, int data_size,
- int *offset, enum AVCodecID *codec)
-{
- int word_bits;
-
- if (IS_16LE_MARKER(state)) {
- word_bits = 16;
- } else if (IS_20LE_MARKER(state)) {
- data_type >>= 8;
- data_size >>= 4;
- word_bits = 20;
- } else {
- data_type >>= 8;
- word_bits = 24;
- }
-
- if ((data_type & 0x1F) != 0x1C) {
- if (avc)
- avpriv_report_missing_feature(avc, "Data type %#x in SMPTE 337M", data_type & 0x1F);
- return AVERROR_PATCHWELCOME;
- }
-
- if (codec)
- *codec = AV_CODEC_ID_DOLBY_E;
+#include "rawdec.h"
- switch (data_size / word_bits) {
- case 3648:
- *offset = 1920;
- break;
- case 3644:
- *offset = 2002;
- break;
- case 3640:
- *offset = 2000;
- break;
- case 3040:
- *offset = 1601;
- break;
- default:
- if (avc)
- avpriv_report_missing_feature(avc, "Dolby E data size %d in SMPTE 337M", data_size);
- return AVERROR_PATCHWELCOME;
- }
+#define AES_DEFAULT_RATE 48000
+#define MAX_FRAME_RATE 30
+#define PROBE_MIN_FRAMES 2
- *offset -= 4;
- *offset *= (word_bits + 7 >> 3) * 2;
- return 0;
-}
-
-static int s337m_probe(const AVProbeData *p)
+static int s337m_probe(const AVProbeData *p, int aes_word_bits)
{
- uint64_t state = 0;
- int markers[3] = { 0 };
- int i, pos, sum, max, data_type, data_size, offset;
- uint8_t *buf;
-
- for (pos = 0; pos < p->buf_size; pos++) {
- state = (state << 8) | p->buf[pos];
- if (!IS_LE_MARKER(state))
- continue;
-
- buf = p->buf + pos + 1;
- if (IS_16LE_MARKER(state)) {
- data_type = AV_RL16(buf );
- data_size = AV_RL16(buf + 2);
- } else {
- data_type = AV_RL24(buf );
- data_size = AV_RL24(buf + 3);
+ SPDIFS337MParseContext *pc1;
+ int count_sync = 0, pos = 0;
+
+ if (p->buf_size / (aes_word_bits >> 2) < PROBE_MIN_FRAMES * AES_DEFAULT_RATE / MAX_FRAME_RATE)
+ return 0;
+ pc1 = av_mallocz(sizeof(*pc1));
+ if (!pc1)
+ return AVERROR(ENOMEM);
+ while(pos < p->buf_size) {
+ int next;
+
+ next = avpriv_spdif_s337m_find_syncword(pc1, p->buf + pos, p->buf_size - pos, aes_word_bits);
+ if (next == END_NOT_FOUND)
+ goto not_found;
+ pos += next;
+ next = avpriv_s337m_parse_header(NULL, p->buf + pos, p->buf_size - pos, aes_word_bits);
+ if (next > 0 && ++count_sync >= PROBE_MIN_FRAMES) {
+ av_free(pc1);
+ return AVPROBE_SCORE_EXTENSION + 1;
}
-
- if (s337m_get_offset_and_codec(NULL, state, data_type, data_size, &offset, NULL))
- continue;
-
- i = IS_16LE_MARKER(state) ? 0 : IS_20LE_MARKER(state) ? 1 : 2;
- markers[i]++;
-
- pos += IS_16LE_MARKER(state) ? 4 : 6;
- pos += offset;
- state = 0;
}
- sum = max = 0;
- for (i = 0; i < FF_ARRAY_ELEMS(markers); i++) {
- sum += markers[i];
- if (markers[max] < markers[i])
- max = i;
- }
-
- if (markers[max] > 3 && markers[max] * 4 > sum * 3)
- return AVPROBE_SCORE_EXTENSION + 1;
-
+not_found:
+ av_free(pc1);
return 0;
}
-static int s337m_read_header(AVFormatContext *s)
+static int s337m_probe_16(const AVProbeData *p)
{
- s->ctx_flags |= AVFMTCTX_NOHEADER;
- return 0;
+ return s337m_probe(p, 16);
}
-
-static void bswap_buf24(uint8_t *data, int size)
+static int s337m_probe_24(const AVProbeData *p)
{
- int i;
-
- for (i = 0; i < size / 3; i++, data += 3)
- FFSWAP(uint8_t, data[0], data[2]);
+ return s337m_probe(p, 24);
}
-static int s337m_read_packet(AVFormatContext *s, AVPacket *pkt)
+static int s337m_read_header(AVFormatContext *s)
{
- AVIOContext *pb = s->pb;
- uint64_t state = 0;
- int ret, data_type, data_size, offset;
- enum AVCodecID codec;
+ AVCodecParameters *par;
+ AVStream *st;
+ int ret = ff_raw_audio_read_header(s);
- while (!IS_LE_MARKER(state)) {
- state = (state << 8) | avio_r8(pb);
- if (avio_feof(pb))
- return AVERROR_EOF;
- }
-
- if (IS_16LE_MARKER(state)) {
- data_type = avio_rl16(pb);
- data_size = avio_rl16(pb);
- } else {
- data_type = avio_rl24(pb);
- data_size = avio_rl24(pb);
- }
-
- if ((ret = s337m_get_offset_and_codec(s, state, data_type, data_size, &offset, &codec)) < 0)
+ if (ret < 0)
return ret;
+ st = s->streams[0];
+ par = st->codecpar;
+ par->sample_rate = AES_DEFAULT_RATE;
+ par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
- if ((ret = av_get_packet(pb, pkt, offset)) != offset)
- return ret < 0 ? ret : AVERROR_EOF;
-
- if (IS_16LE_MARKER(state))
- avpriv_spdif_s337m_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1);
- else
- bswap_buf24(pkt->data, pkt->size);
-
- if (!s->nb_streams) {
- AVStream *st = avformat_new_stream(s, NULL);
- if (!st) {
- return AVERROR(ENOMEM);
- }
- st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codecpar->codec_id = codec;
- ffstream(st)->need_parsing = AVSTREAM_PARSE_HEADERS;
- }
-
+ avpriv_set_pts_info(st, 64, 1, par->sample_rate);
return 0;
}
-const FFInputFormat ff_s337m_demuxer = {
- .p.name = "s337m",
- .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE 337M"),
+const FFInputFormat ff_s337m_16_demuxer = {
+ .p.name = "s337m_16",
+ .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE 337M within 16-bit pcm"),
+ .p.flags = AVFMT_GENERIC_INDEX,
+ .p.priv_class = &ff_raw_demuxer_class,
+ .read_probe = s337m_probe_16,
+ .read_header = s337m_read_header,
+ .read_packet = ff_raw_read_partial_packet,
+ .raw_codec_id = AV_CODEC_ID_S337M_16,
+ .priv_data_size = sizeof(FFRawDemuxerContext),
+};
+const FFInputFormat ff_s337m_24_demuxer = {
+ .p.name = "s337m_24",
+ .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE 337M within 24-bit pcm"),
.p.flags = AVFMT_GENERIC_INDEX,
- .read_probe = s337m_probe,
+ .p.priv_class = &ff_raw_demuxer_class,
+ .read_probe = s337m_probe_24,
.read_header = s337m_read_header,
- .read_packet = s337m_read_packet,
+ .read_packet = ff_raw_read_partial_packet,
+ .raw_codec_id = AV_CODEC_ID_S337M_24,
+ .priv_data_size = sizeof(FFRawDemuxerContext),
};
diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak
index 4d6c479b6b..421c4e12f4 100644
--- a/tests/fate/audio.mak
+++ b/tests/fate/audio.mak
@@ -26,10 +26,11 @@ fate-bmv-audio: CMD = framecrc -i $(TARGET_SAMPLES)/bmv/SURFING-partial.BMV -vn
FATE_SAMPLES_AUDIO-$(call DEMDEC, DSICIN, DSICINAUDIO) += fate-delphine-cin-audio
fate-delphine-cin-audio: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-partial.CIN -vn
-FATE_SAMPLES_AUDIO-$(call DEMDEC, S337M, DOLBY_E, ARESAMPLE_FILTER) += fate-dolby-e
-fate-dolby-e: CMD = pcm -i $(TARGET_SAMPLES)/dolby_e/16-11
+FATE_SAMPLES_AUDIO-$(call PCM, S337M_16, DOLBY_E, ARESAMPLE_FILTER) += fate-dolby-e
+fate-dolby-e: CMD = pcm -i $(TARGET_SAMPLES)/dolby_e/16-11 -ar 44800
fate-dolby-e: CMP = oneoff
fate-dolby-e: REF = $(SAMPLES)/dolby_e/16-11.pcm
+fate-dolby-e: FUZZ = 2
FATE_SAMPLES_AUDIO-$(call DEMDEC, DSS, DSS_SP, ARESAMPLE_FILTER) += fate-dss-lp
fate-dss-lp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/lp.dss -frames 30 -af aresample
diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak
index e0d1fccc8f..f70491f158 100644
--- a/tests/fate/demux.mak
+++ b/tests/fate/demux.mak
@@ -130,7 +130,7 @@ fate-qcp-demux: CMD = crc -i $(TARGET_SAMPLES)/qcp/0036580847.QCP -c:a copy
FATE_SAMPLES_DEMUX-$(CONFIG_R3D_DEMUXER) += fate-redcode-demux
fate-redcode-demux: CMD = framecrc -i $(TARGET_SAMPLES)/r3d/4MB-sample.r3d -c:v copy -c:a copy
-FATE_SAMPLES_DEMUX-$(call ALLYES, S337M_DEMUXER DOLBY_E_PARSER FRAMECRC_MUXER) += fate-s337m-demux
+FATE_SAMPLES_DEMUX-$(call FRAMECRC, S337M_16,, S337M_16_PARSER FRAMECRC_MUXER) += fate-s337m-demux
fate-s337m-demux: CMD = framecrc -i $(TARGET_SAMPLES)/dolby_e/16-11 -c copy -ss 2 -t 1
FATE_SAMPLES_DEMUX-$(CONFIG_SIFF_DEMUXER) += fate-siff-demux
diff --git a/tests/ref/fate/s337m-demux b/tests/ref/fate/s337m-demux
index 42ef4df275..35a7a58d49 100644
--- a/tests/ref/fate/s337m-demux
+++ b/tests/ref/fate/s337m-demux
@@ -1,30 +1,30 @@
-#tb 0: 1/90000
+#tb 0: 1/48000
#media_type 0: audio
-#codec_id 0: dolby_e
-#sample_rate 0: 44800
+#codec_id 0: s337m_16
+#sample_rate 0: 48000
#channel_layout_name 0: 5.1(side)
-0, 0, 0, 3600, 7664, 0x7e73f2fd
-0, 3600, 3600, 3600, 7664, 0x8b980ec8
-0, 7200, 7200, 3600, 7664, 0xa16adbd5
-0, 10800, 10800, 3600, 7664, 0x6d1b43a5
-0, 14400, 14400, 3600, 7664, 0xb7e52e2a
-0, 18000, 18000, 3600, 7664, 0xcb7d6463
-0, 21600, 21600, 3600, 7664, 0x148a557b
-0, 25200, 25200, 3600, 7664, 0x04c0142e
-0, 28800, 28800, 3600, 7664, 0xf96de1d4
-0, 32400, 32400, 3600, 7664, 0x9f3224e0
-0, 36000, 36000, 3600, 7664, 0x6bd905cb
-0, 39600, 39600, 3600, 7664, 0xe6782023
-0, 43200, 43200, 3600, 7664, 0x983f5048
-0, 46800, 46800, 3600, 7664, 0x017df49a
-0, 50400, 50400, 3600, 7664, 0x25e605a9
-0, 54000, 54000, 3600, 7664, 0x764ef01e
-0, 57600, 57600, 3600, 7664, 0x3830f9f0
-0, 61200, 61200, 3600, 7664, 0xbcd62352
-0, 64800, 64800, 3600, 7664, 0x51ab1a35
-0, 68400, 68400, 3600, 7664, 0xc21ff964
-0, 72000, 72000, 3600, 7664, 0x9d6c0efa
-0, 75600, 75600, 3600, 7664, 0x5e55dd80
-0, 79200, 79200, 3600, 7664, 0xfd9eeb6d
-0, 82800, 82800, 3600, 7664, 0xcf86ce9d
-0, 86400, 86400, 3600, 7664, 0xc6e8319c
+0, 345, 345, 1920, 7680, 0x4df0f5d4
+0, 2265, 2265, 1920, 7680, 0x420e119f
+0, 4185, 4185, 1920, 7680, 0x09dfdeac
+0, 6105, 6105, 1920, 7680, 0xd9e3467c
+0, 8025, 8025, 1920, 7680, 0x8ec43101
+0, 9945, 9945, 1920, 7680, 0x955d673a
+0, 11865, 11865, 1920, 7680, 0x2fa95852
+0, 13785, 13785, 1920, 7680, 0x299e1705
+0, 15705, 15705, 1920, 7680, 0x35c1e4ab
+0, 17625, 17625, 1920, 7680, 0x5ae127b7
+0, 19545, 19545, 1920, 7680, 0xe52108a2
+0, 21465, 21465, 1920, 7680, 0x3e5c22fa
+0, 23385, 23385, 1920, 7680, 0x89c1531f
+0, 25305, 25305, 1920, 7680, 0xeb56f771
+0, 27225, 27225, 1920, 7680, 0xae960880
+0, 29145, 29145, 1920, 7680, 0x307ef2f5
+0, 31065, 31065, 1920, 7680, 0x4d54fcc7
+0, 32985, 32985, 1920, 7680, 0x29732629
+0, 34905, 34905, 1920, 7680, 0x57481d0c
+0, 36825, 36825, 1920, 7680, 0xdc91fc3b
+0, 38745, 38745, 1920, 7680, 0x9c4e11d1
+0, 40665, 40665, 1920, 7680, 0x829ce057
+0, 42585, 42585, 1920, 7680, 0xb145ee44
+0, 44505, 44505, 1920, 7680, 0x798ed174
+0, 46425, 46425, 1920, 7680, 0x091c3473
--
2.30.2
More information about the ffmpeg-devel
mailing list