]> git.sesse.net Git - ffmpeg/blob - libavcodec/ac3enc_combined.c
Correctly implement ac3 float/fixed encoder.
[ffmpeg] / libavcodec / ac3enc_combined.c
1
2 #include "libavutil/opt.h"
3 #include "libavutil/samplefmt.h"
4 #include "avcodec.h"
5 #include "ac3.h"
6
7 typedef struct CombineContext{
8     AVClass *av_class;                      ///< AVClass used for AVOption
9     AC3EncOptions options;                  ///< encoding options
10     void *ctx;
11     AVCodec *codec;
12 }CombineContext;
13
14 static AVClass ac3enc_class = { "AC-3 Encoder", av_default_item_name,
15                                 ff_ac3_options, LIBAVUTIL_VERSION_INT };
16
17 static av_cold AVCodec *get_codec(enum AVSampleFormat s){
18 #if CONFIG_AC3_FIXED_ENCODER
19     if(s==AV_SAMPLE_FMT_S16) return &ff_ac3_fixed_encoder;
20 #endif
21 #if CONFIG_AC3_FLOAT_ENCODER
22     if(s==AV_SAMPLE_FMT_FLT) return &ff_ac3_float_encoder;
23 #endif
24     return NULL;
25 }
26
27
28 static av_cold int encode_init(AVCodecContext *avctx)
29 {
30     CombineContext *c= avctx->priv_data;
31     int ret;
32     int offset= (uint8_t*)&c->options - (uint8_t*)c;
33
34     c->codec= get_codec(avctx->sample_fmt);
35     if(!c->codec){
36         av_log(avctx, AV_LOG_ERROR, "Unsupported sample format\n");
37         return -1;
38     }
39     c->ctx= av_mallocz(c->codec->priv_data_size);
40     memcpy((uint8_t*)c->ctx + offset, &c->options, (uint8_t*)&c->ctx - (uint8_t*)&c->options);
41     FFSWAP(void *,avctx->priv_data, c->ctx);
42     ret= c->codec->init(avctx);
43     FFSWAP(void *,avctx->priv_data, c->ctx);
44     return ret;
45 }
46
47 static int encode_frame(AVCodecContext *avctx, unsigned char *frame,
48                         int buf_size, void *data)
49 {
50     CombineContext *c= avctx->priv_data;
51     int ret;
52
53     FFSWAP(void *,avctx->priv_data, c->ctx);
54     ret= c->codec->encode(avctx, frame, buf_size, data);
55     FFSWAP(void *,avctx->priv_data, c->ctx);
56     return ret;
57 }
58
59 static av_cold int encode_close(AVCodecContext *avctx)
60 {
61     CombineContext *c= avctx->priv_data;
62     int ret;
63
64     FFSWAP(void *,avctx->priv_data, c->ctx);
65     ret= c->codec->close(avctx);
66     FFSWAP(void *,avctx->priv_data, c->ctx);
67     return ret;
68 }
69
70 AVCodec ff_ac3_encoder = {
71     "ac3",
72     AVMEDIA_TYPE_AUDIO,
73     CODEC_ID_AC3,
74     sizeof(CombineContext),
75     encode_init,
76     encode_frame,
77     encode_close,
78     NULL,
79     .sample_fmts = (const enum AVSampleFormat[]){
80 #if CONFIG_AC3_FLOAT_ENCODER
81         AV_SAMPLE_FMT_FLT,
82 #endif
83 #if CONFIG_AC3_FIXED_ENCODER
84         AV_SAMPLE_FMT_S16,
85 #endif
86         AV_SAMPLE_FMT_NONE},
87     .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
88     .priv_class = &ac3enc_class,
89     .channel_layouts = ff_ac3_channel_layouts,
90 };