[FFmpeg-devel] [PATCH]Support PCM in DVD-Audio files
Carl Eugen Hoyos
cehoyos at ag.or.at
Mon Dec 2 12:36:42 CET 2013
Hi!
Attached patch partially reverts a42e3a67 and fixes ticket #2758 for me.
Please review, Carl Eugen
-------------- next part --------------
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;
+ 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)
diff --git a/libavformat/version.h b/libavformat/version.h
index 4fe8364..84a75aa 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 55
#define LIBAVFORMAT_VERSION_MINOR 22
-#define LIBAVFORMAT_VERSION_MICRO 100
+#define LIBAVFORMAT_VERSION_MICRO 101
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
More information about the ffmpeg-devel
mailing list