# include "config.h"
#endif
+#include <gst/base/gstbitreader.h>
#include <gst/rtp/gstrtpbuffer.h>
#include <string.h>
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)
{
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);
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 {
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
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 */
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
gst_adapter_clear (rtpmp4adepay->adapter);
+ rtpmp4adepay->frame_len = 0;
+ rtpmp4adepay->numSubFrames = 0;
break;
default:
break;