[libav-devel] [PATCH] avcodec: add support for planar signed 8-bit PCM.

Justin Ruggles justin.ruggles at gmail.com
Wed Nov 2 01:09:57 CET 2011


It is found in some 8svx files (e.g. ones created by SoX).
Currently the decoder reuses the 8svx functions because we already have
handling of a single large planar packet for the compressed 8svx codecs.
---
 libavcodec/8svx.c      |   45 ++++++++++++++++++++++++++++++++++++++++-----
 libavcodec/Makefile    |    1 +
 libavcodec/allcodecs.c |    1 +
 libavcodec/avcodec.h   |    1 +
 libavcodec/version.h   |    2 +-
 libavformat/iff.c      |    2 +-
 6 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c
index a7b9c86..3e3eae6 100644
--- a/libavcodec/8svx.c
+++ b/libavcodec/8svx.c
@@ -73,6 +73,15 @@ static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
     *state = val;
 }
 
+static void raw_decode(uint8_t *dst, const int8_t *src, int src_size,
+                       int channels)
+{
+    while (src_size--) {
+        *dst = *src++ + 128;
+        dst += channels;
+    }
+}
+
 /** decode a frame */
 static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
                                  AVPacket *avpkt)
@@ -81,12 +90,14 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
     int buf_size;
     uint8_t *out_data = data;
     int out_data_size;
+    int is_compr = (avctx->codec_id != CODEC_ID_PCM_S8_PLANAR);
 
     /* for the first packet, copy data to buffer */
     if (avpkt->data) {
-        int chan_size = (avpkt->size / avctx->channels) - 2;
+        int hdr_size  = is_compr ? 2 : 0;
+        int chan_size = (avpkt->size - hdr_size * avctx->channels) / avctx->channels;
 
-        if (avpkt->size < 2) {
+        if (avpkt->size < hdr_size * avctx->channels) {
             av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
             return AVERROR(EINVAL);
         }
@@ -95,9 +106,11 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
             return AVERROR(EINVAL);
         }
 
+        if (is_compr) {
         esc->fib_acc[0] = avpkt->data[1] + 128;
         if (avctx->channels == 2)
             esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
+        }
 
         esc->data_idx  = 0;
         esc->data_size = chan_size;
@@ -109,9 +122,9 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
                 return AVERROR(ENOMEM);
             }
         }
-        memcpy(esc->data[0], &avpkt->data[2], chan_size);
+        memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
         if (avctx->channels == 2)
-            memcpy(esc->data[1], &avpkt->data[2+chan_size+2], chan_size);
+            memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
     }
     if (!esc->data[0]) {
         av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
@@ -124,18 +137,26 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
         *data_size = 0;
         return avpkt->size;
     }
-    out_data_size = buf_size * 2 * avctx->channels;
+    out_data_size = buf_size * (is_compr + 1) * avctx->channels;
     if (*data_size < out_data_size) {
         av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n",
                *data_size);
         return AVERROR(EINVAL);
     }
+    if (is_compr) {
     delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size,
                  &esc->fib_acc[0], esc->table, avctx->channels);
     if (avctx->channels == 2) {
         delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size,
                     &esc->fib_acc[1], esc->table, avctx->channels);
     }
+    } else {
+        int ch;
+        for (ch = 0; ch < avctx->channels; ch++) {
+            raw_decode((int8_t *)&out_data[ch], &esc->data[ch][esc->data_idx],
+                       buf_size, avctx->channels);
+        }
+    }
     esc->data_idx += buf_size;
     *data_size = out_data_size;
 
@@ -159,6 +180,8 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
         case CODEC_ID_8SVX_EXP:
           esc->table = exponential;
           break;
+        case CODEC_ID_PCM_S8_PLANAR:
+            break;
         default:
           return -1;
     }
@@ -199,3 +222,15 @@ AVCodec ff_eightsvx_exp_decoder = {
   .capabilities   = CODEC_CAP_DELAY,
   .long_name      = NULL_IF_CONFIG_SMALL("8SVX exponential"),
 };
+
+AVCodec ff_pcm_s8_planar_decoder = {
+    .name           = "pcm_s8_planar",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = CODEC_ID_PCM_S8_PLANAR,
+    .priv_data_size = sizeof(EightSvxContext),
+    .init           = eightsvx_decode_init,
+    .close          = eightsvx_decode_close,
+    .decode         = eightsvx_decode_frame,
+    .capabilities   = CODEC_CAP_DELAY,
+    .long_name      = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"),
+};
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 421072e..1127357 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -451,6 +451,7 @@ OBJS-$(CONFIG_PCM_MULAW_DECODER)          += pcm.o
 OBJS-$(CONFIG_PCM_MULAW_ENCODER)          += pcm.o
 OBJS-$(CONFIG_PCM_S8_DECODER)             += pcm.o
 OBJS-$(CONFIG_PCM_S8_ENCODER)             += pcm.o
+OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER)      += 8svx.o
 OBJS-$(CONFIG_PCM_S16BE_DECODER)          += pcm.o
 OBJS-$(CONFIG_PCM_S16BE_ENCODER)          += pcm.o
 OBJS-$(CONFIG_PCM_S16LE_DECODER)          += pcm.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 23d2252..288e782 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -297,6 +297,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (PCM_LXF, pcm_lxf);
     REGISTER_ENCDEC  (PCM_MULAW, pcm_mulaw);
     REGISTER_ENCDEC  (PCM_S8, pcm_s8);
+    REGISTER_DECODER (PCM_S8_PLANAR, pcm_s8_planar);
     REGISTER_ENCDEC  (PCM_S16BE, pcm_s16be);
     REGISTER_ENCDEC  (PCM_S16LE, pcm_s16le);
     REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 649bce4..7ae47b3 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -245,6 +245,7 @@ enum CodecID {
     CODEC_ID_PCM_BLURAY,
     CODEC_ID_PCM_LXF,
     CODEC_ID_S302M,
+    CODEC_ID_PCM_S8_PLANAR,
 
     /* various ADPCM codecs */
     CODEC_ID_ADPCM_IMA_QT= 0x11000,
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 65cc559..3fc418e 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -21,7 +21,7 @@
 #define AVCODEC_VERSION_H
 
 #define LIBAVCODEC_VERSION_MAJOR 53
-#define LIBAVCODEC_VERSION_MINOR 15
+#define LIBAVCODEC_VERSION_MINOR 16
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavformat/iff.c b/libavformat/iff.c
index 5e8f168..e621373 100644
--- a/libavformat/iff.c
+++ b/libavformat/iff.c
@@ -220,7 +220,7 @@ static int iff_read_header(AVFormatContext *s,
 
         switch(compression) {
         case COMP_NONE:
-            st->codec->codec_id = CODEC_ID_PCM_S8;
+            st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR;
             break;
         case COMP_FIB:
             st->codec->codec_id = CODEC_ID_8SVX_FIB;
-- 
1.7.1



More information about the libav-devel mailing list