]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/wavpack.c
Remove misplaced Doxygen comment.
[ffmpeg] / libavcodec / wavpack.c
index 95f1d7123bc0274bc11a76fa21301b9f7c1ad053..7358d29735a7ba22db8e08663d5ccd92b289680b 100644 (file)
@@ -24,7 +24,7 @@
 #include "unary.h"
 
 /**
- * @file libavcodec/wavpack.c
+ * @file
  * WavPack lossless audio decoder
  */
 
@@ -67,6 +67,13 @@ enum WP_ID{
     WP_ID_CHANINFO
 };
 
+typedef struct SavedContext {
+    int offset;
+    int size;
+    int bits_used;
+    uint32_t crc;
+} SavedContext;
+
 #define MAX_TERMS 16
 
 typedef struct Decorr {
@@ -107,6 +114,10 @@ typedef struct WavpackContext {
     int float_shift;
     int float_max_exp;
     WvChannel ch[2];
+    int samples_left;
+    int max_samples;
+    int pos;
+    SavedContext sc, extra_sc;
 } WavpackContext;
 
 // exponent table copied from WavPack source
@@ -378,7 +389,7 @@ static float wv_get_value_float(WavpackContext *s, uint32_t *crc, int S)
 
     if(s->got_extra_bits){
         const int max_bits = 1 + 23 + 8 + 1;
-        const int left_bits = s->gb_extra_bits.size_in_bits - get_bits_count(&s->gb_extra_bits);
+        const int left_bits = get_bits_left(&s->gb_extra_bits);
 
         if(left_bits + 8 * FF_INPUT_BUFFER_PADDING_SIZE < max_bits)
             return 0.0;
@@ -439,19 +450,26 @@ static float wv_get_value_float(WavpackContext *s, uint32_t *crc, int S)
     return value.f;
 }
 
+static void wv_reset_saved_context(WavpackContext *s)
+{
+    s->pos = 0;
+    s->sc.crc = s->extra_sc.crc = 0xFFFFFFFF;
+}
+
 static inline int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, void *dst, const int type)
 {
     int i, j, count = 0;
     int last, t;
     int A, B, L, L2, R, R2;
-    int pos = 0;
-    uint32_t crc = 0xFFFFFFFF;
-    uint32_t crc_extra_bits = 0xFFFFFFFF;
+    int pos = s->pos;
+    uint32_t crc = s->sc.crc;
+    uint32_t crc_extra_bits = s->extra_sc.crc;
     int16_t *dst16 = dst;
     int32_t *dst32 = dst;
     float   *dstfl = dst;
 
-    s->one = s->zero = s->zeroes = 0;
+    if(s->samples_left == s->samples)
+        s->one = s->zero = s->zeroes = 0;
     do{
         L = wv_get_value(s, gb, 0, &last);
         if(last) break;
@@ -539,15 +557,27 @@ static inline int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, void *d
             *dst16++ = wv_get_value_integer(s, &crc_extra_bits, R);
         }
         count++;
-    }while(!last && count < s->samples);
+    }while(!last && count < s->max_samples);
 
-    if(crc != s->CRC){
-        av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
-        return -1;
-    }
-    if(s->got_extra_bits && crc_extra_bits != s->crc_extra_bits){
-        av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
-        return -1;
+    s->samples_left -= count;
+    if(!s->samples_left){
+        if(crc != s->CRC){
+            av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
+            return -1;
+        }
+        if(s->got_extra_bits && crc_extra_bits != s->crc_extra_bits){
+            av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
+            return -1;
+        }
+        wv_reset_saved_context(s);
+    }else{
+        s->pos = pos;
+        s->sc.crc = crc;
+        s->sc.bits_used = get_bits_count(&s->gb);
+        if(s->got_extra_bits){
+            s->extra_sc.crc = crc_extra_bits;
+            s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits);
+        }
     }
     return count * 2;
 }
@@ -557,14 +587,15 @@ static inline int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, void *dst
     int i, j, count = 0;
     int last, t;
     int A, S, T;
-    int pos = 0;
-    uint32_t crc = 0xFFFFFFFF;
-    uint32_t crc_extra_bits = 0xFFFFFFFF;
+    int pos = s->pos;
+    uint32_t crc = s->sc.crc;
+    uint32_t crc_extra_bits = s->extra_sc.crc;
     int16_t *dst16 = dst;
     int32_t *dst32 = dst;
     float   *dstfl = dst;
 
-    s->one = s->zero = s->zeroes = 0;
+    if(s->samples_left == s->samples)
+        s->one = s->zero = s->zeroes = 0;
     do{
         T = wv_get_value(s, gb, 0, &last);
         S = 0;
@@ -601,13 +632,25 @@ static inline int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, void *dst
         count++;
     }while(!last && count < s->samples);
 
-    if(crc != s->CRC){
-        av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
-        return -1;
-    }
-    if(s->got_extra_bits && crc_extra_bits != s->crc_extra_bits){
-        av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
-        return -1;
+    s->samples_left -= count;
+    if(!s->samples_left){
+        if(crc != s->CRC){
+            av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
+            return -1;
+        }
+        if(s->got_extra_bits && crc_extra_bits != s->crc_extra_bits){
+            av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
+            return -1;
+        }
+        wv_reset_saved_context(s);
+    }else{
+        s->pos = pos;
+        s->sc.crc = crc;
+        s->sc.bits_used = get_bits_count(&s->gb);
+        if(s->got_extra_bits){
+            s->extra_sc.crc = crc_extra_bits;
+            s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits);
+        }
     }
     return count;
 }
@@ -624,6 +667,8 @@ static av_cold int wavpack_decode_init(AVCodecContext *avctx)
         avctx->sample_fmt = SAMPLE_FMT_S32;
     avctx->channel_layout = (avctx->channels==2) ? CH_LAYOUT_STEREO : CH_LAYOUT_MONO;
 
+    wv_reset_saved_context(s);
+
     return 0;
 }
 
@@ -647,11 +692,13 @@ static int wavpack_decode_frame(AVCodecContext *avctx,
         return 0;
     }
 
-    memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr));
-    memset(s->ch, 0, sizeof(s->ch));
-    s->extra_bits = 0;
-    s->and = s->or = s->shift = 0;
-    s->got_extra_bits = 0;
+    if(!s->samples_left){
+        memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr));
+        memset(s->ch, 0, sizeof(s->ch));
+        s->extra_bits = 0;
+        s->and = s->or = s->shift = 0;
+        s->got_extra_bits = 0;
+    }
 
     s->samples = AV_RL32(buf); buf += 4;
     if(!s->samples){
@@ -676,10 +723,11 @@ static int wavpack_decode_frame(AVCodecContext *avctx,
     s->post_shift = 8 * (bpp-1-(s->frame_flags&0x03)) + ((s->frame_flags >> 13) & 0x1f);
     s->CRC = AV_RL32(buf); buf += 4;
 
-    /* should not happen but who knows */
-    if(s->samples * bpp * avctx->channels > *data_size){
-        av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n");
-        return -1;
+    s->max_samples = *data_size / (bpp * avctx->channels);
+    s->max_samples = FFMIN(s->max_samples, s->samples);
+    if(s->samples_left > 0){
+        s->max_samples = FFMIN(s->max_samples, s->samples_left);
+        buf = buf_end;
     }
 
     // parse metadata blocks
@@ -847,6 +895,8 @@ static int wavpack_decode_frame(AVCodecContext *avctx,
             got_float = 1;
             break;
         case WP_ID_DATA:
+            s->sc.offset = buf - avpkt->data;
+            s->sc.size   = size * 8;
             init_get_bits(&s->gb, buf, size * 8);
             s->data_size = size * 8;
             buf += size;
@@ -858,6 +908,8 @@ static int wavpack_decode_frame(AVCodecContext *avctx,
                 buf += size;
                 continue;
             }
+            s->extra_sc.offset = buf - avpkt->data;
+            s->extra_sc.size   = size * 8;
             init_get_bits(&s->gb_extra_bits, buf, size * 8);
             s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32);
             buf += size;
@@ -868,40 +920,51 @@ static int wavpack_decode_frame(AVCodecContext *avctx,
         }
         if(id & WP_IDF_ODD) buf++;
     }
-    if(!got_terms){
-        av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");
-        return -1;
-    }
-    if(!got_weights){
-        av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n");
-        return -1;
-    }
-    if(!got_samples){
-        av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n");
-        return -1;
-    }
-    if(!got_entropy){
-        av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n");
-        return -1;
-    }
-    if(s->hybrid && !got_hybrid){
-        av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n");
-        return -1;
-    }
-    if(!got_bs){
-        av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");
-        return -1;
-    }
-    if(!got_float && avctx->sample_fmt == SAMPLE_FMT_FLT){
-        av_log(avctx, AV_LOG_ERROR, "Float information not found\n");
-        return -1;
-    }
-    if(s->got_extra_bits && avctx->sample_fmt != SAMPLE_FMT_FLT){
-        const int size = s->gb_extra_bits.size_in_bits - get_bits_count(&s->gb_extra_bits);
-        const int wanted = s->samples * s->extra_bits << s->stereo_in;
-        if(size < wanted){
-            av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n");
-            s->got_extra_bits = 0;
+    if(!s->samples_left){
+        if(!got_terms){
+            av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");
+            return -1;
+        }
+        if(!got_weights){
+            av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n");
+            return -1;
+        }
+        if(!got_samples){
+            av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n");
+            return -1;
+        }
+        if(!got_entropy){
+            av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n");
+            return -1;
+        }
+        if(s->hybrid && !got_hybrid){
+            av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n");
+            return -1;
+        }
+        if(!got_bs){
+            av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");
+            return -1;
+        }
+        if(!got_float && avctx->sample_fmt == SAMPLE_FMT_FLT){
+            av_log(avctx, AV_LOG_ERROR, "Float information not found\n");
+            return -1;
+        }
+        if(s->got_extra_bits && avctx->sample_fmt != SAMPLE_FMT_FLT){
+            const int size = get_bits_left(&s->gb_extra_bits);
+            const int wanted = s->samples * s->extra_bits << s->stereo_in;
+            if(size < wanted){
+                av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n");
+                s->got_extra_bits = 0;
+            }
+        }
+        s->samples_left = s->samples;
+    }else{
+        init_get_bits(&s->gb, avpkt->data + s->sc.offset, s->sc.size);
+        skip_bits_long(&s->gb, s->sc.bits_used);
+        if(s->got_extra_bits){
+            init_get_bits(&s->gb_extra_bits, avpkt->data + s->extra_sc.offset,
+                          s->extra_sc.size);
+            skip_bits_long(&s->gb_extra_bits, s->extra_sc.bits_used);
         }
     }
 
@@ -952,12 +1015,12 @@ static int wavpack_decode_frame(AVCodecContext *avctx,
     }
     *data_size = samplecount * bpp;
 
-    return buf_size;
+    return s->samples_left > 0 ? 0 : buf_size;
 }
 
 AVCodec wavpack_decoder = {
     "wavpack",
-    CODEC_TYPE_AUDIO,
+    AVMEDIA_TYPE_AUDIO,
     CODEC_ID_WAVPACK,
     sizeof(WavpackContext),
     wavpack_decode_init,