[Ffmpeg-devel] [RFC] More PCM formats (was: [PATCH] demuxer for dcinema audio)
Reimar Döffinger
Reimar.Doeffinger
Fri Sep 2 00:08:11 CEST 2005
Hi,
On Thu, Sep 01, 2005 at 10:21:57PM +0200, Reimar D?ffinger wrote:
> > IMHO they should be changed to inline functions, as thats cleaner, unless
> > of course its slower, that brings us to the next point, it must be
> > benchmarked to ensure its not significantly slower
Did that, but did it the lazy way for benchmarking: left the old code
and only used the function for the new code. Hope that's acceptable,
I mess things up anyway when I try to benchmark things...
> > uninitalized bytes are not acceptable, they could messup the regression
> > tests
>
> The best way I could thing of was unfortunately doing
> if (bps > 2) memset(dst, 0, ...).
Did it like that.
Awaiting another round of comments.
Greetings,
Reimar D??ffinger
-------------- next part --------------
Index: etc/codecs.conf
===================================================================
RCS file: /cvsroot/mplayer/main/etc/codecs.conf,v
retrieving revision 1.428
diff -u -r1.428 codecs.conf
--- etc/codecs.conf 25 Aug 2005 15:54:44 -0000 1.428
+++ etc/codecs.conf 1 Sep 2005 21:42:57 -0000
@@ -2314,6 +2339,13 @@
format 0x2033504D ; "MP3 " (used in .nsv files)
driver mp3lib
+audiocodec ffpcmdaud
+ info "D-Cinema audio (FFmpeg)"
+ status untested
+ fourcc "daud"
+ driver ffmpeg
+ dll "pcm_s24daud"
+
audiocodec ffwmav1
info "DivX audio v1 (FFmpeg)"
status untested
Index: libavcodec/allcodecs.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/allcodecs.c,v
retrieving revision 1.109
diff -u -r1.109 allcodecs.c
--- libavcodec/allcodecs.c 17 Jul 2005 00:28:11 -0000 1.109
+++ libavcodec/allcodecs.c 1 Sep 2005 21:43:05 -0000
@@ -524,6 +536,15 @@
register_avcodec(& name ## _decoder);
#endif
+PCM_CODEC(CODEC_ID_PCM_S32LE, pcm_s32le);
+PCM_CODEC(CODEC_ID_PCM_S32BE, pcm_s32be);
+PCM_CODEC(CODEC_ID_PCM_U32LE, pcm_u32le);
+PCM_CODEC(CODEC_ID_PCM_U32BE, pcm_u32be);
+PCM_CODEC(CODEC_ID_PCM_S24LE, pcm_s24le);
+PCM_CODEC(CODEC_ID_PCM_S24BE, pcm_s24be);
+PCM_CODEC(CODEC_ID_PCM_U24LE, pcm_u24le);
+PCM_CODEC(CODEC_ID_PCM_U24BE, pcm_u24be);
+PCM_CODEC(CODEC_ID_PCM_S24DAUD, pcm_s24daud);
PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
Index: libavcodec/avcodec.h
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/avcodec.h,v
retrieving revision 1.415
diff -u -r1.415 avcodec.h
--- libavcodec/avcodec.h 21 Aug 2005 22:31:01 -0000 1.415
+++ libavcodec/avcodec.h 1 Sep 2005 21:43:12 -0000
@@ -121,6 +122,15 @@
CODEC_ID_PCM_U8,
CODEC_ID_PCM_MULAW,
CODEC_ID_PCM_ALAW,
+ CODEC_ID_PCM_S32LE,
+ CODEC_ID_PCM_S32BE,
+ CODEC_ID_PCM_U32LE,
+ CODEC_ID_PCM_U32BE,
+ CODEC_ID_PCM_S24LE,
+ CODEC_ID_PCM_S24BE,
+ CODEC_ID_PCM_U24LE,
+ CODEC_ID_PCM_U24BE,
+ CODEC_ID_PCM_S24DAUD,
/* various adpcm codecs */
CODEC_ID_ADPCM_IMA_QT= 0x11000,
@@ -2097,6 +2113,15 @@
extern AVCodec name ## _decoder; \
extern AVCodec name ## _encoder
+PCM_CODEC(CODEC_ID_PCM_S32LE, pcm_s32le);
+PCM_CODEC(CODEC_ID_PCM_S32BE, pcm_s32be);
+PCM_CODEC(CODEC_ID_PCM_U32LE, pcm_u32le);
+PCM_CODEC(CODEC_ID_PCM_U32BE, pcm_u32be);
+PCM_CODEC(CODEC_ID_PCM_S24LE, pcm_s24le);
+PCM_CODEC(CODEC_ID_PCM_S24BE, pcm_s24be);
+PCM_CODEC(CODEC_ID_PCM_U24LE, pcm_u24le);
+PCM_CODEC(CODEC_ID_PCM_U24BE, pcm_u24be);
+PCM_CODEC(CODEC_ID_PCM_S24DAUD, pcm_s24daud);
PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
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 1 Sep 2005 21:43:29 -0000
@@ -128,6 +128,19 @@
}
switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ avctx->block_align = 4 * avctx->channels;
+ break;
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_U24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_S24DAUD:
+ avctx->block_align = 3 * avctx->channels;
+ break;
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
@@ -170,6 +183,28 @@
return 0;
}
+/**
+ * \brief convert samples from 16 bit
+ * \param bps byte per sample for the destination format, must be >= 2
+ * \param le 0 for big-, 1 for little-endian
+ * \param samples input samples
+ * \param dst output samples
+ * \param n number of samples in samples buffer.
+ */
+static inline void encode_from16(int bps, int le, int us,
+ short **samples, uint8_t **dst, int n) {
+ if (bps > 2)
+ memset(*dst, 0, n * bps);
+ if (le) *dst += bps - 2;
+ for(;n>0;n--) {
+ register int v = *(*samples)++;
+ if (us) v += 0x8000;
+ (*dst)[le] = v >> 8;
+ (*dst)[1 - le] = v & 0xff;
+ *dst += bps;
+ }
+}
+
static int pcm_encode_frame(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data)
{
@@ -178,6 +213,19 @@
unsigned char *dst;
switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ sample_size = 4;
+ break;
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_U24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_S24DAUD:
+ sample_size = 3;
+ break;
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
@@ -193,6 +241,48 @@
dst = frame;
switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ encode_from16(4, 1, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S32BE:
+ encode_from16(4, 0, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U32LE:
+ encode_from16(4, 1, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U32BE:
+ encode_from16(4, 0, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S24LE:
+ encode_from16(3, 1, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S24BE:
+ encode_from16(3, 0, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U24LE:
+ encode_from16(3, 1, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U24BE:
+ encode_from16(3, 0, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S24DAUD:
+ for(;n>0;n--) {
+ uint32_t tmp2 = 0;
+ uint16_t tmp = *samples++;
+ int i;
+ 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:
for(;n>0;n--) {
v = *samples++;
@@ -287,6 +377,25 @@
return 0;
}
+/**
+ * \brief convert samples to 16 bit
+ * \param bps byte per sample for the source format, must be >= 2
+ * \param le 0 for big-, 1 for little-endian
+ * \param src input samples
+ * \param samples output samples
+ * \param src_len number of bytes in src
+ */
+static inline void decode_to16(int bps, int le, int us,
+ uint8_t **src, short **samples, int src_len)
+{
+ register int n = src_len / bps;
+ if (le) *src += bps - 2;
+ for(;n>0;n--) {
+ *(*samples)++ = ((*src)[le] << 8) | (*src)[1 - le] - (us)?0x8000:0;
+ *src += bps;
+ }
+}
+
static int pcm_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
@@ -303,6 +412,46 @@
buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE/2;
switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ decode_to16(4, 1, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S32BE:
+ decode_to16(4, 0, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U32LE:
+ decode_to16(4, 1, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U32BE:
+ decode_to16(4, 0, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S24LE:
+ decode_to16(3, 1, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S24BE:
+ decode_to16(3, 0, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U24LE:
+ decode_to16(3, 1, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U24BE:
+ decode_to16(3, 0, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S24DAUD:
+ n = buf_size / 3;
+ for(;n>0;n--) {
+ uint32_t v = src[0] << 16 | src[1] << 8 | src[2];
+ int i;
+ v >>= 4; // sync flags are here
+ *samples = 0;
+ for (i = 0; i < 16; i++) {
+ *samples <<= 1;
+ *samples |= (v & 1);
+ v >>= 1;
+ }
+ samples++;
+ src += 3;
+ }
+ break;
case CODEC_ID_PCM_S16LE:
n = buf_size >> 1;
for(;n>0;n--) {
@@ -382,6 +531,15 @@
pcm_decode_frame, \
}
+PCM_CODEC(CODEC_ID_PCM_S32LE, pcm_s32le);
+PCM_CODEC(CODEC_ID_PCM_S32BE, pcm_s32be);
+PCM_CODEC(CODEC_ID_PCM_U32LE, pcm_u32le);
+PCM_CODEC(CODEC_ID_PCM_U32BE, pcm_u32be);
+PCM_CODEC(CODEC_ID_PCM_S24LE, pcm_s24le);
+PCM_CODEC(CODEC_ID_PCM_S24BE, pcm_s24be);
+PCM_CODEC(CODEC_ID_PCM_U24LE, pcm_u24le);
+PCM_CODEC(CODEC_ID_PCM_U24BE, pcm_u24be);
+PCM_CODEC(CODEC_ID_PCM_S24DAUD, pcm_s24daud);
PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
Index: libavcodec/utils.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/utils.c,v
retrieving revision 1.148
diff -u -r1.148 utils.c
--- libavcodec/utils.c 21 Aug 2005 19:50:22 -0000 1.148
+++ libavcodec/utils.c 1 Sep 2005 21:43:33 -0000
@@ -828,6 +828,19 @@
/* for PCM codecs, compute bitrate directly */
switch(enc->codec_id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ bitrate = enc->sample_rate * enc->channels * 32;
+ break;
+ 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:
+ bitrate = enc->sample_rate * enc->channels * 24;
+ break;
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
Index: libavformat/Makefile
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavformat/Makefile,v
retrieving revision 1.98
diff -u -r1.98 Makefile
--- libavformat/Makefile 13 Aug 2005 13:45:42 -0000 1.98
+++ libavformat/Makefile 1 Sep 2005 21:43:35 -0000
@@ -17,7 +17,7 @@
yuv4mpeg.o 4xm.o flvenc.o flvdec.o movenc.o psxstr.o idroq.o ipmovie.o \
nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \
sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o asf-enc.o \
- ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o
+ ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o
AMROBJS=
ifeq ($(AMR_NB),yes)
AMROBJS= amr.o
Index: libavformat/allformats.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavformat/allformats.c,v
retrieving revision 1.48
diff -u -r1.48 allformats.c
--- libavformat/allformats.c 15 Jul 2005 12:50:00 -0000 1.48
+++ libavformat/allformats.c 1 Sep 2005 21:43:36 -0000
@@ -109,6 +109,7 @@
sol_init();
ea_init();
nsvdec_init();
+ daud_init();
#ifdef CONFIG_ENCODERS
/* image formats */
Index: libavformat/avformat.h
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavformat/avformat.h,v
retrieving revision 1.132
diff -u -r1.132 avformat.h
--- libavformat/avformat.h 21 Aug 2005 22:31:00 -0000 1.132
+++ libavformat/avformat.h 1 Sep 2005 21:43:38 -0000
@@ -546,6 +546,9 @@
/* nsvdec.c */
int nsvdec_init(void);
+/* daud.c */
+int daud_init(void);
+
#include "rtp.h"
#include "rtsp.h"
Index: libavformat/daud.c
===================================================================
RCS file: libavformat/daud.c
diff -N libavformat/daud.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libavformat/daud.c 1 Sep 2005 21:43:38 -0000
@@ -0,0 +1,63 @@
+/*
+ * D-Cinema audio decoder.
+ * Copyright (c) 2005 Reimar D?ffinger.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "avformat.h"
+
+static int daud_header(AVFormatContext *s, AVFormatParameters *ap) {
+ AVStream *st = av_new_stream(s, 0);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_PCM_S24DAUD;
+ st->codec->codec_tag = MKTAG('d','a','u','d');
+ st->codec->channels = 6;
+ st->codec->sample_rate = 96000;
+ st->codec->bit_rate = 3 * 6 * 96000 * 8;
+ st->codec->block_align = 3 * 6;
+ st->codec->bits_per_sample = 24;
+ return 0;
+}
+
+static int daud_packet(AVFormatContext *s, AVPacket *pkt) {
+ ByteIOContext *pb = &s->pb;
+ int ret, size;
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+ size = get_be16(pb);
+ get_be16(pb); // unknown
+ ret = av_get_packet(pb, pkt, size);
+ pkt->stream_index = 0;
+ return ret;
+}
+
+static AVInputFormat daud_iformat = {
+ "daud",
+ "D-Cinema audio format",
+ 0,
+ NULL,
+ daud_header,
+ daud_packet,
+ NULL,
+ NULL,
+ .extensions = "302",
+};
+
+int daud_init(void)
+{
+ av_register_input_format(&daud_iformat);
+ return 0;
+}
+
More information about the ffmpeg-devel
mailing list