LCOV - code coverage report
Current view: top level - ext/lame - gstlamemp3enc.c (source / functions) Hit Total Coverage
Test: GStreamer Ugly Plug-ins 0.10.17.1 Lines: 248 359 69.1 %
Date: 2011-03-25 Functions: 18 20 90.0 %
Branches: 77 287 26.8 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
       3                 :            :  * Copyright (C) <2004> Wim Taymans <wim@fluendo.com>
       4                 :            :  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
       5                 :            :  * Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
       6                 :            :  *
       7                 :            :  * This library is free software; you can redistribute it and/or
       8                 :            :  * modify it under the terms of the GNU Library General Public
       9                 :            :  * License as published by the Free Software Foundation; either
      10                 :            :  * version 2 of the License, or (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This library 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                 :            :  * Library General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU Library General Public
      18                 :            :  * License along with this library; if not, write to the
      19                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      20                 :            :  * Boston, MA 02111-1307, USA.
      21                 :            :  */
      22                 :            : 
      23                 :            : /**
      24                 :            :  * SECTION:element-lamemp3enc
      25                 :            :  * @see_also: lame, mad, vorbisenc
      26                 :            :  *
      27                 :            :  * This element encodes raw integer audio into an MPEG-1 layer 3 (MP3) stream.
      28                 :            :  * Note that <ulink url="http://en.wikipedia.org/wiki/MP3">MP3</ulink> is not
      29                 :            :  * a free format, there are licensing and patent issues to take into
      30                 :            :  * consideration. See <ulink url="http://www.vorbis.com/">Ogg/Vorbis</ulink>
      31                 :            :  * for a royalty free (and often higher quality) alternative.
      32                 :            :  *
      33                 :            :  * <refsect2>
      34                 :            :  * <title>Output sample rate</title>
      35                 :            :  * If no fixed output sample rate is negotiated on the element's src pad,
      36                 :            :  * the element will choose an optimal sample rate to resample to internally.
      37                 :            :  * For example, a 16-bit 44.1 KHz mono audio stream encoded at 48 kbit will
      38                 :            :  * get resampled to 32 KHz.  Use filter caps on the src pad to force a
      39                 :            :  * particular sample rate.
      40                 :            :  * </refsect2>
      41                 :            :  * <refsect2>
      42                 :            :  * <title>Example pipelines</title>
      43                 :            :  * |[
      44                 :            :  * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! lamemp3enc ! filesink location=sine.mp3
      45                 :            :  * ]| Encode a test sine signal to MP3.
      46                 :            :  * |[
      47                 :            :  * gst-launch -v alsasrc ! audioconvert ! lamemp3enc target=bitrate bitrate=192 ! filesink location=alsasrc.mp3
      48                 :            :  * ]| Record from a sound card using ALSA and encode to MP3 with an average bitrate of 192kbps
      49                 :            :  * |[
      50                 :            :  * gst-launch -v filesrc location=music.wav ! decodebin ! audioconvert ! audioresample ! lamemp3enc target=quality quality=0 ! id3v2mux ! filesink location=music.mp3
      51                 :            :  * ]| Transcode from a .wav file to MP3 (the id3v2mux element is optional) with best VBR quality
      52                 :            :  * |[
      53                 :            :  * gst-launch -v cdda://5 ! audioconvert ! lamemp3enc target=bitrate cbr=true bitrate=192 ! filesink location=track5.mp3
      54                 :            :  * ]| Encode Audio CD track 5 to MP3 with a constant bitrate of 192kbps
      55                 :            :  * |[
      56                 :            :  * gst-launch -v audiotestsrc num-buffers=10 ! audio/x-raw-int,rate=44100,channels=1 ! lamemp3enc target=bitrate cbr=true bitrate=48 ! filesink location=test.mp3
      57                 :            :  * ]| Encode to a fixed sample rate
      58                 :            :  * </refsect2>
      59                 :            :  *
      60                 :            :  * Since: 0.10.12
      61                 :            :  */
      62                 :            : 
      63                 :            : #ifdef HAVE_CONFIG_H
      64                 :            : #include "config.h"
      65                 :            : #endif
      66                 :            : 
      67                 :            : #include <string.h>
      68                 :            : #include "gstlamemp3enc.h"
      69                 :            : #include <gst/gst-i18n-plugin.h>
      70                 :            : 
      71                 :            : /* lame < 3.98 */
      72                 :            : #ifndef HAVE_LAME_SET_VBR_QUALITY
      73                 :            : #define lame_set_VBR_quality(flags,q) lame_set_VBR_q((flags),(int)(q))
      74                 :            : #endif
      75                 :            : 
      76                 :            : GST_DEBUG_CATEGORY_STATIC (debug);
      77                 :            : #define GST_CAT_DEFAULT debug
      78                 :            : 
      79                 :            : /* elementfactory information */
      80                 :            : 
      81                 :            : /* LAMEMP3ENC can do MPEG-1, MPEG-2, and MPEG-2.5, so it has 9 possible
      82                 :            :  * sample rates it supports */
      83                 :            : static GstStaticPadTemplate gst_lamemp3enc_sink_template =
      84                 :            : GST_STATIC_PAD_TEMPLATE ("sink",
      85                 :            :     GST_PAD_SINK,
      86                 :            :     GST_PAD_ALWAYS,
      87                 :            :     GST_STATIC_CAPS ("audio/x-raw-int, "
      88                 :            :         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
      89                 :            :         "signed = (boolean) true, "
      90                 :            :         "width = (int) 16, "
      91                 :            :         "depth = (int) 16, "
      92                 :            :         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
      93                 :            :         "channels = (int) [ 1, 2 ]")
      94                 :            :     );
      95                 :            : 
      96                 :            : static GstStaticPadTemplate gst_lamemp3enc_src_template =
      97                 :            : GST_STATIC_PAD_TEMPLATE ("src",
      98                 :            :     GST_PAD_SRC,
      99                 :            :     GST_PAD_ALWAYS,
     100                 :            :     GST_STATIC_CAPS ("audio/mpeg, "
     101                 :            :         "mpegversion = (int) 1, "
     102                 :            :         "layer = (int) 3, "
     103                 :            :         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
     104                 :            :         "channels = (int) [ 1, 2 ]")
     105                 :            :     );
     106                 :            : 
     107                 :            : /********** Define useful types for non-programmatic interfaces **********/
     108                 :            : enum
     109                 :            : {
     110                 :            :   LAMEMP3ENC_TARGET_QUALITY = 0,
     111                 :            :   LAMEMP3ENC_TARGET_BITRATE
     112                 :            : };
     113                 :            : 
     114                 :            : #define GST_TYPE_LAMEMP3ENC_TARGET (gst_lamemp3enc_target_get_type())
     115                 :            : static GType
     116                 :          6 : gst_lamemp3enc_target_get_type (void)
     117                 :            : {
     118                 :            :   static GType lame_target_type = 0;
     119                 :            :   static GEnumValue lame_targets[] = {
     120                 :            :     {LAMEMP3ENC_TARGET_QUALITY, "Quality", "quality"},
     121                 :            :     {LAMEMP3ENC_TARGET_BITRATE, "Bitrate", "bitrate"},
     122                 :            :     {0, NULL, NULL}
     123                 :            :   };
     124                 :            : 
     125         [ +  - ]:          6 :   if (!lame_target_type) {
     126                 :          6 :     lame_target_type =
     127                 :          6 :         g_enum_register_static ("GstLameMP3EncTarget", lame_targets);
     128                 :            :   }
     129                 :          6 :   return lame_target_type;
     130                 :            : }
     131                 :            : 
     132                 :            : enum
     133                 :            : {
     134                 :            :   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_FAST = 0,
     135                 :            :   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_STANDARD,
     136                 :            :   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_HIGH
     137                 :            : };
     138                 :            : 
     139                 :            : #define GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY (gst_lamemp3enc_encoding_engine_quality_get_type())
     140                 :            : static GType
     141                 :          6 : gst_lamemp3enc_encoding_engine_quality_get_type (void)
     142                 :            : {
     143                 :            :   static GType lame_encoding_engine_quality_type = 0;
     144                 :            :   static GEnumValue lame_encoding_engine_quality[] = {
     145                 :            :     {0, "Fast", "fast"},
     146                 :            :     {1, "Standard", "standard"},
     147                 :            :     {2, "High", "high"},
     148                 :            :     {0, NULL, NULL}
     149                 :            :   };
     150                 :            : 
     151         [ +  - ]:          6 :   if (!lame_encoding_engine_quality_type) {
     152                 :          6 :     lame_encoding_engine_quality_type =
     153                 :          6 :         g_enum_register_static ("GstLameMP3EncEncodingEngineQuality",
     154                 :            :         lame_encoding_engine_quality);
     155                 :            :   }
     156                 :          6 :   return lame_encoding_engine_quality_type;
     157                 :            : }
     158                 :            : 
     159                 :            : /********** Standard stuff for signals and arguments **********/
     160                 :            : 
     161                 :            : enum
     162                 :            : {
     163                 :            :   ARG_0,
     164                 :            :   ARG_TARGET,
     165                 :            :   ARG_BITRATE,
     166                 :            :   ARG_CBR,
     167                 :            :   ARG_QUALITY,
     168                 :            :   ARG_ENCODING_ENGINE_QUALITY,
     169                 :            :   ARG_MONO
     170                 :            : };
     171                 :            : 
     172                 :            : #define DEFAULT_TARGET LAMEMP3ENC_TARGET_QUALITY
     173                 :            : #define DEFAULT_BITRATE 128
     174                 :            : #define DEFAULT_CBR FALSE
     175                 :            : #define DEFAULT_QUALITY 4
     176                 :            : #define DEFAULT_ENCODING_ENGINE_QUALITY LAMEMP3ENC_ENCODING_ENGINE_QUALITY_STANDARD
     177                 :            : #define DEFAULT_MONO FALSE
     178                 :            : 
     179                 :            : static void gst_lamemp3enc_base_init (gpointer g_class);
     180                 :            : static void gst_lamemp3enc_class_init (GstLameMP3EncClass * klass);
     181                 :            : static void gst_lamemp3enc_init (GstLameMP3Enc * gst_lame);
     182                 :            : 
     183                 :            : static void gst_lamemp3enc_set_property (GObject * object, guint prop_id,
     184                 :            :     const GValue * value, GParamSpec * pspec);
     185                 :            : static void gst_lamemp3enc_get_property (GObject * object, guint prop_id,
     186                 :            :     GValue * value, GParamSpec * pspec);
     187                 :            : static gboolean gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event);
     188                 :            : static GstFlowReturn gst_lamemp3enc_chain (GstPad * pad, GstBuffer * buf);
     189                 :            : static gboolean gst_lamemp3enc_setup (GstLameMP3Enc * lame);
     190                 :            : static GstStateChangeReturn gst_lamemp3enc_change_state (GstElement * element,
     191                 :            :     GstStateChange transition);
     192                 :            : 
     193                 :            : static GstElementClass *parent_class = NULL;
     194                 :            : 
     195                 :            : GType
     196                 :         69 : gst_lamemp3enc_get_type (void)
     197                 :            : {
     198                 :            :   static GType gst_lamemp3enc_type = 0;
     199                 :            : 
     200         [ +  + ]:         69 :   if (!gst_lamemp3enc_type) {
     201                 :            :     static const GTypeInfo gst_lamemp3enc_info = {
     202                 :            :       sizeof (GstLameMP3EncClass),
     203                 :            :       gst_lamemp3enc_base_init,
     204                 :            :       NULL,
     205                 :            :       (GClassInitFunc) gst_lamemp3enc_class_init,
     206                 :            :       NULL,
     207                 :            :       NULL,
     208                 :            :       sizeof (GstLameMP3Enc),
     209                 :            :       0,
     210                 :            :       (GInstanceInitFunc) gst_lamemp3enc_init,
     211                 :            :     };
     212                 :            :     static const GInterfaceInfo preset_info = {
     213                 :            :       NULL,
     214                 :            :       NULL,
     215                 :            :       NULL
     216                 :            :     };
     217                 :            : 
     218                 :          7 :     gst_lamemp3enc_type =
     219                 :          7 :         g_type_register_static (GST_TYPE_ELEMENT, "GstLameMP3Enc",
     220                 :            :         &gst_lamemp3enc_info, 0);
     221                 :          7 :     g_type_add_interface_static (gst_lamemp3enc_type, GST_TYPE_PRESET,
     222                 :            :         &preset_info);
     223                 :            :   }
     224                 :         69 :   return gst_lamemp3enc_type;
     225                 :            : }
     226                 :            : 
     227                 :            : static void
     228                 :          9 : gst_lamemp3enc_release_memory (GstLameMP3Enc * lame)
     229                 :            : {
     230         [ +  + ]:          9 :   if (lame->lgf) {
     231                 :          1 :     lame_close (lame->lgf);
     232                 :          1 :     lame->lgf = NULL;
     233                 :            :   }
     234                 :          9 : }
     235                 :            : 
     236                 :            : static void
     237                 :          4 : gst_lamemp3enc_finalize (GObject * obj)
     238                 :            : {
     239                 :          4 :   gst_lamemp3enc_release_memory (GST_LAMEMP3ENC (obj));
     240                 :            : 
     241                 :          4 :   G_OBJECT_CLASS (parent_class)->finalize (obj);
     242                 :          4 : }
     243                 :            : 
     244                 :            : static void
     245                 :          6 : gst_lamemp3enc_base_init (gpointer g_class)
     246                 :            : {
     247                 :          6 :   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
     248                 :            : 
     249                 :          6 :   gst_element_class_add_pad_template (element_class,
     250                 :            :       gst_static_pad_template_get (&gst_lamemp3enc_src_template));
     251                 :          6 :   gst_element_class_add_pad_template (element_class,
     252                 :            :       gst_static_pad_template_get (&gst_lamemp3enc_sink_template));
     253                 :          6 :   gst_element_class_set_details_simple (element_class, "L.A.M.E. mp3 encoder",
     254                 :            :       "Codec/Encoder/Audio",
     255                 :            :       "High-quality free MP3 encoder",
     256                 :            :       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
     257                 :          6 : }
     258                 :            : 
     259                 :            : static void
     260                 :          6 : gst_lamemp3enc_class_init (GstLameMP3EncClass * klass)
     261                 :            : {
     262                 :            :   GObjectClass *gobject_class;
     263                 :            :   GstElementClass *gstelement_class;
     264                 :            : 
     265                 :          6 :   gobject_class = (GObjectClass *) klass;
     266                 :          6 :   gstelement_class = (GstElementClass *) klass;
     267                 :            : 
     268                 :          6 :   parent_class = g_type_class_peek_parent (klass);
     269                 :            : 
     270                 :          6 :   gobject_class->set_property = gst_lamemp3enc_set_property;
     271                 :          6 :   gobject_class->get_property = gst_lamemp3enc_get_property;
     272                 :          6 :   gobject_class->finalize = gst_lamemp3enc_finalize;
     273                 :            : 
     274                 :          6 :   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TARGET,
     275                 :            :       g_param_spec_enum ("target", "Target",
     276                 :            :           "Optimize for quality or bitrate", GST_TYPE_LAMEMP3ENC_TARGET,
     277                 :            :           DEFAULT_TARGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     278                 :          6 :   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
     279                 :            :       g_param_spec_int ("bitrate", "Bitrate (kb/s)",
     280                 :            :           "Bitrate in kbit/sec (Only valid if target is bitrate, for CBR one "
     281                 :            :           "of 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, "
     282                 :            :           "256 or 320)", 8, 320, DEFAULT_BITRATE,
     283                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     284                 :          6 :   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CBR,
     285                 :            :       g_param_spec_boolean ("cbr", "CBR", "Enforce constant bitrate encoding "
     286                 :            :           "(Only valid if target is bitrate)", DEFAULT_CBR,
     287                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     288                 :          6 :   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
     289                 :            :       g_param_spec_float ("quality", "Quality",
     290                 :            :           "VBR Quality from 0 to 10, 0 being the best "
     291                 :            :           "(Only valid if target is quality)", 0.0, 9.999,
     292                 :            :           DEFAULT_QUALITY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     293                 :          6 :   g_object_class_install_property (G_OBJECT_CLASS (klass),
     294                 :            :       ARG_ENCODING_ENGINE_QUALITY, g_param_spec_enum ("encoding-engine-quality",
     295                 :            :           "Encoding Engine Quality", "Quality/speed of the encoding engine, "
     296                 :            :           "this does not affect the bitrate!",
     297                 :            :           GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY,
     298                 :            :           DEFAULT_ENCODING_ENGINE_QUALITY,
     299                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     300                 :          6 :   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MONO,
     301                 :            :       g_param_spec_boolean ("mono", "Mono", "Enforce mono encoding",
     302                 :            :           DEFAULT_MONO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     303                 :            : 
     304                 :          6 :   gstelement_class->change_state =
     305                 :          6 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_change_state);
     306                 :          6 : }
     307                 :            : 
     308                 :            : static gboolean
     309                 :          1 : gst_lamemp3enc_src_setcaps (GstPad * pad, GstCaps * caps)
     310                 :            : {
     311         [ -  + ]:          1 :   GST_DEBUG_OBJECT (pad, "caps: %" GST_PTR_FORMAT, caps);
     312                 :          1 :   return TRUE;
     313                 :            : }
     314                 :            : 
     315                 :            : static gboolean
     316                 :          1 : gst_lamemp3enc_sink_setcaps (GstPad * pad, GstCaps * caps)
     317                 :            : {
     318                 :            :   GstLameMP3Enc *lame;
     319                 :            :   gint out_samplerate;
     320                 :            :   gint version;
     321                 :            :   GstStructure *structure;
     322                 :            :   GstCaps *othercaps;
     323                 :            : 
     324                 :          1 :   lame = GST_LAMEMP3ENC (GST_PAD_PARENT (pad));
     325                 :          1 :   structure = gst_caps_get_structure (caps, 0);
     326                 :            : 
     327         [ -  + ]:          1 :   if (!gst_structure_get_int (structure, "rate", &lame->samplerate))
     328                 :          0 :     goto no_rate;
     329         [ -  + ]:          1 :   if (!gst_structure_get_int (structure, "channels", &lame->num_channels))
     330                 :          0 :     goto no_channels;
     331                 :            : 
     332         [ -  + ]:          1 :   GST_DEBUG_OBJECT (lame, "setting up lame");
     333         [ -  + ]:          1 :   if (!gst_lamemp3enc_setup (lame))
     334                 :          0 :     goto setup_failed;
     335                 :            : 
     336                 :            : 
     337                 :          1 :   out_samplerate = lame_get_out_samplerate (lame->lgf);
     338         [ -  + ]:          1 :   if (out_samplerate == 0)
     339                 :          0 :     goto zero_output_rate;
     340         [ -  + ]:          1 :   if (out_samplerate != lame->samplerate) {
     341         [ #  # ]:          0 :     GST_WARNING_OBJECT (lame,
     342                 :            :         "output samplerate %d is different from incoming samplerate %d",
     343                 :            :         out_samplerate, lame->samplerate);
     344                 :            :   }
     345                 :            : 
     346                 :          1 :   version = lame_get_version (lame->lgf);
     347         [ -  + ]:          1 :   if (version == 0)
     348                 :          0 :     version = 2;
     349         [ +  - ]:          1 :   else if (version == 1)
     350                 :          1 :     version = 1;
     351         [ #  # ]:          0 :   else if (version == 2)
     352                 :          0 :     version = 3;
     353                 :            : 
     354                 :          1 :   othercaps =
     355         [ +  - ]:          1 :       gst_caps_new_simple ("audio/mpeg",
     356                 :            :       "mpegversion", G_TYPE_INT, 1,
     357                 :            :       "mpegaudioversion", G_TYPE_INT, version,
     358                 :            :       "layer", G_TYPE_INT, 3,
     359                 :          1 :       "channels", G_TYPE_INT, lame->mono ? 1 : lame->num_channels,
     360                 :            :       "rate", G_TYPE_INT, out_samplerate, NULL);
     361                 :            : 
     362                 :            :   /* and use these caps */
     363                 :          1 :   gst_pad_set_caps (lame->srcpad, othercaps);
     364                 :          1 :   gst_caps_unref (othercaps);
     365                 :            : 
     366                 :          1 :   return TRUE;
     367                 :            : 
     368                 :            : no_rate:
     369                 :            :   {
     370         [ #  # ]:          0 :     GST_ERROR_OBJECT (lame, "input caps have no sample rate field");
     371                 :          0 :     return FALSE;
     372                 :            :   }
     373                 :            : no_channels:
     374                 :            :   {
     375         [ #  # ]:          0 :     GST_ERROR_OBJECT (lame, "input caps have no channels field");
     376                 :          0 :     return FALSE;
     377                 :            :   }
     378                 :            : zero_output_rate:
     379                 :            :   {
     380 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (lame, LIBRARY, SETTINGS, (NULL),
         [ #  # ][ #  # ]
     381                 :            :         ("LAMEMP3ENC decided on a zero sample rate"));
     382                 :          0 :     return FALSE;
     383                 :            :   }
     384                 :            : setup_failed:
     385                 :            :   {
     386 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (lame, LIBRARY, SETTINGS,
         [ #  # ][ #  # ]
     387                 :            :         (_("Failed to configure LAMEMP3ENC encoder. Check your encoding parameters.")), (NULL));
     388                 :          1 :     return FALSE;
     389                 :            :   }
     390                 :            : }
     391                 :            : 
     392                 :            : static GstCaps *
     393                 :         11 : gst_lamemp3enc_sink_getcaps (GstPad * pad)
     394                 :            : {
     395                 :            :   const GstCaps *templ_caps;
     396                 :            :   GstLameMP3Enc *lame;
     397                 :         11 :   GstCaps *allowed = NULL;
     398                 :            :   GstCaps *caps, *filter_caps;
     399                 :            :   gint i, j;
     400                 :            : 
     401                 :         11 :   lame = GST_LAMEMP3ENC (gst_pad_get_parent (pad));
     402                 :            : 
     403                 :            :   /* we want to be able to communicate to upstream elements like audioconvert
     404                 :            :    * and audioresample any rate/channel restrictions downstream (e.g. muxer
     405                 :            :    * only accepting certain sample rates) */
     406                 :         11 :   templ_caps = gst_pad_get_pad_template_caps (pad);
     407                 :         11 :   allowed = gst_pad_get_allowed_caps (lame->srcpad);
     408 [ +  + ][ +  - ]:         11 :   if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) {
                 [ -  + ]
     409                 :          2 :     caps = gst_caps_copy (templ_caps);
     410                 :          2 :     goto done;
     411                 :            :   }
     412                 :            : 
     413                 :          9 :   filter_caps = gst_caps_new_empty ();
     414                 :            : 
     415         [ +  + ]:         18 :   for (i = 0; i < gst_caps_get_size (templ_caps); i++) {
     416                 :            :     GQuark q_name;
     417                 :            : 
     418                 :          9 :     q_name = gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
     419                 :            : 
     420                 :            :     /* pick rate + channel fields from allowed caps */
     421         [ +  + ]:         18 :     for (j = 0; j < gst_caps_get_size (allowed); j++) {
     422                 :          9 :       const GstStructure *allowed_s = gst_caps_get_structure (allowed, j);
     423                 :            :       const GValue *val;
     424                 :            :       GstStructure *s;
     425                 :            : 
     426                 :          9 :       s = gst_structure_id_empty_new (q_name);
     427         [ +  - ]:          9 :       if ((val = gst_structure_get_value (allowed_s, "rate")))
     428                 :          9 :         gst_structure_set_value (s, "rate", val);
     429         [ +  - ]:          9 :       if ((val = gst_structure_get_value (allowed_s, "channels")))
     430                 :          9 :         gst_structure_set_value (s, "channels", val);
     431                 :            : 
     432                 :          9 :       gst_caps_merge_structure (filter_caps, s);
     433                 :            :     }
     434                 :            :   }
     435                 :            : 
     436                 :          9 :   caps = gst_caps_intersect (filter_caps, templ_caps);
     437                 :          9 :   gst_caps_unref (filter_caps);
     438                 :            : 
     439                 :            : done:
     440                 :            : 
     441                 :         11 :   gst_caps_replace (&allowed, NULL);
     442                 :         11 :   gst_object_unref (lame);
     443                 :            : 
     444                 :         11 :   return caps;
     445                 :            : }
     446                 :            : 
     447                 :            : static gint64
     448                 :          1 : gst_lamemp3enc_get_latency (GstLameMP3Enc * lame)
     449                 :            : {
     450                 :          1 :   return gst_util_uint64_scale_int (lame_get_framesize (lame->lgf),
     451                 :            :       GST_SECOND, lame->samplerate);
     452                 :            : }
     453                 :            : 
     454                 :            : static gboolean
     455                 :          1 : gst_lamemp3enc_src_query (GstPad * pad, GstQuery * query)
     456                 :            : {
     457                 :          1 :   gboolean res = TRUE;
     458                 :            :   GstLameMP3Enc *lame;
     459                 :            :   GstPad *peerpad;
     460                 :            : 
     461                 :          1 :   lame = GST_LAMEMP3ENC (gst_pad_get_parent (pad));
     462                 :          1 :   peerpad = gst_pad_get_peer (GST_PAD (lame->sinkpad));
     463                 :            : 
     464         [ +  - ]:          1 :   switch (GST_QUERY_TYPE (query)) {
     465                 :            :     case GST_QUERY_LATENCY:
     466                 :            :     {
     467         [ +  - ]:          1 :       if ((res = gst_pad_query (peerpad, query))) {
     468                 :            :         gboolean live;
     469                 :            :         GstClockTime min_latency, max_latency;
     470                 :            :         gint64 latency;
     471                 :            : 
     472         [ -  + ]:          1 :         if (lame->lgf == NULL)
     473                 :          0 :           break;
     474                 :            : 
     475                 :          1 :         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
     476                 :            : 
     477                 :          1 :         latency = gst_lamemp3enc_get_latency (lame);
     478                 :            : 
     479                 :            :         /* add our latency */
     480                 :          1 :         min_latency += latency;
     481         [ -  + ]:          1 :         if (max_latency != -1)
     482                 :          0 :           max_latency += latency;
     483                 :            : 
     484                 :          1 :         gst_query_set_latency (query, live, min_latency, max_latency);
     485                 :            :       }
     486                 :          1 :       break;
     487                 :            :     }
     488                 :            :     default:
     489                 :          0 :       res = gst_pad_query (peerpad, query);
     490                 :          0 :       break;
     491                 :            :   }
     492                 :            : 
     493                 :          1 :   gst_object_unref (peerpad);
     494                 :          1 :   gst_object_unref (lame);
     495                 :          1 :   return res;
     496                 :            : }
     497                 :            : 
     498                 :            : static void
     499                 :          4 : gst_lamemp3enc_init (GstLameMP3Enc * lame)
     500                 :            : {
     501         [ -  + ]:          4 :   GST_DEBUG_OBJECT (lame, "starting initialization");
     502                 :            : 
     503                 :          4 :   lame->sinkpad =
     504                 :          4 :       gst_pad_new_from_static_template (&gst_lamemp3enc_sink_template, "sink");
     505                 :          4 :   gst_pad_set_event_function (lame->sinkpad,
     506                 :          4 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_sink_event));
     507                 :          4 :   gst_pad_set_chain_function (lame->sinkpad,
     508                 :          4 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_chain));
     509                 :          4 :   gst_pad_set_setcaps_function (lame->sinkpad,
     510                 :          4 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_sink_setcaps));
     511                 :          4 :   gst_pad_set_getcaps_function (lame->sinkpad,
     512                 :          4 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_sink_getcaps));
     513                 :          4 :   gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
     514                 :            : 
     515                 :          4 :   lame->srcpad =
     516                 :          4 :       gst_pad_new_from_static_template (&gst_lamemp3enc_src_template, "src");
     517                 :          4 :   gst_pad_set_query_function (lame->srcpad,
     518                 :          4 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_src_query));
     519                 :          4 :   gst_pad_set_setcaps_function (lame->srcpad,
     520                 :          4 :       GST_DEBUG_FUNCPTR (gst_lamemp3enc_src_setcaps));
     521                 :          4 :   gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
     522                 :            : 
     523                 :          4 :   lame->samplerate = 44100;
     524                 :          4 :   lame->num_channels = 2;
     525                 :          4 :   lame->setup = FALSE;
     526                 :            : 
     527                 :            :   /* Set default settings */
     528                 :          4 :   lame->target = DEFAULT_TARGET;
     529                 :          4 :   lame->bitrate = DEFAULT_BITRATE;
     530                 :          4 :   lame->cbr = DEFAULT_CBR;
     531                 :          4 :   lame->quality = DEFAULT_QUALITY;
     532                 :          4 :   lame->encoding_engine_quality = DEFAULT_ENCODING_ENGINE_QUALITY;
     533                 :          4 :   lame->mono = DEFAULT_MONO;
     534                 :            : 
     535         [ -  + ]:          4 :   GST_DEBUG_OBJECT (lame, "done initializing");
     536                 :          4 : }
     537                 :            : 
     538                 :            : /* <php-emulation-mode>three underscores for ___rate is really really really
     539                 :            :  * private as opposed to one underscore<php-emulation-mode> */
     540                 :            : /* call this MACRO outside of the NULL state so that we have a higher chance
     541                 :            :  * of actually having a pipeline and bus to get the message through */
     542                 :            : 
     543                 :            : #define CHECK_AND_FIXUP_BITRATE(obj,param,rate)         \
     544                 :            : G_STMT_START {                                                            \
     545                 :            :   gint ___rate = rate;                                                    \
     546                 :            :   gint maxrate = 320;               \
     547                 :            :   gint multiplier = 64;               \
     548                 :            :   if (rate == 0) {                                                        \
     549                 :            :     ___rate = rate;                                                       \
     550                 :            :   } else if (rate <= 64) {                         \
     551                 :            :     maxrate = 64; multiplier = 8;                                         \
     552                 :            :     if ((rate % 8) != 0) ___rate = GST_ROUND_UP_8 (rate);       \
     553                 :            :   } else if (rate <= 128) {              \
     554                 :            :     maxrate = 128; multiplier = 16;                                       \
     555                 :            :     if ((rate % 16) != 0) ___rate = GST_ROUND_UP_16 (rate);               \
     556                 :            :   } else if (rate <= 256) {              \
     557                 :            :     maxrate = 256; multiplier = 32;                                       \
     558                 :            :     if ((rate % 32) != 0) ___rate = GST_ROUND_UP_32 (rate);               \
     559                 :            :   } else if (rate <= 320) {              \
     560                 :            :     maxrate = 320; multiplier = 64;                                       \
     561                 :            :     if ((rate % 64) != 0) ___rate = GST_ROUND_UP_64 (rate);               \
     562                 :            :   }                                                                       \
     563                 :            :   if (___rate != rate) {                                                  \
     564                 :            :     GST_ELEMENT_WARNING (obj, LIBRARY, SETTINGS,        \
     565                 :            :       (_("The requested bitrate %d kbit/s for property '%s' "             \
     566                 :            :        "is not allowed. "                     \
     567                 :            :        "The bitrate was changed to %d kbit/s."), rate,              \
     568                 :            :          param,  ___rate),                    \
     569                 :            :        ("A bitrate below %d should be a multiple of %d.",       \
     570                 :            :           maxrate, multiplier));              \
     571                 :            :     rate = ___rate;                                                       \
     572                 :            :   }                                                                       \
     573                 :            : } G_STMT_END
     574                 :            : 
     575                 :            : static void
     576                 :          0 : gst_lamemp3enc_set_property (GObject * object, guint prop_id,
     577                 :            :     const GValue * value, GParamSpec * pspec)
     578                 :            : {
     579                 :            :   GstLameMP3Enc *lame;
     580                 :            : 
     581                 :          0 :   lame = GST_LAMEMP3ENC (object);
     582                 :            : 
     583   [ #  #  #  #  :          0 :   switch (prop_id) {
                #  #  # ]
     584                 :            :     case ARG_TARGET:
     585                 :          0 :       lame->target = g_value_get_enum (value);
     586                 :          0 :       break;
     587                 :            :     case ARG_BITRATE:
     588                 :          0 :       lame->bitrate = g_value_get_int (value);
     589                 :          0 :       break;
     590                 :            :     case ARG_CBR:
     591                 :          0 :       lame->cbr = g_value_get_boolean (value);
     592                 :          0 :       break;
     593                 :            :     case ARG_QUALITY:
     594                 :          0 :       lame->quality = g_value_get_float (value);
     595                 :          0 :       break;
     596                 :            :     case ARG_ENCODING_ENGINE_QUALITY:
     597                 :          0 :       lame->encoding_engine_quality = g_value_get_enum (value);
     598                 :          0 :       break;
     599                 :            :     case ARG_MONO:
     600                 :          0 :       lame->mono = g_value_get_boolean (value);
     601                 :          0 :       break;
     602                 :            :     default:
     603                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     604                 :          0 :       break;
     605                 :            :   }
     606                 :          0 : }
     607                 :            : 
     608                 :            : static void
     609                 :          0 : gst_lamemp3enc_get_property (GObject * object, guint prop_id, GValue * value,
     610                 :            :     GParamSpec * pspec)
     611                 :            : {
     612                 :            :   GstLameMP3Enc *lame;
     613                 :            : 
     614                 :          0 :   lame = GST_LAMEMP3ENC (object);
     615                 :            : 
     616   [ #  #  #  #  :          0 :   switch (prop_id) {
                #  #  # ]
     617                 :            :     case ARG_TARGET:
     618                 :          0 :       g_value_set_enum (value, lame->target);
     619                 :          0 :       break;
     620                 :            :     case ARG_BITRATE:
     621                 :          0 :       g_value_set_int (value, lame->bitrate);
     622                 :          0 :       break;
     623                 :            :     case ARG_CBR:
     624                 :          0 :       g_value_set_boolean (value, lame->cbr);
     625                 :          0 :       break;
     626                 :            :     case ARG_QUALITY:
     627                 :          0 :       g_value_set_float (value, lame->quality);
     628                 :          0 :       break;
     629                 :            :     case ARG_ENCODING_ENGINE_QUALITY:
     630                 :          0 :       g_value_set_enum (value, lame->encoding_engine_quality);
     631                 :          0 :       break;
     632                 :            :     case ARG_MONO:
     633                 :          0 :       g_value_set_boolean (value, lame->mono);
     634                 :          0 :       break;
     635                 :            :     default:
     636                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     637                 :          0 :       break;
     638                 :            :   }
     639                 :          0 : }
     640                 :            : 
     641                 :            : static gboolean
     642                 :          3 : gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event)
     643                 :            : {
     644                 :            :   gboolean ret;
     645                 :            :   GstLameMP3Enc *lame;
     646                 :            : 
     647                 :          3 :   lame = GST_LAMEMP3ENC (gst_pad_get_parent (pad));
     648                 :            : 
     649   [ +  -  -  +  :          3 :   switch (GST_EVENT_TYPE (event)) {
                      + ]
     650                 :            :     case GST_EVENT_EOS:{
     651         [ -  + ]:          1 :       GST_DEBUG_OBJECT (lame, "handling EOS event");
     652                 :            : 
     653         [ +  - ]:          1 :       if (lame->lgf != NULL) {
     654                 :            :         GstBuffer *buf;
     655                 :            :         gint size;
     656                 :            : 
     657                 :          1 :         buf = gst_buffer_new_and_alloc (7200);
     658                 :          1 :         size = lame_encode_flush (lame->lgf, GST_BUFFER_DATA (buf), 7200);
     659                 :            : 
     660 [ +  - ][ +  - ]:          2 :         if (size > 0 && lame->last_flow == GST_FLOW_OK) {
     661                 :            :           gint64 duration;
     662                 :            : 
     663                 :          1 :           duration = gst_util_uint64_scale (size, 8 * GST_SECOND,
     664                 :          1 :               1000 * lame->bitrate);
     665                 :            : 
     666         [ -  + ]:          1 :           if (lame->last_ts == GST_CLOCK_TIME_NONE) {
     667                 :          0 :             lame->last_ts = lame->eos_ts;
     668                 :          0 :             lame->last_duration = duration;
     669                 :            :           } else {
     670                 :          1 :             lame->last_duration += duration;
     671                 :            :           }
     672                 :            : 
     673                 :          1 :           GST_BUFFER_TIMESTAMP (buf) = lame->last_ts;
     674                 :          1 :           GST_BUFFER_DURATION (buf) = lame->last_duration;
     675                 :          1 :           lame->last_ts = GST_CLOCK_TIME_NONE;
     676                 :          1 :           GST_BUFFER_SIZE (buf) = size;
     677         [ -  + ]:          1 :           GST_DEBUG_OBJECT (lame, "pushing final packet of %u bytes", size);
     678                 :          1 :           gst_buffer_set_caps (buf, GST_PAD_CAPS (lame->srcpad));
     679                 :          1 :           gst_pad_push (lame->srcpad, buf);
     680                 :            :         } else {
     681         [ #  # ]:          0 :           GST_DEBUG_OBJECT (lame, "no final packet (size=%d, last_flow=%s)",
     682                 :            :               size, gst_flow_get_name (lame->last_flow));
     683                 :          0 :           gst_buffer_unref (buf);
     684                 :            :         }
     685                 :            :       }
     686                 :            : 
     687                 :          1 :       ret = gst_pad_event_default (pad, event);
     688                 :          1 :       break;
     689                 :            :     }
     690                 :            :     case GST_EVENT_FLUSH_START:
     691         [ #  # ]:          0 :       GST_DEBUG_OBJECT (lame, "handling FLUSH start event");
     692                 :            :       /* forward event */
     693                 :          0 :       ret = gst_pad_push_event (lame->srcpad, event);
     694                 :          0 :       break;
     695                 :            :     case GST_EVENT_FLUSH_STOP:
     696                 :            :     {
     697                 :          0 :       guchar *mp3_data = NULL;
     698                 :            :       gint mp3_buffer_size;
     699                 :            : 
     700         [ #  # ]:          0 :       GST_DEBUG_OBJECT (lame, "handling FLUSH stop event");
     701                 :            : 
     702         [ #  # ]:          0 :       if (lame->lgf) {
     703                 :            :         /* clear buffers if we already have lame set up */
     704                 :          0 :         mp3_buffer_size = 7200;
     705                 :          0 :         mp3_data = g_malloc (mp3_buffer_size);
     706                 :          0 :         lame_encode_flush (lame->lgf, mp3_data, mp3_buffer_size);
     707                 :          0 :         g_free (mp3_data);
     708                 :            :       }
     709                 :            : 
     710                 :          0 :       ret = gst_pad_push_event (lame->srcpad, event);
     711                 :          0 :       break;
     712                 :            :     }
     713                 :            :     case GST_EVENT_TAG:
     714         [ -  + ]:          1 :       GST_DEBUG_OBJECT (lame, "ignoring TAG event, passing it on");
     715                 :          1 :       ret = gst_pad_push_event (lame->srcpad, event);
     716                 :          1 :       break;
     717                 :            :     default:
     718                 :          1 :       ret = gst_pad_event_default (pad, event);
     719                 :          1 :       break;
     720                 :            :   }
     721                 :          3 :   gst_object_unref (lame);
     722                 :          3 :   return ret;
     723                 :            : }
     724                 :            : 
     725                 :            : static GstFlowReturn
     726                 :          2 : gst_lamemp3enc_chain (GstPad * pad, GstBuffer * buf)
     727                 :            : {
     728                 :            :   GstLameMP3Enc *lame;
     729                 :            :   guchar *mp3_data;
     730                 :            :   gint mp3_buffer_size, mp3_size;
     731                 :            :   gint64 duration;
     732                 :            :   GstFlowReturn result;
     733                 :            :   gint num_samples;
     734                 :            :   guint8 *data;
     735                 :            :   guint size;
     736                 :            : 
     737                 :          2 :   lame = GST_LAMEMP3ENC (GST_PAD_PARENT (pad));
     738                 :            : 
     739         [ -  + ]:          2 :   GST_LOG_OBJECT (lame, "entered chain");
     740                 :            : 
     741         [ -  + ]:          2 :   if (!lame->setup)
     742                 :          0 :     goto not_setup;
     743                 :            : 
     744                 :          2 :   data = GST_BUFFER_DATA (buf);
     745                 :          2 :   size = GST_BUFFER_SIZE (buf);
     746                 :            : 
     747                 :          2 :   num_samples = size / 2;
     748                 :            : 
     749                 :            :   /* allocate space for output */
     750                 :          2 :   mp3_buffer_size = 1.25 * num_samples + 7200;
     751                 :          2 :   mp3_data = g_malloc (mp3_buffer_size);
     752                 :            : 
     753                 :            :   /* lame seems to be too stupid to get mono interleaved going */
     754         [ +  - ]:          2 :   if (lame->num_channels == 1) {
     755                 :          2 :     mp3_size = lame_encode_buffer (lame->lgf,
     756                 :            :         (short int *) data,
     757                 :            :         (short int *) data, num_samples, mp3_data, mp3_buffer_size);
     758                 :            :   } else {
     759                 :          0 :     mp3_size = lame_encode_buffer_interleaved (lame->lgf,
     760                 :            :         (short int *) data,
     761                 :          0 :         num_samples / lame->num_channels, mp3_data, mp3_buffer_size);
     762                 :            :   }
     763                 :            : 
     764         [ -  + ]:          2 :   GST_LOG_OBJECT (lame, "encoded %d bytes of audio to %d bytes of mp3",
     765                 :            :       size, mp3_size);
     766                 :            : 
     767                 :          2 :   duration = gst_util_uint64_scale_int (size, GST_SECOND,
     768                 :          2 :       2 * lame->samplerate * lame->num_channels);
     769                 :            : 
     770 [ +  - ][ +  + ]:          2 :   if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE &&
     771                 :          2 :       GST_BUFFER_DURATION (buf) != duration) {
     772 [ -  + ][ #  # ]:          1 :     GST_DEBUG_OBJECT (lame, "incoming buffer had incorrect duration %"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     773                 :            :         GST_TIME_FORMAT ", outgoing buffer will have correct duration %"
     774                 :            :         GST_TIME_FORMAT,
     775                 :            :         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (duration));
     776                 :            :   }
     777                 :            : 
     778         [ +  + ]:          2 :   if (lame->last_ts == GST_CLOCK_TIME_NONE) {
     779                 :          1 :     lame->last_ts = GST_BUFFER_TIMESTAMP (buf);
     780                 :          1 :     lame->last_offs = GST_BUFFER_OFFSET (buf);
     781                 :          1 :     lame->last_duration = duration;
     782                 :            :   } else {
     783                 :          1 :     lame->last_duration += duration;
     784                 :            :   }
     785                 :            : 
     786                 :          2 :   gst_buffer_unref (buf);
     787                 :            : 
     788         [ -  + ]:          2 :   if (mp3_size < 0) {
     789                 :          0 :     g_warning ("error %d", mp3_size);
     790                 :            :   }
     791                 :            : 
     792         [ -  + ]:          2 :   if (mp3_size > 0) {
     793                 :            :     GstBuffer *outbuf;
     794                 :            : 
     795                 :          0 :     outbuf = gst_buffer_new ();
     796                 :          0 :     GST_BUFFER_DATA (outbuf) = mp3_data;
     797                 :          0 :     GST_BUFFER_MALLOCDATA (outbuf) = mp3_data;
     798                 :          0 :     GST_BUFFER_SIZE (outbuf) = mp3_size;
     799                 :          0 :     GST_BUFFER_TIMESTAMP (outbuf) = lame->last_ts;
     800                 :          0 :     GST_BUFFER_OFFSET (outbuf) = lame->last_offs;
     801                 :          0 :     GST_BUFFER_DURATION (outbuf) = lame->last_duration;
     802                 :          0 :     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (lame->srcpad));
     803                 :            : 
     804                 :          0 :     result = gst_pad_push (lame->srcpad, outbuf);
     805                 :          0 :     lame->last_flow = result;
     806         [ #  # ]:          0 :     if (result != GST_FLOW_OK) {
     807         [ #  # ]:          0 :       GST_DEBUG_OBJECT (lame, "flow return: %s", gst_flow_get_name (result));
     808                 :            :     }
     809                 :            : 
     810         [ #  # ]:          0 :     if (GST_CLOCK_TIME_IS_VALID (lame->last_ts))
     811                 :          0 :       lame->eos_ts = lame->last_ts + lame->last_duration;
     812                 :            :     else
     813                 :          0 :       lame->eos_ts = GST_CLOCK_TIME_NONE;
     814                 :          0 :     lame->last_ts = GST_CLOCK_TIME_NONE;
     815                 :            :   } else {
     816                 :          2 :     g_free (mp3_data);
     817                 :          2 :     result = GST_FLOW_OK;
     818                 :            :   }
     819                 :            : 
     820                 :          2 :   return result;
     821                 :            : 
     822                 :            :   /* ERRORS */
     823                 :            : not_setup:
     824                 :            :   {
     825                 :          0 :     gst_buffer_unref (buf);
     826 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
         [ #  # ][ #  # ]
     827                 :            :         ("encoder not initialized (input is not audio?)"));
     828                 :          2 :     return GST_FLOW_ERROR;
     829                 :            :   }
     830                 :            : }
     831                 :            : 
     832                 :            : /* set up the encoder state */
     833                 :            : static gboolean
     834                 :          1 : gst_lamemp3enc_setup (GstLameMP3Enc * lame)
     835                 :            : {
     836                 :            : 
     837                 :            : #define CHECK_ERROR(command) G_STMT_START {\
     838                 :            :   if ((command) < 0) { \
     839                 :            :     GST_ERROR_OBJECT (lame, "setup failed: " G_STRINGIFY (command)); \
     840                 :            :     return FALSE; \
     841                 :            :   } \
     842                 :            : }G_STMT_END
     843                 :            : 
     844                 :            :   int retval;
     845                 :            :   GstCaps *allowed_caps;
     846                 :            : 
     847         [ -  + ]:          1 :   GST_DEBUG_OBJECT (lame, "starting setup");
     848                 :            : 
     849                 :            :   /* check if we're already setup; if we are, we might want to check
     850                 :            :    * if this initialization is compatible with the previous one */
     851                 :            :   /* FIXME: do this */
     852         [ -  + ]:          1 :   if (lame->setup) {
     853         [ #  # ]:          0 :     GST_WARNING_OBJECT (lame, "already setup");
     854                 :          0 :     lame->setup = FALSE;
     855                 :            :   }
     856                 :            : 
     857                 :          1 :   lame->lgf = lame_init ();
     858                 :            : 
     859         [ -  + ]:          1 :   if (lame->lgf == NULL)
     860                 :          0 :     return FALSE;
     861                 :            : 
     862                 :            :   /* post latency message on the bus */
     863                 :          1 :   gst_element_post_message (GST_ELEMENT (lame),
     864                 :          1 :       gst_message_new_latency (GST_OBJECT (lame)));
     865                 :            : 
     866                 :            :   /* copy the parameters over */
     867                 :          1 :   lame_set_in_samplerate (lame->lgf, lame->samplerate);
     868                 :            : 
     869                 :            :   /* let lame choose default samplerate unless outgoing sample rate is fixed */
     870                 :          1 :   allowed_caps = gst_pad_get_allowed_caps (lame->srcpad);
     871                 :            : 
     872         [ +  - ]:          1 :   if (allowed_caps != NULL) {
     873                 :            :     GstStructure *structure;
     874                 :            :     gint samplerate;
     875                 :            : 
     876                 :          1 :     structure = gst_caps_get_structure (allowed_caps, 0);
     877                 :            : 
     878         [ -  + ]:          1 :     if (gst_structure_get_int (structure, "rate", &samplerate)) {
     879         [ #  # ]:          0 :       GST_DEBUG_OBJECT (lame, "Setting sample rate to %d as fixed in src caps",
     880                 :            :           samplerate);
     881                 :          0 :       lame_set_out_samplerate (lame->lgf, samplerate);
     882                 :            :     } else {
     883         [ -  + ]:          1 :       GST_DEBUG_OBJECT (lame, "Letting lame choose sample rate");
     884                 :          1 :       lame_set_out_samplerate (lame->lgf, 0);
     885                 :            :     }
     886                 :          1 :     gst_caps_unref (allowed_caps);
     887                 :          1 :     allowed_caps = NULL;
     888                 :            :   } else {
     889         [ #  # ]:          0 :     GST_DEBUG_OBJECT (lame, "No peer yet, letting lame choose sample rate");
     890                 :          0 :     lame_set_out_samplerate (lame->lgf, 0);
     891                 :            :   }
     892                 :            : 
     893 [ -  + ][ #  # ]:          1 :   CHECK_ERROR (lame_set_num_channels (lame->lgf, lame->num_channels));
     894 [ -  + ][ #  # ]:          1 :   CHECK_ERROR (lame_set_bWriteVbrTag (lame->lgf, 0));
     895                 :            : 
     896         [ +  - ]:          1 :   if (lame->target == LAMEMP3ENC_TARGET_QUALITY) {
     897 [ -  + ][ #  # ]:          1 :     CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_default));
     898 [ -  + ][ #  # ]:          1 :     CHECK_ERROR (lame_set_VBR_quality (lame->lgf, lame->quality));
     899                 :            :   } else {
     900         [ #  # ]:          0 :     if (lame->cbr) {
     901 [ #  # ][ #  # ]:          0 :       CHECK_AND_FIXUP_BITRATE (lame, "bitrate", lame->bitrate);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     902 [ #  # ][ #  # ]:          0 :       CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_off));
     903 [ #  # ][ #  # ]:          0 :       CHECK_ERROR (lame_set_brate (lame->lgf, lame->bitrate));
     904                 :            :     } else {
     905 [ #  # ][ #  # ]:          0 :       CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_abr));
     906 [ #  # ][ #  # ]:          0 :       CHECK_ERROR (lame_set_VBR_mean_bitrate_kbps (lame->lgf, lame->bitrate));
     907                 :            :     }
     908                 :            :   }
     909                 :            : 
     910         [ -  + ]:          1 :   if (lame->encoding_engine_quality == LAMEMP3ENC_ENCODING_ENGINE_QUALITY_FAST)
     911 [ #  # ][ #  # ]:          0 :     CHECK_ERROR (lame_set_quality (lame->lgf, 7));
     912         [ -  + ]:          1 :   else if (lame->encoding_engine_quality ==
     913                 :            :       LAMEMP3ENC_ENCODING_ENGINE_QUALITY_HIGH)
     914 [ #  # ][ #  # ]:          0 :     CHECK_ERROR (lame_set_quality (lame->lgf, 2));
     915                 :            :   /* else default */
     916                 :            : 
     917         [ -  + ]:          1 :   if (lame->mono)
     918 [ #  # ][ #  # ]:          0 :     CHECK_ERROR (lame_set_mode (lame->lgf, MONO));
     919                 :            : 
     920                 :            :   /* initialize the lame encoder */
     921         [ +  - ]:          1 :   if ((retval = lame_init_params (lame->lgf)) >= 0) {
     922                 :          1 :     lame->setup = TRUE;
     923                 :            :     /* FIXME: it would be nice to print out the mode here */
     924 [ -  + ][ #  # ]:          1 :     GST_INFO
     925                 :            :         ("lame encoder setup (target %s, quality %f, bitrate %d, %d Hz, %d channels)",
     926                 :            :         (lame->target == LAMEMP3ENC_TARGET_QUALITY) ? "quality" : "bitrate",
     927                 :            :         lame->quality, lame->bitrate, lame->samplerate, lame->num_channels);
     928                 :            :   } else {
     929         [ #  # ]:          0 :     GST_ERROR_OBJECT (lame, "lame_init_params returned %d", retval);
     930                 :            :   }
     931                 :            : 
     932         [ -  + ]:          1 :   GST_DEBUG_OBJECT (lame, "done with setup");
     933                 :            : 
     934                 :          1 :   return lame->setup;
     935                 :            : #undef CHECK_ERROR
     936                 :            : }
     937                 :            : 
     938                 :            : static GstStateChangeReturn
     939                 :         40 : gst_lamemp3enc_change_state (GstElement * element, GstStateChange transition)
     940                 :            : {
     941                 :            :   GstLameMP3Enc *lame;
     942                 :            :   GstStateChangeReturn result;
     943                 :            : 
     944                 :         40 :   lame = GST_LAMEMP3ENC (element);
     945                 :            : 
     946         [ +  + ]:         40 :   switch (transition) {
     947                 :            :     case GST_STATE_CHANGE_READY_TO_PAUSED:
     948                 :          8 :       lame->last_flow = GST_FLOW_OK;
     949                 :          8 :       lame->last_ts = GST_CLOCK_TIME_NONE;
     950                 :          8 :       lame->eos_ts = GST_CLOCK_TIME_NONE;
     951                 :          8 :       break;
     952                 :            :     default:
     953                 :         32 :       break;
     954                 :            :   }
     955                 :            : 
     956                 :         40 :   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
     957                 :            : 
     958         [ +  + ]:         40 :   switch (transition) {
     959                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
     960                 :          5 :       gst_lamemp3enc_release_memory (lame);
     961                 :          5 :       break;
     962                 :            :     default:
     963                 :         35 :       break;
     964                 :            :   }
     965                 :            : 
     966                 :         40 :   return result;
     967                 :            : }
     968                 :            : 
     969                 :            : gboolean
     970                 :          7 : gst_lamemp3enc_register (GstPlugin * plugin)
     971                 :            : {
     972         [ +  - ]:          7 :   GST_DEBUG_CATEGORY_INIT (debug, "lamemp3enc", 0, "lame mp3 encoder");
     973                 :            : 
     974         [ -  + ]:          7 :   if (!gst_element_register (plugin, "lamemp3enc", GST_RANK_PRIMARY,
     975                 :            :           GST_TYPE_LAMEMP3ENC))
     976                 :          0 :     return FALSE;
     977                 :            : 
     978                 :          7 :   return TRUE;
     979                 :            : }

Generated by: LCOV version 1.9