gst_plugins_base/ext/vorbis/vorbisenc.c
branchRCL_3
changeset 30 7e817e7e631c
parent 0 0e761a78d257
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
       
     1 /* GStreamer
       
     2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /**
       
    21  * SECTION:element-vorbisenc
       
    22  * @short_description: an encoder that encodes audio to Vorbis
       
    23  * @see_also: vorbisdec, oggmux
       
    24  *
       
    25  * <refsect2>
       
    26  * <para>
       
    27  * This element encodes raw float audio into a Vorbis stream.
       
    28  * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
       
    29  * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
       
    30  * Foundation</ulink>.
       
    31  * </para>
       
    32  * <title>Example pipelines</title>
       
    33  * <para>
       
    34  * Encode a test sine signal to Ogg/Vorbis.  Note that the resulting file
       
    35  * will be really small because a sine signal compresses very well.
       
    36  * </para>
       
    37  * <programlisting>
       
    38  * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg
       
    39  * </programlisting>
       
    40  * <para>
       
    41  * Record from a sound card using ALSA and encode to Ogg/Vorbis.
       
    42  * </para>
       
    43  * <programlisting>
       
    44  * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
       
    45  * </programlisting>
       
    46  * </refsect2>
       
    47  *
       
    48  * Last reviewed on 2006-03-01 (0.10.4)
       
    49  */
       
    50 
       
    51 #ifdef HAVE_CONFIG_H
       
    52 #include "config.h"
       
    53 #endif
       
    54 #include <stdlib.h>
       
    55 #include <string.h>
       
    56 #include <time.h>
       
    57 #include <vorbis/vorbisenc.h>
       
    58 
       
    59 #include <gst/gsttagsetter.h>
       
    60 #include <gst/tag/tag.h>
       
    61 #include <gst/audio/multichannel.h>
       
    62 #include "vorbisenc.h"
       
    63 
       
    64 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
       
    65 #define GST_CAT_DEFAULT vorbisenc_debug
       
    66 
       
    67 static GstPadTemplate *gst_vorbis_enc_src_template,
       
    68     *gst_vorbis_enc_sink_template;
       
    69 
       
    70 /* elementfactory information */
       
    71 static const GstElementDetails vorbisenc_details =
       
    72 GST_ELEMENT_DETAILS ("Vorbis audio encoder",
       
    73     "Codec/Encoder/Audio",
       
    74     "Encodes audio in Vorbis format",
       
    75     "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
       
    76 
       
    77 enum
       
    78 {
       
    79   ARG_0,
       
    80   ARG_MAX_BITRATE,
       
    81   ARG_BITRATE,
       
    82   ARG_MIN_BITRATE,
       
    83   ARG_QUALITY,
       
    84   ARG_MANAGED,
       
    85   ARG_LAST_MESSAGE
       
    86 };
       
    87 
       
    88 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
       
    89 
       
    90 /* this function takes into account the granulepos_offset and the subgranule
       
    91  * time offset */
       
    92 static GstClockTime
       
    93 granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc,
       
    94     ogg_int64_t granulepos)
       
    95 {
       
    96   if (granulepos >= 0)
       
    97     return gst_util_uint64_scale ((guint64) granulepos
       
    98         + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency)
       
    99         + vorbisenc->subgranule_offset;
       
   100   return GST_CLOCK_TIME_NONE;
       
   101 }
       
   102 
       
   103 /* this function does a straight granulepos -> timestamp conversion */
       
   104 static GstClockTime
       
   105 granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos)
       
   106 {
       
   107   if (granulepos >= 0)
       
   108     return gst_util_uint64_scale ((guint64) granulepos,
       
   109         GST_SECOND, vorbisenc->frequency);
       
   110   return GST_CLOCK_TIME_NONE;
       
   111 }
       
   112 
       
   113 #define MAX_BITRATE_DEFAULT     -1
       
   114 #define BITRATE_DEFAULT         -1
       
   115 #define MIN_BITRATE_DEFAULT     -1
       
   116 #define QUALITY_DEFAULT         0.3
       
   117 #define LOWEST_BITRATE          6000    /* lowest allowed for a 8 kHz stream */
       
   118 #define HIGHEST_BITRATE         250001  /* highest allowed for a 44 kHz stream */
       
   119 
       
   120 static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event);
       
   121 static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer);
       
   122 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
       
   123 
       
   124 static void gst_vorbis_enc_dispose (GObject * object);
       
   125 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
       
   126     GValue * value, GParamSpec * pspec);
       
   127 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
       
   128     const GValue * value, GParamSpec * pspec);
       
   129 static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element,
       
   130     GstStateChange transition);
       
   131 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
       
   132 
       
   133 GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstElement,
       
   134     GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces);
       
   135 
       
   136 static void
       
   137 gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
       
   138 {
       
   139   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
       
   140 
       
   141   g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
       
   142       &tag_setter_info);
       
   143 }
       
   144 
       
   145 static GstCaps *
       
   146 vorbis_caps_factory (void)
       
   147 {
       
   148   return gst_caps_new_simple ("audio/x-vorbis", NULL);
       
   149 }
       
   150 
       
   151 static GstCaps *
       
   152 raw_caps_factory (void)
       
   153 {
       
   154   /* lowest, highest sample rates come from vorbis/lib/modes/setup_X.h:
       
   155    * 1-200000 Hz */
       
   156   return
       
   157       gst_caps_new_simple ("audio/x-raw-float",
       
   158       "rate", GST_TYPE_INT_RANGE, 1, 200000,
       
   159       "channels", GST_TYPE_INT_RANGE, 1, 256,
       
   160       "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
       
   161 }
       
   162 
       
   163 static void
       
   164 gst_vorbis_enc_base_init (gpointer g_class)
       
   165 {
       
   166   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
       
   167   GstCaps *raw_caps, *vorbis_caps;
       
   168 
       
   169   raw_caps = raw_caps_factory ();
       
   170   vorbis_caps = vorbis_caps_factory ();
       
   171 
       
   172   gst_vorbis_enc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
       
   173       GST_PAD_ALWAYS, raw_caps);
       
   174   gst_vorbis_enc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
       
   175       GST_PAD_ALWAYS, vorbis_caps);
       
   176   gst_element_class_add_pad_template (element_class,
       
   177       gst_vorbis_enc_sink_template);
       
   178   gst_element_class_add_pad_template (element_class,
       
   179       gst_vorbis_enc_src_template);
       
   180   gst_element_class_set_details (element_class, &vorbisenc_details);
       
   181 }
       
   182 
       
   183 static void
       
   184 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
       
   185 {
       
   186   GObjectClass *gobject_class;
       
   187   GstElementClass *gstelement_class;
       
   188 
       
   189   gobject_class = (GObjectClass *) klass;
       
   190   gstelement_class = (GstElementClass *) klass;
       
   191 
       
   192   gobject_class->set_property = gst_vorbis_enc_set_property;
       
   193   gobject_class->get_property = gst_vorbis_enc_get_property;
       
   194   gobject_class->dispose = gst_vorbis_enc_dispose;
       
   195 
       
   196   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
       
   197       g_param_spec_int ("max-bitrate", "Maximum Bitrate",
       
   198           "Specify a maximum bitrate (in bps). Useful for streaming "
       
   199           "applications. (-1 == disabled)",
       
   200           -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT, G_PARAM_READWRITE));
       
   201   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
       
   202       g_param_spec_int ("bitrate", "Target Bitrate",
       
   203           "Attempt to encode at a bitrate averaging this (in bps). "
       
   204           "This uses the bitrate management engine, and is not recommended for most users. "
       
   205           "Quality is a better alternative. (-1 == disabled)",
       
   206           -1, HIGHEST_BITRATE, BITRATE_DEFAULT, G_PARAM_READWRITE));
       
   207   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
       
   208       g_param_spec_int ("min_bitrate", "Minimum Bitrate",
       
   209           "Specify a minimum bitrate (in bps). Useful for encoding for a "
       
   210           "fixed-size channel. (-1 == disabled)",
       
   211           -1, HIGHEST_BITRATE, MIN_BITRATE_DEFAULT, G_PARAM_READWRITE));
       
   212   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
       
   213       g_param_spec_float ("quality", "Quality",
       
   214           "Specify quality instead of specifying a particular bitrate.",
       
   215           -0.1, 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE));
       
   216   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
       
   217       g_param_spec_boolean ("managed", "Managed",
       
   218           "Enable bitrate management engine", FALSE, G_PARAM_READWRITE));
       
   219   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
       
   220       g_param_spec_string ("last-message", "last-message",
       
   221           "The last status message", NULL, G_PARAM_READABLE));
       
   222 
       
   223   gstelement_class->change_state =
       
   224       GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state);
       
   225 }
       
   226 
       
   227 static void
       
   228 gst_vorbis_enc_dispose (GObject * object)
       
   229 {
       
   230   GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
       
   231 
       
   232   if (vorbisenc->sinkcaps) {
       
   233     gst_caps_unref (vorbisenc->sinkcaps);
       
   234     vorbisenc->sinkcaps = NULL;
       
   235   }
       
   236 
       
   237   G_OBJECT_CLASS (parent_class)->dispose (object);
       
   238 }
       
   239 
       
   240 static const GstAudioChannelPosition vorbischannelpositions[][6] = {
       
   241   {                             /* Mono */
       
   242       GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
       
   243   {                             /* Stereo */
       
   244         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   245       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
       
   246   {                             /* Stereo + Centre */
       
   247         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   248         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   249       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
       
   250   {                             /* Quadraphonic */
       
   251         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   252         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   253         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   254         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   255       },
       
   256   {                             /* Stereo + Centre + rear stereo */
       
   257         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   258         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   259         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   260         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   261         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   262       },
       
   263   {                             /* Full 5.1 Surround */
       
   264         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   265         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   266         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   267         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   268         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   269         GST_AUDIO_CHANNEL_POSITION_LFE,
       
   270       },
       
   271 };
       
   272 static GstCaps *
       
   273 gst_vorbis_enc_generate_sink_caps (void)
       
   274 {
       
   275   GstCaps *caps = gst_caps_new_empty ();
       
   276   int i, c;
       
   277 
       
   278   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
       
   279           "rate", GST_TYPE_INT_RANGE, 1, 200000,
       
   280           "channels", G_TYPE_INT, 1,
       
   281           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
       
   282           NULL));
       
   283 
       
   284   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
       
   285           "rate", GST_TYPE_INT_RANGE, 1, 200000,
       
   286           "channels", G_TYPE_INT, 2,
       
   287           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
       
   288           NULL));
       
   289 
       
   290   for (i = 3; i <= 6; i++) {
       
   291     GValue chanpos = { 0 };
       
   292     GValue pos = { 0 };
       
   293     GstStructure *structure;
       
   294 
       
   295     g_value_init (&chanpos, GST_TYPE_ARRAY);
       
   296     g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
       
   297 
       
   298     for (c = 0; c < i; c++) {
       
   299       g_value_set_enum (&pos, vorbischannelpositions[i - 1][c]);
       
   300       gst_value_array_append_value (&chanpos, &pos);
       
   301     }
       
   302     g_value_unset (&pos);
       
   303 
       
   304     structure = gst_structure_new ("audio/x-raw-float",
       
   305         "rate", GST_TYPE_INT_RANGE, 1, 200000,
       
   306         "channels", G_TYPE_INT, i,
       
   307         "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
       
   308     gst_structure_set_value (structure, "channel-positions", &chanpos);
       
   309     g_value_unset (&chanpos);
       
   310 
       
   311     gst_caps_append_structure (caps, structure);
       
   312   }
       
   313 
       
   314   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
       
   315           "rate", GST_TYPE_INT_RANGE, 1, 200000,
       
   316           "channels", GST_TYPE_INT_RANGE, 7, 256,
       
   317           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
       
   318           NULL));
       
   319 
       
   320   return caps;
       
   321 }
       
   322 
       
   323 static GstCaps *
       
   324 gst_vorbis_enc_sink_getcaps (GstPad * pad)
       
   325 {
       
   326   GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
       
   327 
       
   328   if (vorbisenc->sinkcaps == NULL)
       
   329     vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
       
   330 
       
   331   return gst_caps_ref (vorbisenc->sinkcaps);
       
   332 }
       
   333 
       
   334 static gboolean
       
   335 gst_vorbis_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
       
   336 {
       
   337   GstVorbisEnc *vorbisenc;
       
   338   GstStructure *structure;
       
   339 
       
   340   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
       
   341   vorbisenc->setup = FALSE;
       
   342 
       
   343   structure = gst_caps_get_structure (caps, 0);
       
   344   gst_structure_get_int (structure, "channels", &vorbisenc->channels);
       
   345   gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
       
   346 
       
   347   gst_vorbis_enc_setup (vorbisenc);
       
   348 
       
   349   if (vorbisenc->setup)
       
   350     return TRUE;
       
   351 
       
   352   return FALSE;
       
   353 }
       
   354 
       
   355 static gboolean
       
   356 gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format,
       
   357     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
       
   358 {
       
   359   gboolean res = TRUE;
       
   360   GstVorbisEnc *vorbisenc;
       
   361   gint64 avg;
       
   362 
       
   363   vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
       
   364 
       
   365   if (vorbisenc->samples_in == 0 ||
       
   366       vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) {
       
   367     gst_object_unref (vorbisenc);
       
   368     return FALSE;
       
   369   }
       
   370 
       
   371   avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
       
   372 
       
   373   switch (src_format) {
       
   374     case GST_FORMAT_BYTES:
       
   375       switch (*dest_format) {
       
   376         case GST_FORMAT_TIME:
       
   377           *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg);
       
   378           break;
       
   379         default:
       
   380           res = FALSE;
       
   381       }
       
   382       break;
       
   383     case GST_FORMAT_TIME:
       
   384       switch (*dest_format) {
       
   385         case GST_FORMAT_BYTES:
       
   386           *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND);
       
   387           break;
       
   388         default:
       
   389           res = FALSE;
       
   390       }
       
   391       break;
       
   392     default:
       
   393       res = FALSE;
       
   394   }
       
   395   gst_object_unref (vorbisenc);
       
   396   return res;
       
   397 }
       
   398 
       
   399 static gboolean
       
   400 gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format,
       
   401     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
       
   402 {
       
   403   gboolean res = TRUE;
       
   404   guint scale = 1;
       
   405   gint bytes_per_sample;
       
   406   GstVorbisEnc *vorbisenc;
       
   407 
       
   408   vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
       
   409 
       
   410   bytes_per_sample = vorbisenc->channels * 2;
       
   411 
       
   412   switch (src_format) {
       
   413     case GST_FORMAT_BYTES:
       
   414       switch (*dest_format) {
       
   415         case GST_FORMAT_DEFAULT:
       
   416           if (bytes_per_sample == 0)
       
   417             return FALSE;
       
   418           *dest_value = src_value / bytes_per_sample;
       
   419           break;
       
   420         case GST_FORMAT_TIME:
       
   421         {
       
   422           gint byterate = bytes_per_sample * vorbisenc->frequency;
       
   423 
       
   424           if (byterate == 0)
       
   425             return FALSE;
       
   426           *dest_value =
       
   427               gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
       
   428           break;
       
   429         }
       
   430         default:
       
   431           res = FALSE;
       
   432       }
       
   433       break;
       
   434     case GST_FORMAT_DEFAULT:
       
   435       switch (*dest_format) {
       
   436         case GST_FORMAT_BYTES:
       
   437           *dest_value = src_value * bytes_per_sample;
       
   438           break;
       
   439         case GST_FORMAT_TIME:
       
   440           if (vorbisenc->frequency == 0)
       
   441             return FALSE;
       
   442           *dest_value =
       
   443               gst_util_uint64_scale_int (src_value, GST_SECOND,
       
   444               vorbisenc->frequency);
       
   445           break;
       
   446         default:
       
   447           res = FALSE;
       
   448       }
       
   449       break;
       
   450     case GST_FORMAT_TIME:
       
   451       switch (*dest_format) {
       
   452         case GST_FORMAT_BYTES:
       
   453           scale = bytes_per_sample;
       
   454           /* fallthrough */
       
   455         case GST_FORMAT_DEFAULT:
       
   456           *dest_value =
       
   457               gst_util_uint64_scale_int (src_value,
       
   458               scale * vorbisenc->frequency, GST_SECOND);
       
   459           break;
       
   460         default:
       
   461           res = FALSE;
       
   462       }
       
   463       break;
       
   464     default:
       
   465       res = FALSE;
       
   466   }
       
   467   gst_object_unref (vorbisenc);
       
   468   return res;
       
   469 }
       
   470 
       
   471 static const GstQueryType *
       
   472 gst_vorbis_enc_get_query_types (GstPad * pad)
       
   473 {
       
   474   static const GstQueryType gst_vorbis_enc_src_query_types[] = {
       
   475     GST_QUERY_POSITION,
       
   476     GST_QUERY_DURATION,
       
   477     GST_QUERY_CONVERT,
       
   478     0
       
   479   };
       
   480 
       
   481   return gst_vorbis_enc_src_query_types;
       
   482 }
       
   483 
       
   484 static gboolean
       
   485 gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
       
   486 {
       
   487   gboolean res = TRUE;
       
   488   GstVorbisEnc *vorbisenc;
       
   489   GstPad *peerpad;
       
   490 
       
   491   vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
       
   492   peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));
       
   493 
       
   494   switch (GST_QUERY_TYPE (query)) {
       
   495     case GST_QUERY_POSITION:
       
   496     {
       
   497       GstFormat fmt, req_fmt;
       
   498       gint64 pos, val;
       
   499 
       
   500       gst_query_parse_position (query, &req_fmt, NULL);
       
   501       if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
       
   502         gst_query_set_position (query, req_fmt, val);
       
   503         break;
       
   504       }
       
   505 
       
   506       fmt = GST_FORMAT_TIME;
       
   507       if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
       
   508         break;
       
   509 
       
   510       if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
       
   511         gst_query_set_position (query, req_fmt, val);
       
   512       }
       
   513       break;
       
   514     }
       
   515     case GST_QUERY_DURATION:
       
   516     {
       
   517       GstFormat fmt, req_fmt;
       
   518       gint64 dur, val;
       
   519 
       
   520       gst_query_parse_duration (query, &req_fmt, NULL);
       
   521       if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
       
   522         gst_query_set_duration (query, req_fmt, val);
       
   523         break;
       
   524       }
       
   525 
       
   526       fmt = GST_FORMAT_TIME;
       
   527       if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
       
   528         break;
       
   529 
       
   530       if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
       
   531         gst_query_set_duration (query, req_fmt, val);
       
   532       }
       
   533       break;
       
   534     }
       
   535     case GST_QUERY_CONVERT:
       
   536     {
       
   537       GstFormat src_fmt, dest_fmt;
       
   538       gint64 src_val, dest_val;
       
   539 
       
   540       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
       
   541       if (!(res =
       
   542               gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
       
   543                   &dest_val)))
       
   544         goto error;
       
   545       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
       
   546       break;
       
   547     }
       
   548     default:
       
   549       res = gst_pad_query_default (pad, query);
       
   550       break;
       
   551   }
       
   552 
       
   553 error:
       
   554   gst_object_unref (peerpad);
       
   555   gst_object_unref (vorbisenc);
       
   556   return res;
       
   557 }
       
   558 
       
   559 static gboolean
       
   560 gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query)
       
   561 {
       
   562   gboolean res = TRUE;
       
   563   GstVorbisEnc *vorbisenc;
       
   564 
       
   565   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
       
   566 
       
   567   switch (GST_QUERY_TYPE (query)) {
       
   568     case GST_QUERY_CONVERT:
       
   569     {
       
   570       GstFormat src_fmt, dest_fmt;
       
   571       gint64 src_val, dest_val;
       
   572 
       
   573       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
       
   574       if (!(res =
       
   575               gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
       
   576                   &dest_val)))
       
   577         goto error;
       
   578       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
       
   579       break;
       
   580     }
       
   581     default:
       
   582       res = gst_pad_query_default (pad, query);
       
   583       break;
       
   584   }
       
   585 
       
   586 error:
       
   587   return res;
       
   588 }
       
   589 
       
   590 static void
       
   591 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
       
   592 {
       
   593   vorbisenc->sinkpad =
       
   594       gst_pad_new_from_template (gst_vorbis_enc_sink_template, "sink");
       
   595   gst_pad_set_event_function (vorbisenc->sinkpad,
       
   596       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event));
       
   597   gst_pad_set_chain_function (vorbisenc->sinkpad,
       
   598       GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain));
       
   599   gst_pad_set_setcaps_function (vorbisenc->sinkpad,
       
   600       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_setcaps));
       
   601   gst_pad_set_getcaps_function (vorbisenc->sinkpad,
       
   602       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps));
       
   603   gst_pad_set_query_function (vorbisenc->sinkpad,
       
   604       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query));
       
   605   gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
       
   606 
       
   607   vorbisenc->srcpad =
       
   608       gst_pad_new_from_template (gst_vorbis_enc_src_template, "src");
       
   609   gst_pad_set_query_function (vorbisenc->srcpad,
       
   610       GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query));
       
   611   gst_pad_set_query_type_function (vorbisenc->srcpad,
       
   612       GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types));
       
   613   gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
       
   614 
       
   615   vorbisenc->channels = -1;
       
   616   vorbisenc->frequency = -1;
       
   617 
       
   618   vorbisenc->managed = FALSE;
       
   619   vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
       
   620   vorbisenc->bitrate = BITRATE_DEFAULT;
       
   621   vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
       
   622   vorbisenc->quality = QUALITY_DEFAULT;
       
   623   vorbisenc->quality_set = FALSE;
       
   624   vorbisenc->last_message = NULL;
       
   625 }
       
   626 
       
   627 static void
       
   628 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
       
   629     gpointer vorbisenc)
       
   630 {
       
   631   GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
       
   632   GList *vc_list, *l;
       
   633 
       
   634   vc_list = gst_tag_to_vorbis_comments (list, tag);
       
   635 
       
   636   for (l = vc_list; l != NULL; l = l->next) {
       
   637     const gchar *vc_string = (const gchar *) l->data;
       
   638     gchar *key = NULL, *val = NULL;
       
   639 
       
   640     GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
       
   641     if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
       
   642       vorbis_comment_add_tag (&enc->vc, key, val);
       
   643       g_free (key);
       
   644       g_free (val);
       
   645     }
       
   646   }
       
   647 
       
   648   g_list_foreach (vc_list, (GFunc) g_free, NULL);
       
   649   g_list_free (vc_list);
       
   650 }
       
   651 
       
   652 static void
       
   653 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
       
   654 {
       
   655   GstTagList *merged_tags;
       
   656   const GstTagList *user_tags;
       
   657 
       
   658   vorbis_comment_init (&enc->vc);
       
   659 
       
   660   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
       
   661 
       
   662   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
       
   663   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
       
   664 
       
   665   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
       
   666   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
       
   667       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
       
   668 
       
   669   if (merged_tags) {
       
   670     GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
       
   671     gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
       
   672     gst_tag_list_free (merged_tags);
       
   673   }
       
   674 }
       
   675 
       
   676 static gchar *
       
   677 get_constraints_string (GstVorbisEnc * vorbisenc)
       
   678 {
       
   679   gint min = vorbisenc->min_bitrate;
       
   680   gint max = vorbisenc->max_bitrate;
       
   681   gchar *result;
       
   682 
       
   683   if (min > 0 && max > 0)
       
   684     result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
       
   685   else if (min > 0)
       
   686     result = g_strdup_printf ("(min %d bps, no max)", min);
       
   687   else if (max > 0)
       
   688     result = g_strdup_printf ("(no min, max %d bps)", max);
       
   689   else
       
   690     result = g_strdup_printf ("(no min or max)");
       
   691 
       
   692   return result;
       
   693 }
       
   694 
       
   695 static void
       
   696 update_start_message (GstVorbisEnc * vorbisenc)
       
   697 {
       
   698   gchar *constraints;
       
   699 
       
   700   g_free (vorbisenc->last_message);
       
   701 
       
   702   if (vorbisenc->bitrate > 0) {
       
   703     if (vorbisenc->managed) {
       
   704       constraints = get_constraints_string (vorbisenc);
       
   705       vorbisenc->last_message =
       
   706           g_strdup_printf ("encoding at average bitrate %d bps %s",
       
   707           vorbisenc->bitrate, constraints);
       
   708       g_free (constraints);
       
   709     } else {
       
   710       vorbisenc->last_message =
       
   711           g_strdup_printf
       
   712           ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
       
   713           vorbisenc->bitrate);
       
   714     }
       
   715   } else {
       
   716     if (vorbisenc->quality_set) {
       
   717       if (vorbisenc->managed) {
       
   718         constraints = get_constraints_string (vorbisenc);
       
   719         vorbisenc->last_message =
       
   720             g_strdup_printf
       
   721             ("encoding at quality level %2.2f using constrained VBR %s",
       
   722             vorbisenc->quality, constraints);
       
   723         g_free (constraints);
       
   724       } else {
       
   725         vorbisenc->last_message =
       
   726             g_strdup_printf ("encoding at quality level %2.2f",
       
   727             vorbisenc->quality);
       
   728       }
       
   729     } else {
       
   730       constraints = get_constraints_string (vorbisenc);
       
   731       vorbisenc->last_message =
       
   732           g_strdup_printf ("encoding using bitrate management %s", constraints);
       
   733       g_free (constraints);
       
   734     }
       
   735   }
       
   736 
       
   737   g_object_notify (G_OBJECT (vorbisenc), "last_message");
       
   738 }
       
   739 
       
   740 static gboolean
       
   741 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
       
   742 {
       
   743   vorbisenc->setup = FALSE;
       
   744 
       
   745   if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
       
   746       && vorbisenc->max_bitrate < 0) {
       
   747     vorbisenc->quality_set = TRUE;
       
   748   }
       
   749 
       
   750   update_start_message (vorbisenc);
       
   751 
       
   752   /* choose an encoding mode */
       
   753   /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
       
   754   vorbis_info_init (&vorbisenc->vi);
       
   755 
       
   756   if (vorbisenc->quality_set) {
       
   757     if (vorbis_encode_setup_vbr (&vorbisenc->vi,
       
   758             vorbisenc->channels, vorbisenc->frequency,
       
   759             vorbisenc->quality) != 0) {
       
   760       GST_ERROR_OBJECT (vorbisenc,
       
   761           "vorbisenc: initialisation failed: invalid parameters for quality");
       
   762       vorbis_info_clear (&vorbisenc->vi);
       
   763       return FALSE;
       
   764     }
       
   765 
       
   766     /* do we have optional hard quality restrictions? */
       
   767     if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
       
   768       struct ovectl_ratemanage_arg ai;
       
   769 
       
   770       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
       
   771 
       
   772       ai.bitrate_hard_min = vorbisenc->min_bitrate;
       
   773       ai.bitrate_hard_max = vorbisenc->max_bitrate;
       
   774       ai.management_active = 1;
       
   775 
       
   776       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
       
   777     }
       
   778   } else {
       
   779     long min_bitrate, max_bitrate;
       
   780 
       
   781     min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
       
   782     max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
       
   783 
       
   784     if (vorbis_encode_setup_managed (&vorbisenc->vi,
       
   785             vorbisenc->channels,
       
   786             vorbisenc->frequency,
       
   787             max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
       
   788       GST_ERROR_OBJECT (vorbisenc,
       
   789           "vorbis_encode_setup_managed "
       
   790           "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
       
   791           vorbisenc->channels, vorbisenc->frequency, max_bitrate,
       
   792           vorbisenc->bitrate, min_bitrate);
       
   793       vorbis_info_clear (&vorbisenc->vi);
       
   794       return FALSE;
       
   795     }
       
   796   }
       
   797 
       
   798   if (vorbisenc->managed && vorbisenc->bitrate < 0) {
       
   799     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
       
   800   } else if (!vorbisenc->managed) {
       
   801     /* Turn off management entirely (if it was turned on). */
       
   802     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
       
   803   }
       
   804   vorbis_encode_setup_init (&vorbisenc->vi);
       
   805 
       
   806   /* set up the analysis state and auxiliary encoding storage */
       
   807   vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
       
   808   vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
       
   809 
       
   810   vorbisenc->next_ts = 0;
       
   811 
       
   812   vorbisenc->setup = TRUE;
       
   813 
       
   814   return TRUE;
       
   815 }
       
   816 
       
   817 static GstFlowReturn
       
   818 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
       
   819 {
       
   820   GstFlowReturn ret = GST_FLOW_OK;
       
   821 
       
   822   if (vorbisenc->setup) {
       
   823     vorbis_analysis_wrote (&vorbisenc->vd, 0);
       
   824     ret = gst_vorbis_enc_output_buffers (vorbisenc);
       
   825 
       
   826     vorbisenc->setup = FALSE;
       
   827   }
       
   828 
       
   829   /* clean up and exit.  vorbis_info_clear() must be called last */
       
   830   vorbis_block_clear (&vorbisenc->vb);
       
   831   vorbis_dsp_clear (&vorbisenc->vd);
       
   832   vorbis_info_clear (&vorbisenc->vi);
       
   833 
       
   834   vorbisenc->header_sent = FALSE;
       
   835 
       
   836   return ret;
       
   837 }
       
   838 
       
   839 /* prepare a buffer for transmission by passing data through libvorbis */
       
   840 static GstBuffer *
       
   841 gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc,
       
   842     ogg_packet * packet)
       
   843 {
       
   844   GstBuffer *outbuf;
       
   845 
       
   846   outbuf = gst_buffer_new_and_alloc (packet->bytes);
       
   847   memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
       
   848   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
       
   849    * time representation */
       
   850   GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos +
       
   851       vorbisenc->granulepos_offset;
       
   852   GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc,
       
   853       GST_BUFFER_OFFSET_END (outbuf));
       
   854   GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts;
       
   855 
       
   856   /* update the next timestamp, taking granulepos_offset and subgranule offset
       
   857    * into account */
       
   858   vorbisenc->next_ts =
       
   859       granulepos_to_timestamp_offset (vorbisenc, packet->granulepos);
       
   860   GST_BUFFER_DURATION (outbuf) =
       
   861       vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
       
   862 
       
   863   if (vorbisenc->next_discont) {
       
   864     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
       
   865     vorbisenc->next_discont = FALSE;
       
   866   }
       
   867 
       
   868   GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes",
       
   869       GST_BUFFER_SIZE (outbuf));
       
   870   return outbuf;
       
   871 }
       
   872 
       
   873 /* the same as above, but different logic for setting timestamp and granulepos
       
   874  * */
       
   875 static GstBuffer *
       
   876 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
       
   877     ogg_packet * packet)
       
   878 {
       
   879   GstBuffer *outbuf;
       
   880 
       
   881   outbuf = gst_buffer_new_and_alloc (packet->bytes);
       
   882   memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
       
   883   GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
       
   884   GST_BUFFER_OFFSET_END (outbuf) = 0;
       
   885   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
       
   886   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
       
   887 
       
   888   gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
       
   889 
       
   890   GST_DEBUG ("created header packet buffer, %d bytes",
       
   891       GST_BUFFER_SIZE (outbuf));
       
   892   return outbuf;
       
   893 }
       
   894 
       
   895 /* push out the buffer and do internal bookkeeping */
       
   896 static GstFlowReturn
       
   897 gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
       
   898 {
       
   899   vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
       
   900 
       
   901   GST_DEBUG_OBJECT (vorbisenc, "Pushing buffer with GP %lld, ts %lld",
       
   902       GST_BUFFER_OFFSET_END (buffer), GST_BUFFER_TIMESTAMP (buffer));
       
   903   return gst_pad_push (vorbisenc->srcpad, buffer);
       
   904 }
       
   905 
       
   906 static GstFlowReturn
       
   907 gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
       
   908 {
       
   909   GstBuffer *outbuf;
       
   910 
       
   911   outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet);
       
   912   return gst_vorbis_enc_push_buffer (vorbisenc, outbuf);
       
   913 }
       
   914 
       
   915 /* Set a copy of these buffers as 'streamheader' on the caps.
       
   916  * We need a copy to avoid these buffers ending up with (indirect) refs on
       
   917  * themselves
       
   918  */
       
   919 static GstCaps *
       
   920 gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
       
   921     GstBuffer * buf2, GstBuffer * buf3)
       
   922 {
       
   923   GstBuffer *buf;
       
   924   GstStructure *structure;
       
   925   GValue array = { 0 };
       
   926   GValue value = { 0 };
       
   927 
       
   928   caps = gst_caps_make_writable (caps);
       
   929   structure = gst_caps_get_structure (caps, 0);
       
   930 
       
   931   /* mark buffers */
       
   932   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
       
   933   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
       
   934   GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
       
   935 
       
   936   /* put buffers in a fixed list */
       
   937   g_value_init (&array, GST_TYPE_ARRAY);
       
   938   g_value_init (&value, GST_TYPE_BUFFER);
       
   939   buf = gst_buffer_copy (buf1);
       
   940   gst_value_set_buffer (&value, buf);
       
   941   gst_buffer_unref (buf);
       
   942   gst_value_array_append_value (&array, &value);
       
   943   g_value_unset (&value);
       
   944   g_value_init (&value, GST_TYPE_BUFFER);
       
   945   buf = gst_buffer_copy (buf2);
       
   946   gst_value_set_buffer (&value, buf);
       
   947   gst_buffer_unref (buf);
       
   948   gst_value_array_append_value (&array, &value);
       
   949   g_value_unset (&value);
       
   950   g_value_init (&value, GST_TYPE_BUFFER);
       
   951   buf = gst_buffer_copy (buf3);
       
   952   gst_value_set_buffer (&value, buf);
       
   953   gst_buffer_unref (buf);
       
   954   gst_value_array_append_value (&array, &value);
       
   955   gst_structure_set_value (structure, "streamheader", &array);
       
   956   g_value_unset (&value);
       
   957   g_value_unset (&array);
       
   958 
       
   959   return caps;
       
   960 }
       
   961 
       
   962 static gboolean
       
   963 gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
       
   964 {
       
   965   gboolean res = TRUE;
       
   966   GstVorbisEnc *vorbisenc;
       
   967 
       
   968   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
       
   969 
       
   970   switch (GST_EVENT_TYPE (event)) {
       
   971     case GST_EVENT_EOS:
       
   972       /* Tell the library we're at end of stream so that it can handle
       
   973        * the last frame and mark end of stream in the output properly */
       
   974       GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
       
   975       gst_vorbis_enc_clear (vorbisenc);
       
   976 
       
   977       res = gst_pad_push_event (vorbisenc->srcpad, event);
       
   978       break;
       
   979     case GST_EVENT_TAG:
       
   980       if (vorbisenc->tags) {
       
   981         GstTagList *list;
       
   982 
       
   983         gst_event_parse_tag (event, &list);
       
   984         gst_tag_list_insert (vorbisenc->tags, list,
       
   985             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
       
   986       } else {
       
   987         g_assert_not_reached ();
       
   988       }
       
   989       res = gst_pad_push_event (vorbisenc->srcpad, event);
       
   990       break;
       
   991     default:
       
   992       res = gst_pad_push_event (vorbisenc->srcpad, event);
       
   993       break;
       
   994   }
       
   995   return res;
       
   996 }
       
   997 
       
   998 static gboolean
       
   999 gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
       
  1000     GstBuffer * buffer)
       
  1001 {
       
  1002   gboolean ret = FALSE;
       
  1003 
       
  1004   if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
       
  1005       vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
       
  1006       GST_BUFFER_TIMESTAMP (buffer) != vorbisenc->expected_ts) {
       
  1007     /* It turns out that a lot of elements don't generate perfect streams due
       
  1008      * to rounding errors. So, we permit small errors (< 1/2 a sample) without
       
  1009      * causing a discont.
       
  1010      */
       
  1011     int halfsample = GST_SECOND / vorbisenc->frequency / 2;
       
  1012 
       
  1013     if ((GstClockTimeDiff) (GST_BUFFER_TIMESTAMP (buffer) -
       
  1014             vorbisenc->expected_ts) > halfsample) {
       
  1015       GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
       
  1016           ", buffer TS %" GST_TIME_FORMAT,
       
  1017           GST_TIME_ARGS (vorbisenc->expected_ts),
       
  1018           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
       
  1019       ret = TRUE;
       
  1020     }
       
  1021   }
       
  1022 
       
  1023   if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
       
  1024       GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE) {
       
  1025     vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer) +
       
  1026         GST_BUFFER_DURATION (buffer);
       
  1027   } else
       
  1028     vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
       
  1029 
       
  1030   return ret;
       
  1031 }
       
  1032 
       
  1033 static GstFlowReturn
       
  1034 gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
       
  1035 {
       
  1036   GstVorbisEnc *vorbisenc;
       
  1037   GstFlowReturn ret = GST_FLOW_OK;
       
  1038   gfloat *data;
       
  1039   gulong size;
       
  1040   gulong i, j;
       
  1041   float **vorbis_buffer;
       
  1042   GstBuffer *buf1, *buf2, *buf3;
       
  1043   gboolean first = FALSE;
       
  1044 
       
  1045   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
       
  1046 
       
  1047   if (!vorbisenc->setup)
       
  1048     goto not_setup;
       
  1049 
       
  1050   if (!vorbisenc->header_sent) {
       
  1051     /* Vorbis streams begin with three headers; the initial header (with
       
  1052        most of the codec setup parameters) which is mandated by the Ogg
       
  1053        bitstream spec.  The second header holds any comment fields.  The
       
  1054        third header holds the bitstream codebook.  We merely need to
       
  1055        make the headers, then pass them to libvorbis one at a time;
       
  1056        libvorbis handles the additional Ogg bitstream constraints */
       
  1057     ogg_packet header;
       
  1058     ogg_packet header_comm;
       
  1059     ogg_packet header_code;
       
  1060     GstCaps *caps;
       
  1061 
       
  1062     /* first, make sure header buffers get timestamp == 0 */
       
  1063     vorbisenc->next_ts = 0;
       
  1064     vorbisenc->granulepos_offset = 0;
       
  1065     vorbisenc->subgranule_offset = 0;
       
  1066 
       
  1067     GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
       
  1068     gst_vorbis_enc_set_metadata (vorbisenc);
       
  1069     vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
       
  1070         &header_comm, &header_code);
       
  1071     vorbis_comment_clear (&vorbisenc->vc);
       
  1072 
       
  1073     /* create header buffers */
       
  1074     buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
       
  1075     buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
       
  1076     buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
       
  1077 
       
  1078     /* mark and put on caps */
       
  1079     vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
       
  1080     caps = vorbisenc->srccaps;
       
  1081     caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3);
       
  1082 
       
  1083     /* negotiate with these caps */
       
  1084     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
       
  1085     gst_pad_set_caps (vorbisenc->srcpad, caps);
       
  1086 
       
  1087     gst_buffer_set_caps (buf1, caps);
       
  1088     gst_buffer_set_caps (buf2, caps);
       
  1089     gst_buffer_set_caps (buf3, caps);
       
  1090 
       
  1091     /* push out buffers */
       
  1092     /* push_buffer takes the reference even for failure */
       
  1093     if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
       
  1094       goto failed_header_push;
       
  1095     if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) {
       
  1096       buf2 = NULL;
       
  1097       goto failed_header_push;
       
  1098     }
       
  1099     if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) {
       
  1100       buf3 = NULL;
       
  1101       goto failed_header_push;
       
  1102     }
       
  1103 
       
  1104     /* now adjust starting granulepos accordingly if the buffer's timestamp is
       
  1105        nonzero */
       
  1106     vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
       
  1107     vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer);
       
  1108     vorbisenc->granulepos_offset = gst_util_uint64_scale
       
  1109         (GST_BUFFER_TIMESTAMP (buffer), vorbisenc->frequency, GST_SECOND);
       
  1110     vorbisenc->subgranule_offset = 0;
       
  1111     vorbisenc->subgranule_offset =
       
  1112         vorbisenc->next_ts - granulepos_to_timestamp_offset (vorbisenc, 0);
       
  1113 
       
  1114     vorbisenc->header_sent = TRUE;
       
  1115     first = TRUE;
       
  1116   }
       
  1117 
       
  1118   if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
       
  1119       GST_BUFFER_TIMESTAMP (buffer) < vorbisenc->expected_ts) {
       
  1120     GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
       
  1121         "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
       
  1122         "), cannot handle. Dropping buffer.",
       
  1123         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
       
  1124         GST_TIME_ARGS (vorbisenc->expected_ts));
       
  1125     gst_buffer_unref (buffer);
       
  1126     return GST_FLOW_OK;
       
  1127   }
       
  1128 
       
  1129   if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, buffer) && !first) {
       
  1130     GST_WARNING_OBJECT (vorbisenc, "Buffer is discontinuous, flushing encoder "
       
  1131         "and restarting (Discont from %" GST_TIME_FORMAT
       
  1132         " to %" GST_TIME_FORMAT ")", GST_TIME_ARGS (vorbisenc->next_ts),
       
  1133         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
       
  1134     /* Re-initialise encoder (there's unfortunately no API to flush it) */
       
  1135     if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
       
  1136       return ret;
       
  1137     if (!gst_vorbis_enc_setup (vorbisenc))
       
  1138       return GST_FLOW_ERROR;    /* Should be impossible, we can only get here if
       
  1139                                    we successfully initialised earlier */
       
  1140 
       
  1141     /* Now, set our granulepos offset appropriately. */
       
  1142     vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
       
  1143     /* We need to round to the nearest whole number of samples, not just do
       
  1144      * a truncating division here */
       
  1145     vorbisenc->granulepos_offset = gst_util_uint64_scale
       
  1146         (GST_BUFFER_TIMESTAMP (buffer) + GST_SECOND / vorbisenc->frequency / 2
       
  1147         - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
       
  1148 
       
  1149     vorbisenc->header_sent = TRUE;
       
  1150 
       
  1151     /* And our next output buffer must have DISCONT set on it */
       
  1152     vorbisenc->next_discont = TRUE;
       
  1153   }
       
  1154 
       
  1155   /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */
       
  1156   if (GST_BUFFER_SIZE (buffer) == 0) {
       
  1157     gst_buffer_unref (buffer);
       
  1158     return GST_FLOW_OK;
       
  1159   }
       
  1160 
       
  1161   /* data to encode */
       
  1162   data = (gfloat *) GST_BUFFER_DATA (buffer);
       
  1163   size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
       
  1164 
       
  1165   /* expose the buffer to submit data */
       
  1166   vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
       
  1167 
       
  1168   /* deinterleave samples, write the buffer data */
       
  1169   for (i = 0; i < size; i++) {
       
  1170     for (j = 0; j < vorbisenc->channels; j++) {
       
  1171       vorbis_buffer[j][i] = *data++;
       
  1172     }
       
  1173   }
       
  1174 
       
  1175   /* tell the library how much we actually submitted */
       
  1176   vorbis_analysis_wrote (&vorbisenc->vd, size);
       
  1177 
       
  1178   vorbisenc->samples_in += size;
       
  1179 
       
  1180   gst_buffer_unref (buffer);
       
  1181 
       
  1182   ret = gst_vorbis_enc_output_buffers (vorbisenc);
       
  1183 
       
  1184   return ret;
       
  1185 
       
  1186   /* error cases */
       
  1187 not_setup:
       
  1188   {
       
  1189     gst_buffer_unref (buffer);
       
  1190     GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
       
  1191         ("encoder not initialized (input is not audio?)"));
       
  1192     return GST_FLOW_UNEXPECTED;
       
  1193   }
       
  1194 failed_header_push:
       
  1195   {
       
  1196     GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
       
  1197     /* buf1 is always already unreffed */
       
  1198     if (buf2)
       
  1199       gst_buffer_unref (buf2);
       
  1200     if (buf3)
       
  1201       gst_buffer_unref (buf3);
       
  1202     gst_buffer_unref (buffer);
       
  1203     return ret;
       
  1204   }
       
  1205 }
       
  1206 
       
  1207 static GstFlowReturn
       
  1208 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
       
  1209 {
       
  1210   GstFlowReturn ret;
       
  1211 
       
  1212   /* vorbis does some data preanalysis, then divides up blocks for
       
  1213      more involved (potentially parallel) processing.  Get a single
       
  1214      block for encoding now */
       
  1215   while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
       
  1216     ogg_packet op;
       
  1217 
       
  1218     GST_LOG_OBJECT (vorbisenc, "analysed to a block");
       
  1219 
       
  1220     /* analysis */
       
  1221     vorbis_analysis (&vorbisenc->vb, NULL);
       
  1222     vorbis_bitrate_addblock (&vorbisenc->vb);
       
  1223 
       
  1224     while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
       
  1225       GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
       
  1226       ret = gst_vorbis_enc_push_packet (vorbisenc, &op);
       
  1227 
       
  1228       if (ret != GST_FLOW_OK)
       
  1229         return ret;
       
  1230     }
       
  1231   }
       
  1232 
       
  1233   return GST_FLOW_OK;
       
  1234 }
       
  1235 
       
  1236 static void
       
  1237 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
       
  1238     GParamSpec * pspec)
       
  1239 {
       
  1240   GstVorbisEnc *vorbisenc;
       
  1241 
       
  1242   g_return_if_fail (GST_IS_VORBISENC (object));
       
  1243 
       
  1244   vorbisenc = GST_VORBISENC (object);
       
  1245 
       
  1246   switch (prop_id) {
       
  1247     case ARG_MAX_BITRATE:
       
  1248       g_value_set_int (value, vorbisenc->max_bitrate);
       
  1249       break;
       
  1250     case ARG_BITRATE:
       
  1251       g_value_set_int (value, vorbisenc->bitrate);
       
  1252       break;
       
  1253     case ARG_MIN_BITRATE:
       
  1254       g_value_set_int (value, vorbisenc->min_bitrate);
       
  1255       break;
       
  1256     case ARG_QUALITY:
       
  1257       g_value_set_float (value, vorbisenc->quality);
       
  1258       break;
       
  1259     case ARG_MANAGED:
       
  1260       g_value_set_boolean (value, vorbisenc->managed);
       
  1261       break;
       
  1262     case ARG_LAST_MESSAGE:
       
  1263       g_value_set_string (value, vorbisenc->last_message);
       
  1264       break;
       
  1265     default:
       
  1266       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1267       break;
       
  1268   }
       
  1269 }
       
  1270 
       
  1271 static void
       
  1272 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
       
  1273     const GValue * value, GParamSpec * pspec)
       
  1274 {
       
  1275   GstVorbisEnc *vorbisenc;
       
  1276 
       
  1277   g_return_if_fail (GST_IS_VORBISENC (object));
       
  1278 
       
  1279   vorbisenc = GST_VORBISENC (object);
       
  1280 
       
  1281   switch (prop_id) {
       
  1282     case ARG_MAX_BITRATE:
       
  1283     {
       
  1284       gboolean old_value = vorbisenc->managed;
       
  1285 
       
  1286       vorbisenc->max_bitrate = g_value_get_int (value);
       
  1287       if (vorbisenc->max_bitrate >= 0
       
  1288           && vorbisenc->max_bitrate < LOWEST_BITRATE) {
       
  1289         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
       
  1290         vorbisenc->max_bitrate = LOWEST_BITRATE;
       
  1291       }
       
  1292       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
       
  1293         vorbisenc->managed = TRUE;
       
  1294       else
       
  1295         vorbisenc->managed = FALSE;
       
  1296 
       
  1297       if (old_value != vorbisenc->managed)
       
  1298         g_object_notify (object, "managed");
       
  1299       break;
       
  1300     }
       
  1301     case ARG_BITRATE:
       
  1302       vorbisenc->bitrate = g_value_get_int (value);
       
  1303       if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
       
  1304         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
       
  1305         vorbisenc->bitrate = LOWEST_BITRATE;
       
  1306       }
       
  1307       break;
       
  1308     case ARG_MIN_BITRATE:
       
  1309     {
       
  1310       gboolean old_value = vorbisenc->managed;
       
  1311 
       
  1312       vorbisenc->min_bitrate = g_value_get_int (value);
       
  1313       if (vorbisenc->min_bitrate >= 0
       
  1314           && vorbisenc->min_bitrate < LOWEST_BITRATE) {
       
  1315         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
       
  1316         vorbisenc->min_bitrate = LOWEST_BITRATE;
       
  1317       }
       
  1318       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
       
  1319         vorbisenc->managed = TRUE;
       
  1320       else
       
  1321         vorbisenc->managed = FALSE;
       
  1322 
       
  1323       if (old_value != vorbisenc->managed)
       
  1324         g_object_notify (object, "managed");
       
  1325       break;
       
  1326     }
       
  1327     case ARG_QUALITY:
       
  1328       vorbisenc->quality = g_value_get_float (value);
       
  1329       if (vorbisenc->quality >= 0.0)
       
  1330         vorbisenc->quality_set = TRUE;
       
  1331       else
       
  1332         vorbisenc->quality_set = FALSE;
       
  1333       break;
       
  1334     case ARG_MANAGED:
       
  1335       vorbisenc->managed = g_value_get_boolean (value);
       
  1336       break;
       
  1337     default:
       
  1338       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1339       break;
       
  1340   }
       
  1341 }
       
  1342 
       
  1343 static GstStateChangeReturn
       
  1344 gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
       
  1345 {
       
  1346   GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
       
  1347   GstStateChangeReturn res;
       
  1348 
       
  1349 
       
  1350   switch (transition) {
       
  1351     case GST_STATE_CHANGE_NULL_TO_READY:
       
  1352       vorbisenc->tags = gst_tag_list_new ();
       
  1353       break;
       
  1354     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
  1355       vorbisenc->setup = FALSE;
       
  1356       vorbisenc->next_discont = FALSE;
       
  1357       vorbisenc->header_sent = FALSE;
       
  1358       break;
       
  1359     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       
  1360       break;
       
  1361     default:
       
  1362       break;
       
  1363   }
       
  1364 
       
  1365   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
  1366 
       
  1367   switch (transition) {
       
  1368     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
  1369       break;
       
  1370     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  1371       vorbis_block_clear (&vorbisenc->vb);
       
  1372       vorbis_dsp_clear (&vorbisenc->vd);
       
  1373       vorbis_info_clear (&vorbisenc->vi);
       
  1374       g_free (vorbisenc->last_message);
       
  1375       vorbisenc->last_message = NULL;
       
  1376       if (vorbisenc->srccaps) {
       
  1377         gst_caps_unref (vorbisenc->srccaps);
       
  1378         vorbisenc->srccaps = NULL;
       
  1379       }
       
  1380       break;
       
  1381     case GST_STATE_CHANGE_READY_TO_NULL:
       
  1382       gst_tag_list_free (vorbisenc->tags);
       
  1383       vorbisenc->tags = NULL;
       
  1384     default:
       
  1385       break;
       
  1386   }
       
  1387 
       
  1388   return res;
       
  1389 }