[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