[FFmpeg-devel] [RFC] LPCM 24 bits support
Giuliano Pochini
pochini
Wed Mar 26 01:20:13 CET 2008
On Sun, 23 Mar 2008 22:33:07 +0000
M?ns Rullg?rd <mans at mansr.com> wrote:
> > diff -dupr ffmpeg__orig/libavcodec/adpcm.c ffmpeg/libavcodec/adpcm.c
> > --- ffmpeg__orig/libavcodec/adpcm.c 2008-02-06 12:37:37.000000000 +0000
> > +++ ffmpeg/libavcodec/adpcm.c 2008-03-23 22:26:48.000000000 +0000
>
> 24-bit DVD audio is not ADPCM, so this code is misplaced.
It was just a quick and dirty test... Here you are a somewhat refined and
improved patch. It support any format and number of channels. It seems to
work fine with all the test files I was told about, but of course it needs
more testing. I didn't pay much attention to coding style and performance.
Audio data is first decoded to S24, then it is copied into the destination
buffer in S16 format.
diff -dupr ffmpeg__orig/libavcodec/allcodecs.c ffmpeg/libavcodec/allcodecs.c
--- ffmpeg__orig/libavcodec/allcodecs.c 2008-02-06 12:37:37.000000000 +0000
+++ ffmpeg/libavcodec/allcodecs.c 2008-03-24 23:50:37.000000000 +0000
@@ -227,6 +227,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (PCM_U32BE, pcm_u32be);
REGISTER_ENCDEC (PCM_U32LE, pcm_u32le);
REGISTER_ENCDEC (PCM_ZORK , pcm_zork);
+ REGISTER_DECODER (PCM_DVD, pcm_dvd);
/* dpcm codecs */
REGISTER_DECODER (INTERPLAY_DPCM, interplay_dpcm);
diff -dupr ffmpeg__orig/libavcodec/avcodec.h ffmpeg/libavcodec/avcodec.h
--- ffmpeg__orig/libavcodec/avcodec.h 2008-02-06 12:37:37.000000000 +0000
+++ ffmpeg/libavcodec/avcodec.h 2008-03-25 00:20:36.000000000 +0000
@@ -192,6 +192,7 @@ enum CodecID {
CODEC_ID_PCM_S24DAUD,
CODEC_ID_PCM_ZORK,
CODEC_ID_PCM_S16LE_PLANAR,
+ CODEC_ID_PCM_DVD,
/* various ADPCM codecs */
CODEC_ID_ADPCM_IMA_QT= 0x11000,
diff -dupr ffmpeg__orig/libavcodec/pcm.c ffmpeg/libavcodec/pcm.c
--- ffmpeg__orig/libavcodec/pcm.c 2008-02-06 12:37:37.000000000 +0000
+++ ffmpeg/libavcodec/pcm.c 2008-03-25 23:59:48.000000000 +0000
@@ -492,6 +492,44 @@ static int pcm_decode_frame(AVCodecConte
*samples++ = s->table[*src++];
}
break;
+ case CODEC_ID_PCM_DVD:
+ if (avctx->bits_per_sample==24) {
+ int audio24[8*2], *ap;
+ const uint8_t *src_LSB;
+
+ for (n=buf_size/(avctx->channels * 2 * 3); n>0; n--) {
+ ap = audio24;
+ src_LSB = src + avctx->channels * 2 * 2;
+ for (c=0; c<avctx->channels*2; c++, src+=2, src_LSB++) {
+ *ap++ = (((const int8_t *)src)[0]<<16) + (src[1]<<8) + *src_LSB;
+ }
+ src = src_LSB;
+
+ for (c=0; c<avctx->channels*2; c++)
+ *samples++ = audio24[c] >> 8;
+ }
+ } else if (avctx->bits_per_sample==20) {
+ int audio24[8*2], *ap;
+ const uint8_t *src_LSB;
+
+ for (n=buf_size/(avctx->channels * 5); n>0; n--) {
+ ap = audio24;
+ src_LSB = src + avctx->channels * 2 * 2;
+ for (c=0; c<avctx->channels; c++, src+=4, src_LSB++) {
+ *ap++ = (((const int8_t *)src)[0]<<16) + (src[1]<<8) + (*src_LSB & 0xf0);
+ *ap++ = (((const int8_t *)src)[2]<<16) + (src[3]<<8) + ((*src_LSB << 4) & 0xff);
+ }
+ src = src_LSB;
+
+ for (c=0; c<avctx->channels*2; c++)
+ *samples++ = audio24[c] >> 8;
+ }
+ } else if (avctx->bits_per_sample==16) {
+ /* CODEC_ID_PCM_S16BE */
+ for (n = buf_size >> 1; n>0; n--)
+ *samples++ = bytestream_get_be16(&src);
+ }
+ break;
default:
return -1;
}
@@ -553,3 +591,4 @@ PCM_CODEC (CODEC_ID_PCM_U8, pcm_u8);
PCM_CODEC (CODEC_ID_PCM_ALAW, pcm_alaw);
PCM_CODEC (CODEC_ID_PCM_MULAW, pcm_mulaw);
PCM_CODEC (CODEC_ID_PCM_ZORK, pcm_zork);
+PCM_DECODER(CODEC_ID_PCM_DVD, pcm_dvd);
diff -dupr ffmpeg__orig/libavformat/mpeg.c ffmpeg/libavformat/mpeg.c
--- ffmpeg__orig/libavformat/mpeg.c 2008-02-06 12:37:37.000000000 +0000
+++ ffmpeg/libavformat/mpeg.c 2008-03-25 01:02:11.000000000 +0000
@@ -469,7 +469,7 @@ static int mpegps_read_packet(AVFormatCo
codec_id = CODEC_ID_DTS;
} else if (startcode >= 0xa0 && startcode <= 0xaf) {
type = CODEC_TYPE_AUDIO;
- codec_id = CODEC_ID_PCM_S16BE;
+ codec_id = CODEC_ID_PCM_DVD;
} else if (startcode >= 0xb0 && startcode <= 0xbf) {
type = CODEC_TYPE_AUDIO;
codec_id = CODEC_ID_MLP;
@@ -514,7 +514,9 @@ static int mpegps_read_packet(AVFormatCo
freq = (b1 >> 4) & 3;
st->codec->sample_rate = lpcm_freq_tab[freq];
st->codec->channels = 1 + (b1 & 7);
- st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2;
+ //st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2;
+ st->codec->bits_per_sample = 16 + ((b1 >> 6) & 3) * 4;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_sample;
}
av_new_packet(pkt, len);
get_buffer(s->pb, pkt->data, pkt->size);
--
Giuliano.
More information about the ffmpeg-devel
mailing list