It's a little ugly but without chain demux it isn't something we can do particularly cleanly. This is similar to how we do LATM.
Let me know if you think the git metadata should be different.
From ea084bdc985766ed323232cb22bdf4b04edd40b5 Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier <[email protected]> Date: Tue, 12 Apr 2011 15:29:09 -0700 Subject: [PATCH] Port s302m decoder from FFmbc 0.3. MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------1" This is a multi-part message in MIME format. --------------1 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit Ported-by: Alex Converse <[email protected]> --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/s302m.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/mpegts.c | 1 + 5 files changed, 146 insertions(+), 0 deletions(-) create mode 100644 libavcodec/s302m.c --------------1 Content-Type: text/x-patch; name="0001-Port-s302m-decoder-from-FFmbc-0.3.patch" Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="0001-Port-s302m-decoder-from-FFmbc-0.3.patch" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 1cdae2c..03c96ed 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -324,6 +324,7 @@ OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o \ mpegvideo.o error_resilience.o OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv40dsp.o \ mpegvideo.o error_resilience.o +OBJS-$(CONFIG_S302M_DECODER) += s302m.o OBJS-$(CONFIG_SGI_DECODER) += sgidec.o OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o OBJS-$(CONFIG_SHORTEN_DECODER) += shorten.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 40a7e23..aa2e7dc 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -177,6 +177,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (RV20, rv20); REGISTER_DECODER (RV30, rv30); REGISTER_DECODER (RV40, rv40); + REGISTER_DECODER (S302M, s302m); REGISTER_ENCDEC (SGI, sgi); REGISTER_DECODER (SMACKER, smacker); REGISTER_DECODER (SMC, smc); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 109d2a4..d06d21f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -241,6 +241,7 @@ enum CodecID { CODEC_ID_PCM_F64LE, CODEC_ID_PCM_BLURAY, CODEC_ID_PCM_LXF, + CODEC_ID_S302M, /* various ADPCM codecs */ CODEC_ID_ADPCM_IMA_QT= 0x11000, diff --git a/libavcodec/s302m.c b/libavcodec/s302m.c new file mode 100644 index 0000000..4820db6 --- /dev/null +++ b/libavcodec/s302m.c @@ -0,0 +1,142 @@ +/* + * SMPTE 302M decoder + * Copyright (c) 2008 Laurent Aimar <[email protected]> + * Copyright (c) 2009 Baptiste Coudurier <[email protected]> + * + * 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 "avcodec.h" +#include "libavutil/intreadwrite.h" + +#define AES3_HEADER_LEN 4 + +static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, int buf_size) +{ + uint32_t h; + int frame_size, channels, id, bits; + + if (buf_size <= AES3_HEADER_LEN) { + av_log(avctx, AV_LOG_ERROR, "frame is too short\n"); + return -1; + } + + /* + * 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 = 2 + 2*((h >> 14) & 0x03); + id = (h >> 6) & 0xff; + bits = 16 + 4*((h >> 4) & 0x03); + + if (AES3_HEADER_LEN + frame_size != buf_size || bits > 24) { + av_log(avctx, AV_LOG_ERROR, "frame has invalid header\n"); + return -1; + } + + /* Set output properties */ + avctx->bits_per_coded_sample = bits; + if (bits > 16) + avctx->sample_fmt = SAMPLE_FMT_S32; + else + avctx->sample_fmt = SAMPLE_FMT_S16; + + avctx->channels = channels; + avctx->sample_rate = 48000; + avctx->bit_rate = 48000*avctx->channels*(avctx->bits_per_coded_sample+4) + + 32*(48000/(buf_size*8/(avctx->channels*(avctx->bits_per_coded_sample+4)))); + + return frame_size; +} + +static int s302m_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int frame_size, buf_size = avpkt->size; + + frame_size = s302m_parse_frame_header(avctx, buf, buf_size); + if (frame_size < 0) + return -1; + + buf_size -= AES3_HEADER_LEN; + buf += AES3_HEADER_LEN; + + if (*data_size < 4*buf_size*8/(avctx->bits_per_coded_sample+4)) + return -1; + + if (avctx->bits_per_coded_sample == 24) { + uint32_t *o = data; + for (; buf_size > 6; buf_size -= 7) { + *o++ = (av_reverse[buf[2]] << 24) | + (av_reverse[buf[1]] << 16) | + (av_reverse[buf[0]] << 8); + *o++ = (av_reverse[buf[6]&0xf0] << 28) | + (av_reverse[buf[5]] << 20) | + (av_reverse[buf[4]] << 12) | + (av_reverse[buf[3]&0x0f] << 8); + buf += 7; + } + *data_size = (uint8_t*)o - (uint8_t*)data; + } else if (avctx->bits_per_coded_sample == 20) { + uint32_t *o = data; + for (; buf_size > 5; buf_size -= 6) { + *o++ = (av_reverse[buf[2]&0xf0] << 28) | + (av_reverse[buf[1]] << 20) | + (av_reverse[buf[0]] << 12); + *o++ = (av_reverse[buf[5]&0xf0] << 28) | + (av_reverse[buf[4]] << 20) | + (av_reverse[buf[3]] << 12); + buf += 6; + } + *data_size = (uint8_t*)o - (uint8_t*)data; + } else { + uint16_t *o = data; + for (; buf_size > 4; buf_size -= 5) { + *o++ = (av_reverse[buf[1]] << 8) | + av_reverse[buf[0]]; + *o++ = (av_reverse[buf[4]&0xf0] << 12) | + (av_reverse[buf[3]] << 4) | + av_reverse[buf[2]&0x0f]; + buf += 5; + } + *data_size = (uint8_t*)o - (uint8_t*)data; + } + + return buf - avpkt->data; +} + + +AVCodec ff_s302m_decoder = { + "s302m", + AVMEDIA_TYPE_AUDIO, + CODEC_ID_S302M, + 0, + NULL, + NULL, + NULL, + s302m_decode_frame, + .long_name= NULL_IF_CONFIG_SMALL("SMPTE 302M"), +}; diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 62e9dcb..db85a77 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -524,6 +524,7 @@ static const StreamType MISC_types[] = { static const StreamType REGD_types[] = { { MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, CODEC_ID_DIRAC }, { MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO, CODEC_ID_AC3 }, + { MKTAG('B','S','S','D'), AVMEDIA_TYPE_AUDIO, CODEC_ID_S302M }, { 0 }, }; --------------1--
_______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
