diff options
author | Paul B Mahol <onemda@gmail.com> | 2012-08-01 14:33:34 +0000 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2012-08-05 17:06:59 +0000 |
commit | f5f98727b361c62d3962cef37a100db95d62b702 (patch) | |
tree | e4c51281d6506c23e2abadc5d1d1b9e4cb6fda69 /libavcodec/libtwolame.c | |
parent | fe40dc1cecdf152ffacff6df1d9c5f0c7daced85 (diff) | |
download | ffmpeg-f5f98727b361c62d3962cef37a100db95d62b702.tar.gz |
libtwolame MP2 encoding support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavcodec/libtwolame.c')
-rw-r--r-- | libavcodec/libtwolame.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c new file mode 100644 index 0000000000..72344510fa --- /dev/null +++ b/libavcodec/libtwolame.c @@ -0,0 +1,196 @@ +/* + * Interface to libtwolame for mp2 encoding + * Copyright (c) 2012 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Interface to libtwolame for mp2 encoding. + */ + +#include <twolame.h> + +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "mpegaudio.h" + +typedef struct TWOLAMEContext { + AVClass *class; + int mode; + int psymodel; + int energy; + int error_protection; + int copyright; + int original; + + twolame_options *glopts; + int64_t next_pts; +} TWOLAMEContext; + +static av_cold int twolame_encode_close(AVCodecContext *avctx) +{ + TWOLAMEContext *s = avctx->priv_data; + twolame_close(&s->glopts); + return 0; +} + +static av_cold int twolame_encode_init(AVCodecContext *avctx) +{ + TWOLAMEContext *s = avctx->priv_data; + int ret; + + avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME; + + s->glopts = twolame_init(); + if (!s->glopts) + return AVERROR(ENOMEM); + + twolame_set_verbosity(s->glopts, 0); + twolame_set_mode(s->glopts, s->mode); + twolame_set_psymodel(s->glopts, s->psymodel); + twolame_set_energy_levels(s->glopts, s->energy); + twolame_set_error_protection(s->glopts, s->error_protection); + + twolame_set_num_channels(s->glopts, avctx->channels); + twolame_set_in_samplerate(s->glopts, avctx->sample_rate); + twolame_set_out_samplerate(s->glopts, avctx->sample_rate); + if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) { + twolame_set_VBR(s->glopts, TRUE); + twolame_set_VBR_level(s->glopts, avctx->global_quality); + av_log(avctx, AV_LOG_WARNING, "VBR mode is experimental!\n"); + } else { + twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000); + } + + if ((ret = twolame_init_params(s->glopts))) + goto error; + + return 0; +error: + twolame_encode_close(avctx); + return ret; +} + +static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + TWOLAMEContext *s = avctx->priv_data; + int ret; + + if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE))) + return ret; + + if (frame) { + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_FLT: + ret = twolame_encode_buffer_float32_interleaved(s->glopts, + frame->data[0], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + case AV_SAMPLE_FMT_FLTP: + ret = twolame_encode_buffer_float32(s->glopts, + frame->data[0], frame->data[1], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + case AV_SAMPLE_FMT_S16: + ret = twolame_encode_buffer_interleaved(s->glopts, + frame->data[0], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + case AV_SAMPLE_FMT_S16P: + ret = twolame_encode_buffer(s->glopts, + frame->data[0], frame->data[1], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + default: + return AVERROR_BUG; + } + } else { + ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size); + } + + if (ret > 0) { + avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size); + if (frame) { + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts; + } else { + avpkt->pts = s->next_pts; + } + if (avpkt->pts != AV_NOPTS_VALUE) + s->next_pts = avpkt->pts + avpkt->duration; + + avpkt->size = ret; + *got_packet_ptr = 1; + return 0; + } + + return ret; +} + +#define OFFSET(x) offsetof(TWOLAMEContext, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"}, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" }, + { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { TWOLAME_STEREO }, 0, 0, AE, "mode" }, + { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" }, + { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" }, + { "mono", NULL, 0, AV_OPT_TYPE_CONST, { TWOLAME_MONO }, 0, 0, AE, "mode" }, + { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { 3 }, -1, 4, AE}, + { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { 0 }, 0, 1, AE}, + { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { 0 }, 0, 1, AE}, + { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { 0 }, 0, 1, AE}, + { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { 0 }, 0, 1, AE}, + { NULL }, +}; + +static const AVClass libtwolame_class = { + .class_name = "libtwolame encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libtwolame_encoder = { + .name = "libtwolame", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_MP3, + .priv_data_size = sizeof(TWOLAMEContext), + .init = twolame_encode_init, + .encode2 = twolame_encode_frame, + .close = twolame_encode_close, + .capabilities = CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + 0 }, + .supported_samplerates = (const int[]){ 16000, 22050, 24000, 32000, 44100, 48000, 0 }, + .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"), + .priv_class = &libtwolame_class, +}; |