]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/flacdec.c
mpegvideo_enc: fix indentation in load_input_picture()
[ffmpeg] / libavcodec / flacdec.c
index 3cdd957a555e6f5ce01b17ebd233b28bba0f050d..51fd19628cf89ebb99c34ff6228e5164044ab757 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <limits.h>
 
-#include "libavutil/audioconvert.h"
+#include "libavutil/channel_layout.h"
 #include "libavutil/crc.h"
 #include "avcodec.h"
 #include "internal.h"
@@ -60,20 +60,13 @@ typedef struct FLACContext {
     int got_streaminfo;                     ///< indicates if the STREAMINFO has been read
 
     int32_t *decoded[FLAC_MAX_CHANNELS];    ///< decoded samples
+    uint8_t *decoded_buffer;
+    unsigned int decoded_buffer_size;
 
     FLACDSPContext dsp;
 } FLACContext;
 
-static const int64_t flac_channel_layouts[6] = {
-    AV_CH_LAYOUT_MONO,
-    AV_CH_LAYOUT_STEREO,
-    AV_CH_LAYOUT_SURROUND,
-    AV_CH_LAYOUT_QUAD,
-    AV_CH_LAYOUT_5POINT0,
-    AV_CH_LAYOUT_5POINT1
-};
-
-static void allocate_buffers(FLACContext *s);
+static int allocate_buffers(FLACContext *s);
 
 static void flac_set_bps(FLACContext *s)
 {
@@ -101,6 +94,7 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
 {
     enum FLACExtradataFormat format;
     uint8_t *streaminfo;
+    int ret;
     FLACContext *s = avctx->priv_data;
     s->avctx = avctx;
 
@@ -114,7 +108,9 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
 
     /* initialize based on the demuxer-supplied streamdata header */
     avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
-    allocate_buffers(s);
+    ret = allocate_buffers(s);
+    if (ret < 0)
+        return ret;
     flac_set_bps(s);
     ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps);
     s->got_streaminfo = 1;
@@ -122,9 +118,6 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
     avcodec_get_frame_defaults(&s->frame);
     avctx->coded_frame = &s->frame;
 
-    if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts))
-        avctx->channel_layout = flac_channel_layouts[avctx->channels - 1];
-
     return 0;
 }
 
@@ -137,15 +130,24 @@ static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s)
     av_log(avctx, AV_LOG_DEBUG, "  Bits: %d\n", s->bps);
 }
 
-static void allocate_buffers(FLACContext *s)
+static int allocate_buffers(FLACContext *s)
 {
-    int i;
+    int buf_size;
 
     assert(s->max_blocksize);
 
-    for (i = 0; i < s->channels; i++) {
-        s->decoded[i] = av_malloc(sizeof(int32_t)*s->max_blocksize);
-    }
+    buf_size = av_samples_get_buffer_size(NULL, s->channels, s->max_blocksize,
+                                          AV_SAMPLE_FMT_S32P, 0);
+    if (buf_size < 0)
+        return buf_size;
+
+    av_fast_malloc(&s->decoded_buffer, &s->decoded_buffer_size, buf_size);
+    if (!s->decoded_buffer)
+        return AVERROR(ENOMEM);
+
+    return av_samples_fill_arrays((uint8_t **)s->decoded, NULL,
+                                  s->decoded_buffer, s->channels,
+                                  s->max_blocksize, AV_SAMPLE_FMT_S32P, 0);
 }
 
 /**
@@ -157,7 +159,7 @@ static void allocate_buffers(FLACContext *s)
  */
 static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
 {
-    int metadata_type, metadata_size;
+    int metadata_type, metadata_size, ret;
 
     if (buf_size < FLAC_STREAMINFO_SIZE+8) {
         /* need more data */
@@ -169,7 +171,9 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
         return AVERROR_INVALIDDATA;
     }
     avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
-    allocate_buffers(s);
+    ret = allocate_buffers(s);
+    if (ret < 0)
+        return ret;
     flac_set_bps(s);
     ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
     s->got_streaminfo = 1;
@@ -204,10 +208,11 @@ static int get_metadata_size(const uint8_t *buf, int buf_size)
     return buf_size - (buf_end - buf);
 }
 
-static int decode_residuals(FLACContext *s, int channel, int pred_order)
+static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order)
 {
     int i, tmp, partition, method_type, rice_order;
-    int sample = 0, samples;
+    int rice_bits, rice_esc;
+    int samples;
 
     method_type = get_bits(&s->gb, 2);
     if (method_type > 1) {
@@ -225,17 +230,20 @@ static int decode_residuals(FLACContext *s, int channel, int pred_order)
         return -1;
     }
 
-    sample=
+    rice_bits = 4 + method_type;
+    rice_esc  = (1 << rice_bits) - 1;
+
+    decoded += pred_order;
     i= pred_order;
     for (partition = 0; partition < (1 << rice_order); partition++) {
-        tmp = get_bits(&s->gb, method_type == 0 ? 4 : 5);
-        if (tmp == (method_type == 0 ? 15 : 31)) {
+        tmp = get_bits(&s->gb, rice_bits);
+        if (tmp == rice_esc) {
             tmp = get_bits(&s->gb, 5);
-            for (; i < samples; i++, sample++)
-                s->decoded[channel][sample] = get_sbits_long(&s->gb, tmp);
+            for (; i < samples; i++)
+                *decoded++ = 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);
+            for (; i < samples; i++) {
+                *decoded++ = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
             }
         }
         i= 0;
@@ -244,11 +252,10 @@ static int decode_residuals(FLACContext *s, int channel, int pred_order)
     return 0;
 }
 
-static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order,
-                                 int bps)
+static int decode_subframe_fixed(FLACContext *s, int32_t *decoded,
+                                 int pred_order, int bps)
 {
     const int blocksize = s->blocksize;
-    int32_t *decoded = s->decoded[channel];
     int a, b, c, d, i;
 
     /* warm up samples */
@@ -256,7 +263,7 @@ static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order,
         decoded[i] = get_sbits_long(&s->gb, bps);
     }
 
-    if (decode_residuals(s, channel, pred_order) < 0)
+    if (decode_residuals(s, decoded, pred_order) < 0)
         return -1;
 
     if (pred_order > 0)
@@ -295,13 +302,12 @@ static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order,
     return 0;
 }
 
-static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order,
+static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order,
                                int bps)
 {
     int i;
     int coeff_prec, qlevel;
     int coeffs[32];
-    int32_t *decoded = s->decoded[channel];
 
     /* warm up samples */
     for (i = 0; i < pred_order; i++) {
@@ -324,7 +330,7 @@ static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order,
         coeffs[pred_order - i - 1] = get_sbits(&s->gb, coeff_prec);
     }
 
-    if (decode_residuals(s, channel, pred_order) < 0)
+    if (decode_residuals(s, decoded, pred_order) < 0)
         return -1;
 
     s->dsp.lpc(decoded, coeffs, pred_order, qlevel, s->blocksize);
@@ -334,6 +340,7 @@ static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order,
 
 static inline int decode_subframe(FLACContext *s, int channel)
 {
+    int32_t *decoded = s->decoded[channel];
     int type, wasted = 0;
     int bps = s->bps;
     int i, tmp;
@@ -368,23 +375,23 @@ static inline int decode_subframe(FLACContext *s, int channel)
         bps -= wasted;
     }
     if (bps > 32) {
-        av_log_missing_feature(s->avctx, "decorrelated bit depth > 32", 0);
-        return -1;
+        av_log_missing_feature(s->avctx, "Decorrelated bit depth > 32", 0);
+        return AVERROR_PATCHWELCOME;
     }
 
 //FIXME use av_log2 for types
     if (type == 0) {
         tmp = get_sbits_long(&s->gb, bps);
         for (i = 0; i < s->blocksize; i++)
-            s->decoded[channel][i] = tmp;
+            decoded[i] = tmp;
     } else if (type == 1) {
         for (i = 0; i < s->blocksize; i++)
-            s->decoded[channel][i] = get_sbits_long(&s->gb, bps);
+            decoded[i] = get_sbits_long(&s->gb, bps);
     } else if ((type >= 8) && (type <= 12)) {
-        if (decode_subframe_fixed(s, channel, type & ~0x8, bps) < 0)
+        if (decode_subframe_fixed(s, decoded, type & ~0x8, bps) < 0)
             return -1;
     } else if (type >= 32) {
-        if (decode_subframe_lpc(s, channel, (type & ~0x20)+1, bps) < 0)
+        if (decode_subframe_lpc(s, decoded, (type & ~0x20)+1, bps) < 0)
             return -1;
     } else {
         av_log(s->avctx, AV_LOG_ERROR, "invalid coding type\n");
@@ -394,7 +401,7 @@ static inline int decode_subframe(FLACContext *s, int channel)
     if (wasted) {
         int i;
         for (i = 0; i < s->blocksize; i++)
-            s->decoded[channel][i] <<= wasted;
+            decoded[i] <<= wasted;
     }
 
     return 0;
@@ -402,7 +409,7 @@ static inline int decode_subframe(FLACContext *s, int channel)
 
 static int decode_frame(FLACContext *s)
 {
-    int i;
+    int i, ret;
     GetBitContext *gb = &s->gb;
     FLACFrameInfo fi;
 
@@ -411,12 +418,16 @@ static int decode_frame(FLACContext *s)
         return -1;
     }
 
-    if (s->channels && fi.channels != s->channels) {
-        av_log(s->avctx, AV_LOG_ERROR, "switching channel layout mid-stream "
-                                       "is not supported\n");
-        return -1;
+    if (s->channels && fi.channels != s->channels && s->got_streaminfo) {
+        s->channels = s->avctx->channels = fi.channels;
+        ff_flac_set_channel_layout(s->avctx);
+        ret = allocate_buffers(s);
+        if (ret < 0)
+            return ret;
     }
     s->channels = s->avctx->channels = fi.channels;
+    if (!s->avctx->channel_layout && s->channels <= 6)
+        ff_flac_set_channel_layout(s->avctx);
     s->ch_mode = fi.ch_mode;
 
     if (!s->bps && !fi.bps) {
@@ -450,16 +461,14 @@ static int decode_frame(FLACContext *s)
                                         " or frame header\n");
         return -1;
     }
-    if (fi.samplerate == 0) {
+    if (fi.samplerate == 0)
         fi.samplerate = s->samplerate;
-    } else if (s->samplerate && fi.samplerate != s->samplerate) {
-        av_log(s->avctx, AV_LOG_WARNING, "sample rate changed from %d to %d\n",
-               s->samplerate, fi.samplerate);
-    }
     s->samplerate = s->avctx->sample_rate = fi.samplerate;
 
     if (!s->got_streaminfo) {
-        allocate_buffers(s);
+        ret = allocate_buffers(s);
+        if (ret < 0)
+            return ret;
         ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
         s->got_streaminfo = 1;
         dump_headers(s->avctx, (FLACStreaminfo *)s);
@@ -523,7 +532,7 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data,
 
     /* get output buffer */
     s->frame.nb_samples = s->blocksize;
-    if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+    if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
@@ -549,11 +558,8 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data,
 static av_cold int flac_decode_close(AVCodecContext *avctx)
 {
     FLACContext *s = avctx->priv_data;
-    int i;
 
-    for (i = 0; i < s->channels; i++) {
-        av_freep(&s->decoded[i]);
-    }
+    av_freep(&s->decoded_buffer);
 
     return 0;
 }