]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/flacdec.c
flacdec: use get_sbits_long() where needed.
[ffmpeg] / libavcodec / flacdec.c
index 16aa4763768082b81a1e44f9ee27771181773464..0361394955b61478e37e146e4dc360b90b64cdeb 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 /**
- * @file flacdec.c
+ * @file libavcodec/flacdec.c
  * FLAC (Free Lossless Audio Codec) decoder
  * @author Alex Beregszaszi
  *
@@ -47,7 +47,6 @@
 
 #define MAX_CHANNELS 8
 #define MAX_BLOCKSIZE 65535
-#define FLAC_STREAMINFO_SIZE 34
 
 enum decorrelation_type {
     INDEPENDENT,
@@ -59,14 +58,16 @@ enum decorrelation_type {
 typedef struct FLACContext {
     FLACSTREAMINFO
 
-    AVCodecContext *avctx;
-    GetBitContext gb;
+    AVCodecContext *avctx;                  ///< parent AVCodecContext
+    GetBitContext gb;                       ///< GetBitContext initialized to start at the current frame
 
-    int blocksize/*, last_blocksize*/;
-    int curr_bps;
-    enum decorrelation_type decorrelation;
+    int blocksize;                          ///< number of samples in the current frame
+    int curr_bps;                           ///< bps for current subframe, adjusted for channel correlation and wasted bits
+    int sample_shift;                       ///< shift required to make output samples 16-bit or 32-bit
+    int is32;                               ///< flag to indicate if output should be 32-bit instead of 16-bit
+    enum decorrelation_type decorrelation;  ///< channel decorrelation type in the current frame
 
-    int32_t *decoded[MAX_CHANNELS];
+    int32_t *decoded[MAX_CHANNELS];         ///< decoded samples
     uint8_t *bitstream;
     unsigned int bitstream_size;
     unsigned int bitstream_index;
@@ -95,26 +96,55 @@ static int64_t get_utf8(GetBitContext *gb)
 }
 
 static void allocate_buffers(FLACContext *s);
-static int metadata_parse(FLACContext *s);
+
+int ff_flac_is_extradata_valid(AVCodecContext *avctx,
+                               enum FLACExtradataFormat *format,
+                               uint8_t **streaminfo_start)
+{
+    if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) {
+        av_log(avctx, AV_LOG_ERROR, "extradata NULL or too small.\n");
+        return 0;
+    }
+    if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) {
+        /* extradata contains STREAMINFO only */
+        if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) {
+            av_log(avctx, AV_LOG_WARNING, "extradata contains %d bytes too many.\n",
+                   FLAC_STREAMINFO_SIZE-avctx->extradata_size);
+        }
+        *format = FLAC_EXTRADATA_FORMAT_STREAMINFO;
+        *streaminfo_start = avctx->extradata;
+    } else {
+        if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) {
+            av_log(avctx, AV_LOG_ERROR, "extradata too small.\n");
+            return 0;
+        }
+        *format = FLAC_EXTRADATA_FORMAT_FULL_HEADER;
+        *streaminfo_start = &avctx->extradata[8];
+    }
+    return 1;
+}
 
 static av_cold int flac_decode_init(AVCodecContext *avctx)
 {
+    enum FLACExtradataFormat format;
+    uint8_t *streaminfo;
     FLACContext *s = avctx->priv_data;
     s->avctx = avctx;
 
-    if (avctx->extradata_size > 4) {
-        /* initialize based on the demuxer-supplied streamdata header */
-        if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
-            ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s,
-                                     avctx->extradata);
-            allocate_buffers(s);
-        } else {
-            init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
-            metadata_parse(s);
-        }
-    }
-
     avctx->sample_fmt = SAMPLE_FMT_S16;
+
+    /* for now, the raw FLAC header is allowed to be passed to the decoder as
+       frame data instead of extradata. */
+    if (!avctx->extradata)
+        return 0;
+
+    if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo))
+        return -1;
+
+    /* initialize based on the demuxer-supplied streamdata header */
+    ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
+    allocate_buffers(s);
+
     return 0;
 }
 
@@ -169,11 +199,17 @@ void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
 
     avctx->channels = s->channels;
     avctx->sample_rate = s->samplerate;
+    avctx->bits_per_raw_sample = s->bps;
+    if (s->bps > 16)
+        avctx->sample_fmt = SAMPLE_FMT_S32;
+    else
+        avctx->sample_fmt = SAMPLE_FMT_S16;
 
-    skip_bits(&gb, 36); /* total num of samples */
+    s->samples  = get_bits_long(&gb, 32) << 4;
+    s->samples |= get_bits(&gb, 4);
 
-    skip_bits(&gb, 64); /* md5 sum */
-    skip_bits(&gb, 64); /* md5 sum */
+    skip_bits_long(&gb, 64); /* md5 sum */
+    skip_bits_long(&gb, 64); /* md5 sum */
 
     dump_headers(avctx, s);
 }
@@ -191,7 +227,7 @@ static int metadata_parse(FLACContext *s)
     int initial_pos= get_bits_count(&s->gb);
 
     if (show_bits_long(&s->gb, 32) == MKBETAG('f','L','a','C')) {
-        skip_bits(&s->gb, 32);
+        skip_bits_long(&s->gb, 32);
 
         do {
             metadata_last = get_bits1(&s->gb);
@@ -252,7 +288,7 @@ static int decode_residuals(FLACContext *s, int channel, int pred_order)
         if (tmp == (method_type == 0 ? 15 : 31)) {
             tmp = get_bits(&s->gb, 5);
             for (; i < samples; i++, sample++)
-                s->decoded[channel][sample] = get_sbits(&s->gb, tmp);
+                s->decoded[channel][sample] = get_sbits_long(&s->gb, tmp);
         } else {
             for (; i < samples; i++, sample++) {
                 s->decoded[channel][sample] = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
@@ -268,11 +304,11 @@ static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order)
 {
     const int blocksize = s->blocksize;
     int32_t *decoded = s->decoded[channel];
-    int a, b, c, d, i;
+    int av_uninit(a), av_uninit(b), av_uninit(c), av_uninit(d), i;
 
     /* warm up samples */
     for (i = 0; i < pred_order; i++) {
-        decoded[i] = get_sbits(&s->gb, s->curr_bps);
+        decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
     }
 
     if (decode_residuals(s, channel, pred_order) < 0)
@@ -323,7 +359,7 @@ static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order)
 
     /* warm up samples */
     for (i = 0; i < pred_order; i++) {
-        decoded[i] = get_sbits(&s->gb, s->curr_bps);
+        decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
     }
 
     coeff_prec = get_bits(&s->gb, 4) + 1;
@@ -410,12 +446,12 @@ static inline int decode_subframe(FLACContext *s, int channel)
 
 //FIXME use av_log2 for types
     if (type == 0) {
-        tmp = get_sbits(&s->gb, s->curr_bps);
+        tmp = get_sbits_long(&s->gb, s->curr_bps);
         for (i = 0; i < s->blocksize; i++)
             s->decoded[channel][i] = tmp;
     } else if (type == 1) {
         for (i = 0; i < s->blocksize; i++)
-            s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);
+            s->decoded[channel][i] = get_sbits_long(&s->gb, s->curr_bps);
     } else if ((type >= 8) && (type <= 12)) {
         if (decode_subframe_fixed(s, channel, type & ~0x8) < 0)
             return -1;
@@ -466,6 +502,16 @@ static int decode_frame(FLACContext *s, int alloc_data_size)
                sample_size_code);
         return -1;
     }
+    if (bps > 16) {
+        s->avctx->sample_fmt = SAMPLE_FMT_S32;
+        s->sample_shift = 32 - bps;
+        s->is32 = 1;
+    } else {
+        s->avctx->sample_fmt = SAMPLE_FMT_S16;
+        s->sample_shift = 16 - bps;
+        s->is32 = 0;
+    }
+    s->bps = s->avctx->bits_per_raw_sample = bps;
 
     if (get_bits1(&s->gb)) {
         av_log(s->avctx, AV_LOG_ERROR, "broken stream, invalid padding\n");
@@ -546,7 +592,8 @@ static int flac_decode_frame(AVCodecContext *avctx,
 {
     FLACContext *s = avctx->priv_data;
     int tmp = 0, i, j = 0, input_buf_size = 0;
-    int16_t *samples = data;
+    int16_t *samples_16 = data;
+    int32_t *samples_32 = data;
     int alloc_data_size= *data_size;
 
     *data_size=0;
@@ -608,16 +655,25 @@ static int flac_decode_frame(AVCodecContext *avctx,
             for (i = 0; i < s->blocksize; i++) {\
                 int a= s->decoded[0][i];\
                 int b= s->decoded[1][i];\
-                *samples++ = ((left)  << (24 - s->bps)) >> 8;\
-                *samples++ = ((right) << (24 - s->bps)) >> 8;\
+                if (s->is32) {\
+                    *samples_32++ = (left)  << s->sample_shift;\
+                    *samples_32++ = (right) << s->sample_shift;\
+                } else {\
+                    *samples_16++ = (left)  << s->sample_shift;\
+                    *samples_16++ = (right) << s->sample_shift;\
+                }\
             }\
             break;
 
     switch (s->decorrelation) {
     case INDEPENDENT:
         for (j = 0; j < s->blocksize; j++) {
-            for (i = 0; i < s->channels; i++)
-                *samples++ = (s->decoded[i][j] << (24 - s->bps)) >> 8;
+            for (i = 0; i < s->channels; i++) {
+                if (s->is32)
+                    *samples_32++ = s->decoded[i][j] << s->sample_shift;
+                else
+                    *samples_16++ = s->decoded[i][j] << s->sample_shift;
+            }
         }
         break;
     case LEFT_SIDE:
@@ -628,7 +684,7 @@ static int flac_decode_frame(AVCodecContext *avctx,
         DECORRELATE( (a-=b>>1) + b, a)
     }
 
-    *data_size = (int8_t *)samples - (int8_t *)data;
+    *data_size = s->blocksize * s->channels * (s->is32 ? 4 : 2);
 
 end:
     i= (get_bits_count(&s->gb)+7)/8;