2 * Copyright (C) <2006> Philippe Khalaf <philippe.kalaf@collabora.co.uk>
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.
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.
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.
21 * SECTION:gstbasertpaudiopayload
22 * @short_description: Base class for audio RTP payloader
26 * Provides a base class for audio RTP payloaders for frame or sample based
27 * audio codecs (constant bitrate)
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.
42 * <title>Usage</title>
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.
65 #include <gst/rtp/gstrtpbuffer.h>
66 #include <gst/base/gstadapter.h>
68 #include "gstbasertpaudiopayload.h"
70 GST_DEBUG_CATEGORY_STATIC (basertpaudiopayload_debug);
71 #define GST_CAT_DEFAULT (basertpaudiopayload_debug)
73 /* function to convert bytes to a time */
74 typedef GstClockTime (*GetBytesToTimeFunc) (GstBaseRTPAudioPayload * payload,
76 /* function to convert bytes to a RTP time */
77 typedef guint32 (*GetBytesToRTPTimeFunc) (GstBaseRTPAudioPayload * payload,
79 /* function to convert time to bytes */
80 typedef guint64 (*GetTimeToBytesFunc) (GstBaseRTPAudioPayload * payload,
83 struct _GstBaseRTPAudioPayloadPrivate
85 GetBytesToTimeFunc bytes_to_time;
86 GetBytesToRTPTimeFunc bytes_to_rtptime;
87 GetTimeToBytesFunc time_to_bytes;
91 GstClockTime frame_duration_ns;
94 GstClockTime last_timestamp;
99 guint cached_min_ptime;
100 guint cached_max_ptime;
101 guint cached_min_length;
102 guint cached_max_length;
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))
110 static void gst_base_rtp_audio_payload_finalize (GObject * object);
112 /* bytes to time functions */
114 gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload *
115 payload, guint64 bytes);
117 gst_base_rtp_audio_payload_sample_bytes_to_time (GstBaseRTPAudioPayload *
118 payload, guint64 bytes);
120 /* bytes to RTP time functions */
122 gst_base_rtp_audio_payload_frame_bytes_to_rtptime (GstBaseRTPAudioPayload *
123 payload, guint64 bytes);
125 gst_base_rtp_audio_payload_sample_bytes_to_rtptime (GstBaseRTPAudioPayload *
126 payload, guint64 bytes);
128 /* time to bytes functions */
130 gst_base_rtp_audio_payload_frame_time_to_bytes (GstBaseRTPAudioPayload *
131 payload, GstClockTime time);
133 gst_base_rtp_audio_payload_sample_time_to_bytes (GstBaseRTPAudioPayload *
134 payload, GstClockTime time);
136 static GstFlowReturn gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload
137 * payload, GstBuffer * buffer);
139 static GstStateChangeReturn gst_base_rtp_payload_audio_change_state (GstElement
140 * element, GstStateChange transition);
142 static gboolean gst_base_rtp_payload_audio_handle_event (GstPad * pad,
145 GST_BOILERPLATE (GstBaseRTPAudioPayload, gst_base_rtp_audio_payload,
146 GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD);
149 gst_base_rtp_audio_payload_base_init (gpointer klass)
154 gst_base_rtp_audio_payload_class_init (GstBaseRTPAudioPayloadClass * klass)
156 GObjectClass *gobject_class;
157 GstElementClass *gstelement_class;
158 GstBaseRTPPayloadClass *gstbasertppayload_class;
160 g_type_class_add_private (klass, sizeof (GstBaseRTPAudioPayloadPrivate));
162 gobject_class = (GObjectClass *) klass;
163 gstelement_class = (GstElementClass *) klass;
164 gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
166 gobject_class->finalize =
167 GST_DEBUG_FUNCPTR (gst_base_rtp_audio_payload_finalize);
169 gstelement_class->change_state =
170 GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_change_state);
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);
177 GST_DEBUG_CATEGORY_INIT (basertpaudiopayload_debug, "basertpaudiopayload", 0,
178 "base audio RTP payloader");
182 gst_base_rtp_audio_payload_init (GstBaseRTPAudioPayload * payload,
183 GstBaseRTPAudioPayloadClass * klass)
185 payload->priv = GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE (payload);
187 /* these need to be set by child object if frame based */
188 payload->frame_size = 0;
189 payload->frame_duration = 0;
191 /* these need to be set by child object if sample based */
192 payload->sample_size = 0;
194 payload->priv->adapter = gst_adapter_new ();
198 gst_base_rtp_audio_payload_finalize (GObject * object)
200 GstBaseRTPAudioPayload *payload;
202 payload = GST_BASE_RTP_AUDIO_PAYLOAD (object);
204 g_object_unref (payload->priv->adapter);
206 GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
210 * gst_base_rtp_audio_payload_set_frame_based:
211 * @basertpaudiopayload: a pointer to the element.
213 * Tells #GstBaseRTPAudioPayload that the child element is for a frame based
217 gst_base_rtp_audio_payload_set_frame_based (GstBaseRTPAudioPayload *
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);
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;
234 * gst_base_rtp_audio_payload_set_sample_based:
235 * @basertpaudiopayload: a pointer to the element.
237 * Tells #GstBaseRTPAudioPayload that the child element is for a sample based
241 gst_base_rtp_audio_payload_set_sample_based (GstBaseRTPAudioPayload *
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);
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;
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.
263 * Sets the options for frame based audio codecs.
267 gst_base_rtp_audio_payload_set_frame_options (GstBaseRTPAudioPayload
268 * basertpaudiopayload, gint frame_duration, gint frame_size)
270 GstBaseRTPAudioPayloadPrivate *priv;
272 g_return_if_fail (basertpaudiopayload != NULL);
274 priv = basertpaudiopayload->priv;
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;
281 gst_adapter_clear (priv->adapter);
283 GST_DEBUG_OBJECT (basertpaudiopayload, "frame set to %d ms and size %d",
284 frame_duration, frame_size);
288 * gst_base_rtp_audio_payload_set_sample_options:
289 * @basertpaudiopayload: a pointer to the element.
290 * @sample_size: Size per sample in bytes.
292 * Sets the options for sample based audio codecs.
295 gst_base_rtp_audio_payload_set_sample_options (GstBaseRTPAudioPayload
296 * basertpaudiopayload, gint sample_size)
298 g_return_if_fail (basertpaudiopayload != NULL);
300 /* sample_size is in bits internally */
301 gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload,
306 * gst_base_rtp_audio_payload_set_samplebits_options:
307 * @basertpaudiopayload: a pointer to the element.
308 * @sample_size: Size per sample in bits.
310 * Sets the options for sample based audio codecs.
315 gst_base_rtp_audio_payload_set_samplebits_options (GstBaseRTPAudioPayload
316 * basertpaudiopayload, gint sample_size)
319 GstBaseRTPAudioPayloadPrivate *priv;
321 g_return_if_fail (basertpaudiopayload != NULL);
323 priv = basertpaudiopayload->priv;
325 basertpaudiopayload->sample_size = sample_size;
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;
334 gst_adapter_clear (priv->adapter);
336 GST_DEBUG_OBJECT (basertpaudiopayload,
337 "Samplebits set to sample size %d bits", sample_size);
341 gst_base_rtp_audio_payload_set_meta (GstBaseRTPAudioPayload * payload,
342 GstBuffer * buffer, guint payload_len, GstClockTime timestamp)
344 GstBaseRTPPayload *basepayload;
345 GstBaseRTPAudioPayloadPrivate *priv;
347 basepayload = GST_BASE_RTP_PAYLOAD_CAST (payload);
348 priv = payload->priv;
350 /* set payload type */
351 gst_rtp_buffer_set_payload_type (buffer, basepayload->pt);
352 /* set marker bit for disconts */
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;
359 GST_BUFFER_TIMESTAMP (buffer) = timestamp;
361 /* get the offset in RTP time */
362 GST_BUFFER_OFFSET (buffer) = priv->bytes_to_rtptime (payload, priv->offset);
364 priv->offset += payload_len;
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;
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
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.
383 * Returns: a #GstFlowReturn
388 gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload,
389 const guint8 * data, guint payload_len, GstClockTime timestamp)
391 GstBaseRTPPayload *basepayload;
396 basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
398 GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
399 payload_len, GST_TIME_ARGS (timestamp));
401 /* create buffer to hold the payload */
402 outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
405 payload = gst_rtp_buffer_get_payload (outbuf);
406 memcpy (payload, data, payload_len);
409 gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
412 ret = gst_basertppayload_push (basepayload, outbuf);
418 * gst_base_rtp_audio_payload_flush:
419 * @baseaudiopayload: a #GstBaseRTPPayload
420 * @payload_len: length of payload
421 * @timestamp: a #GstClockTime
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.
427 * If @payload_len is -1, all pending bytes will be flushed. If @timestamp is
428 * -1, the timestamp will be calculated automatically.
430 * Returns: a #GstFlowReturn
435 gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload,
436 guint payload_len, GstClockTime timestamp)
438 GstBaseRTPPayload *basepayload;
439 GstBaseRTPAudioPayloadPrivate *priv;
446 priv = baseaudiopayload->priv;
447 adapter = priv->adapter;
449 basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
451 if (payload_len == -1)
452 payload_len = gst_adapter_available (adapter);
454 /* nothing to do, just return */
455 if (payload_len == 0)
458 if (timestamp == -1) {
459 /* calculate the timestamp */
460 timestamp = gst_adapter_prev_timestamp (adapter, &distance);
462 GST_LOG_OBJECT (baseaudiopayload,
463 "last timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT,
464 GST_TIME_ARGS (timestamp), distance);
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);
473 GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
474 payload_len, GST_TIME_ARGS (timestamp));
476 /* create buffer to hold the payload */
477 outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
479 payload = gst_rtp_buffer_get_payload (outbuf);
480 gst_adapter_copy (adapter, payload, 0, payload_len);
481 gst_adapter_flush (adapter, payload_len);
484 gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
487 ret = gst_basertppayload_push (basepayload, outbuf);
492 #define ALIGN_DOWN(val,len) ((val) - ((val) % (len)))
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 */
498 gst_base_rtp_audio_payload_get_lengths (GstBaseRTPPayload *
499 basepayload, guint * min_payload_len, guint * max_payload_len,
502 GstBaseRTPAudioPayload *payload;
503 GstBaseRTPAudioPayloadPrivate *priv;
505 guint maxptime_octets;
506 guint minptime_octets;
508 payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
509 priv = payload->priv;
511 if (priv->align == 0)
514 *align = priv->align;
516 mtu = GST_BASE_RTP_PAYLOAD_MTU (payload);
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;
529 if (basepayload->max_ptime != -1) {
530 maxptime_octets = priv->time_to_bytes (payload, basepayload->max_ptime);
532 maxptime_octets = G_MAXUINT;
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);
539 /* combine max ptime and max payload length */
540 *max_payload_len = MIN (max_mtu, maxptime_octets);
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);
547 if (*min_payload_len > *max_payload_len)
548 *min_payload_len = *max_payload_len;
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;
560 /* frame conversions functions */
562 gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload *
563 payload, guint64 bytes)
565 return (bytes / payload->frame_size) * (payload->priv->frame_duration_ns);
569 gst_base_rtp_audio_payload_frame_bytes_to_rtptime (GstBaseRTPAudioPayload *
570 payload, guint64 bytes)
574 time = (bytes / payload->frame_size) * (payload->priv->frame_duration_ns);
576 return gst_util_uint64_scale_int (time,
577 GST_BASE_RTP_PAYLOAD (payload)->clock_rate, GST_SECOND);
581 gst_base_rtp_audio_payload_frame_time_to_bytes (GstBaseRTPAudioPayload *
582 payload, GstClockTime time)
584 return gst_util_uint64_scale (time, payload->frame_size,
585 payload->priv->frame_duration_ns);
588 /* sample conversion functions */
590 gst_base_rtp_audio_payload_sample_bytes_to_time (GstBaseRTPAudioPayload *
591 payload, guint64 bytes)
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);
601 return gst_util_uint64_scale_int (rtptime, GST_SECOND,
602 GST_BASE_RTP_PAYLOAD (payload)->clock_rate);
606 gst_base_rtp_audio_payload_sample_bytes_to_rtptime (GstBaseRTPAudioPayload *
607 payload, guint64 bytes)
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);
617 gst_base_rtp_audio_payload_sample_time_to_bytes (GstBaseRTPAudioPayload *
618 payload, guint64 time)
622 samples = gst_util_uint64_scale_int (time,
623 GST_BASE_RTP_PAYLOAD (payload)->clock_rate, GST_SECOND);
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);
633 gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload *
634 basepayload, GstBuffer * buffer)
636 GstBaseRTPAudioPayload *payload;
637 GstBaseRTPAudioPayloadPrivate *priv;
641 guint min_payload_len;
642 guint max_payload_len;
649 payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
650 priv = payload->priv;
652 discont = GST_BUFFER_IS_DISCONT (buffer);
654 GstClockTime timestamp;
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;
661 timestamp = GST_BUFFER_TIMESTAMP (buffer);
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) {
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
676 diff = timestamp - priv->last_timestamp;
677 bytes = priv->time_to_bytes (payload, diff);
678 priv->offset += bytes;
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,
688 if (!gst_base_rtp_audio_payload_get_lengths (basepayload, &min_payload_len,
689 &max_payload_len, &align))
692 GST_DEBUG_OBJECT (payload,
693 "Calculated min_payload_len %u and max_payload_len %u",
694 min_payload_len, max_payload_len);
696 size = GST_BUFFER_SIZE (buffer);
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);
702 GST_DEBUG_OBJECT (payload, "got buffer size %u, available %u",
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);
713 /* push the buffer in the adapter */
714 gst_adapter_push (priv->adapter, buffer);
717 GST_DEBUG_OBJECT (payload, "available now %u", available);
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);
725 /* and flush out the bytes from the adapter, automatically set the
727 ret = gst_base_rtp_audio_payload_flush (payload, payload_len, -1);
729 available -= payload_len;
730 GST_DEBUG_OBJECT (payload, "available after push %u", available);
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;
745 static GstStateChangeReturn
746 gst_base_rtp_payload_audio_change_state (GstElement * element,
747 GstStateChange transition)
749 GstBaseRTPAudioPayload *basertppayload;
750 GstStateChangeReturn ret;
752 basertppayload = GST_BASE_RTP_AUDIO_PAYLOAD (element);
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;
764 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
766 switch (transition) {
767 case GST_STATE_CHANGE_PAUSED_TO_READY:
768 gst_adapter_clear (basertppayload->priv->adapter);
778 gst_base_rtp_payload_audio_handle_event (GstPad * pad, GstEvent * event)
780 GstBaseRTPAudioPayload *payload;
781 gboolean res = FALSE;
783 payload = GST_BASE_RTP_AUDIO_PAYLOAD (gst_pad_get_parent (pad));
785 switch (GST_EVENT_TYPE (event)) {
787 /* flush remaining bytes in the adapter */
788 gst_base_rtp_audio_payload_flush (payload, -1, -1);
790 case GST_EVENT_FLUSH_STOP:
791 gst_adapter_clear (payload->priv->adapter);
797 gst_object_unref (payload);
799 /* return FALSE to let parent handle the remainder of the event */
804 * gst_base_rtp_audio_payload_get_adapter:
805 * @basertpaudiopayload: a #GstBaseRTPAudioPayload
807 * Gets the internal adapter used by the depayloader.
809 * Returns: a #GstAdapter.
814 gst_base_rtp_audio_payload_get_adapter (GstBaseRTPAudioPayload
815 * basertpaudiopayload)
819 if ((adapter = basertpaudiopayload->priv->adapter))
820 g_object_ref (adapter);