summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-12-31 13:57:05 +0100
committerWim Taymans <wim.taymans@gmail.com>2010-12-31 13:57:05 +0100
commit5ed3701a2d0c7f22473d6d4ae551b58adb8049b3 (patch)
treef56194007d4439ada66ec847c7014cafaac4514b
parentcfa7225898948551b590653a10265d6c6344eaf6 (diff)
mp4adepay: improve timestamps on outgoing packets
Improve parsing of the samplerate. Parse the framelen so that we can calculate timestamps. When interpollate the incomming timestamp on outgoing buffers when there are multiple subframes. fixes #625825
-rw-r--r--gst/rtp/gstrtpmp4adepay.c93
-rw-r--r--gst/rtp/gstrtpmp4adepay.h1
2 files changed, 78 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
@@ -18,12 +18,13 @@
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#include <gst/base/gstbitreader.h>
#include <gst/rtp/gstrtpbuffer.h>
#include <string.h>
#include "gstrtpmp4adepay.h"
GST_DEBUG_CATEGORY_STATIC (rtpmp4adepay_debug);
@@ -125,12 +126,16 @@ gst_rtp_mp4a_depay_finalize (GObject * object)
g_object_unref (rtpmp4adepay->adapter);
rtpmp4adepay->adapter = NULL;
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)
{
GstStructure *structure;
GstRtpMP4ADepay *rtpmp4adepay;
GstCaps *srccaps;
@@ -162,16 +167,15 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
g_value_init (&v, GST_TYPE_BUFFER);
if (gst_value_deserialize (&v, str)) {
GstBuffer *buffer;
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);
g_value_unset (&v);
data = GST_BUFFER_DATA (buffer);
@@ -207,28 +211,74 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
/* shift rest of string 15 bits down */
size -= 2;
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 {
g_warning ("cannot convert config to buffer");
}
}
@@ -251,12 +301,13 @@ gst_rtp_mp4a_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
if (GST_BUFFER_IS_DISCONT (buf)) {
gst_adapter_clear (rtpmp4adepay->adapter);
}
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
* and push a buffer */
if (gst_rtp_buffer_get_marker (buf)) {
guint avail;
@@ -312,17 +363,25 @@ gst_rtp_mp4a_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
pos += data_len;
/* update our pointers whith what we consumed */
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 */
if (avail) {
GST_ELEMENT_WARNING (depayload, STREAM, DECODE,
("Packet invalid"), ("Not all payload consumed: "
@@ -352,12 +411,14 @@ gst_rtp_mp4a_depay_change_state (GstElement * element,
rtpmp4adepay = GST_RTP_MP4A_DEPAY (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;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
diff --git a/gst/rtp/gstrtpmp4adepay.h b/gst/rtp/gstrtpmp4adepay.h
index 16c20b7f7..33622fcae 100644
--- a/gst/rtp/gstrtpmp4adepay.h
+++ b/gst/rtp/gstrtpmp4adepay.h
@@ -41,12 +41,13 @@ typedef struct _GstRtpMP4ADepayClass GstRtpMP4ADepayClass;
struct _GstRtpMP4ADepay
{
GstBaseRTPDepayload depayload;
GstAdapter *adapter;
guint8 numSubFrames;
+ guint frame_len;
};
struct _GstRtpMP4ADepayClass
{
GstBaseRTPDepayloadClass parent_class;
};