2 * Interface to libtwolame for mp2 encoding
3 * Copyright (c) 2012 Paul B Mahol
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Interface to libtwolame for mp2 encoding.
29 #include "libavutil/channel_layout.h"
30 #include "libavutil/common.h"
31 #include "libavutil/opt.h"
34 #include "codec_internal.h"
36 #include "mpegaudio.h"
38 typedef struct TWOLAMEContext
{
48 twolame_options
*glopts
;
52 static av_cold
int twolame_encode_close(AVCodecContext
*avctx
)
54 TWOLAMEContext
*s
= avctx
->priv_data
;
55 twolame_close(&s
->glopts
);
59 static av_cold
int twolame_encode_init(AVCodecContext
*avctx
)
61 TWOLAMEContext
*s
= avctx
->priv_data
;
64 avctx
->frame_size
= TWOLAME_SAMPLES_PER_FRAME
;
65 avctx
->initial_padding
= 512 - 32 + 1;
67 s
->glopts
= twolame_init();
69 return AVERROR(ENOMEM
);
71 twolame_set_verbosity(s
->glopts
, s
->verbosity
);
72 twolame_set_mode(s
->glopts
, s
->mode
);
73 twolame_set_psymodel(s
->glopts
, s
->psymodel
);
74 twolame_set_energy_levels(s
->glopts
, s
->energy
);
75 twolame_set_error_protection(s
->glopts
, s
->error_protection
);
76 twolame_set_copyright(s
->glopts
, s
->copyright
);
77 twolame_set_original(s
->glopts
, s
->original
);
79 twolame_set_num_channels(s
->glopts
, avctx
->ch_layout
.nb_channels
);
80 twolame_set_in_samplerate(s
->glopts
, avctx
->sample_rate
);
81 twolame_set_out_samplerate(s
->glopts
, avctx
->sample_rate
);
83 if (!avctx
->bit_rate
) {
84 if ((s
->mode
== TWOLAME_AUTO_MODE
&& avctx
->ch_layout
.nb_channels
== 1) || s
->mode
== TWOLAME_MONO
)
85 avctx
->bit_rate
= avctx
->sample_rate
< 28000 ? 80000 : 192000;
87 avctx
->bit_rate
= avctx
->sample_rate
< 28000 ? 160000 : 384000;
90 if (avctx
->flags
& AV_CODEC_FLAG_QSCALE
|| !avctx
->bit_rate
) {
91 twolame_set_VBR(s
->glopts
, TRUE
);
92 twolame_set_VBR_level(s
->glopts
,
93 avctx
->global_quality
/ (float) FF_QP2LAMBDA
);
94 av_log(avctx
, AV_LOG_WARNING
,
95 "VBR in MP2 is a hack, use another codec that supports it.\n");
97 twolame_set_bitrate(s
->glopts
, avctx
->bit_rate
/ 1000);
100 ret
= twolame_init_params(s
->glopts
);
102 twolame_encode_close(avctx
);
103 return AVERROR_UNKNOWN
;
109 static int twolame_encode_frame(AVCodecContext
*avctx
, AVPacket
*avpkt
,
110 const AVFrame
*frame
, int *got_packet_ptr
)
112 TWOLAMEContext
*s
= avctx
->priv_data
;
115 if ((ret
= ff_alloc_packet(avctx
, avpkt
, MPA_MAX_CODED_FRAME_SIZE
)) < 0)
119 switch (avctx
->sample_fmt
) {
120 case AV_SAMPLE_FMT_FLT
:
121 ret
= twolame_encode_buffer_float32_interleaved(s
->glopts
,
122 (const float *)frame
->data
[0],
127 case AV_SAMPLE_FMT_FLTP
:
128 ret
= twolame_encode_buffer_float32(s
->glopts
,
129 (const float *)frame
->data
[0],
130 (const float *)frame
->data
[1],
132 avpkt
->data
, avpkt
->size
);
134 case AV_SAMPLE_FMT_S16
:
135 ret
= twolame_encode_buffer_interleaved(s
->glopts
,
136 (const short int *)frame
->data
[0],
138 avpkt
->data
, avpkt
->size
);
140 case AV_SAMPLE_FMT_S16P
:
141 ret
= twolame_encode_buffer(s
->glopts
,
142 (const short int *)frame
->data
[0],
143 (const short int *)frame
->data
[1],
145 avpkt
->data
, avpkt
->size
);
148 av_log(avctx
, AV_LOG_ERROR
,
149 "Unsupported sample format %d.\n", avctx
->sample_fmt
);
153 ret
= twolame_encode_flush(s
->glopts
, avpkt
->data
, avpkt
->size
);
156 if (!ret
) // no bytes written
158 if (ret
< 0) // twolame error
159 return AVERROR_UNKNOWN
;
162 avpkt
->duration
= ff_samples_to_time_base(avctx
, frame
->nb_samples
);
163 if (frame
->pts
!= AV_NOPTS_VALUE
)
164 avpkt
->pts
= frame
->pts
- ff_samples_to_time_base(avctx
, avctx
->initial_padding
);
166 avpkt
->pts
= s
->next_pts
;
168 // this is for setting pts for flushed packet(s).
169 if (avpkt
->pts
!= AV_NOPTS_VALUE
)
170 s
->next_pts
= avpkt
->pts
+ avpkt
->duration
;
172 av_shrink_packet(avpkt
, ret
);
177 #define OFFSET(x) offsetof(TWOLAMEContext, x)
178 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
179 static const AVOption options
[] = {
180 { "mode", "Mpeg Mode", OFFSET(mode
), AV_OPT_TYPE_INT
, { .i64
= TWOLAME_AUTO_MODE
}, TWOLAME_AUTO_MODE
, TWOLAME_MONO
, AE
, .unit
= "mode"},
181 { "auto", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= TWOLAME_AUTO_MODE
}, 0, 0, AE
, .unit
= "mode" },
182 { "stereo", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= TWOLAME_STEREO
}, 0, 0, AE
, .unit
= "mode" },
183 { "joint_stereo", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= TWOLAME_JOINT_STEREO
}, 0, 0, AE
, .unit
= "mode" },
184 { "dual_channel", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= TWOLAME_DUAL_CHANNEL
}, 0, 0, AE
, .unit
= "mode" },
185 { "mono", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= TWOLAME_MONO
}, 0, 0, AE
, .unit
= "mode" },
186 { "psymodel", "Psychoacoustic Model", OFFSET(psymodel
), AV_OPT_TYPE_INT
, { .i64
= 3 }, -1, 4, AE
},
187 { "energy_levels","enable energy levels", OFFSET(energy
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, AE
},
188 { "error_protection","enable CRC error protection", OFFSET(error_protection
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, AE
},
189 { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, AE
},
190 { "original", "set MPEG Audio Original flag", OFFSET(original
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, AE
},
191 { "verbosity", "set library optput level (0-10)", OFFSET(verbosity
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 10, AE
},
195 static const AVClass twolame_class
= {
196 .class_name
= "libtwolame encoder",
197 .item_name
= av_default_item_name
,
199 .version
= LIBAVUTIL_VERSION_INT
,
202 static const FFCodecDefault twolame_defaults
[] = {
207 static const int twolame_samplerates
[] = {
208 16000, 22050, 24000, 32000, 44100, 48000, 0
211 const FFCodec ff_libtwolame_encoder
= {
212 .p
.name
= "libtwolame",
213 CODEC_LONG_NAME("libtwolame MP2 (MPEG audio layer 2)"),
214 .p
.type
= AVMEDIA_TYPE_AUDIO
,
215 .p
.id
= AV_CODEC_ID_MP2
,
216 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_DELAY
,
217 .caps_internal
= FF_CODEC_CAP_NOT_INIT_THREADSAFE
,
218 .priv_data_size
= sizeof(TWOLAMEContext
),
219 .init
= twolame_encode_init
,
220 FF_CODEC_ENCODE_CB(twolame_encode_frame
),
221 .close
= twolame_encode_close
,
222 .defaults
= twolame_defaults
,
223 .p
.priv_class
= &twolame_class
,
224 .p
.sample_fmts
= (const enum AVSampleFormat
[]) {
231 .p
.ch_layouts
= (const AVChannelLayout
[]) {
232 AV_CHANNEL_LAYOUT_MONO
,
233 AV_CHANNEL_LAYOUT_STEREO
,
236 .p
.supported_samplerates
= twolame_samplerates
,
237 .p
.wrapper_name
= "libtwolame",