From: Nicolas Gaullier <nicolas.gaullier@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@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 _______________________________________________ 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".