rtpaudiopayload: Only sent exact multiple of the frame size
[platform/upstream/gstreamer.git] / gst-libs / gst / rtp / gstbasertpaudiopayload.c
1 /* GStreamer
2  * Copyright (C) <2006> Philippe Khalaf <philippe.kalaf@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:gstbasertpaudiopayload
22  * @short_description: Base class for audio RTP payloader
23  *
24  * <refsect2>
25  * <para>
26  * Provides a base class for audio RTP payloaders for frame or sample based
27  * audio codecs (constant bitrate)
28  * </para>
29  * <para>
30  * This class derives from GstBaseRTPPayload. It can be used for payloading
31  * audio codecs. It will only work with constant bitrate codecs. It supports
32  * both frame based and sample based codecs. It takes care of packing up the
33  * audio data into RTP packets and filling up the headers accordingly. The
34  * payloading is done based on the maximum MTU (mtu) and the maximum time per
35  * packet (max-ptime). The general idea is to divide large data buffers into
36  * smaller RTP packets. The RTP packet size is the minimum of either the MTU,
37  * max-ptime (if set) or available data. The RTP packet size is always larger or
38  * equal to min-ptime (if set). If min-ptime is not set, any residual data is
39  * sent in a last RTP packet. In the case of frame based codecs, the resulting
40  * RTP packets always contain full frames.
41  * </para>
42  * <title>Usage</title>
43  * <para>
44  * To use this base class, your child element needs to call either
45  * gst_base_rtp_audio_payload_set_frame_based() or
46  * gst_base_rtp_audio_payload_set_sample_based(). This is usually done in the
47  * element's _init() function. Then, the child element must call either
48  * gst_base_rtp_audio_payload_set_frame_options(),
49  * gst_base_rtp_audio_payload_set_sample_options() or
50  * gst_base_rtp_audio_payload_set_samplebits_options. Since
51  * GstBaseRTPAudioPayload derives from GstBaseRTPPayload, the child element
52  * must set any variables or call/override any functions required by that base
53  * class. The child element does not need to override any other functions
54  * specific to GstBaseRTPAudioPayload.
55  * </para>
56  * </refsect2>
57  */
58
59 #ifdef HAVE_CONFIG_H
60 #include "config.h"
61 #endif
62
63 #include <stdlib.h>
64 #include <string.h>
65 #include <gst/rtp/gstrtpbuffer.h>
66 #include <gst/base/gstadapter.h>
67
68 #include "gstbasertpaudiopayload.h"
69
70 GST_DEBUG_CATEGORY_STATIC (basertpaudiopayload_debug);
71 #define GST_CAT_DEFAULT (basertpaudiopayload_debug)
72
73 /* function to convert bytes to a time */
74 typedef GstClockTime (*GetBytesToTimeFunc) (GstBaseRTPAudioPayload * payload,
75     guint64 bytes);
76 /* function to convert bytes to a RTP time */
77 typedef guint32 (*GetBytesToRTPTimeFunc) (GstBaseRTPAudioPayload * payload,
78     guint64 bytes);
79 /* function to convert time to bytes */
80 typedef guint64 (*GetTimeToBytesFunc) (GstBaseRTPAudioPayload * payload,
81     GstClockTime time);
82
83 struct _GstBaseRTPAudioPayloadPrivate
84 {
85   GetBytesToTimeFunc bytes_to_time;
86   GetBytesToRTPTimeFunc bytes_to_rtptime;
87   GetTimeToBytesFunc time_to_bytes;
88
89   GstAdapter *adapter;
90   guint fragment_size;
91   GstClockTime frame_duration_ns;
92   gboolean discont;
93   guint64 offset;
94   GstClockTime last_timestamp;
95   guint32 last_rtptime;
96   guint align;
97
98   guint cached_mtu;
99   guint cached_min_ptime;
100   guint cached_max_ptime;
101   guint cached_min_length;
102   guint cached_max_length;
103 };
104
105
106 #define GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE(o) \
107   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_BASE_RTP_AUDIO_PAYLOAD, \
108                                 GstBaseRTPAudioPayloadPrivate))
109
110 static void gst_base_rtp_audio_payload_finalize (GObject * object);
111
112 /* bytes to time functions */
113 static GstClockTime
114 gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload *
115     payload, guint64 bytes);
116 static GstClockTime
117 gst_base_rtp_audio_payload_sample_bytes_to_time (GstBaseRTPAudioPayload *
118     payload, guint64 bytes);
119
120 /* bytes to RTP time functions */
121 static guint32
122 gst_base_rtp_audio_payload_frame_bytes_to_rtptime (GstBaseRTPAudioPayload *
123     payload, guint64 bytes);
124 static guint32
125 gst_base_rtp_audio_payload_sample_bytes_to_rtptime (GstBaseRTPAudioPayload *
126     payload, guint64 bytes);
127
128 /* time to bytes functions */
129 static guint64
130 gst_base_rtp_audio_payload_frame_time_to_bytes (GstBaseRTPAudioPayload *
131     payload, GstClockTime time);
132 static guint64
133 gst_base_rtp_audio_payload_sample_time_to_bytes (GstBaseRTPAudioPayload *
134     payload, GstClockTime time);
135
136 static GstFlowReturn gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload
137     * payload, GstBuffer * buffer);
138
139 static GstStateChangeReturn gst_base_rtp_payload_audio_change_state (GstElement
140     * element, GstStateChange transition);
141
142 static gboolean gst_base_rtp_payload_audio_handle_event (GstPad * pad,
143     GstEvent * event);
144
145 GST_BOILERPLATE (GstBaseRTPAudioPayload, gst_base_rtp_audio_payload,
146     GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD);
147
148 static void
149 gst_base_rtp_audio_payload_base_init (gpointer klass)
150 {
151 }
152
153 static void
154 gst_base_rtp_audio_payload_class_init (GstBaseRTPAudioPayloadClass * klass)
155 {
156   GObjectClass *gobject_class;
157   GstElementClass *gstelement_class;
158   GstBaseRTPPayloadClass *gstbasertppayload_class;
159
160   g_type_class_add_private (klass, sizeof (GstBaseRTPAudioPayloadPrivate));
161
162   gobject_class = (GObjectClass *) klass;
163   gstelement_class = (GstElementClass *) klass;
164   gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
165
166   gobject_class->finalize =
167       GST_DEBUG_FUNCPTR (gst_base_rtp_audio_payload_finalize);
168
169   gstelement_class->change_state =
170       GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_change_state);
171
172   gstbasertppayload_class->handle_buffer =
173       GST_DEBUG_FUNCPTR (gst_base_rtp_audio_payload_handle_buffer);
174   gstbasertppayload_class->handle_event =
175       GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_handle_event);
176
177   GST_DEBUG_CATEGORY_INIT (basertpaudiopayload_debug, "basertpaudiopayload", 0,
178       "base audio RTP payloader");
179 }
180
181 static void
182 gst_base_rtp_audio_payload_init (GstBaseRTPAudioPayload * payload,
183     GstBaseRTPAudioPayloadClass * klass)
184 {
185   payload->priv = GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE (payload);
186
187   /* these need to be set by child object if frame based */
188   payload->frame_size = 0;
189   payload->frame_duration = 0;
190
191   /* these need to be set by child object if sample based */
192   payload->sample_size = 0;
193
194   payload->priv->adapter = gst_adapter_new ();
195 }
196
197 static void
198 gst_base_rtp_audio_payload_finalize (GObject * object)
199 {
200   GstBaseRTPAudioPayload *payload;
201
202   payload = GST_BASE_RTP_AUDIO_PAYLOAD (object);
203
204   g_object_unref (payload->priv->adapter);
205
206   GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
207 }
208
209 /**
210  * gst_base_rtp_audio_payload_set_frame_based:
211  * @basertpaudiopayload: a pointer to the element.
212  *
213  * Tells #GstBaseRTPAudioPayload that the child element is for a frame based
214  * audio codec
215  */
216 void
217 gst_base_rtp_audio_payload_set_frame_based (GstBaseRTPAudioPayload *
218     basertpaudiopayload)
219 {
220   g_return_if_fail (basertpaudiopayload != NULL);
221   g_return_if_fail (basertpaudiopayload->priv->time_to_bytes == NULL);
222   g_return_if_fail (basertpaudiopayload->priv->bytes_to_time == NULL);
223   g_return_if_fail (basertpaudiopayload->priv->bytes_to_rtptime == NULL);
224
225   basertpaudiopayload->priv->bytes_to_time =
226       gst_base_rtp_audio_payload_frame_bytes_to_time;
227   basertpaudiopayload->priv->bytes_to_rtptime =
228       gst_base_rtp_audio_payload_frame_bytes_to_rtptime;
229   basertpaudiopayload->priv->time_to_bytes =
230       gst_base_rtp_audio_payload_frame_time_to_bytes;
231 }
232
233 /**
234  * gst_base_rtp_audio_payload_set_sample_based:
235  * @basertpaudiopayload: a pointer to the element.
236  *
237  * Tells #GstBaseRTPAudioPayload that the child element is for a sample based
238  * audio codec
239  */
240 void
241 gst_base_rtp_audio_payload_set_sample_based (GstBaseRTPAudioPayload *
242     basertpaudiopayload)
243 {
244   g_return_if_fail (basertpaudiopayload != NULL);
245   g_return_if_fail (basertpaudiopayload->priv->time_to_bytes == NULL);
246   g_return_if_fail (basertpaudiopayload->priv->bytes_to_time == NULL);
247   g_return_if_fail (basertpaudiopayload->priv->bytes_to_rtptime == NULL);
248
249   basertpaudiopayload->priv->bytes_to_time =
250       gst_base_rtp_audio_payload_sample_bytes_to_time;
251   basertpaudiopayload->priv->bytes_to_rtptime =
252       gst_base_rtp_audio_payload_sample_bytes_to_rtptime;
253   basertpaudiopayload->priv->time_to_bytes =
254       gst_base_rtp_audio_payload_sample_time_to_bytes;
255 }
256
257 /**
258  * gst_base_rtp_audio_payload_set_frame_options:
259  * @basertpaudiopayload: a pointer to the element.
260  * @frame_duration: The duraction of an audio frame in milliseconds.
261  * @frame_size: The size of an audio frame in bytes.
262  *
263  * Sets the options for frame based audio codecs.
264  *
265  */
266 void
267 gst_base_rtp_audio_payload_set_frame_options (GstBaseRTPAudioPayload
268     * basertpaudiopayload, gint frame_duration, gint frame_size)
269 {
270   GstBaseRTPAudioPayloadPrivate *priv;
271
272   g_return_if_fail (basertpaudiopayload != NULL);
273
274   priv = basertpaudiopayload->priv;
275
276   basertpaudiopayload->frame_duration = frame_duration;
277   priv->frame_duration_ns = frame_duration * GST_MSECOND;
278   basertpaudiopayload->frame_size = frame_size;
279   priv->align = frame_size;
280
281   gst_adapter_clear (priv->adapter);
282
283   GST_DEBUG_OBJECT (basertpaudiopayload, "frame set to %d ms and size %d",
284       frame_duration, frame_size);
285 }
286
287 /**
288  * gst_base_rtp_audio_payload_set_sample_options:
289  * @basertpaudiopayload: a pointer to the element.
290  * @sample_size: Size per sample in bytes.
291  *
292  * Sets the options for sample based audio codecs.
293  */
294 void
295 gst_base_rtp_audio_payload_set_sample_options (GstBaseRTPAudioPayload
296     * basertpaudiopayload, gint sample_size)
297 {
298   g_return_if_fail (basertpaudiopayload != NULL);
299
300   /* sample_size is in bits internally */
301   gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload,
302       sample_size * 8);
303 }
304
305 /**
306  * gst_base_rtp_audio_payload_set_samplebits_options:
307  * @basertpaudiopayload: a pointer to the element.
308  * @sample_size: Size per sample in bits.
309  *
310  * Sets the options for sample based audio codecs.
311  *
312  * Since: 0.10.18
313  */
314 void
315 gst_base_rtp_audio_payload_set_samplebits_options (GstBaseRTPAudioPayload
316     * basertpaudiopayload, gint sample_size)
317 {
318   guint fragment_size;
319   GstBaseRTPAudioPayloadPrivate *priv;
320
321   g_return_if_fail (basertpaudiopayload != NULL);
322
323   priv = basertpaudiopayload->priv;
324
325   basertpaudiopayload->sample_size = sample_size;
326
327   /* sample_size is in bits and is converted into multiple bytes */
328   fragment_size = sample_size;
329   while ((fragment_size % 8) != 0)
330     fragment_size += fragment_size;
331   priv->fragment_size = fragment_size / 8;
332   priv->align = priv->fragment_size;
333
334   gst_adapter_clear (priv->adapter);
335
336   GST_DEBUG_OBJECT (basertpaudiopayload,
337       "Samplebits set to sample size %d bits", sample_size);
338 }
339
340 static void
341 gst_base_rtp_audio_payload_set_meta (GstBaseRTPAudioPayload * payload,
342     GstBuffer * buffer, guint payload_len, GstClockTime timestamp)
343 {
344   GstBaseRTPPayload *basepayload;
345   GstBaseRTPAudioPayloadPrivate *priv;
346
347   basepayload = GST_BASE_RTP_PAYLOAD_CAST (payload);
348   priv = payload->priv;
349
350   /* set payload type */
351   gst_rtp_buffer_set_payload_type (buffer, basepayload->pt);
352   /* set marker bit for disconts */
353   if (priv->discont) {
354     GST_DEBUG_OBJECT (payload, "Setting marker and DISCONT");
355     gst_rtp_buffer_set_marker (buffer, TRUE);
356     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
357     priv->discont = FALSE;
358   }
359   GST_BUFFER_TIMESTAMP (buffer) = timestamp;
360
361   /* get the offset in RTP time */
362   GST_BUFFER_OFFSET (buffer) = priv->bytes_to_rtptime (payload, priv->offset);
363
364   priv->offset += payload_len;
365
366   /* remember the last rtptime/timestamp pair. We will use this to realign our
367    * RTP timestamp after a buffer discont */
368   priv->last_rtptime = GST_BUFFER_OFFSET (buffer);
369   priv->last_timestamp = timestamp;
370 }
371
372 /**
373  * gst_base_rtp_audio_payload_push:
374  * @baseaudiopayload: a #GstBaseRTPPayload
375  * @data: data to set as payload
376  * @payload_len: length of payload
377  * @timestamp: a #GstClockTime
378  *
379  * Create an RTP buffer and store @payload_len bytes of @data as the
380  * payload. Set the timestamp on the new buffer to @timestamp before pushing
381  * the buffer downstream.
382  *
383  * Returns: a #GstFlowReturn
384  *
385  * Since: 0.10.13
386  */
387 GstFlowReturn
388 gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload,
389     const guint8 * data, guint payload_len, GstClockTime timestamp)
390 {
391   GstBaseRTPPayload *basepayload;
392   GstBuffer *outbuf;
393   guint8 *payload;
394   GstFlowReturn ret;
395
396   basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
397
398   GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
399       payload_len, GST_TIME_ARGS (timestamp));
400
401   /* create buffer to hold the payload */
402   outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
403
404   /* copy payload */
405   payload = gst_rtp_buffer_get_payload (outbuf);
406   memcpy (payload, data, payload_len);
407
408   /* set metadata */
409   gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
410       timestamp);
411
412   ret = gst_basertppayload_push (basepayload, outbuf);
413
414   return ret;
415 }
416
417 /**
418  * gst_base_rtp_audio_payload_flush:
419  * @baseaudiopayload: a #GstBaseRTPPayload
420  * @payload_len: length of payload
421  * @timestamp: a #GstClockTime
422  *
423  * Create an RTP buffer and store @payload_len bytes of the adapter as the
424  * payload. Set the timestamp on the new buffer to @timestamp before pushing
425  * the buffer downstream.
426  *
427  * If @payload_len is -1, all pending bytes will be flushed. If @timestamp is
428  * -1, the timestamp will be calculated automatically.
429  *
430  * Returns: a #GstFlowReturn
431  *
432  * Since: 0.10.25
433  */
434 GstFlowReturn
435 gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload,
436     guint payload_len, GstClockTime timestamp)
437 {
438   GstBaseRTPPayload *basepayload;
439   GstBaseRTPAudioPayloadPrivate *priv;
440   GstBuffer *outbuf;
441   guint8 *payload;
442   GstFlowReturn ret;
443   GstAdapter *adapter;
444   guint64 distance;
445
446   priv = baseaudiopayload->priv;
447   adapter = priv->adapter;
448
449   basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
450
451   if (payload_len == -1)
452     payload_len = gst_adapter_available (adapter);
453
454   /* nothing to do, just return */
455   if (payload_len == 0)
456     return GST_FLOW_OK;
457
458   if (timestamp == -1) {
459     /* calculate the timestamp */
460     timestamp = gst_adapter_prev_timestamp (adapter, &distance);
461
462     GST_LOG_OBJECT (baseaudiopayload,
463         "last timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT,
464         GST_TIME_ARGS (timestamp), distance);
465
466     if (GST_CLOCK_TIME_IS_VALID (timestamp) && distance > 0) {
467       /* convert the number of bytes since the last timestamp to time and add to
468        * the last seen timestamp */
469       timestamp += priv->bytes_to_time (baseaudiopayload, distance);
470     }
471   }
472
473   GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
474       payload_len, GST_TIME_ARGS (timestamp));
475
476   /* create buffer to hold the payload */
477   outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
478
479   payload = gst_rtp_buffer_get_payload (outbuf);
480   gst_adapter_copy (adapter, payload, 0, payload_len);
481   gst_adapter_flush (adapter, payload_len);
482
483   /* set metadata */
484   gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
485       timestamp);
486
487   ret = gst_basertppayload_push (basepayload, outbuf);
488
489   return ret;
490 }
491
492 #define ALIGN_DOWN(val,len) ((val) - ((val) % (len)))
493
494 /* calculate the min and max length of a packet. This depends on the configured
495  * mtu and min/max_ptime values. We cache those so that we don't have to redo
496  * all the calculations */
497 static gboolean
498 gst_base_rtp_audio_payload_get_lengths (GstBaseRTPPayload *
499     basepayload, guint * min_payload_len, guint * max_payload_len,
500     guint * align)
501 {
502   GstBaseRTPAudioPayload *payload;
503   GstBaseRTPAudioPayloadPrivate *priv;
504   guint max_mtu, mtu;
505   guint maxptime_octets;
506   guint minptime_octets;
507
508   payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
509   priv = payload->priv;
510
511   if (priv->align == 0)
512     return FALSE;
513
514   *align = priv->align;
515
516   mtu = GST_BASE_RTP_PAYLOAD_MTU (payload);
517
518   /* check cached values */
519   if (G_LIKELY (priv->cached_mtu == mtu
520           && priv->cached_max_ptime == basepayload->max_ptime
521           && priv->cached_min_ptime == basepayload->min_ptime)) {
522     /* if nothing changed, return cached values */
523     *min_payload_len = priv->cached_min_length;
524     *max_payload_len = priv->cached_max_length;
525     return TRUE;
526   }
527
528   /* ptime max */
529   if (basepayload->max_ptime != -1) {
530     maxptime_octets = priv->time_to_bytes (payload, basepayload->max_ptime);
531   } else {
532     maxptime_octets = G_MAXUINT;
533   }
534   /* MTU max */
535   max_mtu = gst_rtp_buffer_calc_payload_len (mtu, 0, 0);
536   /* round down to alignment */
537   max_mtu = ALIGN_DOWN (max_mtu, *align);
538
539   /* combine max ptime and max payload length */
540   *max_payload_len = MIN (max_mtu, maxptime_octets);
541
542   /* min number of bytes based on a given ptime */
543   minptime_octets = priv->time_to_bytes (payload, basepayload->min_ptime);
544   /* must be at least one frame size */
545   *min_payload_len = MAX (minptime_octets, *align);
546
547   if (*min_payload_len > *max_payload_len)
548     *min_payload_len = *max_payload_len;
549
550   /* cache values */
551   priv->cached_mtu = mtu;
552   priv->cached_min_ptime = basepayload->min_ptime;
553   priv->cached_max_ptime = basepayload->max_ptime;
554   priv->cached_min_length = *min_payload_len;
555   priv->cached_max_length = *max_payload_len;
556
557   return TRUE;
558 }
559
560 /* frame conversions functions */
561 static GstClockTime
562 gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload *
563     payload, guint64 bytes)
564 {
565   return (bytes / payload->frame_size) * (payload->priv->frame_duration_ns);
566 }
567
568 static guint32
569 gst_base_rtp_audio_payload_frame_bytes_to_rtptime (GstBaseRTPAudioPayload *
570     payload, guint64 bytes)
571 {
572   guint64 time;
573
574   time = (bytes / payload->frame_size) * (payload->priv->frame_duration_ns);
575
576   return gst_util_uint64_scale_int (time,
577       GST_BASE_RTP_PAYLOAD (payload)->clock_rate, GST_SECOND);
578 }
579
580 static guint64
581 gst_base_rtp_audio_payload_frame_time_to_bytes (GstBaseRTPAudioPayload *
582     payload, GstClockTime time)
583 {
584   return gst_util_uint64_scale (time, payload->frame_size,
585       payload->priv->frame_duration_ns);
586 }
587
588 /* sample conversion functions */
589 static GstClockTime
590 gst_base_rtp_audio_payload_sample_bytes_to_time (GstBaseRTPAudioPayload *
591     payload, guint64 bytes)
592 {
593   guint64 rtptime;
594
595   /* avoid division when we can */
596   if (G_LIKELY (payload->sample_size != 8))
597     rtptime = gst_util_uint64_scale_int (bytes, 8, payload->sample_size);
598   else
599     rtptime = bytes;
600
601   return gst_util_uint64_scale_int (rtptime, GST_SECOND,
602       GST_BASE_RTP_PAYLOAD (payload)->clock_rate);
603 }
604
605 static guint32
606 gst_base_rtp_audio_payload_sample_bytes_to_rtptime (GstBaseRTPAudioPayload *
607     payload, guint64 bytes)
608 {
609   /* avoid division when we can */
610   if (G_LIKELY (payload->sample_size != 8))
611     return gst_util_uint64_scale_int (bytes, 8, payload->sample_size);
612   else
613     return bytes;
614 }
615
616 static guint64
617 gst_base_rtp_audio_payload_sample_time_to_bytes (GstBaseRTPAudioPayload *
618     payload, guint64 time)
619 {
620   guint64 samples;
621
622   samples = gst_util_uint64_scale_int (time,
623       GST_BASE_RTP_PAYLOAD (payload)->clock_rate, GST_SECOND);
624
625   /* avoid multiplication when we can */
626   if (G_LIKELY (payload->sample_size != 8))
627     return gst_util_uint64_scale_int (samples, payload->sample_size, 8);
628   else
629     return samples;
630 }
631
632 static GstFlowReturn
633 gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload *
634     basepayload, GstBuffer * buffer)
635 {
636   GstBaseRTPAudioPayload *payload;
637   GstBaseRTPAudioPayloadPrivate *priv;
638   guint payload_len;
639   GstFlowReturn ret;
640   guint available;
641   guint min_payload_len;
642   guint max_payload_len;
643   guint align;
644   guint size;
645   gboolean discont;
646
647   ret = GST_FLOW_OK;
648
649   payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
650   priv = payload->priv;
651
652   discont = GST_BUFFER_IS_DISCONT (buffer);
653   if (discont) {
654     GstClockTime timestamp;
655
656     GST_DEBUG_OBJECT (payload, "Got DISCONT");
657     /* flush everything out of the adapter, mark DISCONT */
658     ret = gst_base_rtp_audio_payload_flush (payload, -1, -1);
659     priv->discont = TRUE;
660
661     timestamp = GST_BUFFER_TIMESTAMP (buffer);
662
663     /* get the distance between the timestamp gap and produce the same gap in
664      * the RTP timestamps */
665     if (priv->last_timestamp != -1 && timestamp != -1) {
666       /* we had a last timestamp, compare it to the new timestamp and update the
667        * offset counter for RTP timestamps. The effect is that we will produce
668        * output buffers containing the same RTP timestamp gap as the gap
669        * between the GST timestamps. */
670       if (timestamp > priv->last_timestamp) {
671         GstClockTime diff;
672         guint64 bytes;
673         /* we're only going to apply a positive gap, otherwise we let the marker
674          * bit do its thing. simply convert to bytes and add the the current
675          * offset */
676         diff = timestamp - priv->last_timestamp;
677         bytes = priv->time_to_bytes (payload, diff);
678         priv->offset += bytes;
679
680         GST_DEBUG_OBJECT (payload,
681             "elapsed time %" GST_TIME_FORMAT ", bytes %" G_GUINT64_FORMAT
682             ", new offset %" G_GUINT64_FORMAT, GST_TIME_ARGS (diff), bytes,
683             priv->offset);
684       }
685     }
686   }
687
688   if (!gst_base_rtp_audio_payload_get_lengths (basepayload, &min_payload_len,
689           &max_payload_len, &align))
690     goto config_error;
691
692   GST_DEBUG_OBJECT (payload,
693       "Calculated min_payload_len %u and max_payload_len %u",
694       min_payload_len, max_payload_len);
695
696   size = GST_BUFFER_SIZE (buffer);
697
698   /* shortcut, we don't need to use the adapter when the packet can be pushed
699    * through directly. */
700   available = gst_adapter_available (priv->adapter);
701
702   GST_DEBUG_OBJECT (payload, "got buffer size %u, available %u",
703       size, available);
704
705   if (available == 0 && (size >= min_payload_len && size <= max_payload_len)) {
706     /* If buffer fits on an RTP packet, let's just push it through
707      * this will check against max_ptime and max_mtu */
708     GST_DEBUG_OBJECT (payload, "Fast packet push");
709     ret = gst_base_rtp_audio_payload_push (payload,
710         GST_BUFFER_DATA (buffer), size, GST_BUFFER_TIMESTAMP (buffer));
711     gst_buffer_unref (buffer);
712   } else {
713     /* push the buffer in the adapter */
714     gst_adapter_push (priv->adapter, buffer);
715     available += size;
716
717     GST_DEBUG_OBJECT (payload, "available now %u", available);
718
719     /* as long as we have full frames */
720     while (available >= min_payload_len) {
721       /* get multiple of alignment */
722       payload_len = MIN (max_payload_len, available);
723       payload_len = ALIGN_DOWN (payload_len, align);
724
725       /* and flush out the bytes from the adapter, automatically set the
726        * timestamp. */
727       ret = gst_base_rtp_audio_payload_flush (payload, payload_len, -1);
728
729       available -= payload_len;
730       GST_DEBUG_OBJECT (payload, "available after push %u", available);
731     }
732   }
733   return ret;
734
735   /* ERRORS */
736 config_error:
737   {
738     GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
739         ("subclass did not configure us properly"));
740     gst_buffer_unref (buffer);
741     return GST_FLOW_ERROR;
742   }
743 }
744
745 static GstStateChangeReturn
746 gst_base_rtp_payload_audio_change_state (GstElement * element,
747     GstStateChange transition)
748 {
749   GstBaseRTPAudioPayload *basertppayload;
750   GstStateChangeReturn ret;
751
752   basertppayload = GST_BASE_RTP_AUDIO_PAYLOAD (element);
753
754   switch (transition) {
755     case GST_STATE_CHANGE_READY_TO_PAUSED:
756       basertppayload->priv->cached_mtu = -1;
757       basertppayload->priv->last_rtptime = -1;
758       basertppayload->priv->last_timestamp = -1;
759       break;
760     default:
761       break;
762   }
763
764   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
765
766   switch (transition) {
767     case GST_STATE_CHANGE_PAUSED_TO_READY:
768       gst_adapter_clear (basertppayload->priv->adapter);
769       break;
770     default:
771       break;
772   }
773
774   return ret;
775 }
776
777 static gboolean
778 gst_base_rtp_payload_audio_handle_event (GstPad * pad, GstEvent * event)
779 {
780   GstBaseRTPAudioPayload *payload;
781   gboolean res = FALSE;
782
783   payload = GST_BASE_RTP_AUDIO_PAYLOAD (gst_pad_get_parent (pad));
784
785   switch (GST_EVENT_TYPE (event)) {
786     case GST_EVENT_EOS:
787       /* flush remaining bytes in the adapter */
788       gst_base_rtp_audio_payload_flush (payload, -1, -1);
789       break;
790     case GST_EVENT_FLUSH_STOP:
791       gst_adapter_clear (payload->priv->adapter);
792       break;
793     default:
794       break;
795   }
796
797   gst_object_unref (payload);
798
799   /* return FALSE to let parent handle the remainder of the event */
800   return res;
801 }
802
803 /**
804  * gst_base_rtp_audio_payload_get_adapter:
805  * @basertpaudiopayload: a #GstBaseRTPAudioPayload
806  *
807  * Gets the internal adapter used by the depayloader.
808  *
809  * Returns: a #GstAdapter.
810  *
811  * Since: 0.10.13
812  */
813 GstAdapter *
814 gst_base_rtp_audio_payload_get_adapter (GstBaseRTPAudioPayload
815     * basertpaudiopayload)
816 {
817   GstAdapter *adapter;
818
819   if ((adapter = basertpaudiopayload->priv->adapter))
820     g_object_ref (adapter);
821
822   return adapter;
823 }