[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