Correctly implement ac3 float/fixed encoder.
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 16 Apr 2011 21:20:48 +0000 (23:20 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 16 Apr 2011 21:24:10 +0000 (23:24 +0200)
There is no need to have 2 encoders, the input sample format can,does and should choose which is used
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/Makefile
libavcodec/ac3.h
libavcodec/ac3enc.c
libavcodec/ac3enc_combined.c [new file with mode: 0644]
libavcodec/ac3enc_fixed.c
libavcodec/ac3enc_float.c
libavcodec/allcodecs.c

index ad0a3cc..e1432b3 100644 (file)
@@ -59,7 +59,8 @@ OBJS-$(CONFIG_AAC_ENCODER)             += aacenc.o aaccoder.o    \
                                           mpeg4audio.o kbdwin.o
 OBJS-$(CONFIG_AASC_DECODER)            += aasc.o msrledec.o
 OBJS-$(CONFIG_AC3_DECODER)             += ac3dec.o ac3dec_data.o ac3.o kbdwin.o
-OBJS-$(CONFIG_AC3_ENCODER)             += ac3enc_float.o ac3tab.o ac3.o kbdwin.o
+OBJS-$(CONFIG_AC3_ENCODER)             += ac3enc_combined.o ac3enc_fixed.o ac3enc_float.o ac3tab.o ac3.o kbdwin.o
+OBJS-$(CONFIG_AC3_FLOAT_ENCODER)       += ac3enc_float.o ac3tab.o ac3.o kbdwin.o
 OBJS-$(CONFIG_AC3_FIXED_ENCODER)       += ac3enc_fixed.o ac3tab.o ac3.o
 OBJS-$(CONFIG_ALAC_DECODER)            += alac.o
 OBJS-$(CONFIG_ALAC_ENCODER)            += alacenc.o
index 371d0a2..6baf989 100644 (file)
@@ -38,6 +38,8 @@
 #define AC3_CRITICAL_BANDS 50
 #define AC3_MAX_CPL_BANDS  18
 
+#include "libavutil/opt.h"
+#include "avcodec.h"
 #include "ac3tab.h"
 
 /* exponent encoding strategy */
@@ -128,8 +130,45 @@ typedef enum {
     EAC3_FRAME_TYPE_RESERVED
 } EAC3FrameType;
 
+/**
+ * Encoding Options used by AVOption.
+ */
+typedef struct AC3EncOptions {
+    /* AC-3 metadata options*/
+    int dialogue_level;
+    int bitstream_mode;
+    float center_mix_level;
+    float surround_mix_level;
+    int dolby_surround_mode;
+    int audio_production_info;
+    int mixing_level;
+    int room_type;
+    int copyright;
+    int original;
+    int extended_bsi_1;
+    int preferred_stereo_downmix;
+    float ltrt_center_mix_level;
+    float ltrt_surround_mix_level;
+    float loro_center_mix_level;
+    float loro_surround_mix_level;
+    int extended_bsi_2;
+    int dolby_surround_ex_mode;
+    int dolby_headphone_mode;
+    int ad_converter_type;
+
+    /* other encoding options */
+    int allow_per_frame_metadata;
+} AC3EncOptions;
+
+
 void ff_ac3_common_init(void);
 
+extern const int64_t ff_ac3_channel_layouts[];
+extern const AVOption ff_ac3_options[];
+
+extern AVCodec ff_ac3_float_encoder;
+extern AVCodec ff_ac3_fixed_encoder;
+
 /**
  * Calculate the log power-spectral density of the input signal.
  * This gives a rough estimate of signal power in the frequency domain by using
index 1c353b6..77ebcdc 100644 (file)
@@ -75,36 +75,6 @@ typedef struct AC3MDCTContext {
     FFTContext fft;                     ///< FFT context for MDCT calculation
 } AC3MDCTContext;
 
-/**
- * Encoding Options used by AVOption.
- */
-typedef struct AC3EncOptions {
-    /* AC-3 metadata options*/
-    int dialogue_level;
-    int bitstream_mode;
-    float center_mix_level;
-    float surround_mix_level;
-    int dolby_surround_mode;
-    int audio_production_info;
-    int mixing_level;
-    int room_type;
-    int copyright;
-    int original;
-    int extended_bsi_1;
-    int preferred_stereo_downmix;
-    float ltrt_center_mix_level;
-    float ltrt_surround_mix_level;
-    float loro_center_mix_level;
-    float loro_surround_mix_level;
-    int extended_bsi_2;
-    int dolby_surround_ex_mode;
-    int dolby_headphone_mode;
-    int ad_converter_type;
-
-    /* other encoding options */
-    int allow_per_frame_metadata;
-} AC3EncOptions;
-
 /**
  * Data for a single audio block.
  */
@@ -229,7 +199,8 @@ static const float extmixlev_options[EXTMIXLEV_NUM_OPTIONS] = {
 #define OFFSET(param) offsetof(AC3EncodeContext, options.param)
 #define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
 
-static const AVOption options[] = {
+#if CONFIG_AC3ENC_FLOAT || !CONFIG_AC3_FLOAT_ENCODER //we need this exactly once compiled in
+const AVOption ff_ac3_options[] = {
 /* Metadata Options */
 {"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), FF_OPT_TYPE_INT, 0, 0, 1, AC3ENC_PARAM},
 /* downmix levels */
@@ -271,13 +242,14 @@ static const AVOption options[] = {
     {"hdcd",     "HDCD",               0, FF_OPT_TYPE_CONST, 1, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
 {NULL}
 };
+#endif
 
 #if CONFIG_AC3ENC_FLOAT
 static AVClass ac3enc_class = { "AC-3 Encoder", av_default_item_name,
-                                options, LIBAVUTIL_VERSION_INT };
+                                ff_ac3_options, LIBAVUTIL_VERSION_INT };
 #else
 static AVClass ac3enc_class = { "Fixed-Point AC-3 Encoder", av_default_item_name,
-                                options, LIBAVUTIL_VERSION_INT };
+                                ff_ac3_options, LIBAVUTIL_VERSION_INT };
 #endif
 
 
@@ -306,7 +278,8 @@ static uint8_t exponent_group_tab[3][256];
 /**
  * List of supported channel layouts.
  */
-static const int64_t ac3_channel_layouts[] = {
+#if CONFIG_AC3ENC_FLOAT || !CONFIG_AC3_FLOAT_ENCODER //we need this exactly once compiled in
+const int64_t ff_ac3_channel_layouts[] = {
      AV_CH_LAYOUT_MONO,
      AV_CH_LAYOUT_STEREO,
      AV_CH_LAYOUT_2_1,
@@ -327,6 +300,7 @@ static const int64_t ac3_channel_layouts[] = {
      AV_CH_LAYOUT_5POINT1_BACK,
      0
 };
+#endif
 
 
 /**
diff --git a/libavcodec/ac3enc_combined.c b/libavcodec/ac3enc_combined.c
new file mode 100644 (file)
index 0000000..3d6b3d9
--- /dev/null
@@ -0,0 +1,90 @@
+
+#include "libavutil/opt.h"
+#include "libavutil/samplefmt.h"
+#include "avcodec.h"
+#include "ac3.h"
+
+typedef struct CombineContext{
+    AVClass *av_class;                      ///< AVClass used for AVOption
+    AC3EncOptions options;                  ///< encoding options
+    void *ctx;
+    AVCodec *codec;
+}CombineContext;
+
+static AVClass ac3enc_class = { "AC-3 Encoder", av_default_item_name,
+                                ff_ac3_options, LIBAVUTIL_VERSION_INT };
+
+static av_cold AVCodec *get_codec(enum AVSampleFormat s){
+#if CONFIG_AC3_FIXED_ENCODER
+    if(s==AV_SAMPLE_FMT_S16) return &ff_ac3_fixed_encoder;
+#endif
+#if CONFIG_AC3_FLOAT_ENCODER
+    if(s==AV_SAMPLE_FMT_FLT) return &ff_ac3_float_encoder;
+#endif
+    return NULL;
+}
+
+
+static av_cold int encode_init(AVCodecContext *avctx)
+{
+    CombineContext *c= avctx->priv_data;
+    int ret;
+    int offset= (uint8_t*)&c->options - (uint8_t*)c;
+
+    c->codec= get_codec(avctx->sample_fmt);
+    if(!c->codec){
+        av_log(avctx, AV_LOG_ERROR, "Unsupported sample format\n");
+        return -1;
+    }
+    c->ctx= av_mallocz(c->codec->priv_data_size);
+    memcpy((uint8_t*)c->ctx + offset, &c->options, (uint8_t*)&c->ctx - (uint8_t*)&c->options);
+    FFSWAP(void *,avctx->priv_data, c->ctx);
+    ret= c->codec->init(avctx);
+    FFSWAP(void *,avctx->priv_data, c->ctx);
+    return ret;
+}
+
+static int encode_frame(AVCodecContext *avctx, unsigned char *frame,
+                        int buf_size, void *data)
+{
+    CombineContext *c= avctx->priv_data;
+    int ret;
+
+    FFSWAP(void *,avctx->priv_data, c->ctx);
+    ret= c->codec->encode(avctx, frame, buf_size, data);
+    FFSWAP(void *,avctx->priv_data, c->ctx);
+    return ret;
+}
+
+static av_cold int encode_close(AVCodecContext *avctx)
+{
+    CombineContext *c= avctx->priv_data;
+    int ret;
+
+    FFSWAP(void *,avctx->priv_data, c->ctx);
+    ret= c->codec->close(avctx);
+    FFSWAP(void *,avctx->priv_data, c->ctx);
+    return ret;
+}
+
+AVCodec ff_ac3_encoder = {
+    "ac3",
+    AVMEDIA_TYPE_AUDIO,
+    CODEC_ID_AC3,
+    sizeof(CombineContext),
+    encode_init,
+    encode_frame,
+    encode_close,
+    NULL,
+    .sample_fmts = (const enum AVSampleFormat[]){
+#if CONFIG_AC3_FLOAT_ENCODER
+        AV_SAMPLE_FMT_FLT,
+#endif
+#if CONFIG_AC3_FIXED_ENCODER
+        AV_SAMPLE_FMT_S16,
+#endif
+        AV_SAMPLE_FMT_NONE},
+    .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
+    .priv_class = &ac3enc_class,
+    .channel_layouts = ff_ac3_channel_layouts,
+};
index 4d8b756..462e658 100644 (file)
@@ -121,5 +121,5 @@ AVCodec ff_ac3_fixed_encoder = {
     .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
     .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
     .priv_class = &ac3enc_class,
-    .channel_layouts = ac3_channel_layouts,
+    .channel_layouts = ff_ac3_channel_layouts,
 };
index d898805..1a145e5 100644 (file)
@@ -98,8 +98,8 @@ static void scale_coefficients(AC3EncodeContext *s)
 }
 
 
-AVCodec ff_ac3_encoder = {
-    "ac3",
+AVCodec ff_ac3_float_encoder = {
+    "ac3_float",
     AVMEDIA_TYPE_AUDIO,
     CODEC_ID_AC3,
     sizeof(AC3EncodeContext),
@@ -110,5 +110,5 @@ AVCodec ff_ac3_encoder = {
     .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_FLT,AV_SAMPLE_FMT_NONE},
     .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
     .priv_class = &ac3enc_class,
-    .channel_layouts = ac3_channel_layouts,
+    .channel_layouts = ff_ac3_channel_layouts,
 };
index 8f53e25..56fa628 100644 (file)
@@ -234,7 +234,8 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC  (AAC, aac);
     REGISTER_DECODER (AAC_LATM, aac_latm);
     REGISTER_ENCDEC  (AC3, ac3);
-    REGISTER_ENCODER (AC3_FIXED, ac3_fixed);
+    REGISTER_ENCODER (AC3_FIXED, ac3_fixed); //deprecated, just for libav compatibility
+//    REGISTER_ENCODER (AC3_FLOAT, ac3_float); dont remove dont outcomment, for configure
     REGISTER_ENCDEC  (ALAC, alac);
     REGISTER_DECODER (ALS, als);
     REGISTER_DECODER (AMRNB, amrnb);