00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include <twolame.h>
00028
00029 #include "libavutil/opt.h"
00030 #include "avcodec.h"
00031 #include "internal.h"
00032 #include "mpegaudio.h"
00033
00034 typedef struct TWOLAMEContext {
00035 AVClass *class;
00036 int mode;
00037 int psymodel;
00038 int energy;
00039 int error_protection;
00040 int copyright;
00041 int original;
00042
00043 twolame_options *glopts;
00044 int64_t next_pts;
00045 } TWOLAMEContext;
00046
00047 static av_cold int twolame_encode_close(AVCodecContext *avctx)
00048 {
00049 TWOLAMEContext *s = avctx->priv_data;
00050 twolame_close(&s->glopts);
00051 return 0;
00052 }
00053
00054 static av_cold int twolame_encode_init(AVCodecContext *avctx)
00055 {
00056 TWOLAMEContext *s = avctx->priv_data;
00057 int ret;
00058
00059 avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME;
00060
00061 s->glopts = twolame_init();
00062 if (!s->glopts)
00063 return AVERROR(ENOMEM);
00064
00065 twolame_set_verbosity(s->glopts, 0);
00066 twolame_set_mode(s->glopts, s->mode);
00067 twolame_set_psymodel(s->glopts, s->psymodel);
00068 twolame_set_energy_levels(s->glopts, s->energy);
00069 twolame_set_error_protection(s->glopts, s->error_protection);
00070
00071 twolame_set_num_channels(s->glopts, avctx->channels);
00072 twolame_set_in_samplerate(s->glopts, avctx->sample_rate);
00073 twolame_set_out_samplerate(s->glopts, avctx->sample_rate);
00074 if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) {
00075 twolame_set_VBR(s->glopts, TRUE);
00076 twolame_set_VBR_level(s->glopts, avctx->global_quality);
00077 av_log(avctx, AV_LOG_WARNING, "VBR mode is experimental!\n");
00078 } else {
00079 twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000);
00080 }
00081
00082 if ((ret = twolame_init_params(s->glopts)))
00083 goto error;
00084
00085 return 0;
00086 error:
00087 twolame_encode_close(avctx);
00088 return ret;
00089 }
00090
00091 static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
00092 const AVFrame *frame, int *got_packet_ptr)
00093 {
00094 TWOLAMEContext *s = avctx->priv_data;
00095 int ret;
00096
00097 if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE)))
00098 return ret;
00099
00100 if (frame) {
00101 switch (avctx->sample_fmt) {
00102 case AV_SAMPLE_FMT_FLT:
00103 ret = twolame_encode_buffer_float32_interleaved(s->glopts,
00104 frame->data[0],
00105 frame->nb_samples,
00106 avpkt->data, avpkt->size);
00107 break;
00108 case AV_SAMPLE_FMT_FLTP:
00109 ret = twolame_encode_buffer_float32(s->glopts,
00110 frame->data[0], frame->data[1],
00111 frame->nb_samples,
00112 avpkt->data, avpkt->size);
00113 break;
00114 case AV_SAMPLE_FMT_S16:
00115 ret = twolame_encode_buffer_interleaved(s->glopts,
00116 frame->data[0],
00117 frame->nb_samples,
00118 avpkt->data, avpkt->size);
00119 break;
00120 case AV_SAMPLE_FMT_S16P:
00121 ret = twolame_encode_buffer(s->glopts,
00122 frame->data[0], frame->data[1],
00123 frame->nb_samples,
00124 avpkt->data, avpkt->size);
00125 break;
00126 default:
00127 return AVERROR_BUG;
00128 }
00129 } else {
00130 ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size);
00131 }
00132
00133 if (ret > 0) {
00134 avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size);
00135 if (frame) {
00136 if (frame->pts != AV_NOPTS_VALUE)
00137 avpkt->pts = frame->pts;
00138 } else {
00139 avpkt->pts = s->next_pts;
00140 }
00141 if (avpkt->pts != AV_NOPTS_VALUE)
00142 s->next_pts = avpkt->pts + avpkt->duration;
00143
00144 avpkt->size = ret;
00145 *got_packet_ptr = 1;
00146 return 0;
00147 }
00148
00149 return ret;
00150 }
00151
00152 #define OFFSET(x) offsetof(TWOLAMEContext, x)
00153 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
00154 static const AVOption options[] = {
00155 { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"},
00156 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" },
00157 { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO }, 0, 0, AE, "mode" },
00158 { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" },
00159 { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" },
00160 { "mono", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO }, 0, 0, AE, "mode" },
00161 { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE},
00162 { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
00163 { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
00164 { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
00165 { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
00166 { NULL },
00167 };
00168
00169 static const AVClass libtwolame_class = {
00170 .class_name = "libtwolame encoder",
00171 .item_name = av_default_item_name,
00172 .option = options,
00173 .version = LIBAVUTIL_VERSION_INT,
00174 };
00175
00176 AVCodec ff_libtwolame_encoder = {
00177 .name = "libtwolame",
00178 .type = AVMEDIA_TYPE_AUDIO,
00179 .id = AV_CODEC_ID_MP2,
00180 .priv_data_size = sizeof(TWOLAMEContext),
00181 .init = twolame_encode_init,
00182 .encode2 = twolame_encode_frame,
00183 .close = twolame_encode_close,
00184 .capabilities = CODEC_CAP_DELAY,
00185 .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
00186 AV_SAMPLE_FMT_FLTP,
00187 AV_SAMPLE_FMT_S16,
00188 AV_SAMPLE_FMT_S16P,
00189 AV_SAMPLE_FMT_NONE },
00190 .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
00191 AV_CH_LAYOUT_STEREO,
00192 0 },
00193 .supported_samplerates = (const int[]){ 16000, 22050, 24000, 32000, 44100, 48000, 0 },
00194 .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"),
00195 .priv_class = &libtwolame_class,
00196 };