audiortppay: move function around
[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 calculate the min/max length and alignment of a packet */
74 typedef gboolean (*GetLengthsFunc) (GstBaseRTPPayload * basepayload,
75     guint * min_payload_len, guint * max_payload_len, guint * align);
76 /* function to convert bytes to a duration */
77 typedef GstClockTime (*GetDurationFunc) (GstBaseRTPAudioPayload * payload,
78     guint64 bytes);
79
80 struct _GstBaseRTPAudioPayloadPrivate
81 {
82   GetLengthsFunc get_lengths;
83   GetDurationFunc get_duration;
84
85   GstAdapter *adapter;
86   guint fragment_size;
87 };
88
89
90 #define GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE(o) \
91   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_BASE_RTP_AUDIO_PAYLOAD, \
92                                 GstBaseRTPAudioPayloadPrivate))
93
94 static void gst_base_rtp_audio_payload_finalize (GObject * object);
95
96 /* length functions */
97 static gboolean gst_base_rtp_audio_payload_get_frame_lengths (GstBaseRTPPayload
98     * basepayload, guint * min_payload_len, guint * max_payload_len,
99     guint * align);
100 static gboolean gst_base_rtp_audio_payload_get_sample_lengths (GstBaseRTPPayload
101     * basepayload, guint * min_payload_len, guint * max_payload_len,
102     guint * align);
103
104 /* duration functions */
105 static GstClockTime
106 gst_base_rtp_audio_payload_get_frame_duration (GstBaseRTPAudioPayload * payload,
107     guint64 bytes);
108 static GstClockTime
109 gst_base_rtp_audio_payload_get_sample_duration (GstBaseRTPAudioPayload *
110     payload, guint64 bytes);
111
112 static GstFlowReturn gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload
113     * payload, GstBuffer * buffer);
114
115 static GstStateChangeReturn gst_base_rtp_payload_audio_change_state (GstElement
116     * element, GstStateChange transition);
117
118 static gboolean gst_base_rtp_payload_audio_handle_event (GstPad * pad,
119     GstEvent * event);
120
121 GST_BOILERPLATE (GstBaseRTPAudioPayload, gst_base_rtp_audio_payload,
122     GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD);
123
124 static void
125 gst_base_rtp_audio_payload_base_init (gpointer klass)
126 {
127 }
128
129 static void
130 gst_base_rtp_audio_payload_class_init (GstBaseRTPAudioPayloadClass * klass)
131 {
132   GObjectClass *gobject_class;
133   GstElementClass *gstelement_class;
134   GstBaseRTPPayloadClass *gstbasertppayload_class;
135
136   g_type_class_add_private (klass, sizeof (GstBaseRTPAudioPayloadPrivate));
137
138   gobject_class = (GObjectClass *) klass;
139   gstelement_class = (GstElementClass *) klass;
140   gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
141
142   gobject_class->finalize =
143       GST_DEBUG_FUNCPTR (gst_base_rtp_audio_payload_finalize);
144
145   gstelement_class->change_state =
146       GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_change_state);
147
148   gstbasertppayload_class->handle_buffer =
149       GST_DEBUG_FUNCPTR (gst_base_rtp_audio_payload_handle_buffer);
150   gstbasertppayload_class->handle_event =
151       GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_handle_event);
152
153   GST_DEBUG_CATEGORY_INIT (basertpaudiopayload_debug, "basertpaudiopayload", 0,
154       "base audio RTP payloader");
155 }
156
157 static void
158 gst_base_rtp_audio_payload_init (GstBaseRTPAudioPayload * basertpaudiopayload,
159     GstBaseRTPAudioPayloadClass * klass)
160 {
161   basertpaudiopayload->priv =
162       GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE (basertpaudiopayload);
163
164   /* these need to be set by child object if frame based */
165   basertpaudiopayload->frame_size = 0;
166   basertpaudiopayload->frame_duration = 0;
167
168   /* these need to be set by child object if sample based */
169   basertpaudiopayload->sample_size = 0;
170
171   basertpaudiopayload->priv->adapter = gst_adapter_new ();
172 }
173
174 static void
175 gst_base_rtp_audio_payload_finalize (GObject * object)
176 {
177   GstBaseRTPAudioPayload *basertpaudiopayload;
178
179   basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (object);
180
181   g_object_unref (basertpaudiopayload->priv->adapter);
182
183   GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
184 }
185
186 /**
187  * gst_base_rtp_audio_payload_set_frame_based:
188  * @basertpaudiopayload: a pointer to the element.
189  *
190  * Tells #GstBaseRTPAudioPayload that the child element is for a frame based
191  * audio codec
192  */
193 void
194 gst_base_rtp_audio_payload_set_frame_based (GstBaseRTPAudioPayload *
195     basertpaudiopayload)
196 {
197   g_return_if_fail (basertpaudiopayload != NULL);
198   g_return_if_fail (basertpaudiopayload->priv->get_lengths == NULL);
199   g_return_if_fail (basertpaudiopayload->priv->get_duration == NULL);
200
201   basertpaudiopayload->priv->get_lengths =
202       gst_base_rtp_audio_payload_get_frame_lengths;
203   basertpaudiopayload->priv->get_duration =
204       gst_base_rtp_audio_payload_get_frame_duration;
205 }
206
207 /**
208  * gst_base_rtp_audio_payload_set_sample_based:
209  * @basertpaudiopayload: a pointer to the element.
210  *
211  * Tells #GstBaseRTPAudioPayload that the child element is for a sample based
212  * audio codec
213  */
214 void
215 gst_base_rtp_audio_payload_set_sample_based (GstBaseRTPAudioPayload *
216     basertpaudiopayload)
217 {
218   g_return_if_fail (basertpaudiopayload != NULL);
219   g_return_if_fail (basertpaudiopayload->priv->get_lengths == NULL);
220   g_return_if_fail (basertpaudiopayload->priv->get_duration == NULL);
221
222   basertpaudiopayload->priv->get_lengths =
223       gst_base_rtp_audio_payload_get_sample_lengths;
224   basertpaudiopayload->priv->get_duration =
225       gst_base_rtp_audio_payload_get_sample_duration;
226 }
227
228 /**
229  * gst_base_rtp_audio_payload_set_frame_options:
230  * @basertpaudiopayload: a pointer to the element.
231  * @frame_duration: The duraction of an audio frame in milliseconds.
232  * @frame_size: The size of an audio frame in bytes.
233  *
234  * Sets the options for frame based audio codecs.
235  *
236  */
237 void
238 gst_base_rtp_audio_payload_set_frame_options (GstBaseRTPAudioPayload
239     * basertpaudiopayload, gint frame_duration, gint frame_size)
240 {
241   g_return_if_fail (basertpaudiopayload != NULL);
242
243   basertpaudiopayload->frame_size = frame_size;
244   basertpaudiopayload->frame_duration = frame_duration;
245
246   gst_adapter_clear (basertpaudiopayload->priv->adapter);
247 }
248
249 /**
250  * gst_base_rtp_audio_payload_set_sample_options:
251  * @basertpaudiopayload: a pointer to the element.
252  * @sample_size: Size per sample in bytes.
253  *
254  * Sets the options for sample based audio codecs.
255  */
256 void
257 gst_base_rtp_audio_payload_set_sample_options (GstBaseRTPAudioPayload
258     * basertpaudiopayload, gint sample_size)
259 {
260   g_return_if_fail (basertpaudiopayload != NULL);
261
262   /* sample_size is in bits internally */
263   gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload,
264       sample_size * 8);
265 }
266
267 /**
268  * gst_base_rtp_audio_payload_set_samplebits_options:
269  * @basertpaudiopayload: a pointer to the element.
270  * @sample_size: Size per sample in bits.
271  *
272  * Sets the options for sample based audio codecs.
273  *
274  * Since: 0.10.18
275  */
276 void
277 gst_base_rtp_audio_payload_set_samplebits_options (GstBaseRTPAudioPayload
278     * basertpaudiopayload, gint sample_size)
279 {
280   guint fragment_size;
281
282   g_return_if_fail (basertpaudiopayload != NULL);
283
284   basertpaudiopayload->sample_size = sample_size;
285
286   /* sample_size is in bits and is converted into multiple bytes */
287   fragment_size = sample_size;
288   while ((fragment_size % 8) != 0)
289     fragment_size += fragment_size;
290   basertpaudiopayload->priv->fragment_size = fragment_size / 8;
291
292   gst_adapter_clear (basertpaudiopayload->priv->adapter);
293 }
294
295 /**
296  * gst_base_rtp_audio_payload_push:
297  * @baseaudiopayload: a #GstBaseRTPPayload
298  * @data: data to set as payload
299  * @payload_len: length of payload
300  * @timestamp: a #GstClockTime
301  *
302  * Create an RTP buffer and store @payload_len bytes of @data as the
303  * payload. Set the timestamp on the new buffer to @timestamp before pushing
304  * the buffer downstream.
305  *
306  * Returns: a #GstFlowReturn
307  *
308  * Since: 0.10.13
309  */
310 GstFlowReturn
311 gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload,
312     const guint8 * data, guint payload_len, GstClockTime timestamp)
313 {
314   GstBaseRTPPayload *basepayload;
315   GstBuffer *outbuf;
316   guint8 *payload;
317   GstFlowReturn ret;
318
319   basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
320
321   GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
322       payload_len, GST_TIME_ARGS (timestamp));
323
324   /* create buffer to hold the payload */
325   outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
326
327   /* copy payload */
328   gst_rtp_buffer_set_payload_type (outbuf, basepayload->pt);
329   payload = gst_rtp_buffer_get_payload (outbuf);
330   memcpy (payload, data, payload_len);
331
332   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
333   ret = gst_basertppayload_push (basepayload, outbuf);
334
335   return ret;
336 }
337
338 /**
339  * gst_base_rtp_audio_payload_flush:
340  * @baseaudiopayload: a #GstBaseRTPPayload
341  * @payload_len: length of payload
342  * @timestamp: a #GstClockTime
343  *
344  * Create an RTP buffer and store @payload_len bytes of the adapter as the
345  * payload. Set the timestamp on the new buffer to @timestamp before pushing
346  * the buffer downstream.
347  *
348  * Returns: a #GstFlowReturn
349  *
350  * Since: 0.10.25
351  */
352 GstFlowReturn
353 gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload,
354     guint payload_len, GstClockTime timestamp)
355 {
356   GstBaseRTPPayload *basepayload;
357   GstBuffer *outbuf;
358   guint8 *payload;
359   GstFlowReturn ret;
360
361   basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
362
363   GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
364       payload_len, GST_TIME_ARGS (timestamp));
365
366   /* create buffer to hold the payload */
367   outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
368
369   /* copy payload */
370   gst_rtp_buffer_set_payload_type (outbuf, basepayload->pt);
371   payload = gst_rtp_buffer_get_payload (outbuf);
372   gst_adapter_copy (baseaudiopayload->priv->adapter, payload, 0, payload_len);
373   gst_adapter_flush (baseaudiopayload->priv->adapter, payload_len);
374
375   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
376   ret = gst_basertppayload_push (basepayload, outbuf);
377
378   return ret;
379 }
380
381 #define ALIGN_DOWN(val,len) ((val) - ((val) % (len)))
382
383 /* this assumes all frames have a constant duration and a constant size */
384 static gboolean
385 gst_base_rtp_audio_payload_get_frame_lengths (GstBaseRTPPayload *
386     basepayload, guint * min_payload_len, guint * max_payload_len,
387     guint * align)
388 {
389   GstBaseRTPAudioPayload *payload;
390   guint frame_size;
391   guint frame_duration;
392   guint max_frames;
393   guint maxptime_octets;
394   guint minptime_octets;
395
396   payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
397
398   if (payload->frame_size == 0 || payload->frame_duration == 0)
399     return FALSE;
400
401   *align = frame_size = payload->frame_size;
402   frame_duration = payload->frame_duration * GST_MSECOND;
403
404   if (basepayload->max_ptime != -1) {
405     maxptime_octets =
406         gst_util_uint64_scale (frame_size, basepayload->max_ptime,
407         frame_duration);
408     /* must be a multiple of the frame_size */
409     maxptime_octets = MAX (frame_size, maxptime_octets);
410   } else {
411     maxptime_octets = G_MAXUINT;
412   }
413
414   /* MTU max */
415   max_frames =
416       gst_rtp_buffer_calc_payload_len (GST_BASE_RTP_PAYLOAD_MTU (payload), 0,
417       0);
418   /* round down to frame_size */
419   max_frames = ALIGN_DOWN (max_frames, frame_size);
420   /* max payload length */
421   *max_payload_len = MIN (max_frames, maxptime_octets);
422
423   /* min number of bytes based on a given ptime, has to be a multiple
424      of frame duration */
425   minptime_octets =
426       gst_util_uint64_scale (frame_size, basepayload->min_ptime,
427       frame_duration);
428   *min_payload_len = MAX (minptime_octets, frame_size);
429
430   if (*min_payload_len > *max_payload_len)
431     *min_payload_len = *max_payload_len;
432
433   return TRUE;
434 }
435
436 static GstClockTime
437 gst_base_rtp_audio_payload_get_frame_duration (GstBaseRTPAudioPayload *
438     payload, guint64 bytes)
439 {
440   return gst_util_uint64_scale (bytes, payload->frame_duration * GST_MSECOND,
441       payload->frame_size);
442 }
443
444 static gboolean
445 gst_base_rtp_audio_payload_get_sample_lengths (GstBaseRTPPayload *
446     basepayload, guint * min_payload_len, guint * max_payload_len,
447     guint * align)
448 {
449   GstBaseRTPAudioPayload *payload;
450   guint maxptime_octets;
451   guint minptime_octets;
452
453   payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
454
455   if (payload->sample_size == 0)
456     return FALSE;
457
458   /* sample_size is in bits and is converted into multiple bytes */
459   *align = payload->priv->fragment_size;
460
461   /* max number of bytes based on given ptime */
462   if (basepayload->max_ptime != -1) {
463     maxptime_octets = gst_util_uint64_scale (basepayload->max_ptime * 8,
464         basepayload->clock_rate, payload->sample_size * GST_SECOND);
465   } else {
466     maxptime_octets = G_MAXUINT;
467   }
468
469   *max_payload_len = MIN (
470       /* MTU max */
471       gst_rtp_buffer_calc_payload_len (GST_BASE_RTP_PAYLOAD_MTU
472           (payload), 0, 0),
473       /* ptime max */
474       maxptime_octets);
475
476   /* min number of bytes based on a given ptime, has to be a multiple
477    * of sample rate */
478   minptime_octets = gst_util_uint64_scale (basepayload->min_ptime * 8,
479       basepayload->clock_rate, payload->sample_size * GST_SECOND);
480
481   *min_payload_len = MAX (minptime_octets, *align);
482
483   if (*min_payload_len > *max_payload_len)
484     *min_payload_len = *max_payload_len;
485
486   return TRUE;
487 }
488
489 static GstClockTime
490 gst_base_rtp_audio_payload_get_sample_duration (GstBaseRTPAudioPayload *
491     payload, guint64 bytes)
492 {
493   return (bytes * 8 * GST_SECOND) /
494       (GST_BASE_RTP_PAYLOAD (payload)->clock_rate * payload->sample_size);
495 }
496
497 static GstFlowReturn
498 gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload *
499     basepayload, GstBuffer * buffer)
500 {
501   GstBaseRTPAudioPayload *payload;
502   guint payload_len;
503   GstFlowReturn ret;
504   guint available;
505   guint min_payload_len;
506   guint max_payload_len;
507   guint align;
508   guint size;
509
510   ret = GST_FLOW_OK;
511
512   payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
513
514   if (payload->priv->get_lengths == NULL || payload->priv->get_duration == NULL)
515     goto config_error;
516
517   if (!payload->priv->get_lengths (basepayload, &min_payload_len,
518           &max_payload_len, &align))
519     goto config_error;
520
521   GST_DEBUG_OBJECT (payload,
522       "Calculated min_payload_len %u and max_payload_len %u",
523       min_payload_len, max_payload_len);
524
525   size = GST_BUFFER_SIZE (buffer);
526
527   /* shortcut, we don't need to use the adapter when the packet can be pushed
528    * through directly. */
529   available = gst_adapter_available (payload->priv->adapter);
530
531   GST_DEBUG_OBJECT (payload, "got buffer size %u, available %u",
532       size, available);
533
534   if (available == 0 && (size >= min_payload_len && size <= max_payload_len)) {
535     /* If buffer fits on an RTP packet, let's just push it through
536      * this will check against max_ptime and max_mtu */
537     GST_DEBUG_OBJECT (payload, "Fast packet push");
538     ret = gst_base_rtp_audio_payload_push (payload,
539         GST_BUFFER_DATA (buffer), size, GST_BUFFER_TIMESTAMP (buffer));
540     gst_buffer_unref (buffer);
541   } else {
542     /* push the buffer in the adapter */
543     gst_adapter_push (payload->priv->adapter, buffer);
544     available += size;
545
546     GST_DEBUG_OBJECT (payload, "available now %u", available);
547
548     /* as long as we have full frames */
549     while (available >= min_payload_len) {
550       guint64 distance;
551       GstClockTime timestamp;
552
553       payload_len = ALIGN_DOWN (available, align);
554       payload_len = MIN (max_payload_len, payload_len);
555
556       /* calculate the timestamp */
557       timestamp =
558           gst_adapter_prev_timestamp (payload->priv->adapter, &distance);
559
560       GST_LOG_OBJECT (payload,
561           "last timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT,
562           GST_TIME_ARGS (timestamp), distance);
563
564       if (GST_CLOCK_TIME_IS_VALID (timestamp) && distance > 0) {
565         /* convert the number of bytes since the last timestamp to time and add to
566          * the last seen timestamp */
567         timestamp += payload->priv->get_duration (payload, distance);
568       }
569
570       /* and flush out the bytes from the adapter */
571       ret = gst_base_rtp_audio_payload_flush (payload, payload_len, timestamp);
572
573       available -= payload_len;
574       GST_DEBUG_OBJECT (payload, "available after push %u", available);
575     }
576   }
577   return ret;
578
579   /* ERRORS */
580 config_error:
581   {
582     GST_DEBUG_OBJECT (payload, "Required options not set");
583     gst_buffer_unref (buffer);
584     return GST_FLOW_ERROR;
585   }
586 }
587
588 static GstStateChangeReturn
589 gst_base_rtp_payload_audio_change_state (GstElement * element,
590     GstStateChange transition)
591 {
592   GstBaseRTPAudioPayload *basertppayload;
593   GstStateChangeReturn ret;
594
595   basertppayload = GST_BASE_RTP_AUDIO_PAYLOAD (element);
596
597   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
598
599   switch (transition) {
600     case GST_STATE_CHANGE_PAUSED_TO_READY:
601       gst_adapter_clear (basertppayload->priv->adapter);
602       break;
603     default:
604       break;
605   }
606
607   return ret;
608 }
609
610 static gboolean
611 gst_base_rtp_payload_audio_handle_event (GstPad * pad, GstEvent * event)
612 {
613   GstBaseRTPAudioPayload *payload;
614   gboolean res = FALSE;
615
616   payload = GST_BASE_RTP_AUDIO_PAYLOAD (gst_pad_get_parent (pad));
617
618   switch (GST_EVENT_TYPE (event)) {
619     case GST_EVENT_EOS:
620       /* FIXME. push remaining bytes? maybe not because it would violate the
621        * min-ptime. */
622       gst_adapter_clear (payload->priv->adapter);
623       break;
624     case GST_EVENT_FLUSH_STOP:
625       gst_adapter_clear (payload->priv->adapter);
626       break;
627     default:
628       break;
629   }
630
631   gst_object_unref (payload);
632
633   /* return FALSE to let parent handle the remainder of the event */
634   return res;
635 }
636
637 /**
638  * gst_base_rtp_audio_payload_get_adapter:
639  * @basertpaudiopayload: a #GstBaseRTPAudioPayload
640  *
641  * Gets the internal adapter used by the depayloader.
642  *
643  * Returns: a #GstAdapter.
644  *
645  * Since: 0.10.13
646  */
647 GstAdapter *
648 gst_base_rtp_audio_payload_get_adapter (GstBaseRTPAudioPayload
649     * basertpaudiopayload)
650 {
651   GstAdapter *adapter;
652
653   if ((adapter = basertpaudiopayload->priv->adapter))
654     g_object_ref (adapter);
655
656   return adapter;
657 }