[libav-commits] flacdec: add planar output support

Mans Rullgard git at libav.org
Thu Jul 5 23:02:44 CEST 2012


Module: libav
Branch: master
Commit: 784514a4a8c621290fc5fa942ad286f9726475a9

Author:    Mans Rullgard <mans at mansr.com>
Committer: Mans Rullgard <mans at mansr.com>
Date:      Tue Jul  3 00:29:30 2012 +0100

flacdec: add planar output support

Signed-off-by: Mans Rullgard <mans at mansr.com>

---

 libavcodec/flacdec.c          |   34 ++++++++++++++++++++++-------
 libavcodec/flacdsp.c          |   35 +++++++++++++++++++++++++++--
 libavcodec/flacdsp.h          |    2 +-
 libavcodec/flacdsp_template.c |   47 +++++++++++++++++++++++++++-------------
 4 files changed, 91 insertions(+), 27 deletions(-)

diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index 7295e2e..89819e3 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -104,11 +104,22 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
 
 static void flac_set_bps(FLACContext *s)
 {
-    if (s->bps > 16) {
-        s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
+    enum AVSampleFormat req = s->avctx->request_sample_fmt;
+    int need32 = s->bps > 16;
+    int want32 = av_get_bytes_per_sample(req) > 2;
+    int planar = av_sample_fmt_is_planar(req);
+
+    if (need32 || want32) {
+        if (planar)
+            s->avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
+        else
+            s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
         s->sample_shift = 32 - s->bps;
     } else {
-        s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+        if (planar)
+            s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
+        else
+            s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
         s->sample_shift = 16 - s->bps;
     }
 }
@@ -132,7 +143,7 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
     avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
     allocate_buffers(s);
     flac_set_bps(s);
-    ff_flacdsp_init(&s->dsp, avctx->sample_fmt);
+    ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps);
     s->got_streaminfo = 1;
 
     avcodec_get_frame_defaults(&s->frame);
@@ -233,7 +244,7 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
     avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
     allocate_buffers(s);
     flac_set_bps(s);
-    ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
+    ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
     s->got_streaminfo = 1;
 
     return 0;
@@ -492,9 +503,11 @@ static int decode_frame(FLACContext *s)
                                        "supported\n");
         return -1;
     }
-    s->bps = s->avctx->bits_per_raw_sample = fi.bps;
 
-    flac_set_bps(s);
+    if (!s->bps) {
+        s->bps = s->avctx->bits_per_raw_sample = fi.bps;
+        flac_set_bps(s);
+    }
 
     if (!s->max_blocksize)
         s->max_blocksize = FLAC_MAX_BLOCKSIZE;
@@ -520,7 +533,7 @@ static int decode_frame(FLACContext *s)
 
     if (!s->got_streaminfo) {
         allocate_buffers(s);
-        ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
+        ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
         s->got_streaminfo = 1;
         dump_headers(s->avctx, (FLACStreaminfo *)s);
     }
@@ -628,4 +641,9 @@ AVCodec ff_flac_decoder = {
     .decode         = flac_decode_frame,
     .capabilities   = CODEC_CAP_DR1,
     .long_name      = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
+                                                      AV_SAMPLE_FMT_S16P,
+                                                      AV_SAMPLE_FMT_S32,
+                                                      AV_SAMPLE_FMT_S32P,
+                                                      -1 },
 };
diff --git a/libavcodec/flacdsp.c b/libavcodec/flacdsp.c
index fcee8e4..a2e335b 100644
--- a/libavcodec/flacdsp.c
+++ b/libavcodec/flacdsp.c
@@ -23,10 +23,21 @@
 #include "flacdsp.h"
 
 #define SAMPLE_SIZE 16
+#define PLANAR 0
+#include "flacdsp_template.c"
+
+#undef  PLANAR
+#define PLANAR 1
 #include "flacdsp_template.c"
 
 #undef  SAMPLE_SIZE
+#undef  PLANAR
 #define SAMPLE_SIZE 32
+#define PLANAR 0
+#include "flacdsp_template.c"
+
+#undef  PLANAR
+#define PLANAR 1
 #include "flacdsp_template.c"
 
 static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32],
@@ -72,15 +83,27 @@ static void flac_lpc_32_c(int32_t *decoded, const int coeffs[32],
 
 }
 
-av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt)
+av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt,
+                             int bps)
 {
+    if (bps > 16)
+        c->lpc            = flac_lpc_32_c;
+    else
+        c->lpc            = flac_lpc_16_c;
+
     switch (fmt) {
     case AV_SAMPLE_FMT_S32:
         c->decorrelate[0] = flac_decorrelate_indep_c_32;
         c->decorrelate[1] = flac_decorrelate_ls_c_32;
         c->decorrelate[2] = flac_decorrelate_rs_c_32;
         c->decorrelate[3] = flac_decorrelate_ms_c_32;
-        c->lpc            = flac_lpc_32_c;
+        break;
+
+    case AV_SAMPLE_FMT_S32P:
+        c->decorrelate[0] = flac_decorrelate_indep_c_32p;
+        c->decorrelate[1] = flac_decorrelate_ls_c_32p;
+        c->decorrelate[2] = flac_decorrelate_rs_c_32p;
+        c->decorrelate[3] = flac_decorrelate_ms_c_32p;
         break;
 
     case AV_SAMPLE_FMT_S16:
@@ -88,7 +111,13 @@ av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt)
         c->decorrelate[1] = flac_decorrelate_ls_c_16;
         c->decorrelate[2] = flac_decorrelate_rs_c_16;
         c->decorrelate[3] = flac_decorrelate_ms_c_16;
-        c->lpc            = flac_lpc_16_c;
+        break;
+
+    case AV_SAMPLE_FMT_S16P:
+        c->decorrelate[0] = flac_decorrelate_indep_c_16p;
+        c->decorrelate[1] = flac_decorrelate_ls_c_16p;
+        c->decorrelate[2] = flac_decorrelate_rs_c_16p;
+        c->decorrelate[3] = flac_decorrelate_ms_c_16p;
         break;
     }
 }
diff --git a/libavcodec/flacdsp.h b/libavcodec/flacdsp.h
index fe5ca53..1651553 100644
--- a/libavcodec/flacdsp.h
+++ b/libavcodec/flacdsp.h
@@ -29,6 +29,6 @@ typedef struct FLACDSPContext {
                 int qlevel, int len);
 } FLACDSPContext;
 
-void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt);
+void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int bps);
 
 #endif /* AVCODEC_FLACDSP_H */
diff --git a/libavcodec/flacdsp_template.c b/libavcodec/flacdsp_template.c
index 34da5a6..0affe22 100644
--- a/libavcodec/flacdsp_template.c
+++ b/libavcodec/flacdsp_template.c
@@ -19,68 +19,85 @@
  */
 
 #include <stdint.h>
+#include "libavutil/avutil.h"
 
 #undef FUNC
+#undef FSUF
 #undef sample
+#undef sample_type
+#undef OUT
+#undef S
 
 #if SAMPLE_SIZE == 32
-#   define FUNC(n) n ## _32
-#   define sample  int32_t
+#   define sample_type  int32_t
 #else
-#   define FUNC(n) n ## _16
-#   define sample  int16_t
+#   define sample_type  int16_t
 #endif
 
+#if PLANAR
+#   define FSUF   AV_JOIN(SAMPLE_SIZE, p)
+#   define sample sample_type *
+#   define OUT(n) n
+#   define S(s, c, i) (s[c][i])
+#else
+#   define FSUF   SAMPLE_SIZE
+#   define sample sample_type
+#   define OUT(n) n[0]
+#   define S(s, c, i) (*s++)
+#endif
+
+#define FUNC(n) AV_JOIN(n ## _, FSUF)
+
 static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in,
                                            int channels, int len, int shift)
 {
-    sample *samples = (sample *) out[0];
+    sample *samples = (sample *) OUT(out);
     int i, j;
 
     for (j = 0; j < len; j++)
         for (i = 0; i < channels; i++)
-            *samples++ = in[i][j] << shift;
+            S(samples, i, j) = in[i][j] << shift;
 }
 
 static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in,
                                         int channels, int len, int shift)
 {
-    sample *samples = (sample *) out[0];
+    sample *samples = (sample *) OUT(out);
     int i;
 
     for (i = 0; i < len; i++) {
         int a = in[0][i];
         int b = in[1][i];
-        *samples++ =  a      << shift;
-        *samples++ = (a - b) << shift;
+        S(samples, 0, i) =  a      << shift;
+        S(samples, 1, i) = (a - b) << shift;
     }
 }
 
 static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in,
                                         int channels, int len, int shift)
 {
-    sample *samples = (sample *) out[0];
+    sample *samples = (sample *) OUT(out);
     int i;
 
     for (i = 0; i < len; i++) {
         int a = in[0][i];
         int b = in[1][i];
-        *samples++ = (a + b) << shift;
-        *samples++ =  b      << shift;
+        S(samples, 0, i) = (a + b) << shift;
+        S(samples, 1, i) =  b      << shift;
     }
 }
 
 static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in,
                                         int channels, int len, int shift)
 {
-    sample *samples = (sample *) out[0];
+    sample *samples = (sample *) OUT(out);
     int i;
 
     for (i = 0; i < len; i++) {
         int a = in[0][i];
         int b = in[1][i];
         a -= b >> 1;
-        *samples++ = (a + b) << shift;
-        *samples++ =  a      << shift;
+        S(samples, 0, i) = (a + b) << shift;
+        S(samples, 1, i) =  a      << shift;
     }
 }



More information about the libav-commits mailing list