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