From: Nicolas Gaullier <nicolas.gaullier@cji.paris> Move s302m decoder from avcodec to avformat. Set AVSTREAM_PARSE_FULL for s337m support.
Signed-off-by: Nicolas Gaullier <nicolas.gaullier@cji.paris> --- 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_id 8 + * bits per samples 2 + * alignments 4 + */ + + h = AV_RB32(buf); + frame_size = (h >> 16) & 0xffff; + 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] << 12)); + av_shrink_packet(pkt, buf_out - pkt->data); + } + return 0; +} + static int new_pes_packet(PESContext *pes, AVPacket *pkt) { uint8_t *sd; @@ -1032,6 +1152,20 @@ static int new_pes_packet(PESContext *pes, AVPacket *pkt) pkt->stream_index = pes->sub_st->index; else pkt->stream_index = pes->st->index; + + if (pes->st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D')) { + AVCodecParameters *par = pes->st->codecpar; + int expected_buf_size = s302m_parse_frame_header(pes->stream, par, pkt->data, pkt->size); + + if (expected_buf_size != pkt->size) + pes->flags |= AV_PKT_FLAG_CORRUPT; + if (expected_buf_size > 0) { + int ret = s302m_demux(par, pkt); + if (ret < 0) + return ret; + } + } + pkt->pts = pes->pts; pkt->dts = pes->dts; /* store position of first TS packet of this PES packet */ @@ -2024,8 +2158,10 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codecpar->codec_tag); if (st->codecpar->codec_id == AV_CODEC_ID_NONE || sti->request_probe > 0) { mpegts_find_stream_type(st, st->codecpar->codec_tag, REGD_types); - if (st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D')) + if (st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D')) { sti->request_probe = 50; + sti->need_parsing = AVSTREAM_PARSE_FULL; + } } break; case 0x52: /* stream identifier descriptor */ diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak index 5bdb89250f..f2def432be 100644 --- a/tests/fate/acodec.mak +++ b/tests/fate/acodec.mak @@ -159,7 +159,8 @@ 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_S302M-$(call ENCDEC, S302M, MPEGTS, ARESAMPLE_FILTER) += 16bit 20bit 24bit +FATE_ACODEC_S302M-$(call ENCDEC, S302M PCM_S16LE, MPEGTS, ARESAMPLE_FILTER) += 16bit +FATE_ACODEC_S302M-$(call ENCDEC, S302M PCM_S24LE, MPEGTS, ARESAMPLE_FILTER) += 20bit 24bit FATE_ACODEC_S302M := $(addprefix fate-acodec-s302m-, $(FATE_ACODEC_S302M-yes)) FATE_ACODEC += $(FATE_ACODEC_S302M) fate-acodec-s302m: $(FATE_ACODEC_S302M) -- 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".