Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Interface to libtwolame for mp2 encoding
  3.  * Copyright (c) 2012 Paul B Mahol
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  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.
  11.  *
  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.
  16.  *
  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
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * Interface to libtwolame for mp2 encoding.
  25.  */
  26.  
  27. #include <twolame.h>
  28.  
  29. #include "libavutil/common.h"
  30. #include "libavutil/opt.h"
  31.  
  32. #include "avcodec.h"
  33. #include "internal.h"
  34. #include "mpegaudio.h"
  35.  
  36. typedef struct TWOLAMEContext {
  37.     AVClass *class;
  38.     int mode;
  39.     int psymodel;
  40.     int energy;
  41.     int error_protection;
  42.     int copyright;
  43.     int original;
  44.     int verbosity;
  45.  
  46.     twolame_options *glopts;
  47.     int64_t next_pts;
  48. } TWOLAMEContext;
  49.  
  50. static av_cold int twolame_encode_close(AVCodecContext *avctx)
  51. {
  52.     TWOLAMEContext *s = avctx->priv_data;
  53.     twolame_close(&s->glopts);
  54.     return 0;
  55. }
  56.  
  57. static av_cold int twolame_encode_init(AVCodecContext *avctx)
  58. {
  59.     TWOLAMEContext *s = avctx->priv_data;
  60.     int ret;
  61.  
  62.     avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME;
  63.     avctx->initial_padding = 512 - 32 + 1;
  64.  
  65.     s->glopts = twolame_init();
  66.     if (!s->glopts)
  67.         return AVERROR(ENOMEM);
  68.  
  69.     twolame_set_verbosity(s->glopts, s->verbosity);
  70.     twolame_set_mode(s->glopts, s->mode);
  71.     twolame_set_psymodel(s->glopts, s->psymodel);
  72.     twolame_set_energy_levels(s->glopts, s->energy);
  73.     twolame_set_error_protection(s->glopts, s->error_protection);
  74.     twolame_set_copyright(s->glopts, s->copyright);
  75.     twolame_set_original(s->glopts, s->original);
  76.  
  77.     twolame_set_num_channels(s->glopts, avctx->channels);
  78.     twolame_set_in_samplerate(s->glopts, avctx->sample_rate);
  79.     twolame_set_out_samplerate(s->glopts, avctx->sample_rate);
  80.  
  81.     if (!avctx->bit_rate)
  82.         avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000;
  83.  
  84.     if (avctx->flags & AV_CODEC_FLAG_QSCALE || !avctx->bit_rate) {
  85.         twolame_set_VBR(s->glopts, TRUE);
  86.         twolame_set_VBR_level(s->glopts,
  87.                               avctx->global_quality / (float) FF_QP2LAMBDA);
  88.         av_log(avctx, AV_LOG_WARNING,
  89.                "VBR in MP2 is a hack, use another codec that supports it.\n");
  90.     } else {
  91.         twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000);
  92.     }
  93.  
  94.     ret = twolame_init_params(s->glopts);
  95.     if (ret) {
  96.         twolame_encode_close(avctx);
  97.         return AVERROR_UNKNOWN;
  98.     }
  99.  
  100.     return 0;
  101. }
  102.  
  103. static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
  104.                                 const AVFrame *frame, int *got_packet_ptr)
  105. {
  106.     TWOLAMEContext *s = avctx->priv_data;
  107.     int ret;
  108.  
  109.     if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE, 0)) < 0)
  110.         return ret;
  111.  
  112.     if (frame) {
  113.         switch (avctx->sample_fmt) {
  114.         case AV_SAMPLE_FMT_FLT:
  115.             ret = twolame_encode_buffer_float32_interleaved(s->glopts,
  116.                                                             (const float *)frame->data[0],
  117.                                                             frame->nb_samples,
  118.                                                             avpkt->data,
  119.                                                             avpkt->size);
  120.             break;
  121.         case AV_SAMPLE_FMT_FLTP:
  122.             ret = twolame_encode_buffer_float32(s->glopts,
  123.                                                 (const float *)frame->data[0],
  124.                                                 (const float *)frame->data[1],
  125.                                                 frame->nb_samples,
  126.                                                 avpkt->data, avpkt->size);
  127.             break;
  128.         case AV_SAMPLE_FMT_S16:
  129.             ret = twolame_encode_buffer_interleaved(s->glopts,
  130.                                                     (const short int *)frame->data[0],
  131.                                                     frame->nb_samples,
  132.                                                     avpkt->data, avpkt->size);
  133.             break;
  134.         case AV_SAMPLE_FMT_S16P:
  135.             ret = twolame_encode_buffer(s->glopts,
  136.                                         (const short int *)frame->data[0],
  137.                                         (const short int *)frame->data[1],
  138.                                         frame->nb_samples,
  139.                                         avpkt->data, avpkt->size);
  140.             break;
  141.         default:
  142.             av_log(avctx, AV_LOG_ERROR,
  143.                    "Unsupported sample format %d.\n", avctx->sample_fmt);
  144.             return AVERROR_BUG;
  145.         }
  146.     } else {
  147.         ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size);
  148.     }
  149.  
  150.     if (!ret)     // no bytes written
  151.         return 0;
  152.     if (ret < 0)  // twolame error
  153.         return AVERROR_UNKNOWN;
  154.  
  155.     if (frame) {
  156.         avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples);
  157.         if (frame->pts != AV_NOPTS_VALUE)
  158.             avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding);
  159.     } else {
  160.         avpkt->pts = s->next_pts;
  161.     }
  162.     // this is for setting pts for flushed packet(s).
  163.     if (avpkt->pts != AV_NOPTS_VALUE)
  164.         s->next_pts = avpkt->pts + avpkt->duration;
  165.  
  166.     av_shrink_packet(avpkt, ret);
  167.     *got_packet_ptr = 1;
  168.     return 0;
  169. }
  170.  
  171. #define OFFSET(x) offsetof(TWOLAMEContext, x)
  172. #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  173. static const AVOption options[] = {
  174.     { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"},
  175.         { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" },
  176.         { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO }, 0, 0, AE, "mode" },
  177.         { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" },
  178.         { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" },
  179.         { "mono", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO }, 0, 0, AE, "mode" },
  180.     { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE},
  181.     { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { .i64 = 0 },  0, 1, AE},
  182.     { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { .i64 = 0 },  0, 1, AE},
  183.     { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
  184.     { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE},
  185.     { "verbosity", "set library optput level (0-10)", OFFSET(verbosity), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 10, AE},
  186.     { NULL },
  187. };
  188.  
  189. static const AVClass twolame_class = {
  190.     .class_name = "libtwolame encoder",
  191.     .item_name  = av_default_item_name,
  192.     .option     = options,
  193.     .version    = LIBAVUTIL_VERSION_INT,
  194. };
  195.  
  196. static const AVCodecDefault twolame_defaults[] = {
  197.     { "b", "0" },
  198.     { NULL },
  199. };
  200.  
  201. static const int twolame_samplerates[] = {
  202.     16000, 22050, 24000, 32000, 44100, 48000, 0
  203. };
  204.  
  205. AVCodec ff_libtwolame_encoder = {
  206.     .name           = "libtwolame",
  207.     .long_name      = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"),
  208.     .type           = AVMEDIA_TYPE_AUDIO,
  209.     .id             = AV_CODEC_ID_MP2,
  210.     .priv_data_size = sizeof(TWOLAMEContext),
  211.     .init           = twolame_encode_init,
  212.     .encode2        = twolame_encode_frame,
  213.     .close          = twolame_encode_close,
  214.     .capabilities   = AV_CODEC_CAP_DELAY,
  215.     .defaults       = twolame_defaults,
  216.     .priv_class     = &twolame_class,
  217.     .sample_fmts    = (const enum AVSampleFormat[]) {
  218.         AV_SAMPLE_FMT_FLT,
  219.         AV_SAMPLE_FMT_FLTP,
  220.         AV_SAMPLE_FMT_S16,
  221.         AV_SAMPLE_FMT_S16P,
  222.         AV_SAMPLE_FMT_NONE
  223.     },
  224.     .channel_layouts = (const uint64_t[]) {
  225.         AV_CH_LAYOUT_MONO,
  226.         AV_CH_LAYOUT_STEREO,
  227.         0 },
  228.     .supported_samplerates = twolame_samplerates,
  229. };
  230.