[FFmpeg-devel] [PATCH] libavcodec/pcm-dvd: support a subset of AOB
Carl Eugen Hoyos
cehoyos at ag.or.at
Thu Jun 11 08:11:50 CEST 2015
On Thursday 11 June 2015 05:05:48 am Michael Niedermayer wrote:
> Fixes Ticket2758
> + if (avctx->bits_per_coded_sample != 16) {
> + avpriv_request_sample(avctx, "Unsupported sample size\n");
24bit sample is available:
http://samples.ffmpeg.org/DVD-Audio/ats.AOB
Attached is a variant of my patch from years ago,
the lavc part is a revert of an earlier codec removal.
This should be a separate codec imo because
remuxing to mpeg-ts will fail badly iirc.
Carl Eugen
-------------- next part --------------
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 4aeb57a..f261ce7 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -359,6 +359,7 @@ enum AVCodecID {
AV_CODEC_ID_PCM_S24LE_PLANAR = MKBETAG(24,'P','S','P'),
AV_CODEC_ID_PCM_S32LE_PLANAR = MKBETAG(32,'P','S','P'),
AV_CODEC_ID_PCM_S16BE_PLANAR = MKBETAG('P','S','P',16),
+ AV_CODEC_ID_PCM_AOB = MKBETAG('P','A','O','B'),
/* various ADPCM codecs */
AV_CODEC_ID_ADPCM_IMA_QT = 0x11000,
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 0a4ad0b..3549a66 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -302,6 +302,17 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
/* we process 40-bit blocks per channel for LXF */
samples_per_block = 2;
sample_size = 5;
+ } else if (avctx->codec_id == AV_CODEC_ID_PCM_AOB) {
+ if (avctx->bits_per_coded_sample != 20 &&
+ avctx->bits_per_coded_sample != 24) {
+ av_log(avctx, AV_LOG_ERROR,
+ "PCM DVD unsupported sample depth %i\n",
+ avctx->bits_per_coded_sample);
+ return AVERROR(EINVAL);
+ }
+ /* 2 samples are interleaved per block in PCM_DVD */
+ samples_per_block = 2;
+ sample_size = avctx->bits_per_coded_sample * 2 / 8;
}
if (sample_size == 0) {
@@ -459,6 +470,37 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
samples += 2;
}
break;
+ case AV_CODEC_ID_PCM_AOB:
+ {
+ const uint8_t *src8;
+ dst_int32_t = (int32_t *)frame->data[0];
+ n /= avctx->channels;
+ switch (avctx->bits_per_coded_sample) {
+ case 20:
+ while (n--) {
+ c = avctx->channels;
+ src8 = src + 4 * c;
+ while (c--) {
+ *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8 & 0xf0) << 8);
+ *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8++ & 0x0f) << 12);
+ }
+ src = src8;
+ }
+ break;
+ case 24:
+ while (n--) {
+ c = avctx->channels;
+ src8 = src + 4 * c;
+ while (c--) {
+ *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8++) << 8);
+ *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8++) << 8);
+ }
+ src = src8;
+ }
+ break;
+ }
+ break;
+ }
case AV_CODEC_ID_PCM_LXF:
{
int i;
@@ -541,6 +583,7 @@ AVCodec ff_ ## name_ ## _decoder = { \
/* Note: Do not forget to add new entries to the Makefile as well. */
PCM_CODEC (PCM_ALAW, AV_SAMPLE_FMT_S16, pcm_alaw, "PCM A-law / G.711 A-law");
+PCM_DECODER(PCM_AOB, AV_SAMPLE_FMT_S32, pcm_aob, "PCM signed 20|24-bit big-endian");
PCM_CODEC (PCM_F32BE, AV_SAMPLE_FMT_FLT, pcm_f32be, "PCM 32-bit floating point big-endian");
PCM_CODEC (PCM_F32LE, AV_SAMPLE_FMT_FLT, pcm_f32le, "PCM 32-bit floating point little-endian");
PCM_CODEC (PCM_F64BE, AV_SAMPLE_FMT_DBL, pcm_f64be, "PCM 64-bit floating point big-endian");
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index edb134f..6d6c9a9 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -611,7 +611,52 @@ skip:
found:
if (st->discard >= AVDISCARD_ALL)
goto skip;
- if (startcode >= 0xa0 && startcode <= 0xaf) {
+ if (av_match_ext(s->filename, "aob") && lpcm_header_len > 8 && startcode == 0xa0) {
+ // DVD-A LPCM audio
+ int sample_rates[] = { 48000, 96000, 192000,
+ 0, 0, 0, 0, 0,
+ 44100, 88200, 176400,
+ 0, 0, 0, 0, 0 };
+ avio_skip(s->pb, 2); // Pointer to start of audio frame
+ avio_skip(s->pb, 1); // Unknown
+ switch (avio_r8(s->pb) >> 4) {
+ case 2:
+ st->codec->codec_id = AV_CODEC_ID_PCM_AOB;
+ st->codec->bits_per_coded_sample = 24;
+ break;
+ case 1:
+ st->codec->codec_id = AV_CODEC_ID_PCM_AOB;
+ st->codec->bits_per_coded_sample = 20;
+ break;
+ case 0:
+ st->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
+ st->codec->bits_per_coded_sample = 16;
+ break;
+ default:
+ len -= 4;
+ goto skip;
+ }
+ st->codec->sample_rate = sample_rates[avio_r8(s->pb) >> 4];
+ len -= 5;
+ if (!st->codec->sample_rate)
+ goto skip;
+ avio_skip(s->pb, 1); // Unknown
+ switch (avio_r8(s->pb)) {
+ case 0:
+ st->codec->channels = 1;
+ st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+ break;
+ case 1:
+ st->codec->channels = 2;
+ st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+ break;
+ default:
+ avpriv_request_sample(s, "Multichannel DVD-A LPCM audio");
+ return AVERROR_PATCHWELCOME;
+ }
+ avio_skip(s->pb, lpcm_header_len - 7);
+ len -= lpcm_header_len - 5;
+ } else if (startcode >= 0xa0 && startcode <= 0xaf) {
if (lpcm_header_len == 6 && st->codec->codec_id == AV_CODEC_ID_MLP) {
if (len < 6)
goto skip;
More information about the ffmpeg-devel
mailing list