yading@10
|
1 /*
|
yading@10
|
2 * Interface to libtwolame for mp2 encoding
|
yading@10
|
3 * Copyright (c) 2012 Paul B Mahol
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21
|
yading@10
|
22 /**
|
yading@10
|
23 * @file
|
yading@10
|
24 * Interface to libtwolame for mp2 encoding.
|
yading@10
|
25 */
|
yading@10
|
26
|
yading@10
|
27 #include <twolame.h>
|
yading@10
|
28
|
yading@10
|
29 #include "libavutil/opt.h"
|
yading@10
|
30 #include "avcodec.h"
|
yading@10
|
31 #include "internal.h"
|
yading@10
|
32 #include "mpegaudio.h"
|
yading@10
|
33
|
yading@10
|
34 typedef struct TWOLAMEContext {
|
yading@10
|
35 AVClass *class;
|
yading@10
|
36 int mode;
|
yading@10
|
37 int psymodel;
|
yading@10
|
38 int energy;
|
yading@10
|
39 int error_protection;
|
yading@10
|
40 int copyright;
|
yading@10
|
41 int original;
|
yading@10
|
42
|
yading@10
|
43 twolame_options *glopts;
|
yading@10
|
44 int64_t next_pts;
|
yading@10
|
45 } TWOLAMEContext;
|
yading@10
|
46
|
yading@10
|
47 static av_cold int twolame_encode_close(AVCodecContext *avctx)
|
yading@10
|
48 {
|
yading@10
|
49 TWOLAMEContext *s = avctx->priv_data;
|
yading@10
|
50 twolame_close(&s->glopts);
|
yading@10
|
51 return 0;
|
yading@10
|
52 }
|
yading@10
|
53
|
yading@10
|
54 static av_cold int twolame_encode_init(AVCodecContext *avctx)
|
yading@10
|
55 {
|
yading@10
|
56 TWOLAMEContext *s = avctx->priv_data;
|
yading@10
|
57 int ret;
|
yading@10
|
58
|
yading@10
|
59 avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME;
|
yading@10
|
60
|
yading@10
|
61 s->glopts = twolame_init();
|
yading@10
|
62 if (!s->glopts)
|
yading@10
|
63 return AVERROR(ENOMEM);
|
yading@10
|
64
|
yading@10
|
65 twolame_set_verbosity(s->glopts, 0);
|
yading@10
|
66 twolame_set_mode(s->glopts, s->mode);
|
yading@10
|
67 twolame_set_psymodel(s->glopts, s->psymodel);
|
yading@10
|
68 twolame_set_energy_levels(s->glopts, s->energy);
|
yading@10
|
69 twolame_set_error_protection(s->glopts, s->error_protection);
|
yading@10
|
70
|
yading@10
|
71 twolame_set_num_channels(s->glopts, avctx->channels);
|
yading@10
|
72 twolame_set_in_samplerate(s->glopts, avctx->sample_rate);
|
yading@10
|
73 twolame_set_out_samplerate(s->glopts, avctx->sample_rate);
|
yading@10
|
74 if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) {
|
yading@10
|
75 twolame_set_VBR(s->glopts, TRUE);
|
yading@10
|
76 twolame_set_VBR_level(s->glopts, avctx->global_quality);
|
yading@10
|
77 av_log(avctx, AV_LOG_WARNING, "VBR mode is experimental!\n");
|
yading@10
|
78 } else {
|
yading@10
|
79 twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000);
|
yading@10
|
80 }
|
yading@10
|
81
|
yading@10
|
82 if ((ret = twolame_init_params(s->glopts)))
|
yading@10
|
83 goto error;
|
yading@10
|
84
|
yading@10
|
85 return 0;
|
yading@10
|
86 error:
|
yading@10
|
87 twolame_encode_close(avctx);
|
yading@10
|
88 return ret;
|
yading@10
|
89 }
|
yading@10
|
90
|
yading@10
|
91 static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
yading@10
|
92 const AVFrame *frame, int *got_packet_ptr)
|
yading@10
|
93 {
|
yading@10
|
94 TWOLAMEContext *s = avctx->priv_data;
|
yading@10
|
95 int ret;
|
yading@10
|
96
|
yading@10
|
97 if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE)) < 0)
|
yading@10
|
98 return ret;
|
yading@10
|
99
|
yading@10
|
100 if (frame) {
|
yading@10
|
101 switch (avctx->sample_fmt) {
|
yading@10
|
102 case AV_SAMPLE_FMT_FLT:
|
yading@10
|
103 ret = twolame_encode_buffer_float32_interleaved(s->glopts,
|
yading@10
|
104 frame->data[0],
|
yading@10
|
105 frame->nb_samples,
|
yading@10
|
106 avpkt->data, avpkt->size);
|
yading@10
|
107 break;
|
yading@10
|
108 case AV_SAMPLE_FMT_FLTP:
|
yading@10
|
109 ret = twolame_encode_buffer_float32(s->glopts,
|
yading@10
|
110 frame->data[0], frame->data[1],
|
yading@10
|
111 frame->nb_samples,
|
yading@10
|
112 avpkt->data, avpkt->size);
|
yading@10
|
113 break;
|
yading@10
|
114 case AV_SAMPLE_FMT_S16:
|
yading@10
|
115 ret = twolame_encode_buffer_interleaved(s->glopts,
|
yading@10
|
116 frame->data[0],
|
yading@10
|
117 frame->nb_samples,
|
yading@10
|
118 avpkt->data, avpkt->size);
|
yading@10
|
119 break;
|
yading@10
|
120 case AV_SAMPLE_FMT_S16P:
|
yading@10
|
121 ret = twolame_encode_buffer(s->glopts,
|
yading@10
|
122 frame->data[0], frame->data[1],
|
yading@10
|
123 frame->nb_samples,
|
yading@10
|
124 avpkt->data, avpkt->size);
|
yading@10
|
125 break;
|
yading@10
|
126 default:
|
yading@10
|
127 return AVERROR_BUG;
|
yading@10
|
128 }
|
yading@10
|
129 } else {
|
yading@10
|
130 ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size);
|
yading@10
|
131 }
|
yading@10
|
132
|
yading@10
|
133 if (ret > 0) {
|
yading@10
|
134 avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size);
|
yading@10
|
135 if (frame) {
|
yading@10
|
136 if (frame->pts != AV_NOPTS_VALUE)
|
yading@10
|
137 avpkt->pts = frame->pts;
|
yading@10
|
138 } else {
|
yading@10
|
139 avpkt->pts = s->next_pts;
|
yading@10
|
140 }
|
yading@10
|
141 if (avpkt->pts != AV_NOPTS_VALUE)
|
yading@10
|
142 s->next_pts = avpkt->pts + avpkt->duration;
|
yading@10
|
143
|
yading@10
|
144 avpkt->size = ret;
|
yading@10
|
145 *got_packet_ptr = 1;
|
yading@10
|
146 return 0;
|
yading@10
|
147 }
|
yading@10
|
148
|
yading@10
|
149 return ret;
|
yading@10
|
150 }
|
yading@10
|
151
|
yading@10
|
152 #define OFFSET(x) offsetof(TWOLAMEContext, x)
|
yading@10
|
153 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
yading@10
|
154 static const AVOption options[] = {
|
yading@10
|
155 { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"},
|
yading@10
|
156 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" },
|
yading@10
|
157 { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO }, 0, 0, AE, "mode" },
|
yading@10
|
158 { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" },
|
yading@10
|
159 { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" },
|
yading@10
|
160 { "mono", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO }, 0, 0, AE, "mode" },
|
yading@10
|
161 { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE},
|
yading@10
|
162 { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
|
yading@10
|
163 { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
|
yading@10
|
164 { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
|
yading@10
|
165 { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
|
yading@10
|
166 { NULL },
|
yading@10
|
167 };
|
yading@10
|
168
|
yading@10
|
169 static const AVClass libtwolame_class = {
|
yading@10
|
170 .class_name = "libtwolame encoder",
|
yading@10
|
171 .item_name = av_default_item_name,
|
yading@10
|
172 .option = options,
|
yading@10
|
173 .version = LIBAVUTIL_VERSION_INT,
|
yading@10
|
174 };
|
yading@10
|
175
|
yading@10
|
176 AVCodec ff_libtwolame_encoder = {
|
yading@10
|
177 .name = "libtwolame",
|
yading@10
|
178 .type = AVMEDIA_TYPE_AUDIO,
|
yading@10
|
179 .id = AV_CODEC_ID_MP2,
|
yading@10
|
180 .priv_data_size = sizeof(TWOLAMEContext),
|
yading@10
|
181 .init = twolame_encode_init,
|
yading@10
|
182 .encode2 = twolame_encode_frame,
|
yading@10
|
183 .close = twolame_encode_close,
|
yading@10
|
184 .capabilities = CODEC_CAP_DELAY,
|
yading@10
|
185 .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
|
yading@10
|
186 AV_SAMPLE_FMT_FLTP,
|
yading@10
|
187 AV_SAMPLE_FMT_S16,
|
yading@10
|
188 AV_SAMPLE_FMT_S16P,
|
yading@10
|
189 AV_SAMPLE_FMT_NONE },
|
yading@10
|
190 .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
|
yading@10
|
191 AV_CH_LAYOUT_STEREO,
|
yading@10
|
192 0 },
|
yading@10
|
193 .supported_samplerates = (const int[]){ 16000, 22050, 24000, 32000, 44100, 48000, 0 },
|
yading@10
|
194 .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"),
|
yading@10
|
195 .priv_class = &libtwolame_class,
|
yading@10
|
196 };
|