[FFmpeg-devel] [RFC] LPCM 24 bits support

Giuliano Pochini pochini
Sun Mar 30 20:56:17 CEST 2008


On Sun, 30 Mar 2008 01:48:22 +0100
Michael Niedermayer <michaelni at gmx.at> wrote:

> On Sat, Mar 29, 2008 at 08:25:45PM +0000, Giuliano Pochini wrote:
> > On Wed, 26 Mar 2008 00:48:39 +0100
> > Michael Niedermayer <michaelni at gmx.at> wrote:
> > 
> > > On Wed, Mar 26, 2008 at 12:20:13AM +0000, Giuliano Pochini wrote:
> > > >      } else if (startcode >= 0xa0 && startcode <= 0xaf) {
> > > >          type = CODEC_TYPE_AUDIO;
> > > > -        codec_id = CODEC_ID_PCM_S16BE;
> > > > +        codec_id = CODEC_ID_PCM_DVD;
> > >
> > > CODEC_ID_PCM_S16BE should stay CODEC_ID_PCM_S16BE
> > 
> > My patch also handles that format. If codec_id stays CODEC_ID_PCM_S16BE
> > then I have to place the DVD LPCM decoder into the CODEC_ID_PCM_S16BE case
> > in pcm.c which doesn't look correct IMHO. Any hints ?
> 
> If it is 16bit PCM set CODEC_ID_PCM_S16BE, if it is not set CODEC_ID_DVD_LPCM
> or whatever is the correct name.

Ok, here is the revised patch. In case bits_per_sample is unknown it
returns AVERROR(EINVAL). I'm not sure if it's correct and if we actually
need to check that.



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-30 16:59:35.000000000 +0000
@@ -227,6 +227,8 @@ 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_DVD20, pcm_dvd20);
+    REGISTER_DECODER (PCM_DVD24, pcm_dvd24);
 
     /* 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-30 16:59:35.000000000 +0000
@@ -192,6 +192,8 @@ enum CodecID {
     CODEC_ID_PCM_S24DAUD,
     CODEC_ID_PCM_ZORK,
     CODEC_ID_PCM_S16LE_PLANAR,
+    CODEC_ID_PCM_DVD20,
+    CODEC_ID_PCM_DVD24,
 
     /* 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-30 18:41:30.000000000 +0000
@@ -492,6 +492,43 @@ static int pcm_decode_frame(AVCodecConte
             *samples++ = s->table[*src++];
         }
         break;
+    case CODEC_ID_PCM_DVD20:
+    {
+        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;
+        }
+        break;
+    }
+    case CODEC_ID_PCM_DVD24:
+    {
+        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;
+        }
+        break;
+    }
     default:
         return -1;
     }
@@ -553,3 +590,5 @@ 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_DVD20, pcm_dvd20);
+PCM_DECODER(CODEC_ID_PCM_DVD24, pcm_dvd24);
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-30 18:43:27.000000000 +0000
@@ -514,7 +514,21 @@ 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->bits_per_sample = 16 + ((b1 >> 6) & 3) * 4;
+        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_sample;
+        switch (st->codec->bits_per_sample) {
+        case 16:
+            st->codec->codec_id = CODEC_ID_PCM_S16BE;
+            break;
+        case 20:
+            st->codec->codec_id = CODEC_ID_PCM_DVD20;
+            break;
+        case 24:
+            st->codec->codec_id = CODEC_ID_PCM_DVD24;
+            break;
+        default:
+            return AVERROR(EINVAL);
+        }
     }
     av_new_packet(pkt, len);
     get_buffer(s->pb, pkt->data, pkt->size);


--
Giuliano.




More information about the ffmpeg-devel mailing list