diff options
Diffstat (limited to 'gst/rtp/gstrtpmp4adepay.c')
-rw-r--r-- | gst/rtp/gstrtpmp4adepay.c | 93 |
1 files changed, 77 insertions, 16 deletions
diff --git a/gst/rtp/gstrtpmp4adepay.c b/gst/rtp/gstrtpmp4adepay.c index 836ff9f09..394fc0d28 100644 --- a/gst/rtp/gstrtpmp4adepay.c +++ b/gst/rtp/gstrtpmp4adepay.c @@ -21,6 +21,7 @@ # include "config.h" #endif +#include <gst/base/gstbitreader.h> #include <gst/rtp/gstrtpbuffer.h> #include <string.h> @@ -128,6 +129,10 @@ gst_rtp_mp4a_depay_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 +}; + static gboolean gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) { @@ -165,10 +170,9 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) guint8 *data; guint size; gint i; - guint sr_idx; - static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 - }; + guint32 rate; + guint8 obj_type, sr_idx, channels; + GstBitReader br; buffer = gst_value_get_buffer (&v); gst_buffer_ref (buffer); @@ -210,22 +214,68 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) for (i = 0; i < size; i++) { data[i] = ((data[i + 1] & 1) << 7) | ((data[i + 2] & 0xfe) >> 1); } + /* ignore remaining bit, we're only interested in full bytes */ + GST_BUFFER_SIZE (buffer) = size; + + gst_bit_reader_init (&br, data, size); + + /* any object type is fine, we need to copy it to the profile-level-id field. */ + if (!gst_bit_reader_get_bits_uint8 (&br, &obj_type, 5)) + goto bad_config; + if (obj_type == 0) { + GST_WARNING_OBJECT (depayload, "invalid object type 0"); + goto bad_config; + } + + if (!gst_bit_reader_get_bits_uint8 (&br, &sr_idx, 4)) + goto bad_config; + if (sr_idx > 12 && sr_idx != 15) { + GST_WARNING_OBJECT (depayload, "invalid sample rate index %d", sr_idx); + goto bad_config; + } + GST_LOG_OBJECT (rtpmp4adepay, "sample rate index %u", sr_idx); - /* grab and set sampling rate */ - sr_idx = ((data[0] & 0x07) << 1) | ((data[1] & 0x80) >> 7); - if (sr_idx < G_N_ELEMENTS (aac_sample_rates)) { - gst_caps_set_simple (srccaps, - "rate", G_TYPE_INT, (gint) aac_sample_rates[sr_idx], NULL); - GST_DEBUG_OBJECT (depayload, "sampling rate from stream-config %u", - aac_sample_rates[sr_idx]); + if (!gst_bit_reader_get_bits_uint8 (&br, &channels, 4)) + goto bad_config; + if (channels > 7) { + GST_WARNING_OBJECT (depayload, "invalid channels %u", (guint) channels); + goto bad_config; + } + + /* rtp rate depends on sampling rate of the audio */ + if (sr_idx == 15) { + /* index of 15 means we get the rate in the next 24 bits */ + if (!gst_bit_reader_get_bits_uint32 (&br, &rate, 24)) + goto bad_config; } else { - GST_WARNING_OBJECT (depayload, "Invalid sample rate index %u", sr_idx); + /* else use the rate from the table */ + rate = aac_sample_rates[sr_idx]; } - /* ignore remaining bit, we're only interested in full bytes */ - GST_BUFFER_SIZE (buffer) = size; + rtpmp4adepay->frame_len = 1024; + + switch (obj_type) { + case 1: + case 2: + case 3: + case 4: + case 6: + case 7: + { + guint8 frameLenFlag = 0; + + if (gst_bit_reader_get_bits_uint8 (&br, &frameLenFlag, 1)) + if (frameLenFlag) + rtpmp4adepay->frame_len = 960; + break; + } + default: + break; + } gst_caps_set_simple (srccaps, + "channels", G_TYPE_INT, (gint) channels, + "rate", G_TYPE_INT, (gint) rate, "codec_data", GST_TYPE_BUFFER, buffer, NULL); gst_buffer_unref (buffer); } else { @@ -254,6 +304,7 @@ gst_rtp_mp4a_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) outbuf = gst_rtp_buffer_get_payload_buffer (buf); + gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS); gst_adapter_push (rtpmp4adepay->adapter, outbuf); /* RTP marker bit indicates the last packet of the AudioMuxElement => create @@ -315,11 +366,19 @@ gst_rtp_mp4a_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) data += skip; avail -= skip; + if (offset > 0 && timestamp != -1 && depayload->clock_rate != 0) { + timestamp += + gst_util_uint64_scale_int (offset, GST_SECOND, + depayload->clock_rate); + } + GST_BUFFER_TIMESTAMP (tmp) = timestamp; gst_base_rtp_depayload_push (depayload, tmp); - /* only apply the timestamp for the first buffer */ - timestamp = -1; + /* calculate offsets for next buffers */ + if (rtpmp4adepay->frame_len) { + offset += rtpmp4adepay->frame_len; + } } /* just a check that lengths match */ @@ -355,6 +414,8 @@ gst_rtp_mp4a_depay_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_adapter_clear (rtpmp4adepay->adapter); + rtpmp4adepay->frame_len = 0; + rtpmp4adepay->numSubFrames = 0; break; default: break; |