8svx: Fixing header size, move decoding to per call instead of the first call.
authorJustin Ruggles <justin.ruggles@gmail.com>
Wed, 3 Oct 2012 01:42:33 +0000 (03:42 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 3 Oct 2012 01:49:24 +0000 (03:49 +0200)
The fate checksum change is due to the header size having been wrong.

Credit&Authorship for the code belongs to Justin Ruggles
Blame for bugs in this merging of the code belong to the Commiter
Commit message by Commiter
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/8svx.c
tests/ref/fate/iff-fibonacci

index e6ad061..4a0cb37 100644 (file)
 /** decoder context */
 typedef struct EightSvxContext {
     AVFrame frame;
+    uint8_t fib_acc[2];
     const int8_t *table;
 
-    /* buffer used to store the whole audio decoded/interleaved chunk,
-     * which is sent with the first packet */
-    uint8_t *samples;
-    int64_t samples_size;
-    int samples_idx;
+    /* buffer used to store the whole first packet.
+       data is only sent as one large packet */
+    uint8_t *data[2];
+    int data_size;
+    int data_idx;
 } EightSvxContext;
 
 static const int8_t fibonacci[16]   = { -34,  -21, -13,  -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8,  13, 21 };
@@ -60,16 +61,15 @@ static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0,
 
 /**
  * Delta decode the compressed values in src, and put the resulting
- * decoded samples in dst.
+ * decoded samples in dst.
  *
- * @param val starting value assumed by the delta sequence
+ * @param[in,out] state starting value. it is saved for use in the next call.
  * @param table delta sequence table
- * @return size in bytes of the decoded data, must be src_size*2
  */
-static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
-                         unsigned val, const int8_t *table)
+static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
+                         uint8_t *state, const int8_t *table)
 {
-    uint8_t *dst0 = dst;
+    uint8_t val = *state;
 
     while (src_size--) {
         uint8_t d = *src++;
@@ -79,7 +79,7 @@ static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
         *dst++ = val;
     }
 
-    return dst-dst0;
+    *state = val;
 }
 
 static void raw_decode(uint8_t *dst, const int8_t *src, int src_size)
@@ -93,72 +93,79 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
                                  int *got_frame_ptr, AVPacket *avpkt)
 {
     EightSvxContext *esc = avctx->priv_data;
-    int n, out_data_size;
+    int buf_size;
     int ch, ret;
+    int is_compr = (avctx->codec_id != AV_CODEC_ID_PCM_S8_PLANAR);
     uint8_t *src;
+    int hdr_size  = is_compr ? 2 : 0;
 
     /* decode and interleave the first packet */
-    if (!esc->samples && avpkt) {
-        int packet_size = avpkt->size;
+    if (!esc->data[0] && avpkt) {
+        int chan_size = avpkt->size / avctx->channels - hdr_size;
 
-        if (packet_size % avctx->channels) {
+        if (avpkt->size % avctx->channels) {
             av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
-            if (packet_size < avctx->channels)
-                return packet_size;
-            packet_size -= packet_size % avctx->channels;
         }
-        esc->samples_size = !esc->table ?
-            packet_size : avctx->channels + (packet_size-avctx->channels) * 2;
-        if (!(esc->samples = av_malloc(esc->samples_size)))
-            return AVERROR(ENOMEM);
-
-        /* decompress */
-        if (esc->table) {
-            const uint8_t *buf = avpkt->data;
-            uint8_t *dst;
-            int buf_size = avpkt->size;
-            int i, n = esc->samples_size;
+        if (avpkt->size < (hdr_size + 1) * avctx->channels) {
+            av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
+            return AVERROR(EINVAL);
+        }
 
-            if (buf_size < 2) {
-                av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
-                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;
+        }
 
-            /* the uncompressed starting value is contained in the first byte */
-            dst = esc->samples;
-            for (i = 0; i < avctx->channels; i++) {
-                *(dst++) = buf[0]+128;
-                delta_decode(dst, buf + 1, buf_size / avctx->channels - 1, (buf[0]+128)&0xFF, esc->table);
-                buf += buf_size / avctx->channels;
-                dst += n / avctx->channels - 1;
+        esc->data_idx  = 0;
+        esc->data_size = chan_size;
+        if (!(esc->data[0] = av_malloc(chan_size)))
+            return AVERROR(ENOMEM);
+        if (avctx->channels == 2) {
+            if (!(esc->data[1] = av_malloc(chan_size))) {
+                av_freep(&esc->data[0]);
+                return AVERROR(ENOMEM);
             }
-        } else {
-            raw_decode(esc->samples, avpkt->data, esc->samples_size);
         }
+        memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
+        if (avctx->channels == 2)
+            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");
+        return AVERROR(EINVAL);
+    }
+
+    /* decode next piece of data from the buffer */
+    buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
+    if (buf_size <= 0) {
+        *got_frame_ptr = 0;
+        return avpkt->size;
     }
 
     /* get output buffer */
-    av_assert1(!(esc->samples_size % avctx->channels || esc->samples_idx % avctx->channels));
-    esc->frame.nb_samples = FFMIN(MAX_FRAME_SIZE, esc->samples_size - esc->samples_idx)  / avctx->channels;
+    esc->frame.nb_samples = buf_size * (is_compr + 1);
     if ((ret = avctx->get_buffer(avctx, &esc->frame)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
 
+    for (ch = 0; ch < avctx->channels; ch++) {
+        if (is_compr) {
+            delta_decode(esc->frame.data[ch], &esc->data[ch][esc->data_idx],
+                         buf_size, &esc->fib_acc[ch], esc->table);
+        } else {
+            raw_decode(esc->frame.data[ch], &esc->data[ch][esc->data_idx],
+                       buf_size);
+        }
+    }
+
+    esc->data_idx += buf_size;
+
     *got_frame_ptr   = 1;
     *(AVFrame *)data = esc->frame;
 
-    out_data_size = esc->frame.nb_samples;
-    for (ch = 0; ch<avctx->channels; ch++) {
-        src = esc->samples + esc->samples_idx / avctx->channels + ch * esc->samples_size / avctx->channels;
-        memcpy(esc->frame.data[ch], src, out_data_size);
-    }
-    out_data_size *= avctx->channels;
-    esc->samples_idx += out_data_size;
-
-    return esc->table ?
-        (avctx->frame_number == 0)*2 + out_data_size / 2 :
-        out_data_size;
+    return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels;
 }
 
 static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
@@ -191,9 +198,10 @@ static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
 {
     EightSvxContext *esc = avctx->priv_data;
 
-    av_freep(&esc->samples);
-    esc->samples_size = 0;
-    esc->samples_idx = 0;
+    av_freep(&esc->data[0]);
+    av_freep(&esc->data[1]);
+    esc->data_size = 0;
+    esc->data_idx = 0;
 
     return 0;
 }
index 5b93329..e452f31 100644 (file)
@@ -1 +1 @@
-96a20cd1fae705cbc11eee5d6046b8e4
+e968a853779bb6438339e3b8d69d8d24