]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/flac.c
Add libavcodec to compiler include flags in order to simplify header
[ffmpeg] / libavcodec / flac.c
index 47459b2f36aaad5e41e334f599625d9f91157e31..1016ed47f6eff46ed09fdba98ee68cf02af8dc84 100644 (file)
@@ -95,18 +95,23 @@ static int64_t get_utf8(GetBitContext *gb){
 }
 
 static void metadata_streaminfo(FLACContext *s);
-static void dump_headers(FLACContext *s);
+static void allocate_buffers(FLACContext *s);
+static int metadata_parse(FLACContext *s);
 
 static int flac_decode_init(AVCodecContext * avctx)
 {
     FLACContext *s = avctx->priv_data;
     s->avctx = avctx;
 
-    /* initialize based on the demuxer-supplied streamdata header */
-    if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
+    if (avctx->extradata_size > 4) {
+        /* initialize based on the demuxer-supplied streamdata header */
         init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
-        metadata_streaminfo(s);
-        dump_headers(s);
+        if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
+            metadata_streaminfo(s);
+            allocate_buffers(s);
+        } else {
+            metadata_parse(s);
+        }
     }
 
     return 0;
@@ -159,7 +164,51 @@ static void metadata_streaminfo(FLACContext *s)
     skip_bits(&s->gb, 64); /* md5 sum */
     skip_bits(&s->gb, 64); /* md5 sum */
 
-    allocate_buffers(s);
+    dump_headers(s);
+}
+
+/**
+ * Parse a list of metadata blocks. This list of blocks must begin with
+ * the fLaC marker.
+ * @param s the flac decoding context containing the gb bit reader used to
+ *          parse metadata
+ * @return 1 if some metadata was read, 0 if no fLaC marker was found
+ */
+static int metadata_parse(FLACContext *s)
+{
+    int i, metadata_last, metadata_type, metadata_size, streaminfo_updated=0;
+
+    if (show_bits_long(&s->gb, 32) == MKBETAG('f','L','a','C')) {
+        skip_bits(&s->gb, 32);
+
+        av_log(s->avctx, AV_LOG_DEBUG, "STREAM HEADER\n");
+        do {
+            metadata_last = get_bits(&s->gb, 1);
+            metadata_type = get_bits(&s->gb, 7);
+            metadata_size = get_bits_long(&s->gb, 24);
+
+            av_log(s->avctx, AV_LOG_DEBUG,
+                   " metadata block: flag = %d, type = %d, size = %d\n",
+                   metadata_last, metadata_type, metadata_size);
+            if (metadata_size) {
+                switch (metadata_type) {
+                case METADATA_TYPE_STREAMINFO:
+                    metadata_streaminfo(s);
+                    streaminfo_updated = 1;
+                    break;
+
+                default:
+                    for (i=0; i<metadata_size; i++)
+                        skip_bits(&s->gb, 8);
+                }
+            }
+        } while (!metadata_last);
+
+        if (streaminfo_updated)
+            allocate_buffers(s);
+        return 1;
+    }
+    return 0;
 }
 
 static int decode_residuals(FLACContext *s, int channel, int pred_order)
@@ -176,6 +225,10 @@ static int decode_residuals(FLACContext *s, int channel, int pred_order)
     rice_order = get_bits(&s->gb, 4);
 
     samples= s->blocksize >> rice_order;
+    if (pred_order > samples) {
+        av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n", pred_order, samples);
+        return -1;
+    }
 
     sample=
     i= pred_order;
@@ -405,7 +458,7 @@ static inline int decode_subframe(FLACContext *s, int channel)
     return 0;
 }
 
-static int decode_frame(FLACContext *s)
+static int decode_frame(FLACContext *s, int alloc_data_size)
 {
     int blocksize_code, sample_rate_code, sample_size_code, assignment, i, crc8;
     int decorrelation, bps, blocksize, samplerate;
@@ -467,6 +520,9 @@ static int decode_frame(FLACContext *s)
         return -1;
     }
 
+    if(blocksize * s->channels * sizeof(int16_t) > alloc_data_size)
+        return -1;
+
     if (sample_rate_code == 0){
         samplerate= s->samplerate;
     }else if ((sample_rate_code > 3) && (sample_rate_code < 12))
@@ -528,9 +584,11 @@ static int flac_decode_frame(AVCodecContext *avctx,
                             uint8_t *buf, int buf_size)
 {
     FLACContext *s = avctx->priv_data;
-    int metadata_last, metadata_type, metadata_size;
     int tmp = 0, i, j = 0, input_buf_size = 0;
     int16_t *samples = data;
+    int alloc_data_size= *data_size;
+
+    *data_size=0;
 
     if(s->max_framesize == 0){
         s->max_framesize= 65536; // should hopefully be enough for the first header
@@ -559,47 +617,8 @@ static int flac_decode_frame(AVCodecContext *avctx,
 
     init_get_bits(&s->gb, buf, buf_size*8);
 
-    /* fLaC signature (be) */
-    if (show_bits_long(&s->gb, 32) == bswap_32(ff_get_fourcc("fLaC")))
+    if (!metadata_parse(s))
     {
-        skip_bits(&s->gb, 32);
-
-        av_log(s->avctx, AV_LOG_DEBUG, "STREAM HEADER\n");
-        do {
-            metadata_last = get_bits(&s->gb, 1);
-            metadata_type = get_bits(&s->gb, 7);
-            metadata_size = get_bits_long(&s->gb, 24);
-
-            av_log(s->avctx, AV_LOG_DEBUG, " metadata block: flag = %d, type = %d, size = %d\n",
-                metadata_last, metadata_type,
-                metadata_size);
-            if(metadata_size){
-                switch(metadata_type)
-                {
-                case METADATA_TYPE_STREAMINFO:{
-                    metadata_streaminfo(s);
-
-                    /* Buffer might have been reallocated, reinit bitreader */
-                    if(buf != &s->bitstream[s->bitstream_index])
-                    {
-                        int bits_count = get_bits_count(&s->gb);
-                        buf= &s->bitstream[s->bitstream_index];
-                        init_get_bits(&s->gb, buf, buf_size*8);
-                        skip_bits(&s->gb, bits_count);
-                    }
-
-                    dump_headers(s);
-                    break;}
-                default:
-                    for(i=0; i<metadata_size; i++)
-                        skip_bits(&s->gb, 8);
-                }
-            }
-        } while(!metadata_last);
-    }
-    else
-    {
-
         tmp = show_bits(&s->gb, 16);
         if(tmp != 0xFFF8){
             av_log(s->avctx, AV_LOG_ERROR, "FRAME HEADER not here\n");
@@ -608,7 +627,7 @@ static int flac_decode_frame(AVCodecContext *avctx,
             goto end; // we may not have enough bits left to decode a frame, so try next time
         }
         skip_bits(&s->gb, 16);
-        if (decode_frame(s) < 0){
+        if (decode_frame(s, alloc_data_size) < 0){
             av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
             s->bitstream_size=0;
             s->bitstream_index=0;