audioencoder: Use GST_BOILERPLATE instead of custom GObject boilerplate code
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstaudioencoder.c
1 /* GStreamer
2  * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
3  * Copyright (C) 2011 Nokia Corporation. All rights reserved.
4  *   Contact: Stefan Kost <stefan.kost@nokia.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstaudioencoder
24  * @short_description: Base class for audio encoders
25  * @see_also: #GstBaseTransform
26  * @since: 0.10.36
27  *
28  * This base class is for audio encoders turning raw audio samples into
29  * encoded audio data.
30  *
31  * GstAudioEncoder and subclass should cooperate as follows.
32  * <orderedlist>
33  * <listitem>
34  *   <itemizedlist><title>Configuration</title>
35  *   <listitem><para>
36  *     Initially, GstAudioEncoder calls @start when the encoder element
37  *     is activated, which allows subclass to perform any global setup.
38  *   </para></listitem>
39  *   <listitem><para>
40  *     GstAudioEncoder calls @set_format to inform subclass of the format
41  *     of input audio data that it is about to receive.  Subclass should
42  *     setup for encoding and configure various base class parameters
43  *     appropriately, notably those directing desired input data handling.
44  *     While unlikely, it might be called more than once, if changing input
45  *     parameters require reconfiguration.
46  *   </para></listitem>
47  *   <listitem><para>
48  *     GstAudioEncoder calls @stop at end of all processing.
49  *   </para></listitem>
50  *   </itemizedlist>
51  * </listitem>
52  * As of configuration stage, and throughout processing, GstAudioEncoder
53  * maintains various parameters that provide required context,
54  * e.g. describing the format of input audio data.
55  * Conversely, subclass can and should configure these context parameters
56  * to inform base class of its expectation w.r.t. buffer handling.
57  * <listitem>
58  *   <itemizedlist>
59  *   <title>Data processing</title>
60  *     <listitem><para>
61  *       Base class gathers input sample data (as directed by the context's
62  *       frame_samples and frame_max) and provides this to subclass' @handle_frame.
63  *     </para></listitem>
64  *     <listitem><para>
65  *       If codec processing results in encoded data, subclass should call
66  *       @gst_audio_encoder_finish_frame to have encoded data pushed
67  *       downstream.  Alternatively, it might also call to indicate dropped
68  *       (non-encoded) samples.
69  *     </para></listitem>
70  *     <listitem><para>
71  *       Just prior to actually pushing a buffer downstream,
72  *       it is passed to @pre_push.
73  *     </para></listitem>
74  *     <listitem><para>
75  *       During the parsing process GstAudioEncoderClass will handle both
76  *       srcpad and sinkpad events. Sink events will be passed to subclass
77  *       if @event callback has been provided.
78  *     </para></listitem>
79  *   </itemizedlist>
80  * </listitem>
81  * <listitem>
82  *   <itemizedlist><title>Shutdown phase</title>
83  *   <listitem><para>
84  *     GstAudioEncoder class calls @stop to inform the subclass that data
85  *     parsing will be stopped.
86  *   </para></listitem>
87  *   </itemizedlist>
88  * </listitem>
89  * </orderedlist>
90  *
91  * Subclass is responsible for providing pad template caps for
92  * source and sink pads. The pads need to be named "sink" and "src". It also 
93  * needs to set the fixed caps on srcpad, when the format is ensured.  This
94  * is typically when base class calls subclass' @set_format function, though
95  * it might be delayed until calling @gst_audio_encoder_finish_frame.
96  *
97  * In summary, above process should have subclass concentrating on
98  * codec data processing while leaving other matters to base class,
99  * such as most notably timestamp handling.  While it may exert more control
100  * in this area (see e.g. @pre_push), it is very much not recommended.
101  *
102  * In particular, base class will either favor tracking upstream timestamps
103  * (at the possible expense of jitter) or aim to arrange for a perfect stream of
104  * output timestamps, depending on #GstAudioEncoder:perfect-timestamp.
105  * However, in the latter case, the input may not be so perfect or ideal, which
106  * is handled as follows.  An input timestamp is compared with the expected
107  * timestamp as dictated by input sample stream and if the deviation is less
108  * than #GstAudioEncoder:tolerance, the deviation is discarded.
109  * Otherwise, it is considered a discontuinity and subsequent output timestamp
110  * is resynced to the new position after performing configured discontinuity
111  * processing.  In the non-perfect-timestamp case, an upstream variation
112  * exceeding tolerance only leads to marking DISCONT on subsequent outgoing
113  * (while timestamps are adjusted to upstream regardless of variation).
114  * While DISCONT is also marked in the perfect-timestamp case, this one
115  * optionally (see #GstAudioEncoder:hard-resync)
116  * performs some additional steps, such as clipping of (early) input samples
117  * or draining all currently remaining input data, depending on the direction
118  * of the discontuinity.
119  *
120  * If perfect timestamps are arranged, it is also possible to request baseclass
121  * (usually set by subclass) to provide additional buffer metadata (in OFFSET
122  * and OFFSET_END) fields according to granule defined semantics currently
123  * needed by oggmux.  Specifically, OFFSET is set to granulepos (= sample count
124  * including buffer) and OFFSET_END to corresponding timestamp (as determined
125  * by same sample count and sample rate).
126  *
127  * Things that subclass need to take care of:
128  * <itemizedlist>
129  *   <listitem><para>Provide pad templates</para></listitem>
130  *   <listitem><para>
131  *      Set source pad caps when appropriate
132  *   </para></listitem>
133  *   <listitem><para>
134  *      Inform base class of buffer processing needs using context's
135  *      frame_samples and frame_bytes.
136  *   </para></listitem>
137  *   <listitem><para>
138  *      Set user-configurable properties to sane defaults for format and
139  *      implementing codec at hand, e.g. those controlling timestamp behaviour
140  *      and discontinuity processing.
141  *   </para></listitem>
142  *   <listitem><para>
143  *      Accept data in @handle_frame and provide encoded results to
144  *      @gst_audio_encoder_finish_frame.
145  *   </para></listitem>
146  * </itemizedlist>
147  *
148  */
149
150 #ifdef HAVE_CONFIG_H
151 #  include "config.h"
152 #endif
153
154 #define GST_USE_UNSTABLE_API
155 #include "gstaudioencoder.h"
156 #include <gst/base/gstadapter.h>
157 #include <gst/audio/audio.h>
158 #include <gst/pbutils/descriptions.h>
159
160 #include <stdlib.h>
161 #include <string.h>
162
163
164 GST_DEBUG_CATEGORY_STATIC (gst_audio_encoder_debug);
165 #define GST_CAT_DEFAULT gst_audio_encoder_debug
166
167 #define GST_AUDIO_ENCODER_GET_PRIVATE(obj)  \
168     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_AUDIO_ENCODER, \
169         GstAudioEncoderPrivate))
170
171 enum
172 {
173   PROP_0,
174   PROP_PERFECT_TS,
175   PROP_GRANULE,
176   PROP_HARD_RESYNC,
177   PROP_TOLERANCE
178 };
179
180 #define DEFAULT_PERFECT_TS   FALSE
181 #define DEFAULT_GRANULE      FALSE
182 #define DEFAULT_HARD_RESYNC  FALSE
183 #define DEFAULT_TOLERANCE    40000000
184
185 typedef struct _GstAudioEncoderContext
186 {
187   /* input */
188   GstAudioInfo info;
189
190   /* output */
191   gint frame_samples;
192   gint frame_max;
193   gint lookahead;
194   /* MT-protected (with LOCK) */
195   GstClockTime min_latency;
196   GstClockTime max_latency;
197 } GstAudioEncoderContext;
198
199 struct _GstAudioEncoderPrivate
200 {
201   /* activation status */
202   gboolean active;
203
204   /* input base/first ts as basis for output ts;
205    * kept nearly constant for perfect_ts,
206    * otherwise resyncs to upstream ts */
207   GstClockTime base_ts;
208   /* corresponding base granulepos */
209   gint64 base_gp;
210   /* input samples processed and sent downstream so far (w.r.t. base_ts) */
211   guint64 samples;
212
213   /* currently collected sample data */
214   GstAdapter *adapter;
215   /* offset in adapter up to which already supplied to encoder */
216   gint offset;
217   /* mark outgoing discont */
218   gboolean discont;
219   /* to guess duration of drained data */
220   GstClockTime last_duration;
221
222   /* subclass provided data in processing round */
223   gboolean got_data;
224   /* subclass gave all it could already */
225   gboolean drained;
226   /* subclass currently being forcibly drained */
227   gboolean force;
228
229   /* output bps estimatation */
230   /* global in samples seen */
231   guint64 samples_in;
232   /* global bytes sent out */
233   guint64 bytes_out;
234
235   /* context storage */
236   GstAudioEncoderContext ctx;
237
238   /* properties */
239   gint64 tolerance;
240   gboolean perfect_ts;
241   gboolean hard_resync;
242   gboolean granule;
243
244   /* pending tags */
245   GstTagList *tags;
246 };
247
248 static void gst_audio_encoder_finalize (GObject * object);
249 static void gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full);
250
251 static void gst_audio_encoder_set_property (GObject * object,
252     guint prop_id, const GValue * value, GParamSpec * pspec);
253 static void gst_audio_encoder_get_property (GObject * object,
254     guint prop_id, GValue * value, GParamSpec * pspec);
255
256 static gboolean gst_audio_encoder_sink_activate_push (GstPad * pad,
257     gboolean active);
258
259 static gboolean gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event);
260 static gboolean gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps);
261 static GstFlowReturn gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer);
262 static gboolean gst_audio_encoder_src_query (GstPad * pad, GstQuery * query);
263 static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query);
264 static const GstQueryType *gst_audio_encoder_get_query_types (GstPad * pad);
265 static GstCaps *gst_audio_encoder_sink_getcaps (GstPad * pad);
266
267 static void
268 do_init (GType gtype)
269 {
270   const GInterfaceInfo preset_interface_info = {
271     NULL,                       /* interface_init */
272     NULL,                       /* interface_finalize */
273     NULL                        /* interface_data */
274   };
275
276   g_type_add_interface_static (gtype, GST_TYPE_PRESET, &preset_interface_info);
277 }
278
279 GST_BOILERPLATE_FULL (GstAudioEncoder, gst_audio_encoder, GstElement,
280     GST_TYPE_ELEMENT, do_init);
281
282 static void
283 gst_audio_encoder_class_init (GstAudioEncoderClass * klass)
284 {
285   GObjectClass *gobject_class;
286
287   gobject_class = G_OBJECT_CLASS (klass);
288
289   GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0,
290       "audio encoder base class");
291
292   g_type_class_add_private (klass, sizeof (GstAudioEncoderPrivate));
293
294   gobject_class->set_property = gst_audio_encoder_set_property;
295   gobject_class->get_property = gst_audio_encoder_get_property;
296
297   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_audio_encoder_finalize);
298
299   /* properties */
300   g_object_class_install_property (gobject_class, PROP_PERFECT_TS,
301       g_param_spec_boolean ("perfect-timestamp", "Perfect Timestamps",
302           "Favour perfect timestamps over tracking upstream timestamps",
303           DEFAULT_PERFECT_TS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
304   g_object_class_install_property (gobject_class, PROP_GRANULE,
305       g_param_spec_boolean ("mark-granule", "Granule Marking",
306           "Apply granule semantics to buffer metadata (implies perfect-timestamp)",
307           DEFAULT_GRANULE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
308   g_object_class_install_property (gobject_class, PROP_HARD_RESYNC,
309       g_param_spec_boolean ("hard-resync", "Hard Resync",
310           "Perform clipping and sample flushing upon discontinuity",
311           DEFAULT_HARD_RESYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
312   g_object_class_install_property (gobject_class, PROP_TOLERANCE,
313       g_param_spec_int64 ("tolerance", "Tolerance",
314           "Consider discontinuity if timestamp jitter/imperfection exceeds tolerance (ns)",
315           0, G_MAXINT64, DEFAULT_TOLERANCE,
316           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317 }
318
319 static void
320 gst_audio_encoder_base_init (gpointer g_class)
321 {
322 }
323
324 static void
325 gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass)
326 {
327   GstPadTemplate *pad_template;
328
329   GST_DEBUG_OBJECT (enc, "gst_audio_encoder_init");
330
331   enc->priv = GST_AUDIO_ENCODER_GET_PRIVATE (enc);
332
333   /* only push mode supported */
334   pad_template =
335       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
336   g_return_if_fail (pad_template != NULL);
337   enc->sinkpad = gst_pad_new_from_template (pad_template, "sink");
338   gst_pad_set_event_function (enc->sinkpad,
339       GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_event));
340   gst_pad_set_setcaps_function (enc->sinkpad,
341       GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_setcaps));
342   gst_pad_set_getcaps_function (enc->sinkpad,
343       GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_getcaps));
344   gst_pad_set_query_function (enc->sinkpad,
345       GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_query));
346   gst_pad_set_chain_function (enc->sinkpad,
347       GST_DEBUG_FUNCPTR (gst_audio_encoder_chain));
348   gst_pad_set_activatepush_function (enc->sinkpad,
349       GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_activate_push));
350   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
351
352   GST_DEBUG_OBJECT (enc, "sinkpad created");
353
354   /* and we don't mind upstream traveling stuff that much ... */
355   pad_template =
356       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
357   g_return_if_fail (pad_template != NULL);
358   enc->srcpad = gst_pad_new_from_template (pad_template, "src");
359   gst_pad_set_query_function (enc->srcpad,
360       GST_DEBUG_FUNCPTR (gst_audio_encoder_src_query));
361   gst_pad_set_query_type_function (enc->srcpad,
362       GST_DEBUG_FUNCPTR (gst_audio_encoder_get_query_types));
363   gst_pad_use_fixed_caps (enc->srcpad);
364   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
365   GST_DEBUG_OBJECT (enc, "src created");
366
367   enc->priv->adapter = gst_adapter_new ();
368
369   /* property default */
370   enc->priv->granule = DEFAULT_GRANULE;
371   enc->priv->perfect_ts = DEFAULT_PERFECT_TS;
372   enc->priv->hard_resync = DEFAULT_HARD_RESYNC;
373   enc->priv->tolerance = DEFAULT_TOLERANCE;
374
375   /* init state */
376   gst_audio_encoder_reset (enc, TRUE);
377   GST_DEBUG_OBJECT (enc, "init ok");
378 }
379
380 static void
381 gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full)
382 {
383   GST_OBJECT_LOCK (enc);
384
385   GST_LOG_OBJECT (enc, "reset full %d", full);
386
387   if (full) {
388     enc->priv->active = FALSE;
389     enc->priv->samples_in = 0;
390     enc->priv->bytes_out = 0;
391     gst_audio_info_clear (&enc->priv->ctx.info);
392     memset (&enc->priv->ctx, 0, sizeof (enc->priv->ctx));
393
394     if (enc->priv->tags)
395       gst_tag_list_free (enc->priv->tags);
396     enc->priv->tags = NULL;
397   }
398
399   gst_segment_init (&enc->segment, GST_FORMAT_TIME);
400
401   gst_adapter_clear (enc->priv->adapter);
402   enc->priv->got_data = FALSE;
403   enc->priv->drained = TRUE;
404   enc->priv->offset = 0;
405   enc->priv->base_ts = GST_CLOCK_TIME_NONE;
406   enc->priv->base_gp = -1;
407   enc->priv->samples = 0;
408   enc->priv->discont = FALSE;
409
410   GST_OBJECT_UNLOCK (enc);
411 }
412
413 static void
414 gst_audio_encoder_finalize (GObject * object)
415 {
416   GstAudioEncoder *enc = GST_AUDIO_ENCODER (object);
417
418   g_object_unref (enc->priv->adapter);
419
420   G_OBJECT_CLASS (parent_class)->finalize (object);
421 }
422
423 /**
424  * gst_audio_encoder_finish_frame:
425  * @enc: a #GstAudioEncoder
426  * @buffer: encoded data
427  * @samples: number of samples (per channel) represented by encoded data
428  *
429  * Collects encoded data and/or pushes encoded data downstream.
430  * Source pad caps must be set when this is called.  Depending on the nature
431  * of the (framing of) the format, subclass can decide whether to push
432  * encoded data directly or to collect various "frames" in a single buffer.
433  * Note that the latter behaviour is recommended whenever the format is allowed,
434  * as it incurs no additional latency and avoids otherwise generating a
435  * a multitude of (small) output buffers.  If not explicitly pushed,
436  * any available encoded data is pushed at the end of each processing cycle,
437  * i.e. which encodes as much data as available input data allows.
438  *
439  * If @samples < 0, then best estimate is all samples provided to encoder
440  * (subclass) so far.  @buf may be NULL, in which case next number of @samples
441  * are considered discarded, e.g. as a result of discontinuous transmission,
442  * and a discontinuity is marked (note that @buf == NULL => push == TRUE).
443  *
444  * Returns: a #GstFlowReturn that should be escalated to caller (of caller)
445  *
446  * Since: 0.10.36
447  */
448 GstFlowReturn
449 gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf,
450     gint samples)
451 {
452   GstAudioEncoderClass *klass;
453   GstAudioEncoderPrivate *priv;
454   GstAudioEncoderContext *ctx;
455   GstFlowReturn ret = GST_FLOW_OK;
456
457   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
458   priv = enc->priv;
459   ctx = &enc->priv->ctx;
460
461   /* subclass should know what it is producing by now */
462   g_return_val_if_fail (GST_PAD_CAPS (enc->srcpad) != NULL, GST_FLOW_ERROR);
463   /* subclass should not hand us no data */
464   g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0,
465       GST_FLOW_ERROR);
466
467   if (G_UNLIKELY (enc->priv->tags)) {
468     GstTagList *tags;
469
470     /* add codec info to pending tags */
471     tags = enc->priv->tags;
472     /* no more pending */
473     enc->priv->tags = NULL;
474     gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_CODEC,
475         GST_PAD_CAPS (enc->srcpad));
476     gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_AUDIO_CODEC,
477         GST_PAD_CAPS (enc->srcpad));
478     GST_DEBUG_OBJECT (enc, "sending tags %" GST_PTR_FORMAT, tags);
479     gst_element_found_tags_for_pad (GST_ELEMENT (enc), enc->srcpad, tags);
480   }
481
482   GST_LOG_OBJECT (enc, "accepting %d bytes encoded data as %d samples",
483       buf ? GST_BUFFER_SIZE (buf) : -1, samples);
484
485   /* mark subclass still alive and providing */
486   priv->got_data = TRUE;
487
488   /* remove corresponding samples from input */
489   if (samples < 0)
490     samples = (enc->priv->offset / ctx->info.bpf);
491
492   if (G_LIKELY (samples)) {
493     /* track upstream ts if so configured */
494     if (!enc->priv->perfect_ts) {
495       guint64 ts, distance;
496
497       ts = gst_adapter_prev_timestamp (priv->adapter, &distance);
498       g_assert (distance % ctx->info.bpf == 0);
499       distance /= ctx->info.bpf;
500       GST_LOG_OBJECT (enc, "%" G_GUINT64_FORMAT " samples past prev_ts %"
501           GST_TIME_FORMAT, distance, GST_TIME_ARGS (ts));
502       GST_LOG_OBJECT (enc, "%" G_GUINT64_FORMAT " samples past base_ts %"
503           GST_TIME_FORMAT, priv->samples, GST_TIME_ARGS (priv->base_ts));
504       /* when draining adapter might be empty and no ts to offer */
505       if (GST_CLOCK_TIME_IS_VALID (ts) && ts != priv->base_ts) {
506         GstClockTimeDiff diff;
507         GstClockTime old_ts, next_ts;
508
509         /* passed into another buffer;
510          * mild check for discontinuity and only mark if so */
511         next_ts = ts +
512             gst_util_uint64_scale (distance, GST_SECOND, ctx->info.rate);
513         old_ts = priv->base_ts +
514             gst_util_uint64_scale (priv->samples, GST_SECOND, ctx->info.rate);
515         diff = GST_CLOCK_DIFF (next_ts, old_ts);
516         GST_LOG_OBJECT (enc, "ts diff %d ms", (gint) (diff / GST_MSECOND));
517         /* only mark discontinuity if beyond tolerance */
518         if (G_UNLIKELY (diff < -enc->priv->tolerance ||
519                 diff > enc->priv->tolerance)) {
520           GST_DEBUG_OBJECT (enc, "marked discont");
521           priv->discont = TRUE;
522         }
523         if (diff > GST_SECOND / ctx->info.rate / 2 ||
524             diff < -GST_SECOND / ctx->info.rate / 2) {
525           GST_LOG_OBJECT (enc, "new upstream ts %" GST_TIME_FORMAT
526               " at distance %" G_GUINT64_FORMAT, GST_TIME_ARGS (ts), distance);
527           /* re-sync to upstream ts */
528           priv->base_ts = ts;
529           priv->samples = distance;
530         } else {
531           GST_LOG_OBJECT (enc, "new upstream ts only introduces jitter");
532         }
533       }
534     }
535     /* advance sample view */
536     if (G_UNLIKELY (samples * ctx->info.bpf > priv->offset)) {
537       if (G_LIKELY (!priv->force)) {
538         /* no way we can let this pass */
539         g_assert_not_reached ();
540         /* really no way */
541         goto overflow;
542       } else {
543         priv->offset = 0;
544         if (samples * ctx->info.bpf >= gst_adapter_available (priv->adapter))
545           gst_adapter_clear (priv->adapter);
546         else
547           gst_adapter_flush (priv->adapter, samples * ctx->info.bpf);
548       }
549     } else {
550       gst_adapter_flush (priv->adapter, samples * ctx->info.bpf);
551       priv->offset -= samples * ctx->info.bpf;
552       /* avoid subsequent stray prev_ts */
553       if (G_UNLIKELY (gst_adapter_available (priv->adapter) == 0))
554         gst_adapter_clear (priv->adapter);
555     }
556     /* sample count advanced below after buffer handling */
557   }
558
559   /* collect output */
560   if (G_LIKELY (buf)) {
561     GST_LOG_OBJECT (enc, "taking %d bytes for output", GST_BUFFER_SIZE (buf));
562     buf = gst_buffer_make_metadata_writable (buf);
563
564     /* decorate */
565     gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
566     if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (priv->base_ts))) {
567       /* FIXME ? lookahead could lead to weird ts and duration ?
568        * (particularly if not in perfect mode) */
569       /* mind sample rounding and produce perfect output */
570       GST_BUFFER_TIMESTAMP (buf) = priv->base_ts +
571           gst_util_uint64_scale (priv->samples - ctx->lookahead, GST_SECOND,
572           ctx->info.rate);
573       GST_DEBUG_OBJECT (enc, "out samples %d", samples);
574       if (G_LIKELY (samples > 0)) {
575         priv->samples += samples;
576         GST_BUFFER_DURATION (buf) = priv->base_ts +
577             gst_util_uint64_scale (priv->samples - ctx->lookahead, GST_SECOND,
578             ctx->info.rate) - GST_BUFFER_TIMESTAMP (buf);
579         priv->last_duration = GST_BUFFER_DURATION (buf);
580       } else {
581         /* duration forecast in case of handling remainder;
582          * the last one is probably like the previous one ... */
583         GST_BUFFER_DURATION (buf) = priv->last_duration;
584       }
585       if (priv->base_gp >= 0) {
586         /* pamper oggmux */
587         /* FIXME: in longer run, muxer should take care of this ... */
588         /* offset_end = granulepos for ogg muxer */
589         GST_BUFFER_OFFSET_END (buf) = priv->base_gp + priv->samples -
590             enc->priv->ctx.lookahead;
591         /* offset = timestamp corresponding to granulepos for ogg muxer */
592         GST_BUFFER_OFFSET (buf) =
593             GST_FRAMES_TO_CLOCK_TIME (GST_BUFFER_OFFSET_END (buf),
594             ctx->info.rate);
595       } else {
596         GST_BUFFER_OFFSET (buf) = priv->bytes_out;
597         GST_BUFFER_OFFSET_END (buf) = priv->bytes_out + GST_BUFFER_SIZE (buf);
598       }
599     }
600
601     priv->bytes_out += GST_BUFFER_SIZE (buf);
602
603     if (G_UNLIKELY (priv->discont)) {
604       GST_LOG_OBJECT (enc, "marking discont");
605       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
606       priv->discont = FALSE;
607     }
608
609     if (klass->pre_push) {
610       /* last chance for subclass to do some dirty stuff */
611       ret = klass->pre_push (enc, &buf);
612       if (ret != GST_FLOW_OK || !buf) {
613         GST_DEBUG_OBJECT (enc, "subclass returned %s, buf %p",
614             gst_flow_get_name (ret), buf);
615         if (buf)
616           gst_buffer_unref (buf);
617         goto exit;
618       }
619     }
620
621     GST_LOG_OBJECT (enc, "pushing buffer of size %d with ts %" GST_TIME_FORMAT
622         ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
623         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
624         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
625
626     ret = gst_pad_push (enc->srcpad, buf);
627     GST_LOG_OBJECT (enc, "buffer pushed: %s", gst_flow_get_name (ret));
628   } else {
629     /* merely advance samples, most work for that already done above */
630     priv->samples += samples;
631   }
632
633 exit:
634   return ret;
635
636   /* ERRORS */
637 overflow:
638   {
639     GST_ELEMENT_ERROR (enc, STREAM, ENCODE,
640         ("received more encoded samples %d than provided %d",
641             samples, priv->offset / ctx->info.bpf), (NULL));
642     if (buf)
643       gst_buffer_unref (buf);
644     return GST_FLOW_ERROR;
645   }
646 }
647
648  /* adapter tracking idea:
649   * - start of adapter corresponds with what has already been encoded
650   * (i.e. really returned by encoder subclass)
651   * - start + offset is what needs to be fed to subclass next */
652 static GstFlowReturn
653 gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force)
654 {
655   GstAudioEncoderClass *klass;
656   GstAudioEncoderPrivate *priv;
657   GstAudioEncoderContext *ctx;
658   gint av, need;
659   GstBuffer *buf;
660   GstFlowReturn ret = GST_FLOW_OK;
661
662   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
663
664   g_return_val_if_fail (klass->handle_frame != NULL, GST_FLOW_ERROR);
665
666   priv = enc->priv;
667   ctx = &enc->priv->ctx;
668
669   while (ret == GST_FLOW_OK) {
670
671     buf = NULL;
672     av = gst_adapter_available (priv->adapter);
673
674     g_assert (priv->offset <= av);
675     av -= priv->offset;
676
677     need = ctx->frame_samples > 0 ? ctx->frame_samples * ctx->info.bpf : av;
678     GST_LOG_OBJECT (enc, "available: %d, needed: %d, force: %d",
679         av, need, force);
680
681     if ((need > av) || !av) {
682       if (G_UNLIKELY (force)) {
683         priv->force = TRUE;
684         need = av;
685       } else {
686         break;
687       }
688     } else {
689       priv->force = FALSE;
690     }
691
692     /* if we have some extra metadata,
693      * provide for integer multiple of frames to allow for better granularity
694      * of processing */
695     if (ctx->frame_samples > 0 && need) {
696       if (ctx->frame_max > 1)
697         need = need * MIN ((av / need), ctx->frame_max);
698       else if (ctx->frame_max == 0)
699         need = need * (av / need);
700     }
701
702     if (need) {
703       buf = gst_buffer_new ();
704       GST_BUFFER_DATA (buf) = (guint8 *)
705           gst_adapter_peek (priv->adapter, priv->offset + need) + priv->offset;
706       GST_BUFFER_SIZE (buf) = need;
707     }
708
709     GST_LOG_OBJECT (enc, "providing subclass with %d bytes at offset %d",
710         need, priv->offset);
711
712     /* mark this already as consumed,
713      * which it should be when subclass gives us data in exchange for samples */
714     priv->offset += need;
715     priv->samples_in += need / ctx->info.bpf;
716
717     priv->got_data = FALSE;
718     ret = klass->handle_frame (enc, buf);
719
720     if (G_LIKELY (buf))
721       gst_buffer_unref (buf);
722
723     /* no data to feed, no leftover provided, then bail out */
724     if (G_UNLIKELY (!buf && !priv->got_data)) {
725       priv->drained = TRUE;
726       GST_LOG_OBJECT (enc, "no more data drained from subclass");
727       break;
728     }
729   }
730
731   return ret;
732 }
733
734 static GstFlowReturn
735 gst_audio_encoder_drain (GstAudioEncoder * enc)
736 {
737   if (enc->priv->drained)
738     return GST_FLOW_OK;
739   else
740     return gst_audio_encoder_push_buffers (enc, TRUE);
741 }
742
743 static void
744 gst_audio_encoder_set_base_gp (GstAudioEncoder * enc)
745 {
746   GstClockTime ts;
747
748   if (!enc->priv->granule)
749     return;
750
751   /* use running time for granule */
752   /* incoming data is clipped, so a valid input should yield a valid output */
753   ts = gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME,
754       enc->priv->base_ts);
755   if (GST_CLOCK_TIME_IS_VALID (ts)) {
756     enc->priv->base_gp =
757         GST_CLOCK_TIME_TO_FRAMES (enc->priv->base_ts, enc->priv->ctx.info.rate);
758     GST_DEBUG_OBJECT (enc, "new base gp %" G_GINT64_FORMAT, enc->priv->base_gp);
759   } else {
760     /* should reasonably have a valid base,
761      * otherwise start at 0 if we did not already start there earlier */
762     if (enc->priv->base_gp < 0) {
763       enc->priv->base_gp = 0;
764       GST_DEBUG_OBJECT (enc, "new base gp %" G_GINT64_FORMAT,
765           enc->priv->base_gp);
766     }
767   }
768 }
769
770 static GstFlowReturn
771 gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer)
772 {
773   GstAudioEncoder *enc;
774   GstAudioEncoderPrivate *priv;
775   GstAudioEncoderContext *ctx;
776   GstFlowReturn ret = GST_FLOW_OK;
777   gboolean discont;
778
779   enc = GST_AUDIO_ENCODER (GST_OBJECT_PARENT (pad));
780
781   priv = enc->priv;
782   ctx = &enc->priv->ctx;
783
784   /* should know what is coming by now */
785   if (!ctx->info.bpf)
786     goto not_negotiated;
787
788   GST_LOG_OBJECT (enc,
789       "received buffer of size %d with ts %" GST_TIME_FORMAT
790       ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
791       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
792       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
793
794   /* input shoud be whole number of sample frames */
795   if (GST_BUFFER_SIZE (buffer) % ctx->info.bpf)
796     goto wrong_buffer;
797
798 #ifndef GST_DISABLE_GST_DEBUG
799   {
800     GstClockTime duration;
801     GstClockTimeDiff diff;
802
803     /* verify buffer duration */
804     duration = gst_util_uint64_scale (GST_BUFFER_SIZE (buffer), GST_SECOND,
805         ctx->info.rate * ctx->info.bpf);
806     diff = GST_CLOCK_DIFF (duration, GST_BUFFER_DURATION (buffer));
807     if (GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE &&
808         (diff > GST_SECOND / ctx->info.rate / 2 ||
809             diff < -GST_SECOND / ctx->info.rate / 2)) {
810       GST_DEBUG_OBJECT (enc, "incoming buffer had incorrect duration %"
811           GST_TIME_FORMAT ", expected duration %" GST_TIME_FORMAT,
812           GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
813           GST_TIME_ARGS (duration));
814     }
815   }
816 #endif
817
818   discont = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT);
819   if (G_UNLIKELY (discont)) {
820     GST_LOG_OBJECT (buffer, "marked discont");
821     enc->priv->discont = discont;
822   }
823
824   /* clip to segment */
825   /* NOTE: slightly painful linking -laudio only for this one ... */
826   buffer = gst_audio_buffer_clip (buffer, &enc->segment, ctx->info.rate,
827       ctx->info.bpf);
828   if (G_UNLIKELY (!buffer)) {
829     GST_DEBUG_OBJECT (buffer, "no data after clipping to segment");
830     goto done;
831   }
832
833   GST_LOG_OBJECT (enc,
834       "buffer after segment clipping has size %d with ts %" GST_TIME_FORMAT
835       ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
836       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
837       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
838
839   if (!GST_CLOCK_TIME_IS_VALID (priv->base_ts)) {
840     priv->base_ts = GST_BUFFER_TIMESTAMP (buffer);
841     GST_DEBUG_OBJECT (enc, "new base ts %" GST_TIME_FORMAT,
842         GST_TIME_ARGS (priv->base_ts));
843     gst_audio_encoder_set_base_gp (enc);
844   }
845
846   /* check for continuity;
847    * checked elsewhere in non-perfect case */
848   if (enc->priv->perfect_ts) {
849     GstClockTimeDiff diff = 0;
850     GstClockTime next_ts = 0;
851
852     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
853         GST_CLOCK_TIME_IS_VALID (priv->base_ts)) {
854       guint64 samples;
855
856       samples = priv->samples +
857           gst_adapter_available (priv->adapter) / ctx->info.bpf;
858       next_ts = priv->base_ts +
859           gst_util_uint64_scale (samples, GST_SECOND, ctx->info.rate);
860       GST_LOG_OBJECT (enc, "buffer is %" G_GUINT64_FORMAT
861           " samples past base_ts %" GST_TIME_FORMAT
862           ", expected ts %" GST_TIME_FORMAT, samples,
863           GST_TIME_ARGS (priv->base_ts), GST_TIME_ARGS (next_ts));
864       diff = GST_CLOCK_DIFF (next_ts, GST_BUFFER_TIMESTAMP (buffer));
865       GST_LOG_OBJECT (enc, "ts diff %d ms", (gint) (diff / GST_MSECOND));
866       /* if within tolerance,
867        * discard buffer ts and carry on producing perfect stream,
868        * otherwise clip or resync to ts */
869       if (G_UNLIKELY (diff < -enc->priv->tolerance ||
870               diff > enc->priv->tolerance)) {
871         GST_DEBUG_OBJECT (enc, "marked discont");
872         discont = TRUE;
873       }
874     }
875
876     /* do some fancy tweaking in hard resync case */
877     if (discont && enc->priv->hard_resync) {
878       if (diff < 0) {
879         guint64 diff_bytes;
880
881         GST_WARNING_OBJECT (enc, "Buffer is older than expected ts %"
882             GST_TIME_FORMAT ".  Clipping buffer", GST_TIME_ARGS (next_ts));
883
884         diff_bytes =
885             GST_CLOCK_TIME_TO_FRAMES (-diff, ctx->info.rate) * ctx->info.bpf;
886         if (diff_bytes >= GST_BUFFER_SIZE (buffer)) {
887           gst_buffer_unref (buffer);
888           goto done;
889         }
890         buffer = gst_buffer_make_metadata_writable (buffer);
891         GST_BUFFER_DATA (buffer) += diff_bytes;
892         GST_BUFFER_SIZE (buffer) -= diff_bytes;
893
894         GST_BUFFER_TIMESTAMP (buffer) += diff;
895         /* care even less about duration after this */
896       } else {
897         /* drain stuff prior to resync */
898         gst_audio_encoder_drain (enc);
899       }
900     }
901     /* now re-sync ts */
902     priv->base_ts += diff;
903     gst_audio_encoder_set_base_gp (enc);
904     priv->discont |= discont;
905   }
906
907   gst_adapter_push (enc->priv->adapter, buffer);
908   /* new stuff, so we can push subclass again */
909   enc->priv->drained = FALSE;
910
911   ret = gst_audio_encoder_push_buffers (enc, FALSE);
912
913 done:
914   GST_LOG_OBJECT (enc, "chain leaving");
915   return ret;
916
917   /* ERRORS */
918 not_negotiated:
919   {
920     GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
921         ("encoder not initialized"));
922     gst_buffer_unref (buffer);
923     return GST_FLOW_NOT_NEGOTIATED;
924   }
925 wrong_buffer:
926   {
927     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
928         ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buffer),
929             ctx->info.bpf));
930     gst_buffer_unref (buffer);
931     return GST_FLOW_ERROR;
932   }
933 }
934
935 static gboolean
936 audio_info_is_equal (GstAudioInfo * from, GstAudioInfo * to)
937 {
938   if (from == to)
939     return TRUE;
940   if (from->finfo == NULL || to->finfo == NULL)
941     return FALSE;
942   if (GST_AUDIO_INFO_FORMAT (from) != GST_AUDIO_INFO_FORMAT (to))
943     return FALSE;
944   if (GST_AUDIO_INFO_RATE (from) != GST_AUDIO_INFO_RATE (to))
945     return FALSE;
946   if (GST_AUDIO_INFO_CHANNELS (from) != GST_AUDIO_INFO_CHANNELS (to))
947     return FALSE;
948   if (GST_AUDIO_INFO_CHANNELS (from) > 64)
949     return TRUE;
950   return memcmp (from->position, to->position,
951       GST_AUDIO_INFO_CHANNELS (from) * sizeof (to->position[0]));
952 }
953
954 static gboolean
955 gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps)
956 {
957   GstAudioEncoder *enc;
958   GstAudioEncoderClass *klass;
959   GstAudioEncoderContext *ctx;
960   GstAudioInfo *state, *old_state;
961   gboolean res = TRUE, changed = FALSE;
962   guint old_rate;
963
964   enc = GST_AUDIO_ENCODER (GST_PAD_PARENT (pad));
965   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
966
967   /* subclass must do something here ... */
968   g_return_val_if_fail (klass->set_format != NULL, FALSE);
969
970   ctx = &enc->priv->ctx;
971   state = &ctx->info;
972
973   GST_DEBUG_OBJECT (enc, "caps: %" GST_PTR_FORMAT, caps);
974
975   if (!gst_caps_is_fixed (caps))
976     goto refuse_caps;
977
978   /* adjust ts tracking to new sample rate */
979   old_rate = GST_AUDIO_INFO_RATE (state);
980   if (GST_CLOCK_TIME_IS_VALID (enc->priv->base_ts) && old_rate) {
981     enc->priv->base_ts +=
982         GST_FRAMES_TO_CLOCK_TIME (enc->priv->samples, old_rate);
983     enc->priv->samples = 0;
984   }
985
986   old_state = gst_audio_info_copy (state);
987   if (!gst_audio_info_from_caps (state, caps))
988     goto refuse_caps;
989
990   changed = !audio_info_is_equal (state, old_state);
991   gst_audio_info_free (old_state);
992
993   if (changed) {
994     GstClockTime old_min_latency;
995     GstClockTime old_max_latency;
996
997     /* drain any pending old data stuff */
998     gst_audio_encoder_drain (enc);
999
1000     /* context defaults */
1001     enc->priv->ctx.frame_samples = 0;
1002     enc->priv->ctx.frame_max = 0;
1003     enc->priv->ctx.lookahead = 0;
1004
1005     /* element might report latency */
1006     GST_OBJECT_LOCK (enc);
1007     old_min_latency = ctx->min_latency;
1008     old_max_latency = ctx->max_latency;
1009     GST_OBJECT_UNLOCK (enc);
1010
1011     if (klass->set_format)
1012       res = klass->set_format (enc, state);
1013
1014     /* notify if new latency */
1015     GST_OBJECT_LOCK (enc);
1016     if ((ctx->min_latency > 0 && ctx->min_latency != old_min_latency) ||
1017         (ctx->max_latency > 0 && ctx->max_latency != old_max_latency)) {
1018       GST_OBJECT_UNLOCK (enc);
1019       /* post latency message on the bus */
1020       gst_element_post_message (GST_ELEMENT (enc),
1021           gst_message_new_latency (GST_OBJECT (enc)));
1022       GST_OBJECT_LOCK (enc);
1023     }
1024     GST_OBJECT_UNLOCK (enc);
1025   } else {
1026     GST_DEBUG_OBJECT (enc, "new audio format identical to configured format");
1027   }
1028
1029   return res;
1030
1031   /* ERRORS */
1032 refuse_caps:
1033   {
1034     GST_WARNING_OBJECT (enc, "rejected caps %" GST_PTR_FORMAT, caps);
1035     return res;
1036   }
1037 }
1038
1039
1040 /**
1041  * gst_audio_encoder_proxy_getcaps:
1042  * @enc: a #GstAudioEncoder
1043  * @caps: initial caps
1044  *
1045  * Returns caps that express @caps (or sink template caps if @caps == NULL)
1046  * restricted to channel/rate combinations supported by downstream elements
1047  * (e.g. muxers).
1048  *
1049  * Returns: a #GstCaps owned by caller
1050  *
1051  * Since: 0.10.36
1052  */
1053 GstCaps *
1054 gst_audio_encoder_proxy_getcaps (GstAudioEncoder * enc, GstCaps * caps)
1055 {
1056   const GstCaps *templ_caps;
1057   GstCaps *allowed = NULL;
1058   GstCaps *fcaps, *filter_caps;
1059   gint i, j;
1060
1061   /* we want to be able to communicate to upstream elements like audioconvert
1062    * and audioresample any rate/channel restrictions downstream (e.g. muxer
1063    * only accepting certain sample rates) */
1064   templ_caps = caps ? caps : gst_pad_get_pad_template_caps (enc->sinkpad);
1065   allowed = gst_pad_get_allowed_caps (enc->srcpad);
1066   if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) {
1067     fcaps = gst_caps_copy (templ_caps);
1068     goto done;
1069   }
1070
1071   GST_LOG_OBJECT (enc, "template caps %" GST_PTR_FORMAT, templ_caps);
1072   GST_LOG_OBJECT (enc, "allowed caps %" GST_PTR_FORMAT, allowed);
1073
1074   filter_caps = gst_caps_new_empty ();
1075
1076   for (i = 0; i < gst_caps_get_size (templ_caps); i++) {
1077     GQuark q_name;
1078
1079     q_name = gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
1080
1081     /* pick rate + channel fields from allowed caps */
1082     for (j = 0; j < gst_caps_get_size (allowed); j++) {
1083       const GstStructure *allowed_s = gst_caps_get_structure (allowed, j);
1084       const GValue *val;
1085       GstStructure *s;
1086
1087       s = gst_structure_id_empty_new (q_name);
1088       if ((val = gst_structure_get_value (allowed_s, "rate")))
1089         gst_structure_set_value (s, "rate", val);
1090       if ((val = gst_structure_get_value (allowed_s, "channels")))
1091         gst_structure_set_value (s, "channels", val);
1092       /* following might also make sense for some encoded formats,
1093        * e.g. wavpack */
1094       if ((val = gst_structure_get_value (allowed_s, "width")))
1095         gst_structure_set_value (s, "width", val);
1096       if ((val = gst_structure_get_value (allowed_s, "depth")))
1097         gst_structure_set_value (s, "depth", val);
1098       if ((val = gst_structure_get_value (allowed_s, "endianness")))
1099         gst_structure_set_value (s, "endianness", val);
1100       if ((val = gst_structure_get_value (allowed_s, "signed")))
1101         gst_structure_set_value (s, "signed", val);
1102       if ((val = gst_structure_get_value (allowed_s, "channel-positions")))
1103         gst_structure_set_value (s, "channel-positions", val);
1104
1105       gst_caps_merge_structure (filter_caps, s);
1106     }
1107   }
1108
1109   fcaps = gst_caps_intersect (filter_caps, templ_caps);
1110   gst_caps_unref (filter_caps);
1111
1112 done:
1113   gst_caps_replace (&allowed, NULL);
1114
1115   GST_LOG_OBJECT (enc, "proxy caps %" GST_PTR_FORMAT, fcaps);
1116
1117   return fcaps;
1118 }
1119
1120 static GstCaps *
1121 gst_audio_encoder_sink_getcaps (GstPad * pad)
1122 {
1123   GstAudioEncoder *enc;
1124   GstAudioEncoderClass *klass;
1125   GstCaps *caps;
1126
1127   enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
1128   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
1129   g_assert (pad == enc->sinkpad);
1130
1131   if (klass->getcaps)
1132     caps = klass->getcaps (enc);
1133   else
1134     caps = gst_audio_encoder_proxy_getcaps (enc, NULL);
1135   gst_object_unref (enc);
1136
1137   GST_LOG_OBJECT (enc, "returning caps %" GST_PTR_FORMAT, caps);
1138
1139   return caps;
1140 }
1141
1142 static gboolean
1143 gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event)
1144 {
1145   GstAudioEncoderClass *klass;
1146   gboolean handled = FALSE;
1147
1148   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
1149
1150   switch (GST_EVENT_TYPE (event)) {
1151     case GST_EVENT_NEWSEGMENT:
1152     {
1153       GstFormat format;
1154       gdouble rate, arate;
1155       gint64 start, stop, time;
1156       gboolean update;
1157
1158       gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
1159           &start, &stop, &time);
1160
1161       if (format == GST_FORMAT_TIME) {
1162         GST_DEBUG_OBJECT (enc, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT
1163             " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
1164             ", rate %g, applied_rate %g",
1165             GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time),
1166             rate, arate);
1167       } else {
1168         GST_DEBUG_OBJECT (enc, "received NEW_SEGMENT %" G_GINT64_FORMAT
1169             " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
1170             ", rate %g, applied_rate %g", start, stop, time, rate, arate);
1171         GST_DEBUG_OBJECT (enc, "unsupported format; ignoring");
1172         break;
1173       }
1174
1175       /* finish current segment */
1176       gst_audio_encoder_drain (enc);
1177       /* reset partially for new segment */
1178       gst_audio_encoder_reset (enc, FALSE);
1179       /* and follow along with segment */
1180       gst_segment_set_newsegment_full (&enc->segment, update, rate, arate,
1181           format, start, stop, time);
1182       break;
1183     }
1184
1185     case GST_EVENT_FLUSH_START:
1186       break;
1187
1188     case GST_EVENT_FLUSH_STOP:
1189       /* discard any pending stuff */
1190       /* TODO route through drain ?? */
1191       if (!enc->priv->drained && klass->flush)
1192         klass->flush (enc);
1193       /* and get (re)set for the sequel */
1194       gst_audio_encoder_reset (enc, FALSE);
1195       break;
1196
1197     case GST_EVENT_EOS:
1198       gst_audio_encoder_drain (enc);
1199       break;
1200
1201     case GST_EVENT_TAG:
1202     {
1203       GstTagList *tags;
1204
1205       gst_event_parse_tag (event, &tags);
1206       tags = gst_tag_list_copy (tags);
1207       gst_event_unref (event);
1208       gst_tag_list_remove_tag (tags, GST_TAG_CODEC);
1209       gst_tag_list_remove_tag (tags, GST_TAG_AUDIO_CODEC);
1210       event = gst_event_new_tag (tags);
1211
1212       gst_pad_push_event (enc->srcpad, event);
1213       handled = TRUE;
1214       break;
1215     }
1216
1217     default:
1218       break;
1219   }
1220
1221   return handled;
1222 }
1223
1224 static gboolean
1225 gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event)
1226 {
1227   GstAudioEncoder *enc;
1228   GstAudioEncoderClass *klass;
1229   gboolean handled = FALSE;
1230   gboolean ret = TRUE;
1231
1232   enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
1233   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
1234
1235   GST_DEBUG_OBJECT (enc, "received event %d, %s", GST_EVENT_TYPE (event),
1236       GST_EVENT_TYPE_NAME (event));
1237
1238   if (klass->event)
1239     handled = klass->event (enc, event);
1240
1241   if (!handled)
1242     handled = gst_audio_encoder_sink_eventfunc (enc, event);
1243
1244   if (!handled)
1245     ret = gst_pad_event_default (pad, event);
1246
1247   GST_DEBUG_OBJECT (enc, "event handled");
1248
1249   gst_object_unref (enc);
1250   return ret;
1251 }
1252
1253 static gboolean
1254 gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query)
1255 {
1256   gboolean res = TRUE;
1257   GstAudioEncoder *enc;
1258
1259   enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
1260
1261   switch (GST_QUERY_TYPE (query)) {
1262     case GST_QUERY_FORMATS:
1263     {
1264       gst_query_set_formats (query, 3,
1265           GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT);
1266       res = TRUE;
1267       break;
1268     }
1269     case GST_QUERY_CONVERT:
1270     {
1271       GstFormat src_fmt, dest_fmt;
1272       gint64 src_val, dest_val;
1273
1274       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
1275       if (!(res = gst_audio_info_convert (&enc->priv->ctx.info,
1276                   src_fmt, src_val, dest_fmt, &dest_val)))
1277         goto error;
1278       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1279       break;
1280     }
1281     default:
1282       res = gst_pad_query_default (pad, query);
1283       break;
1284   }
1285
1286 error:
1287   gst_object_unref (enc);
1288   return res;
1289 }
1290
1291 static const GstQueryType *
1292 gst_audio_encoder_get_query_types (GstPad * pad)
1293 {
1294   static const GstQueryType gst_audio_encoder_src_query_types[] = {
1295     GST_QUERY_POSITION,
1296     GST_QUERY_DURATION,
1297     GST_QUERY_CONVERT,
1298     GST_QUERY_LATENCY,
1299     0
1300   };
1301
1302   return gst_audio_encoder_src_query_types;
1303 }
1304
1305 /*
1306  * gst_audio_encoded_audio_convert:
1307  * @fmt: audio format of the encoded audio
1308  * @bytes: number of encoded bytes
1309  * @samples: number of encoded samples
1310  * @src_format: source format
1311  * @src_value: source value
1312  * @dest_format: destination format
1313  * @dest_value: destination format
1314  *
1315  * Helper function to convert @src_value in @src_format to @dest_value in
1316  * @dest_format for encoded audio data.  Conversion is possible between
1317  * BYTE and TIME format by using estimated bitrate based on
1318  * @samples and @bytes (and @fmt).
1319  *
1320  * Since: 0.10.36
1321  */
1322 /* FIXME: make gst_audio_encoded_audio_convert() public? */
1323 static gboolean
1324 gst_audio_encoded_audio_convert (GstAudioInfo * fmt,
1325     gint64 bytes, gint64 samples, GstFormat src_format,
1326     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
1327 {
1328   gboolean res = FALSE;
1329
1330   g_return_val_if_fail (dest_format != NULL, FALSE);
1331   g_return_val_if_fail (dest_value != NULL, FALSE);
1332
1333   if (G_UNLIKELY (src_format == *dest_format || src_value == 0 ||
1334           src_value == -1)) {
1335     if (dest_value)
1336       *dest_value = src_value;
1337     return TRUE;
1338   }
1339
1340   if (samples == 0 || bytes == 0 || fmt->rate == 0) {
1341     GST_DEBUG ("not enough metadata yet to convert");
1342     goto exit;
1343   }
1344
1345   bytes *= fmt->rate;
1346
1347   switch (src_format) {
1348     case GST_FORMAT_BYTES:
1349       switch (*dest_format) {
1350         case GST_FORMAT_TIME:
1351           *dest_value = gst_util_uint64_scale (src_value,
1352               GST_SECOND * samples, bytes);
1353           res = TRUE;
1354           break;
1355         default:
1356           res = FALSE;
1357       }
1358       break;
1359     case GST_FORMAT_TIME:
1360       switch (*dest_format) {
1361         case GST_FORMAT_BYTES:
1362           *dest_value = gst_util_uint64_scale (src_value, bytes,
1363               samples * GST_SECOND);
1364           res = TRUE;
1365           break;
1366         default:
1367           res = FALSE;
1368       }
1369       break;
1370     default:
1371       res = FALSE;
1372   }
1373
1374 exit:
1375   return res;
1376 }
1377
1378 /* FIXME ? are any of these queries (other than latency) an encoder's business
1379  * also, the conversion stuff might seem to make sense, but seems to not mind
1380  * segment stuff etc at all
1381  * Supposedly that's backward compatibility ... */
1382 static gboolean
1383 gst_audio_encoder_src_query (GstPad * pad, GstQuery * query)
1384 {
1385   GstAudioEncoder *enc;
1386   GstPad *peerpad;
1387   gboolean res = FALSE;
1388
1389   enc = GST_AUDIO_ENCODER (GST_PAD_PARENT (pad));
1390   peerpad = gst_pad_get_peer (GST_PAD (enc->sinkpad));
1391
1392   GST_LOG_OBJECT (enc, "handling query: %" GST_PTR_FORMAT, query);
1393
1394   switch (GST_QUERY_TYPE (query)) {
1395     case GST_QUERY_POSITION:
1396     {
1397       GstFormat fmt, req_fmt;
1398       gint64 pos, val;
1399
1400       if ((res = gst_pad_peer_query (enc->sinkpad, query))) {
1401         GST_LOG_OBJECT (enc, "returning peer response");
1402         break;
1403       }
1404
1405       if (!peerpad) {
1406         GST_LOG_OBJECT (enc, "no peer");
1407         break;
1408       }
1409
1410       gst_query_parse_position (query, &req_fmt, NULL);
1411       fmt = GST_FORMAT_TIME;
1412       if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
1413         break;
1414
1415       if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
1416         gst_query_set_position (query, req_fmt, val);
1417       }
1418       break;
1419     }
1420     case GST_QUERY_DURATION:
1421     {
1422       GstFormat fmt, req_fmt;
1423       gint64 dur, val;
1424
1425       if ((res = gst_pad_peer_query (enc->sinkpad, query))) {
1426         GST_LOG_OBJECT (enc, "returning peer response");
1427         break;
1428       }
1429
1430       if (!peerpad) {
1431         GST_LOG_OBJECT (enc, "no peer");
1432         break;
1433       }
1434
1435       gst_query_parse_duration (query, &req_fmt, NULL);
1436       fmt = GST_FORMAT_TIME;
1437       if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
1438         break;
1439
1440       if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
1441         gst_query_set_duration (query, req_fmt, val);
1442       }
1443       break;
1444     }
1445     case GST_QUERY_FORMATS:
1446     {
1447       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
1448       res = TRUE;
1449       break;
1450     }
1451     case GST_QUERY_CONVERT:
1452     {
1453       GstFormat src_fmt, dest_fmt;
1454       gint64 src_val, dest_val;
1455
1456       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
1457       if (!(res = gst_audio_encoded_audio_convert (&enc->priv->ctx.info,
1458                   enc->priv->bytes_out, enc->priv->samples_in, src_fmt, src_val,
1459                   &dest_fmt, &dest_val)))
1460         break;
1461       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1462       break;
1463     }
1464     case GST_QUERY_LATENCY:
1465     {
1466       if ((res = gst_pad_peer_query (enc->sinkpad, query))) {
1467         gboolean live;
1468         GstClockTime min_latency, max_latency;
1469
1470         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
1471         GST_DEBUG_OBJECT (enc, "Peer latency: live %d, min %"
1472             GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
1473             GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
1474
1475         GST_OBJECT_LOCK (enc);
1476         /* add our latency */
1477         if (min_latency != -1)
1478           min_latency += enc->priv->ctx.min_latency;
1479         if (max_latency != -1)
1480           max_latency += enc->priv->ctx.max_latency;
1481         GST_OBJECT_UNLOCK (enc);
1482
1483         gst_query_set_latency (query, live, min_latency, max_latency);
1484       }
1485       break;
1486     }
1487     default:
1488       res = gst_pad_query_default (pad, query);
1489       break;
1490   }
1491
1492   gst_object_unref (peerpad);
1493   return res;
1494 }
1495
1496 static void
1497 gst_audio_encoder_set_property (GObject * object, guint prop_id,
1498     const GValue * value, GParamSpec * pspec)
1499 {
1500   GstAudioEncoder *enc;
1501
1502   enc = GST_AUDIO_ENCODER (object);
1503
1504   switch (prop_id) {
1505     case PROP_PERFECT_TS:
1506       if (enc->priv->granule && !g_value_get_boolean (value))
1507         GST_WARNING_OBJECT (enc, "perfect-timestamp can not be set FALSE "
1508             "while granule handling is enabled");
1509       else
1510         enc->priv->perfect_ts = g_value_get_boolean (value);
1511       break;
1512     case PROP_HARD_RESYNC:
1513       enc->priv->hard_resync = g_value_get_boolean (value);
1514       break;
1515     case PROP_TOLERANCE:
1516       enc->priv->tolerance = g_value_get_int64 (value);
1517       break;
1518     default:
1519       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1520       break;
1521   }
1522 }
1523
1524 static void
1525 gst_audio_encoder_get_property (GObject * object, guint prop_id,
1526     GValue * value, GParamSpec * pspec)
1527 {
1528   GstAudioEncoder *enc;
1529
1530   enc = GST_AUDIO_ENCODER (object);
1531
1532   switch (prop_id) {
1533     case PROP_PERFECT_TS:
1534       g_value_set_boolean (value, enc->priv->perfect_ts);
1535       break;
1536     case PROP_GRANULE:
1537       g_value_set_boolean (value, enc->priv->granule);
1538       break;
1539     case PROP_HARD_RESYNC:
1540       g_value_set_boolean (value, enc->priv->hard_resync);
1541       break;
1542     case PROP_TOLERANCE:
1543       g_value_set_int64 (value, enc->priv->tolerance);
1544       break;
1545     default:
1546       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1547       break;
1548   }
1549 }
1550
1551 static gboolean
1552 gst_audio_encoder_activate (GstAudioEncoder * enc, gboolean active)
1553 {
1554   GstAudioEncoderClass *klass;
1555   gboolean result = FALSE;
1556
1557   klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
1558
1559   g_return_val_if_fail (!enc->priv->granule || enc->priv->perfect_ts, FALSE);
1560
1561   GST_DEBUG_OBJECT (enc, "activate %d", active);
1562
1563   if (active) {
1564
1565     if (enc->priv->tags)
1566       gst_tag_list_free (enc->priv->tags);
1567     enc->priv->tags = gst_tag_list_new ();
1568
1569     if (!enc->priv->active && klass->start)
1570       result = klass->start (enc);
1571   } else {
1572     /* We must make sure streaming has finished before resetting things
1573      * and calling the ::stop vfunc */
1574     GST_PAD_STREAM_LOCK (enc->sinkpad);
1575     GST_PAD_STREAM_UNLOCK (enc->sinkpad);
1576
1577     if (enc->priv->active && klass->stop)
1578       result = klass->stop (enc);
1579
1580     /* clean up */
1581     gst_audio_encoder_reset (enc, TRUE);
1582   }
1583   GST_DEBUG_OBJECT (enc, "activate return: %d", result);
1584   return result;
1585 }
1586
1587
1588 static gboolean
1589 gst_audio_encoder_sink_activate_push (GstPad * pad, gboolean active)
1590 {
1591   gboolean result = TRUE;
1592   GstAudioEncoder *enc;
1593
1594   enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
1595
1596   GST_DEBUG_OBJECT (enc, "sink activate push %d", active);
1597
1598   result = gst_audio_encoder_activate (enc, active);
1599
1600   if (result)
1601     enc->priv->active = active;
1602
1603   GST_DEBUG_OBJECT (enc, "sink activate push return: %d", result);
1604
1605   gst_object_unref (enc);
1606   return result;
1607 }
1608
1609 /**
1610  * gst_audio_encoder_get_audio_info:
1611  * @enc: a #GstAudioEncoder
1612  *
1613  * Returns: a #GstAudioInfo describing the input audio format
1614  *
1615  * Since: 0.10.36
1616  */
1617 GstAudioInfo *
1618 gst_audio_encoder_get_audio_info (GstAudioEncoder * enc)
1619 {
1620   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), NULL);
1621
1622   return &enc->priv->ctx.info;
1623 }
1624
1625 /**
1626  * gst_audio_encoder_set_frame_samples:
1627  * @enc: a #GstAudioEncoder
1628  * @num: number of samples per frame
1629  *
1630  * Sets number of samples (per channel) subclass needs to be handed,
1631  * or will be handed all available if 0.
1632  *
1633  * Since: 0.10.36
1634  */
1635 void
1636 gst_audio_encoder_set_frame_samples (GstAudioEncoder * enc, gint num)
1637 {
1638   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1639
1640   enc->priv->ctx.frame_samples = num;
1641 }
1642
1643 /**
1644  * gst_audio_encoder_get_frame_samples:
1645  * @enc: a #GstAudioEncoder
1646  *
1647  * Returns: currently requested samples per frame
1648  *
1649  * Since: 0.10.36
1650  */
1651 gint
1652 gst_audio_encoder_get_frame_samples (GstAudioEncoder * enc)
1653 {
1654   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0);
1655
1656   return enc->priv->ctx.frame_samples;
1657 }
1658
1659 /**
1660  * gst_audio_encoder_set_frame_max:
1661  * @enc: a #GstAudioEncoder
1662  * @num: number of frames
1663  *
1664  * Sets max number of frames accepted at once (assumed minimally 1)
1665  *
1666  * Since: 0.10.36
1667  */
1668 void
1669 gst_audio_encoder_set_frame_max (GstAudioEncoder * enc, gint num)
1670 {
1671   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1672
1673   enc->priv->ctx.frame_max = num;
1674 }
1675
1676 /**
1677  * gst_audio_encoder_get_frame_max:
1678  * @enc: a #GstAudioEncoder
1679  *
1680  * Returns: currently configured maximum handled frames
1681  *
1682  * Since: 0.10.36
1683  */
1684 gint
1685 gst_audio_encoder_get_frame_max (GstAudioEncoder * enc)
1686 {
1687   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0);
1688
1689   return enc->priv->ctx.frame_max;
1690 }
1691
1692 /**
1693  * gst_audio_encoder_set_lookahead:
1694  * @enc: a #GstAudioEncoder
1695  * @num: lookahead
1696  *
1697  * Sets encoder lookahead (in units of input rate samples)
1698  *
1699  * Since: 0.10.36
1700  */
1701 void
1702 gst_audio_encoder_set_lookahead (GstAudioEncoder * enc, gint num)
1703 {
1704   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1705
1706   enc->priv->ctx.lookahead = num;
1707 }
1708
1709 /**
1710  * gst_audio_encoder_get_lookahead:
1711  * @enc: a #GstAudioEncoder
1712  *
1713  * Returns: currently configured encoder lookahead
1714  */
1715 gint
1716 gst_audio_encoder_get_lookahead (GstAudioEncoder * enc)
1717 {
1718   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0);
1719
1720   return enc->priv->ctx.lookahead;
1721 }
1722
1723 /**
1724  * gst_audio_encoder_set_latency:
1725  * @enc: a #GstAudioEncoder
1726  * @min: minimum latency
1727  * @max: maximum latency
1728  *
1729  * Sets encoder latency.
1730  *
1731  * Since: 0.10.36
1732  */
1733 void
1734 gst_audio_encoder_set_latency (GstAudioEncoder * enc,
1735     GstClockTime min, GstClockTime max)
1736 {
1737   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1738
1739   GST_OBJECT_LOCK (enc);
1740   enc->priv->ctx.min_latency = min;
1741   enc->priv->ctx.max_latency = max;
1742   GST_OBJECT_UNLOCK (enc);
1743 }
1744
1745 /**
1746  * gst_audio_encoder_get_latency:
1747  * @enc: a #GstAudioEncoder
1748  * @min: (out) (allow-none): a pointer to storage to hold minimum latency
1749  * @max: (out) (allow-none): a pointer to storage to hold maximum latency
1750  *
1751  * Sets the variables pointed to by @min and @max to the currently configured
1752  * latency.
1753  *
1754  * Since: 0.10.36
1755  */
1756 void
1757 gst_audio_encoder_get_latency (GstAudioEncoder * enc,
1758     GstClockTime * min, GstClockTime * max)
1759 {
1760   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1761
1762   GST_OBJECT_LOCK (enc);
1763   if (min)
1764     *min = enc->priv->ctx.min_latency;
1765   if (max)
1766     *max = enc->priv->ctx.max_latency;
1767   GST_OBJECT_UNLOCK (enc);
1768 }
1769
1770 /**
1771  * gst_audio_encoder_set_mark_granule:
1772  * @enc: a #GstAudioEncoder
1773  * @enabled: new state
1774  *
1775  * Enable or disable encoder granule handling.
1776  *
1777  * MT safe.
1778  *
1779  * Since: 0.10.36
1780  */
1781 void
1782 gst_audio_encoder_set_mark_granule (GstAudioEncoder * enc, gboolean enabled)
1783 {
1784   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1785
1786   GST_LOG_OBJECT (enc, "enabled: %d", enabled);
1787
1788   GST_OBJECT_LOCK (enc);
1789   enc->priv->granule = enabled;
1790   GST_OBJECT_UNLOCK (enc);
1791 }
1792
1793 /**
1794  * gst_audio_encoder_get_mark_granule:
1795  * @enc: a #GstAudioEncoder
1796  *
1797  * Queries if the encoder will handle granule marking.
1798  *
1799  * Returns: TRUE if granule marking is enabled.
1800  *
1801  * MT safe.
1802  *
1803  * Since: 0.10.36
1804  */
1805 gboolean
1806 gst_audio_encoder_get_mark_granule (GstAudioEncoder * enc)
1807 {
1808   gboolean result;
1809
1810   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), FALSE);
1811
1812   GST_OBJECT_LOCK (enc);
1813   result = enc->priv->granule;
1814   GST_OBJECT_UNLOCK (enc);
1815
1816   return result;
1817 }
1818
1819 /**
1820  * gst_audio_encoder_set_perfect_timestamp:
1821  * @enc: a #GstAudioEncoder
1822  * @enabled: new state
1823  *
1824  * Enable or disable encoder perfect output timestamp preference.
1825  *
1826  * MT safe.
1827  *
1828  * Since: 0.10.36
1829  */
1830 void
1831 gst_audio_encoder_set_perfect_timestamp (GstAudioEncoder * enc,
1832     gboolean enabled)
1833 {
1834   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1835
1836   GST_LOG_OBJECT (enc, "enabled: %d", enabled);
1837
1838   GST_OBJECT_LOCK (enc);
1839   enc->priv->perfect_ts = enabled;
1840   GST_OBJECT_UNLOCK (enc);
1841 }
1842
1843 /**
1844  * gst_audio_encoder_get_perfect_timestamp:
1845  * @enc: a #GstAudioEncoder
1846  *
1847  * Queries encoder perfect timestamp behaviour.
1848  *
1849  * Returns: TRUE if pefect timestamp setting enabled.
1850  *
1851  * MT safe.
1852  *
1853  * Since: 0.10.36
1854  */
1855 gboolean
1856 gst_audio_encoder_get_perfect_timestamp (GstAudioEncoder * enc)
1857 {
1858   gboolean result;
1859
1860   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), FALSE);
1861
1862   GST_OBJECT_LOCK (enc);
1863   result = enc->priv->perfect_ts;
1864   GST_OBJECT_UNLOCK (enc);
1865
1866   return result;
1867 }
1868
1869 /**
1870  * gst_audio_encoder_set_hard_sync:
1871  * @enc: a #GstAudioEncoder
1872  * @enabled: new state
1873  *
1874  * Sets encoder hard resync handling.
1875  *
1876  * MT safe.
1877  *
1878  * Since: 0.10.36
1879  */
1880 void
1881 gst_audio_encoder_set_hard_resync (GstAudioEncoder * enc, gboolean enabled)
1882 {
1883   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1884
1885   GST_LOG_OBJECT (enc, "enabled: %d", enabled);
1886
1887   GST_OBJECT_LOCK (enc);
1888   enc->priv->hard_resync = enabled;
1889   GST_OBJECT_UNLOCK (enc);
1890 }
1891
1892 /**
1893  * gst_audio_encoder_get_hard_sync:
1894  * @enc: a #GstAudioEncoder
1895  *
1896  * Queries encoder's hard resync setting.
1897  *
1898  * Returns: TRUE if hard resync is enabled.
1899  *
1900  * MT safe.
1901  *
1902  * Since: 0.10.36
1903  */
1904 gboolean
1905 gst_audio_encoder_get_hard_resync (GstAudioEncoder * enc)
1906 {
1907   gboolean result;
1908
1909   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), FALSE);
1910
1911   GST_OBJECT_LOCK (enc);
1912   result = enc->priv->hard_resync;
1913   GST_OBJECT_UNLOCK (enc);
1914
1915   return result;
1916 }
1917
1918 /**
1919  * gst_audio_encoder_set_tolerance:
1920  * @enc: a #GstAudioEncoder
1921  * @tolerance: new tolerance
1922  *
1923  * Configures encoder audio jitter tolerance threshold.
1924  *
1925  * MT safe.
1926  *
1927  * Since: 0.10.36
1928  */
1929 void
1930 gst_audio_encoder_set_tolerance (GstAudioEncoder * enc, gint64 tolerance)
1931 {
1932   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1933
1934   GST_OBJECT_LOCK (enc);
1935   enc->priv->tolerance = tolerance;
1936   GST_OBJECT_UNLOCK (enc);
1937 }
1938
1939 /**
1940  * gst_audio_encoder_get_tolerance:
1941  * @enc: a #GstAudioEncoder
1942  *
1943  * Queries current audio jitter tolerance threshold.
1944  *
1945  * Returns: encoder audio jitter tolerance threshold.
1946  *
1947  * MT safe.
1948  *
1949  * Since: 0.10.36
1950  */
1951 gint64
1952 gst_audio_encoder_get_tolerance (GstAudioEncoder * enc)
1953 {
1954   gint64 result;
1955
1956   g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0);
1957
1958   GST_OBJECT_LOCK (enc);
1959   result = enc->priv->tolerance;
1960   GST_OBJECT_UNLOCK (enc);
1961
1962   return result;
1963 }
1964
1965 /**
1966  * gst_audio_encoder_merge_tags:
1967  * @enc: a #GstAudioEncoder
1968  * @tags: a #GstTagList to merge
1969  * @mode: the #GstTagMergeMode to use
1970  *
1971  * Adds tags to so-called pending tags, which will be processed
1972  * before pushing out data downstream.
1973  *
1974  * Note that this is provided for convenience, and the subclass is
1975  * not required to use this and can still do tag handling on its own,
1976  * although it should be aware that baseclass already takes care
1977  * of the usual CODEC/AUDIO_CODEC tags.
1978  *
1979  * MT safe.
1980  *
1981  * Since: 0.10.36
1982  */
1983 void
1984 gst_audio_encoder_merge_tags (GstAudioEncoder * enc,
1985     const GstTagList * tags, GstTagMergeMode mode)
1986 {
1987   GstTagList *otags;
1988
1989   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
1990   g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags));
1991
1992   GST_OBJECT_LOCK (enc);
1993   if (tags)
1994     GST_DEBUG_OBJECT (enc, "merging tags %" GST_PTR_FORMAT, tags);
1995   otags = enc->priv->tags;
1996   enc->priv->tags = gst_tag_list_merge (enc->priv->tags, tags, mode);
1997   if (otags)
1998     gst_tag_list_free (otags);
1999   GST_OBJECT_UNLOCK (enc);
2000 }