[FFmpeg-devel] [PATCH 0/7] RFC: complete rework of s337m support

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

I would like to have some feedback on this work before going on...
I send this as an RFC, and so, I have not considered versioning,
changelog, doc, deprecation schemes. More testing and testing by
other people is also obviously required.

The fate samples are available here: https://0x0.st/X7mV.zip

To begin, I'd like to raise the issues in current code:
- current code requires a constant 'offset' between each frame, but
this requirement is not standard and prevents conformant files to be
decoded. It also prevents support for unexpected forms of Dolby E
(Dolby E D2 is not supported because its 'offset' is not recognised).
- current code does not allow 'missing frames' with silence fallback.
However, this is very commonplace: for example, someone wants to add
a still picture with credits and no audio, so inserts some null bytes
= pcm/silence. The standard recommands to be able to switch between pcm
and Dolby E frame by frame, so it 'should' be supported.
- the Dolby E sample rate is not always an integer, and its rounded
value makes its sync slightly drift.
- spdif and s337m are implemented separately, despite it's almost the
same thing; the spdif syncword is even the same as the 16-bit s337m
syncword!

At the end, it really seems unreasonable to handle raw dolby_e streams
without the upper s337m layer. The native dolby_e decoder output with
its weird sample rate (specially @29.97) is not very convenient, too.

Here is what I designed:
- the mpegts/wav/mxf(stereo) support is handled via stream probing which
is a proven feature for years, with very little code addition and low
dependance to the demuxers. It is the spirit of the standard: every
uncompressed stereo audio can support s337m.
- a s337m parser: full parsing is required even for frame-wrapped mxf
as broken files that do not have a valid s337m phase results in audio
frames crossing the edit unit boundaries.
- a s337m decoder: it includes a resampler: output and input sample_rate
are the same, sync is always correct. It would be possible to implement
a full pcm fallback, but currently only a silence/pcm fallback is
provided. A 'passthrough' option is also provided and would make it
possible to mux again into wav, mxf or whatever. I guess one could
imagine a bitstream filter to fix the s337m phase to a clean, fixed
offset value (as expected by the current s337m demuxer for example).
- the demuxer is split in two raw demuxers: a 16-bit and a 24-bit. All
the logic remains in avcodec.
- mpegts: the s302m decoder is embedded in the mpegts demuxer; it does
not care about s337m as everything relies on ffmpeg's stream probing.

What could be done further: I am not used to working with spdif,
but I guess much of the code and design should be shared with s337m.

Tricks:
I really have no idea what a migration path could be for users and
developpers, notably the "non_pcm_data" option of mpegts seems
pretty 'unmappable'...

Please comment!

Thank you
Nicolas

Nicolas Gaullier (7):
  avcodec: add s337m parser and decoder
  avformat/spdif,s337m: use shared code from avcodec
  avformat/s337m: switch to two rawdec for 16- and 24-bit
  fate/acodec: add 20/24bit s302m tests
  avformat/mpegts: add s337m support
  avformat: add s337m support in mpegts, wav and mxf stereo tracks
  fate: add s337m decode and demux tests

 configure|   2 +
 libavcodec/Makefile  |   4 +
 libavcodec/allcodecs.c   |   2 +
 libavcodec/codec_desc.c  |  14 +
 libavcodec/codec_id.h|   2 +
 libavcodec/dolby_e_parse.c   |   3 +
 libavcodec/parsers.c |   2 +
 libavcodec/s337m.c   | 327 +++
 libavcodec/s337m_parser.c| 133 +
 libavcodec/spdif_s337m_parse.c   | 142 ++
 libavcodec/spdif_s337m_parser_internal.h |  92 +++
 libavcodec/utils.c   |   2 +
 libavcodec/version.c |   2 +-
 libavformat/Makefile |   7 +-
 libavformat/allformats.c |   3 +-
 libavformat/demux.c  |   2 +
 libavformat/mpegts.c | 138 +-
 libavformat/mxfdec.c |   9 +-
 libavformat/s337m.c  | 217 +--
 libavformat/spdif.c  |  42 ---
 libavformat/spdif.h  |   1 -
 libavformat/spdifdec.c   |   3 +-
 libavformat/spdifenc.c   |   3 +-
 libavformat/wavdec.c |   3 +-
 tests/fate/acodec.mak|  16 +-
 tests/fate/audio.mak |  15 +-
 tests/fate/demux.mak |  15 +-
 tests/ref/acodec/s302m   |   4 -
 tests/ref/acodec/s302m-16bit |   4 +
 tests/ref/acodec/s302m-20bit |   4 +
 tests/ref/acodec/s302m-24bit |   4 +
 tests/ref/fate/s337m-demux  

[FFmpeg-devel] [PATCH 1/7] avcodec: add s337m parser and decoder

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

Signed-off-by: Nicolas Gaullier 
---
 configure|   2 +
 libavcodec/Makefile  |   4 +
 libavcodec/allcodecs.c   |   2 +
 libavcodec/codec_desc.c  |  14 +
 libavcodec/codec_id.h|   2 +
 libavcodec/dolby_e_parse.c   |   3 +
 libavcodec/parsers.c |   2 +
 libavcodec/s337m.c   | 327 +++
 libavcodec/s337m_parser.c| 133 +
 libavcodec/spdif_s337m_parse.c   | 142 ++
 libavcodec/spdif_s337m_parser_internal.h |  92 +++
 libavcodec/utils.c   |   2 +
 libavcodec/version.c |   2 +-
 13 files changed, 726 insertions(+), 1 deletion(-)
 create mode 100644 libavcodec/s337m.c
 create mode 100644 libavcodec/s337m_parser.c
 create mode 100644 libavcodec/spdif_s337m_parse.c
 create mode 100644 libavcodec/spdif_s337m_parser_internal.h

diff --git a/configure b/configure
index d7b7b49f92..eb4eea97a9 100755
--- a/configure
+++ b/configure
@@ -3072,6 +3072,8 @@ rv20_encoder_select="h263_encoder"
 rv30_decoder_select="golomb h264pred h264qpel mpegvideodec rv34dsp"
 rv40_decoder_select="golomb h264pred h264qpel mpegvideodec rv34dsp"
 rv60_decoder_select="videodsp golomb"
+s337m_16_decoder_select="dolby_e_decoder"
+s337m_24_decoder_select="dolby_e_decoder"
 screenpresso_decoder_deps="zlib"
 shorten_decoder_select="bswapdsp"
 sipr_decoder_select="lsp"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index a6e0e0b55e..deff288312 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -672,6 +672,8 @@ OBJS-$(CONFIG_RV60_DECODER)+= rv60dec.o 
rv60dsp.o
 OBJS-$(CONFIG_SAMI_DECODER)+= samidec.o ass.o htmlsubtitles.o
 OBJS-$(CONFIG_S302M_DECODER)   += s302m.o
 OBJS-$(CONFIG_S302M_ENCODER)   += s302menc.o
+OBJS-$(CONFIG_S337M_16_DECODER)+= spdif_s337m_parse.o s337m.o
+OBJS-$(CONFIG_S337M_24_DECODER)+= spdif_s337m_parse.o s337m.o
 OBJS-$(CONFIG_SANM_DECODER)+= sanm.o
 OBJS-$(CONFIG_SCPR_DECODER)+= scpr.o
 OBJS-$(CONFIG_SCREENPRESSO_DECODER)+= screenpresso.o
@@ -1233,6 +1235,8 @@ OBJS-$(CONFIG_PNG_PARSER)  += png_parser.o
 OBJS-$(CONFIG_PNM_PARSER)  += pnm_parser.o pnm.o
 OBJS-$(CONFIG_QOI_PARSER)  += qoi_parser.o
 OBJS-$(CONFIG_RV34_PARSER) += rv34_parser.o
+OBJS-$(CONFIG_S337M_16_PARSER) += spdif_s337m_parse.o s337m_parser.o
+OBJS-$(CONFIG_S337M_24_PARSER) += spdif_s337m_parse.o s337m_parser.o
 OBJS-$(CONFIG_SBC_PARSER)  += sbc_parser.o
 OBJS-$(CONFIG_SIPR_PARSER) += sipr_parser.o
 OBJS-$(CONFIG_TAK_PARSER)  += tak_parser.o tak.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 0b559dfc58..04e294734d 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -522,6 +522,8 @@ extern const FFCodec ff_ra_144_encoder;
 extern const FFCodec ff_ra_144_decoder;
 extern const FFCodec ff_ra_288_decoder;
 extern const FFCodec ff_ralf_decoder;
+extern const FFCodec ff_s337m_16_decoder;
+extern const FFCodec ff_s337m_24_decoder;
 extern const FFCodec ff_sbc_encoder;
 extern const FFCodec ff_sbc_decoder;
 extern const FFCodec ff_shorten_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index bc9163bf98..927d19a8f9 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -3451,6 +3451,20 @@ static const AVCodecDescriptor codec_descriptors[] = {
 .long_name = NULL_IF_CONFIG_SMALL("LC3 (Low Complexity Communication 
Codec)"),
 .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
 },
+{
+.id= AV_CODEC_ID_S337M_16,
+.type  = AVMEDIA_TYPE_AUDIO,
+.name  = "s337m_16",
+.long_name = NULL_IF_CONFIG_SMALL("S337M within 16-bit pcm"),
+.props = AV_CODEC_PROP_LOSSY,
+},
+{
+.id= AV_CODEC_ID_S337M_24,
+.type  = AVMEDIA_TYPE_AUDIO,
+.name  = "s337m_24",
+.long_name = NULL_IF_CONFIG_SMALL("S337M within 24-bit pcm"),
+.props = AV_CODEC_PROP_LOSSY,
+},
 
 /* subtitle codecs */
 {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 6bfaa02601..60cb33eec2 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -550,6 +550,8 @@ enum AVCodecID {
 AV_CODEC_ID_OSQ,
 AV_CODEC_ID_QOA,
 AV_CODEC_ID_LC3,
+AV_CODEC_ID_S337M_16,
+AV_CODEC_ID_S337M_24,
 
 /* subtitle codecs */
 AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,  ///< A dummy ID pointing at 
the start of subtitle codecs.
diff --git a/libavcodec/dolby_e_parse.c b/libavcodec/dolby_e_parse.c
index ffedcd99a4..3f6e1abc02 100644
--- a/libavcodec/dolby_e_parse.c
+++ b/libavcodec/dolby_e_parse.c
@@ -30,6 +30,9 @@ static const uint8_t nb_channels_tab[MAX_PROG_CONF + 1] = {
 8, 

[FFmpeg-devel] [PATCH 2/7] avformat/spdif, s337m: use shared code from avcodec

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

---
 libavformat/Makefile   |  6 +++---
 libavformat/s337m.c|  3 ++-
 libavformat/spdif.c| 42 --
 libavformat/spdif.h|  1 -
 libavformat/spdifdec.c |  3 ++-
 libavformat/spdifenc.c |  3 ++-
 6 files changed, 9 insertions(+), 49 deletions(-)
 delete mode 100644 libavformat/spdif.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 7ca68a7036..52aa64d43b 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -531,7 +531,7 @@ 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 spdif.o
+OBJS-$(CONFIG_S337M_DEMUXER) += s337m.o
 OBJS-$(CONFIG_SAMI_DEMUXER)  += samidec.o subtitles.o
 OBJS-$(CONFIG_SAP_DEMUXER)   += sapdec.o
 OBJS-$(CONFIG_SAP_MUXER) += sapenc.o
@@ -563,8 +563,8 @@ OBJS-$(CONFIG_SMUSH_DEMUXER) += smush.o
 OBJS-$(CONFIG_SOL_DEMUXER)   += sol.o pcm.o
 OBJS-$(CONFIG_SOX_DEMUXER)   += soxdec.o pcm.o
 OBJS-$(CONFIG_SOX_MUXER) += soxenc.o rawenc.o
-OBJS-$(CONFIG_SPDIF_DEMUXER) += spdif.o spdifdec.o
-OBJS-$(CONFIG_SPDIF_MUXER)   += spdif.o spdifenc.o
+OBJS-$(CONFIG_SPDIF_DEMUXER) += spdifdec.o
+OBJS-$(CONFIG_SPDIF_MUXER)   += spdifenc.o
 OBJS-$(CONFIG_SPEEX_MUXER)   += oggenc.o \
 vorbiscomment.o
 OBJS-$(CONFIG_SRT_DEMUXER)   += srtdec.o subtitles.o
diff --git a/libavformat/s337m.c b/libavformat/s337m.c
index 4518f032d2..feb0f66cb3 100644
--- a/libavformat/s337m.c
+++ b/libavformat/s337m.c
@@ -19,6 +19,7 @@
  */
 
 #include "libavutil/intreadwrite.h"
+#include "libavcodec/spdif_s337m_parser_internal.h"
 #include "avformat.h"
 #include "demux.h"
 #include "internal.h"
@@ -171,7 +172,7 @@ static int s337m_read_packet(AVFormatContext *s, AVPacket 
*pkt)
 return ret < 0 ? ret : AVERROR_EOF;
 
 if (IS_16LE_MARKER(state))
-ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, 
pkt->size >> 1);
+avpriv_spdif_s337m_bswap_buf16((uint16_t *)pkt->data, (uint16_t 
*)pkt->data, pkt->size >> 1);
 else
 bswap_buf24(pkt->data, pkt->size);
 
diff --git a/libavformat/spdif.c b/libavformat/spdif.c
deleted file mode 100644
index 604141a261..00
--- a/libavformat/spdif.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * IEC 61937 common code
- * Copyright (c) 2009 Bartlomiej Wolowiec
- *
- * 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 "spdif.h"
-#include "libavutil/bswap.h"
-
-//TODO move to DSP
-void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w)
-{
-int i;
-
-for (i = 0; i + 8 <= w; i += 8) {
-dst[i + 0] = av_bswap16(src[i + 0]);
-dst[i + 1] = av_bswap16(src[i + 1]);
-dst[i + 2] = av_bswap16(src[i + 2]);
-dst[i + 3] = av_bswap16(src[i + 3]);
-dst[i + 4] = av_bswap16(src[i + 4]);
-dst[i + 5] = av_bswap16(src[i + 5]);
-dst[i + 6] = av_bswap16(src[i + 6]);
-dst[i + 7] = av_bswap16(src[i + 7]);
-}
-for (; i < w; i++)
-dst[i + 0] = av_bswap16(src[i + 0]);
-}
diff --git a/libavformat/spdif.h b/libavformat/spdif.h
index 0039fcfe5c..b5ab70022b 100644
--- a/libavformat/spdif.h
+++ b/libavformat/spdif.h
@@ -58,7 +58,6 @@ static const uint16_t spdif_mpeg_pkt_offset[2][3] = {
 { 1536,4608,   4608 }, // MPEG-1
 };
 
-void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w);
 int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt);
 int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec);
 
diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c
index dcfe471f45..0879a315e7 100644
--- a/libavformat/spdifdec.c
+++ b/libavformat/spdifdec.c
@@ -29,6 +29,7 @@
 
 #include "libavcodec/ac3defs.h"
 #include "libavcodec/adts_parser.h"
+#include "libavcodec/spdif_s337m_parser_internal.h"
 
 #include "avformat.h"
 #include "demux.h"
@@ -215,7 +216,

[FFmpeg-devel] [PATCH 3/7] avformat/s337m: switch to two rawdec for 16- and 24-bit

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

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 
---
 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 & 0x) == MARKER_16LE)
-#define IS_20LE_MARKER(state)   ((state & 0xF0F0) == MARKER_20LE)
-#define IS_24LE_MARKER(state)   ((state & 0x) == 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);
- 

[FFmpeg-devel] [PATCH 4/7] fate/acodec: add 20/24bit s302m tests

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

Prepare for s302m decoder re-implementation in mpegts.

Signed-off-by: Nicolas Gaullier 
---
 tests/fate/acodec.mak| 15 ++-
 tests/ref/acodec/s302m   |  4 
 tests/ref/acodec/s302m-16bit |  4 
 tests/ref/acodec/s302m-20bit |  4 
 tests/ref/acodec/s302m-24bit |  4 
 5 files changed, 22 insertions(+), 9 deletions(-)
 delete mode 100644 tests/ref/acodec/s302m
 create mode 100644 tests/ref/acodec/s302m-16bit
 create mode 100644 tests/ref/acodec/s302m-20bit
 create mode 100644 tests/ref/acodec/s302m-24bit

diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak
index 7b09e3bd63..5bdb89250f 100644
--- a/tests/fate/acodec.mak
+++ b/tests/fate/acodec.mak
@@ -159,11 +159,16 @@ fate-acodec-roqaudio: CODEC = roq_dpcm
 fate-acodec-roqaudio: ENCOPTS = -af aresample=22050:tsf=s16p
 fate-acodec-roqaudio: DECOPTS = -af aresample=44100:tsf=s16p
 
-FATE_ACODEC-$(call ENCDEC, S302M, MPEGTS, ARESAMPLE_FILTER) += 
fate-acodec-s302m
-fate-acodec-s302m: FMT = mpegts
-fate-acodec-s302m: CODEC = s302m
-fate-acodec-s302m: ENCOPTS = -af aresample=48000:tsf=s16p -strict -2
-fate-acodec-s302m: DECOPTS = -af aresample=44100:tsf=s16p
+FATE_ACODEC_S302M-$(call ENCDEC, S302M, MPEGTS, ARESAMPLE_FILTER) += 16bit 
20bit 24bit
+FATE_ACODEC_S302M := $(addprefix fate-acodec-s302m-, $(FATE_ACODEC_S302M-yes))
+FATE_ACODEC += $(FATE_ACODEC_S302M)
+fate-acodec-s302m: $(FATE_ACODEC_S302M)
+fate-acodec-s302m-%: CODEC = s302m
+fate-acodec-s302m-%: FMT = mpegts
+fate-acodec-s302m-16bit: ENCOPTS = -af aresample=48000:tsf=s16p -strict -2
+fate-acodec-s302m-16bit: DECOPTS = -af aresample=44100:tsf=s16p
+fate-acodec-s302m-20bit: ENCOPTS = -af aresample=48000:osf=s32p 
-bits_per_raw_sample 20 -strict -2
+fate-acodec-s302m-24bit: ENCOPTS = -af aresample=48000:osf=s32p 
-bits_per_raw_sample 24 -strict -2
 
 FATE_ACODEC-$(call ENCDEC, WAVPACK, WV, ARESAMPLE_FILTER) += 
fate-acodec-wavpack
 fate-acodec-wavpack: FMT = wv
diff --git a/tests/ref/acodec/s302m b/tests/ref/acodec/s302m
deleted file mode 100644
index bc4986cabd..00
--- a/tests/ref/acodec/s302m
+++ /dev/null
@@ -1,4 +0,0 @@
-08a3bec0e1626ad8c8a13b181ee1afb5 *tests/data/fate/acodec-s302m.mpegts
-1496104 tests/data/fate/acodec-s302m.mpegts
-abc1b26737c8103c3f122539d239f6be *tests/data/fate/acodec-s302m.out.wav
-stddev:  986.15 PSNR: 36.45 MAXDIFF:18571 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/s302m-16bit b/tests/ref/acodec/s302m-16bit
new file mode 100644
index 00..479c75e5cb
--- /dev/null
+++ b/tests/ref/acodec/s302m-16bit
@@ -0,0 +1,4 @@
+08a3bec0e1626ad8c8a13b181ee1afb5 *tests/data/fate/acodec-s302m-16bit.mpegts
+1496104 tests/data/fate/acodec-s302m-16bit.mpegts
+abc1b26737c8103c3f122539d239f6be *tests/data/fate/acodec-s302m-16bit.out.wav
+stddev:  986.15 PSNR: 36.45 MAXDIFF:18571 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/s302m-20bit b/tests/ref/acodec/s302m-20bit
new file mode 100644
index 00..32abe210dc
--- /dev/null
+++ b/tests/ref/acodec/s302m-20bit
@@ -0,0 +1,4 @@
+3b61de99b3ffb1bd8d8e4faf0c69c898 *tests/data/fate/acodec-s302m-20bit.mpegts
+1787692 tests/data/fate/acodec-s302m-20bit.mpegts
+a2d243021a8aa0d3463a24fe2bce253e *tests/data/fate/acodec-s302m-20bit.out.wav
+stddev:11358.21 PSNR: 15.22 MAXDIFF:65498 bytes:  1058400/  1152000
diff --git a/tests/ref/acodec/s302m-24bit b/tests/ref/acodec/s302m-24bit
new file mode 100644
index 00..e584cd589b
--- /dev/null
+++ b/tests/ref/acodec/s302m-24bit
@@ -0,0 +1,4 @@
+f1a59487a89575913fce360a332700f7 *tests/data/fate/acodec-s302m-24bit.mpegts
+2079280 tests/data/fate/acodec-s302m-24bit.mpegts
+a2d243021a8aa0d3463a24fe2bce253e *tests/data/fate/acodec-s302m-24bit.out.wav
+stddev:11358.21 PSNR: 15.22 MAXDIFF:65498 bytes:  1058400/  1152000
-- 
2.30.2

___
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".


[FFmpeg-devel] [PATCH 5/7] avformat/mpegts: add s337m support

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

Move s302m decoder from avcodec to avformat.
Set AVSTREAM_PARSE_FULL for s337m support.

Signed-off-by: Nicolas Gaullier 
---
 libavformat/mpegts.c  | 138 +-
 tests/fate/acodec.mak |   3 +-
 2 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 177e610e53..fd649751fc 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -31,6 +31,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/avassert.h"
 #include "libavutil/dovi_meta.h"
+#include "libavutil/reverse.h"
 #include "libavcodec/bytestream.h"
 #include "libavcodec/defs.h"
 #include "libavcodec/get_bits.h"
@@ -1009,6 +1010,125 @@ static void new_data_packet(const uint8_t *buffer, int 
len, AVPacket *pkt)
 pkt->size = len;
 }
 
+#define AES3_HEADER_LEN 4
+static int s302m_parse_frame_header(void *avc, AVCodecParameters *par, const 
uint8_t *buf,
+int buf_size)
+{
+uint32_t h;
+int frame_size, channels, bits;
+
+if (buf_size <= AES3_HEADER_LEN) {
+av_log(avc, AV_LOG_ERROR, "frame is too short\n");
+return AVERROR_INVALIDDATA;
+}
+
+/*
+ * AES3 header :
+ * size:16
+ * number channels   2
+ * channel_id8
+ * bits per samples  2
+ * alignments4
+ */
+
+h = AV_RB32(buf);
+frame_size =  (h >> 16) & 0x;
+channels   = ((h >> 14) & 0x0003) * 2 +  2;
+bits   = ((h >>  4) & 0x0003) * 4 + 16;
+
+if (bits > 24) {
+av_log(avc, AV_LOG_ERROR, "frame has invalid header\n");
+return AVERROR_INVALIDDATA;
+}
+
+/* Output properties may have been overriden by stream probing after
+ * avformat_find_stream_info and must be preserved */
+if (par->codec_id != AV_CODEC_ID_S302M
+&& par->codec_id != AV_CODEC_ID_PCM_S24LE
+&& par->codec_id != AV_CODEC_ID_PCM_S16LE)
+goto end;
+
+/* Set output properties */
+par->bits_per_raw_sample = bits;
+if (bits > 16)
+par->codec_id = AV_CODEC_ID_PCM_S24LE;
+else
+par->codec_id = AV_CODEC_ID_PCM_S16LE;
+
+av_channel_layout_uninit(&par->ch_layout);
+switch(channels) {
+case 2:
+par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+break;
+case 4:
+par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD;
+break;
+case 6:
+par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK;
+break;
+case 8:
+av_channel_layout_from_mask(&par->ch_layout,
+AV_CH_LAYOUT_5POINT1_BACK | 
AV_CH_LAYOUT_STEREO_DOWNMIX);
+break;
+default:
+par->ch_layout.order   = AV_CHANNEL_ORDER_UNSPEC;
+par->ch_layout.nb_channels = channels;
+break;
+}
+
+par->sample_rate = 48000;
+
+end:
+return AES3_HEADER_LEN + frame_size;
+}
+
+static int s302m_demux(AVCodecParameters *par, AVPacket *pkt)
+{
+int ret = av_packet_make_writable(pkt);
+if (ret < 0)
+return ret;
+pkt->data += AES3_HEADER_LEN;
+av_shrink_packet(pkt, pkt->size - AES3_HEADER_LEN);
+
+if (par->bits_per_raw_sample == 24) {
+uint8_t *buf = pkt->data;
+uint8_t *buf_out = buf;
+for (; buf + 6 < pkt->data + pkt->size; buf+=7, buf_out+=6)
+AV_WL48(buf_out,
+((uint64_t)ff_reverse[buf[2]] << 16) |
+((uint64_t)ff_reverse[buf[1]] <<  8) |
+((uint64_t)ff_reverse[buf[0]])   |
+((uint64_t)ff_reverse[buf[6] & 0xf0] << 44) |
+((uint64_t)ff_reverse[buf[5]]<< 36) |
+((uint64_t)ff_reverse[buf[4]]<< 28) |
+((uint64_t)ff_reverse[buf[3] & 0x0f] << 20));
+av_shrink_packet(pkt, buf_out - pkt->data);
+}
+else if (par->bits_per_raw_sample == 20) {
+uint8_t *buf = pkt->data;
+for (; buf + 5 < pkt->data + pkt->size; buf+=6)
+AV_WL48(buf,
+((uint64_t)ff_reverse[buf[2] & 0xf0] << 20) |
+((uint64_t)ff_reverse[buf[1]]<< 12) |
+((uint64_t)ff_reverse[buf[0]]<< 4)  |
+((uint64_t)ff_reverse[buf[5] & 0xf0] << 44) |
+((uint64_t)ff_reverse[buf[4]]<< 36) |
+((uint64_t)ff_reverse[buf[3]]<< 28));
+} else {
+uint8_t *buf = pkt->data;
+uint8_t *buf_out = buf;
+for (; buf + 4 < pkt->data + pkt->size; buf+=5, buf_out+=4)
+AV_WL32(buf_out,
+((uint32_t)ff_reverse[buf[1]]<< 8)  |
+((uint32_t)ff_reverse[buf[0]])  |
+((uint32_t)ff_reverse[buf[4] & 0xf0] << 28) |
+((uint32_t)ff_reverse[buf[3]]<< 20) |
+((uint32_t)ff_reverse[buf[2] & 0x0f] <

[FFmpeg-devel] [PATCH 6/7] avformat: add s337m support in mpegts, wav and mxf stereo tracks

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

Signed-off-by: Nicolas Gaullier 
---
 libavformat/demux.c  | 2 ++
 libavformat/mxfdec.c | 9 +++--
 libavformat/wavdec.c | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/libavformat/demux.c b/libavformat/demux.c
index cba1f2e4df..d26d207a46 100644
--- a/libavformat/demux.c
+++ b/libavformat/demux.c
@@ -125,6 +125,8 @@ static int set_codec_from_probe_data(AVFormatContext *s, 
AVStream *st,
 { "truehd", AV_CODEC_ID_TRUEHD,   AVMEDIA_TYPE_AUDIO},
 { "evc",AV_CODEC_ID_EVC,  AVMEDIA_TYPE_VIDEO},
 { "vvc",AV_CODEC_ID_VVC,  AVMEDIA_TYPE_VIDEO},
+{ "s337m_16",   AV_CODEC_ID_S337M_16, AVMEDIA_TYPE_AUDIO},
+{ "s337m_24",   AV_CODEC_ID_S337M_24, AVMEDIA_TYPE_AUDIO},
 { 0 }
 };
 int score;
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 9ecaa287bb..2eaca7565b 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -634,7 +634,7 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, 
AVStream *st, AVPacket *pkt,
 for (; end_ptr - buf_ptr >= st->codecpar->ch_layout.nb_channels * 4; ) {
 for (int i = 0; i < st->codecpar->ch_layout.nb_channels; i++) {
 uint32_t sample = bytestream_get_le32(&buf_ptr);
-if (st->codecpar->bits_per_coded_sample == 24)
+if (av_get_bits_per_sample(st->codecpar->codec_id) == 24)
 bytestream_put_le24(&data_ptr, (sample >> 4) & 0xff);
 else
 bytestream_put_le16(&data_ptr, (sample >> 12) & 0x);
@@ -3080,7 +3080,12 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
 } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
 sti->need_parsing = AVSTREAM_PARSE_FULL;
 }
-st->codecpar->bits_per_coded_sample = 
av_get_bits_per_sample(st->codecpar->codec_id);
+if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE
+ || st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
+FFStream *const sti = ffstream(st);
+sti->request_probe = AVPROBE_SCORE_EXTENSION;
+sti->need_parsing  = AVSTREAM_PARSE_FULL;
+}
 
 if (descriptor->channels <= 0 || descriptor->channels >= 
FF_SANE_NB_CHANNELS) {
 av_log(mxf->fc, AV_LOG_ERROR, "Invalid number of channels %d, 
must be less than %d\n", descriptor->channels, FF_SANE_NB_CHANNELS);
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 78e37b88d7..c55aa915e6 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -176,7 +176,8 @@ static int wav_probe(const AVProbeData *p)
 
 static void handle_stream_probing(AVStream *st)
 {
-if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) {
+if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE
+ || st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
 FFStream *const sti = ffstream(st);
 sti->request_probe = AVPROBE_SCORE_EXTENSION;
 sti->probe_packets = FFMIN(sti->probe_packets, 32);
-- 
2.30.2

___
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".


[FFmpeg-devel] [PATCH 7/7] fate: add s337m decode and demux tests

2024-12-04 Thread ffnicolasg
From: Nicolas Gaullier 

Signed-off-by: Nicolas Gaullier 
---
 tests/fate/audio.mak  | 10 
 tests/fate/demux.mak  | 15 -
 tests/ref/fate/s337m-demux-mxf| 56 +++
 .../ref/fate/{s337m-demux => s337m-demux-raw} |  0
 tests/ref/fate/s337m-demux-ts-20  | 44 +++
 tests/ref/fate/s337m-demux-ts-24  | 39 +
 tests/ref/fate/s337m-demux-wav| 11 
 tests/ref/fate/s337m-demux-wav-miss1-3-5  |  8 +++
 8 files changed, 181 insertions(+), 2 deletions(-)
 create mode 100644 tests/ref/fate/s337m-demux-mxf
 rename tests/ref/fate/{s337m-demux => s337m-demux-raw} (100%)
 create mode 100644 tests/ref/fate/s337m-demux-ts-20
 create mode 100644 tests/ref/fate/s337m-demux-ts-24
 create mode 100644 tests/ref/fate/s337m-demux-wav
 create mode 100644 tests/ref/fate/s337m-demux-wav-miss1-3-5

diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak
index 421c4e12f4..805014dfbe 100644
--- a/tests/fate/audio.mak
+++ b/tests/fate/audio.mak
@@ -74,6 +74,16 @@ fate-on2avc: CMD = framecrc -i 
$(TARGET_SAMPLES)/vp7/potter-40.vp7 -frames 30 -v
 FATE_SAMPLES_AUDIO-$(call DEMDEC, PAF, PAF_AUDIO) += fate-paf-audio
 fate-paf-audio: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -vn
 
+FATE_S337MAUDIO-$(call PCM, S337M_24, S337M_24) += 20bit 24bit
+FATE_S337MAUDIO := $(addprefix fate-s337m-decode-, $(FATE_S337MAUDIO-yes))
+FATE_SAMPLES_AUDIO-yes += $(FATE_S337MAUDIO)
+fate-s337m-decode: $(FATE_S337MAUDIO)
+fate-s337m-decode-%: CMP = oneoff
+fate-s337m-decode-20bit: CMD = pcm -i 
$(TARGET_SAMPLES)/dolby_e/20-bit-s302m_20-bit_5.1_2.0_phase000750.ts
+fate-s337m-decode-20bit: REF = 
$(SAMPLES)/dolby_e/20-bit-s302m_20-bit_5.1_2.0_phase000750.ts.pcm
+fate-s337m-decode-24bit: CMD = pcm -i 
$(TARGET_SAMPLES)/dolby_e/24-bit-s302m_20-bit_5.1_2.0_phase001021.ts
+fate-s337m-decode-24bit: REF = 
$(SAMPLES)/dolby_e/24-bit-s302m_20-bit_5.1_2.0_phase001021.ts.pcm
+
 FATE_SAMPLES_AUDIO-$(call DEMDEC, VMD, VMDAUDIO, ARESAMPLE_FILTER) += 
fate-sierra-vmd-audio
 fate-sierra-vmd-audio: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -vn -af 
aresample
 
diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak
index f70491f158..4154969ac5 100644
--- a/tests/fate/demux.mak
+++ b/tests/fate/demux.mak
@@ -130,8 +130,19 @@ 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 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_S337M_DEMUX-$(call FRAMECRC, S337M_16,, S337M_16_PARSER) += raw
+FATE_SAMPLES_S337M_DEMUX-$(call FRAMECRC, S337M_24,, S337M_24_PARSER) += $(if 
$(CONFIG_WAV_DEMUXER), wav wav-miss1-3-5) \
+ $(if 
$(CONFIG_MXF_DEMUXER), mxf) \
+ $(if 
$(CONFIG_MPEGTS_DEMUXER), ts-20 ts-24)
+FATE_SAMPLES_S337M_DEMUX := $(addprefix fate-s337m-demux-, 
$(FATE_SAMPLES_S337M_DEMUX-yes))
+FATE_SAMPLES_DEMUX += $(FATE_SAMPLES_S337M_DEMUX)
+fate-s337m-demux: $(FATE_SAMPLES_S337M_DEMUX)
+fate-s337m-demux-raw: CMD = framecrc -i $(TARGET_SAMPLES)/dolby_e/16-11 -c 
copy -ss 2 -t 1
+fate-s337m-demux-wav: CMD = framecrc -i 
$(TARGET_SAMPLES)/dolby_e/20-bit_5.1_2.0.wav -vn -c:a copy
+fate-s337m-demux-wav-miss1-3-5: CMD = framecrc -i 
$(TARGET_SAMPLES)/dolby_e/20-bit_5.1_2.0_miss1-3-5.wav -vn -c:a copy
+fate-s337m-demux-mxf: CMD = framecrc -i 
$(TARGET_SAMPLES)/dolby_e/24-bit_5.1_2.0.mxf -vn -c:a copy
+fate-s337m-demux-ts-20: CMD = framecrc -i 
$(TARGET_SAMPLES)/dolby_e/20-bit-s302m_20-bit_5.1_2.0_phase000750.ts -vn -c:a 
copy
+fate-s337m-demux-ts-24: CMD = framecrc -i 
$(TARGET_SAMPLES)/dolby_e/24-bit-s302m_20-bit_5.1_2.0_phase001021.ts -vn -c:a 
copy
 
 FATE_SAMPLES_DEMUX-$(CONFIG_SIFF_DEMUXER) += fate-siff-demux
 fate-siff-demux: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -c copy
diff --git a/tests/ref/fate/s337m-demux-mxf b/tests/ref/fate/s337m-demux-mxf
new file mode 100644
index 00..ce6dc4c440
--- /dev/null
+++ b/tests/ref/fate/s337m-demux-mxf
@@ -0,0 +1,56 @@
+#tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: s337m_24
+#sample_rate 0: 48000
+#channel_layout_name 0: 7.1
+0,  0,  0,   30,  180, 0x
+0, 30, 30, 1920,11520, 0x985f72f4
+0,   1920,   1920, 1920,11520, 0xbc1b27cc
+0,   3840,   3840, 1920,11520, 0x08db3200
+0,   5760,   5760, 1920,11520, 0x135b7c07
+0,   7680,   7680, 1920,11520, 0x0b4647d1
+0,   9600,   9600, 1920,11520, 0xd0fa478c
+0,  11520,  11520, 1920,11520, 0