[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