[FFmpeg-devel] [PATCH 0/7] RFC: complete rework of s337m support
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
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
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
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
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
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
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
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