[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