[FFmpeg-devel] [PATCH]Support PCM in DVD-Audio files

Michael Niedermayer michaelni at gmx.at
Fri Dec 6 01:05:53 CET 2013


On Mon, Dec 02, 2013 at 12:36:42PM +0100, Carl Eugen Hoyos wrote:
> Hi!
> 
> Attached patch partially reverts a42e3a67 and fixes ticket #2758 for me.
> 
> Please review, Carl Eugen

>  libavcodec/allcodecs.c  |    1 +
>  libavcodec/avcodec.h    |    1 +
>  libavcodec/codec_desc.c |    7 +++++++
>  libavcodec/pcm.c        |   43 +++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/version.h    |    2 +-
>  libavformat/mpeg.c      |   47 +++++++++++++++++++++++++++++++++++++++++++++++
>  libavformat/version.h   |    2 +-
>  7 files changed, 101 insertions(+), 2 deletions(-)
> 605ee2934602bb708766f6265e03081f213dedfb  patchaob.diff
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index a47a85d..5adb5c4 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -387,6 +387,7 @@ void avcodec_register_all(void)
>  
>      /* PCM codecs */
>      REGISTER_ENCDEC (PCM_ALAW,          pcm_alaw);
> +    REGISTER_DECODER(PCM_AOB,           pcm_aob);
>      REGISTER_DECODER(PCM_BLURAY,        pcm_bluray);
>      REGISTER_DECODER(PCM_DVD,           pcm_dvd);
>      REGISTER_ENCDEC (PCM_F32BE,         pcm_f32be);
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 7e5aee2..cf480b7 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -349,6 +349,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/codec_desc.c b/libavcodec/codec_desc.c
> index c62734f..5181d5f 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -1567,6 +1567,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
>          .props     = AV_CODEC_PROP_LOSSLESS,
>      },
>      {
> +        .id        = AV_CODEC_ID_PCM_AOB,
> +        .type      = AVMEDIA_TYPE_AUDIO,
> +        .name      = "pcm_aob",
> +        .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20|24-bit big-endian for DVD-A media"),
> +        .props     = AV_CODEC_PROP_LOSSLESS,
> +    },
> +    {
>          .id        = AV_CODEC_ID_PCM_F32BE,
>          .type      = AVMEDIA_TYPE_AUDIO,
>          .name      = "pcm_f32be",
> diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
> index 0a4ad0b..28d85f3 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_AOB */
> +        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/libavcodec/version.h b/libavcodec/version.h
> index 8f61301..eab1622 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -29,7 +29,7 @@
>  #include "libavutil/avutil.h"
>  
>  #define LIBAVCODEC_VERSION_MAJOR 55
> -#define LIBAVCODEC_VERSION_MINOR  44
> +#define LIBAVCODEC_VERSION_MINOR  45
>  #define LIBAVCODEC_VERSION_MICRO 100
>  
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
> diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
> index 90434a1..78b9e50 100644
> --- a/libavformat/mpeg.c
> +++ b/libavformat/mpeg.c
> @@ -579,6 +579,53 @@ static int mpegps_read_packet(AVFormatContext *s,
>   found:
>      if(st->discard >= AVDISCARD_ALL)
>          goto skip;
> +    if (av_match_ext(s->filename, "aob") && lpcm_header_len > 8
> +        && startcode >= 0xa0 && startcode <= 0xaf) {
> +        // 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;

you cannot change channels, bps, ... on a per packet level from the
demuxer this way, as the decoder can be run in a seperate thread
and could be decoding a random past packet which still uses the past
count of channels.

it might be easiest to put this in a decoder in libavcodec

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Observe your enemies, for they first find out your faults. -- Antisthenes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20131206/48ba47a2/attachment.asc>


More information about the ffmpeg-devel mailing list