[Ffmpeg-devel] [RFC] More PCM formats (was: [PATCH] demuxer for dcinema audio)

Reimar Döffinger Reimar.Doeffinger
Wed Aug 31 12:55:32 CEST 2005


Hi,
On Wed, Aug 31, 2005 at 09:54:19AM +0200, Reimar D?ffinger wrote:
> On Wed, Aug 31, 2005 at 03:33:13AM +0200, Michael Niedermayer wrote:
> > uhm, well, messy ... too messy, and we have enough messy code aleady ...
> 
> Hmm... what would be an acceptable solution? Just moving the 24bit weird
> audio -> "normal" 32bit audio conversion to libavcodec/pcm.c?
> I would then have to "invent" a new format ID for MPlayer though.
> Or which part of it is messy?

Ok, I did a quick hack to show what I am thinking about. It is not
finished and will not yet work, but before spending more time on it I
want to get some comments.

Greetings,
Reimar D??ffinger
-------------- next part --------------
Index: libavcodec/pcm.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/pcm.c,v
retrieving revision 1.15
diff -u -r1.15 pcm.c
--- libavcodec/pcm.c	13 Feb 2005 23:36:04 -0000	1.15
+++ libavcodec/pcm.c	31 Aug 2005 10:53:53 -0000
@@ -128,6 +128,13 @@
     }
     
     switch(avctx->codec->id) {
+    case CODEC_ID_PCM_S24LE:
+    case CODEC_ID_PCM_S24BE:
+    case CODEC_ID_PCM_U24LE:
+    case CODEC_ID_PCM_U24BE:
+    case CODEC_ID_PCM_S24R:
+        avctx->block_align = 3 * avctx->channels;
+        break;
     case CODEC_ID_PCM_S16LE:
     case CODEC_ID_PCM_S16BE:
     case CODEC_ID_PCM_U16LE:
@@ -178,6 +185,13 @@
     unsigned char *dst;
 
     switch(avctx->codec->id) {
+    case CODEC_ID_PCM_S24LE:
+    case CODEC_ID_PCM_S24BE:
+    case CODEC_ID_PCM_U24LE:
+    case CODEC_ID_PCM_U24BE:
+    case CODEC_ID_PCM_S24R:
+        sample_size = 3;
+        break;
     case CODEC_ID_PCM_S16LE:
     case CODEC_ID_PCM_S16BE:
     case CODEC_ID_PCM_U16LE:
@@ -192,40 +206,71 @@
     samples = data;
     dst = frame;
 
+// rely a bit on compiler optimization
+// low bits are not initialized, maybe use memset before?
+#define TO_PCM(bps, le, us) \
+  if (le) dst += bps - 2 \
+  for(;n>0;n--) { \
+    v = *samples++; \
+    if (us) v += 0x8000; \
+    dst[le] = v >> 8; \
+    dst[1 - le] = v & 0xff; \
+    src += bps; \
+  }
+
     switch(avctx->codec->id) {
-    case CODEC_ID_PCM_S16LE:
-        for(;n>0;n--) {
-            v = *samples++;
-            dst[0] = v & 0xff;
-            dst[1] = v >> 8;
-            dst += 2;
+    case CODEC_ID_PCM_S32LE:
+        TO_PCM(4, 1, 0);
+        break;
+    case CODEC_ID_PCM_S32BE:
+        TO_PCM(4, 0, 0);
+        break;
+    case CODEC_ID_PCM_U32LE:
+        TO_PCM(4, 1, 1);
+        break;
+    case CODEC_ID_PCM_U32BE:
+        TO_PCM(4, 0, 1);
+        break;
+    case CODEC_ID_PCM_S24LE:
+        TO_PCM(3, 1, 0);
+        break;
+    case CODEC_ID_PCM_S24BE:
+        TO_PCM(3, 0, 0);
+        break;
+    case CODEC_ID_PCM_U24LE:
+        TO_PCM(3, 1, 1);
+        break;
+    case CODEC_ID_PCM_U24BE:
+        TO_PCM(3, 0, 1);
+        break;
+    case CODEC_ID_PCM_S24R:
+        for(;n>0;n--) {
+            uint32_t tmp2 = 0;
+            uint16_t tmp = *samples++;
+            for (i = 0; i < 16; i++) {
+              tmp2 <<= 1;
+              tmp2 |= (tmp & 1);
+              tmp >>= 1;
+            }
+            tmp2 <<= 4; // sync flags would go here
+            dst[2] = tmp2 & 0xff;
+            tmp2 >>= 8;
+            dst[1] = tmp2 & 0xff;
+            dst[0] = tmp2 >> 8;
+            dst += 3;
         }
         break;
+    case CODEC_ID_PCM_S16LE:
+        TO_PCM(2, 1, 0);
+        break;
     case CODEC_ID_PCM_S16BE:
-        for(;n>0;n--) {
-            v = *samples++;
-            dst[0] = v >> 8;
-            dst[1] = v;
-            dst += 2;
-        }
+        TO_PCM(2, 0, 0);
         break;
     case CODEC_ID_PCM_U16LE:
-        for(;n>0;n--) {
-            v = *samples++;
-            v += 0x8000;
-            dst[0] = v & 0xff;
-            dst[1] = v >> 8;
-            dst += 2;
-        }
+        TO_PCM(2, 1, 1);
         break;
     case CODEC_ID_PCM_U16BE:
-        for(;n>0;n--) {
-            v = *samples++;
-            v += 0x8000;
-            dst[0] = v >> 8;
-            dst[1] = v;
-            dst += 2;
-        }
+        TO_PCM(2, 0, 1);
         break;
     case CODEC_ID_PCM_S8:
         for(;n>0;n--) {
@@ -302,34 +347,67 @@
     if(buf_size > AVCODEC_MAX_AUDIO_FRAME_SIZE/2)
         buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE/2;
 
+// general purpose PCM conversion macro, hopefully
+// the compiler will optimize out the parts that
+// are not used in the special instance
+#define FROM_PCM(bps, le, us) \
+  n = buf_size / bps; \
+  if (le) src += bps - 2 \
+  for(;n>0;n--) { \
+    *samples++ = (src[le] << 8) | src[1 - le] - (us)?0x8000:0; \
+    src += bps; \
+  }
+
     switch(avctx->codec->id) {
-    case CODEC_ID_PCM_S16LE:
-        n = buf_size >> 1;
-        for(;n>0;n--) {
-            *samples++ = src[0] | (src[1] << 8);
-            src += 2;
+    case CODEC_ID_PCM_S32LE:
+        FROM_PCM(4, 1, 0);
+        break;
+    case CODEC_ID_PCM_S32BE:
+        FROM_PCM(4, 0, 0);
+        break;
+    case CODEC_ID_PCM_U32LE:
+        FROM_PCM(4, 1, 1);
+        break;
+    case CODEC_ID_PCM_U32BE:
+        FROM_PCM(4, 0, 1);
+        break;
+    case CODEC_ID_PCM_S24LE:
+        FROM_PCM(3, 1, 0);
+        break;
+    case CODEC_ID_PCM_S24BE:
+        FROM_PCM(3, 0, 0);
+        break;
+    case CODEC_ID_PCM_U24LE:
+        FROM_PCM(3, 1, 1);
+        break;
+    case CODEC_ID_PCM_U24BE:
+        FROM_PCM(3, 0, 1);
+        break;
+    case CODEC_ID_PCM_S24R:
+        n = buf_size / 3;
+        for(;n>0;n--) {
+          uint32_t v = src[0] << 16 | src[1] << 8 | src[0];
+          v >>= 4; // sync flags are here
+          *samples = 0;
+          for (i = 0; i < 16; i++) {
+            *samples <<= 1;
+            *samples |= (v & 1);
+            v >>= 1;
+          }
+          samples++;
         }
         break;
+    case CODEC_ID_PCM_S16LE:
+        FROM_PCM(2, 1, 0);
+        break;
     case CODEC_ID_PCM_S16BE:
-        n = buf_size >> 1;
-        for(;n>0;n--) {
-            *samples++ = (src[0] << 8) | src[1];
-            src += 2;
-        }
+        FROM_PCM(2, 0, 0);
         break;
     case CODEC_ID_PCM_U16LE:
-        n = buf_size >> 1;
-        for(;n>0;n--) {
-            *samples++ = (src[0] | (src[1] << 8)) - 0x8000;
-            src += 2;
-        }
+        FROM_PCM(2, 1, 1);
         break;
     case CODEC_ID_PCM_U16BE:
-        n = buf_size >> 1;
-        for(;n>0;n--) {
-            *samples++ = ((src[0] << 8) | src[1]) - 0x8000;
-            src += 2;
-        }
+        FROM_PCM(2, 0, 1);
         break;
     case CODEC_ID_PCM_S8:
         n = buf_size;



More information about the ffmpeg-devel mailing list