avcodec: add support for planar signed 8-bit PCM.
authorJustin Ruggles <justin.ruggles@gmail.com>
Mon, 31 Oct 2011 17:41:47 +0000 (13:41 -0400)
committerJustin Ruggles <justin.ruggles@gmail.com>
Wed, 9 Nov 2011 22:48:54 +0000 (17:48 -0500)
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
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/version.h
libavformat/iff.c

index a7b9c86..3e3eae6 100644 (file)
@@ -73,6 +73,15 @@ static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
     *state = val;
 }
 
     *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)
 /** 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 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) {
 
     /* 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);
         }
             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);
         }
 
             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->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;
 
         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);
             }
         }
                 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)
         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");
     }
     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;
     }
         *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 (*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);
     }
     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;
 
     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_8SVX_EXP:
           esc->table = exponential;
           break;
+        case CODEC_ID_PCM_S8_PLANAR:
+            break;
         default:
           return -1;
     }
         default:
           return -1;
     }
@@ -199,3 +222,15 @@ AVCodec ff_eightsvx_exp_decoder = {
   .capabilities   = CODEC_CAP_DELAY,
   .long_name      = NULL_IF_CONFIG_SMALL("8SVX exponential"),
 };
   .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"),
+};
index 413b04d..5fabd8b 100644 (file)
@@ -453,6 +453,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_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
 OBJS-$(CONFIG_PCM_S16BE_DECODER)          += pcm.o
 OBJS-$(CONFIG_PCM_S16BE_ENCODER)          += pcm.o
 OBJS-$(CONFIG_PCM_S16LE_DECODER)          += pcm.o
index 2beb81c..e9be063 100644 (file)
@@ -299,6 +299,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_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);
     REGISTER_ENCDEC  (PCM_S16BE, pcm_s16be);
     REGISTER_ENCDEC  (PCM_S16LE, pcm_s16le);
     REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar);
index f169bec..7656283 100644 (file)
@@ -250,6 +250,7 @@ enum CodecID {
     CODEC_ID_PCM_BLURAY,
     CODEC_ID_PCM_LXF,
     CODEC_ID_S302M,
     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,
 
     /* various ADPCM codecs */
     CODEC_ID_ADPCM_IMA_QT = 0x11000,
index 5e07ec2..c11f09c 100644 (file)
@@ -21,7 +21,7 @@
 #define AVCODEC_VERSION_H
 
 #define LIBAVCODEC_VERSION_MAJOR 53
 #define AVCODEC_VERSION_H
 
 #define LIBAVCODEC_VERSION_MAJOR 53
-#define LIBAVCODEC_VERSION_MINOR 17
+#define LIBAVCODEC_VERSION_MINOR 18
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
index 5e8f168..e621373 100644 (file)
@@ -220,7 +220,7 @@ static int iff_read_header(AVFormatContext *s,
 
         switch(compression) {
         case COMP_NONE:
 
         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;
             break;
         case COMP_FIB:
             st->codec->codec_id = CODEC_ID_8SVX_FIB;