summaryrefslogtreecommitdiffstats
path: root/gst/rtp/gstrtpvorbispay.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-09-22 15:15:13 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-09-22 15:15:13 +0000
commit25a44f8e02457e811a979b982997fdc01b218e96 (patch)
tree11b0f5c42caf9d805b7b2ab6815b1f5705b8ca07 /gst/rtp/gstrtpvorbispay.c
parente4ba5018559d09e153aafca1d1d52d9e1cced648 (diff)
gst/rtp/: More fixage, set endoder-params correctly in the payloader.
Original commit message from CVS: * gst/rtp/Makefile.am: * gst/rtp/gstrtp.c: (plugin_init): * gst/rtp/gstrtpvorbisdepay.c: (gst_rtp_vorbis_depay_process): * gst/rtp/gstrtpvorbispay.c: (gst_rtp_vorbis_pay_setcaps), (gst_rtp_vorbis_pay_reset_packet), (gst_rtp_vorbis_pay_init_packet), (gst_rtp_vorbis_pay_flush_packet), (gst_rtp_vorbis_pay_parse_id), (gst_rtp_vorbis_pay_handle_buffer): More fixage, set endoder-params correctly in the payloader.
Diffstat (limited to 'gst/rtp/gstrtpvorbispay.c')
-rw-r--r--gst/rtp/gstrtpvorbispay.c276
1 files changed, 187 insertions, 89 deletions
diff --git a/gst/rtp/gstrtpvorbispay.c b/gst/rtp/gstrtpvorbispay.c
index 30336425..be706714 100644
--- a/gst/rtp/gstrtpvorbispay.c
+++ b/gst/rtp/gstrtpvorbispay.c
@@ -123,40 +123,41 @@ gst_rtp_vorbis_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
rtpvorbispay = GST_RTP_VORBIS_PAY (basepayload);
- gst_basertppayload_set_options (basepayload, "audio", TRUE, "vorbis", 8000);
- gst_basertppayload_set_outcaps (basepayload,
- "encoding-params", G_TYPE_STRING, "1",
- /* don't set the defaults
- */
- NULL);
-
return TRUE;
}
static void
-gst_rtp_vorbis_pay_init_packet (GstRtpVorbisPay * rtpvorbispay)
+gst_rtp_vorbis_pay_reset_packet (GstRtpVorbisPay * rtpvorbispay, guint8 VDT)
{
guint payload_len;
- if (rtpvorbispay->packet)
- gst_buffer_unref (rtpvorbispay->packet);
+ GST_DEBUG_OBJECT (rtpvorbispay, "reset packet");
- GST_DEBUG_OBJECT (rtpvorbispay, "starting new packet");
-
- /* new packet allocate max packet size */
- rtpvorbispay->packet =
- gst_rtp_buffer_new_allocate_len (GST_BASE_RTP_PAYLOAD_MTU
- (rtpvorbispay), 0, 0);
rtpvorbispay->payload_pos = 4;
payload_len = gst_rtp_buffer_get_payload_len (rtpvorbispay->packet);
rtpvorbispay->payload_left = payload_len - 4;
rtpvorbispay->payload_duration = 0;
rtpvorbispay->payload_ident = 0;
rtpvorbispay->payload_F = 0;
- rtpvorbispay->payload_VDT = 0;
+ rtpvorbispay->payload_VDT = VDT;
rtpvorbispay->payload_pkts = 0;
}
+static void
+gst_rtp_vorbis_pay_init_packet (GstRtpVorbisPay * rtpvorbispay, guint8 VDT)
+{
+ GST_DEBUG_OBJECT (rtpvorbispay, "starting new packet, VDT: %d", VDT);
+
+ if (rtpvorbispay->packet)
+ gst_buffer_unref (rtpvorbispay->packet);
+
+ /* new packet allocate max packet size */
+ rtpvorbispay->packet =
+ gst_rtp_buffer_new_allocate_len (GST_BASE_RTP_PAYLOAD_MTU
+ (rtpvorbispay), 0, 0);
+ gst_rtp_vorbis_pay_reset_packet (rtpvorbispay, VDT);
+}
+
static GstFlowReturn
gst_rtp_vorbis_pay_flush_packet (GstRtpVorbisPay * rtpvorbispay)
{
@@ -165,7 +166,7 @@ gst_rtp_vorbis_pay_flush_packet (GstRtpVorbisPay * rtpvorbispay)
guint hlen;
/* check for empty packet */
- if (!rtpvorbispay || rtpvorbispay->payload_pos <= 4)
+ if (!rtpvorbispay->packet || rtpvorbispay->payload_pos <= 4)
return GST_FLOW_OK;
GST_DEBUG_OBJECT (rtpvorbispay, "flushing packet");
@@ -200,85 +201,77 @@ gst_rtp_vorbis_pay_flush_packet (GstRtpVorbisPay * rtpvorbispay)
rtpvorbispay->packet);
rtpvorbispay->packet = NULL;
- /* prepare new packet */
- gst_rtp_vorbis_pay_init_packet (rtpvorbispay);
-
return ret;
}
-static GstFlowReturn
-gst_rtp_vorbis_pay_append_buffer (GstRtpVorbisPay * rtpvorbispay,
- GstBuffer * buffer)
+static gboolean
+gst_rtp_vorbis_pay_parse_id (GstBaseRTPPayload * basepayload, guint8 * data,
+ guint size)
{
- GstFlowReturn res;
- guint size;
- GstClockTime duration;
- guint plen;
- guint8 *ppos, *payload, *data;
- gboolean fragmented;
+ guint8 channels;
+ gint32 rate, version;
+ gchar *cstr;
- res = GST_FLOW_OK;
+ if (G_UNLIKELY (size < 16))
+ goto too_short;
- if (rtpvorbispay->payload_left < 2)
- return res;
+ if (G_UNLIKELY (memcmp (data, "\001vorbis", 7)))
+ goto invalid_start;
+ data += 7;
- size = GST_BUFFER_SIZE (buffer);
- /* skip packets that are too big */
- if (size > 0xffff)
- return res;
+ if (G_UNLIKELY ((version = GST_READ_UINT32_LE (data)) != 0))
+ goto invalid_version;
+ data += 4;
- data = GST_BUFFER_DATA (buffer);
- duration = GST_BUFFER_DURATION (buffer);
- payload = gst_rtp_buffer_get_payload (rtpvorbispay->packet);
- ppos = payload + rtpvorbispay->payload_pos;
- fragmented = FALSE;
-
- while (size) {
- plen = MIN (rtpvorbispay->payload_left - 2, size);
-
- GST_DEBUG_OBJECT (rtpvorbispay, "append %u bytes", plen);
+ if (G_UNLIKELY ((channels = *data++) < 1))
+ goto invalid_channels;
- ppos[0] = (plen >> 8) & 0xff;
- ppos[1] = (plen & 0xff);
- memcpy (&ppos[2], data, plen);
+ if (G_UNLIKELY ((rate = GST_READ_UINT32_LE (data)) < 1))
+ goto invalid_rate;
- size -= plen;
- data += plen;
+ cstr = g_strdup_printf ("%d", channels);
+ gst_basertppayload_set_options (basepayload, "audio", TRUE, "vorbis", rate);
+ gst_basertppayload_set_outcaps (basepayload,
+ "encoding-params", G_TYPE_STRING, cstr,
+ /* don't set the defaults
+ */
+ NULL);
+ g_free (cstr);
- rtpvorbispay->payload_pos += plen + 2;
- rtpvorbispay->payload_left -= plen + 2;
+ return TRUE;
- if (fragmented) {
- if (size == 0)
- /* last fragment, set F to 0x3. */
- rtpvorbispay->payload_F = 0x3;
- else
- /* fragment continues, set F to 0x2. */
- rtpvorbispay->payload_F = 0x2;
- } else {
- if (size == 0) {
- /* unfragmented packet, update stats for next packet */
- rtpvorbispay->payload_pkts++;
- if (duration != GST_CLOCK_TIME_NONE)
- rtpvorbispay->payload_duration += duration;
- } else {
- /* fragmented packet starts, set F to 0x1, mark ourselves as
- * fragmented. */
- rtpvorbispay->payload_F = 0x1;
- fragmented = TRUE;
- }
- }
- if (fragmented) {
- /* fragmented packets are always flushed and have ptks of 0 */
- rtpvorbispay->payload_pkts = 0;
- res = gst_rtp_vorbis_pay_flush_packet (rtpvorbispay);
- /* get new pointers */
- payload = gst_rtp_buffer_get_payload (rtpvorbispay->packet);
- ppos = payload + rtpvorbispay->payload_pos;
- }
+ /* ERRORS */
+too_short:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, DECODE,
+ ("Identification packet is too short, need at least 16, got %d", size),
+ (NULL));
+ return FALSE;
+ }
+invalid_start:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, DECODE,
+ ("Invalid header start in identification packet"), (NULL));
+ return FALSE;
+ }
+invalid_version:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, DECODE,
+ ("Invalid version, expected 0, got %d", version), (NULL));
+ return FALSE;
+ }
+invalid_rate:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, DECODE,
+ ("Invalid rate %d", rate), (NULL));
+ return FALSE;
+ }
+invalid_channels:
+ {
+ GST_ELEMENT_ERROR (basepayload, STREAM, DECODE,
+ ("Invalid channels %d", channels), (NULL));
+ return FALSE;
}
-
- return res;
}
static GstFlowReturn
@@ -288,20 +281,45 @@ gst_rtp_vorbis_pay_handle_buffer (GstBaseRTPPayload * basepayload,
GstRtpVorbisPay *rtpvorbispay;
GstFlowReturn ret;
guint size, newsize;
+ guint8 *data;
guint packet_len;
GstClockTime duration, newduration;
gboolean flush;
+ guint8 VDT;
+ guint plen;
+ guint8 *ppos, *payload;
+ gboolean fragmented;
rtpvorbispay = GST_RTP_VORBIS_PAY (basepayload);
size = GST_BUFFER_SIZE (buffer);
+ data = GST_BUFFER_DATA (buffer);
duration = GST_BUFFER_DURATION (buffer);
GST_DEBUG_OBJECT (rtpvorbispay, "size %u, duration %" GST_TIME_FORMAT,
size, GST_TIME_ARGS (duration));
- if (!rtpvorbispay->packet)
- gst_rtp_vorbis_pay_init_packet (rtpvorbispay);
+ if (G_UNLIKELY (size < 1 || size > 0xffff))
+ goto wrong_size;
+
+ /* find packet type */
+ if (data[0] & 1) {
+ /* header */
+ if (data[0] == 1) {
+ /* identification, we need to parse this in order to get the clock rate. */
+ if (G_UNLIKELY (!gst_rtp_vorbis_pay_parse_id (basepayload, data, size)))
+ goto parse_id_failed;
+ VDT = 1;
+ } else if (data[0] == 5)
+ /* setup */
+ VDT = 1;
+ else if (data[0] == 3)
+ VDT = 2;
+ else
+ goto unknown_header;
+ } else
+ /* data */
+ VDT = 0;
/* size increases with packet length and 2 bytes size eader. */
newduration = rtpvorbispay->payload_duration;
@@ -315,14 +333,94 @@ gst_rtp_vorbis_pay_handle_buffer (GstBaseRTPPayload * basepayload,
flush = gst_basertppayload_is_filled (basepayload, packet_len, newduration);
/* we can store up to 15 vorbis packets in one RTP packet. */
flush |= (rtpvorbispay->payload_pkts == 15);
-
+ /* flush if we have a new VDT */
+ if (rtpvorbispay->packet)
+ flush |= (rtpvorbispay->payload_VDT != VDT);
if (flush)
ret = gst_rtp_vorbis_pay_flush_packet (rtpvorbispay);
- /* put buffer in packet */
- ret = gst_rtp_vorbis_pay_append_buffer (rtpvorbispay, buffer);
+ /* create new packet if we must */
+ if (!rtpvorbispay->packet)
+ gst_rtp_vorbis_pay_init_packet (rtpvorbispay, VDT);
+
+ payload = gst_rtp_buffer_get_payload (rtpvorbispay->packet);
+ ppos = payload + rtpvorbispay->payload_pos;
+ fragmented = FALSE;
+
+ ret = GST_FLOW_OK;
+
+ /* put buffer in packet, it either fits completely or needs to be fragmented
+ * over multiple RTP packets. */
+ while (size) {
+ plen = MIN (rtpvorbispay->payload_left - 2, size);
+
+ GST_DEBUG_OBJECT (rtpvorbispay, "append %u bytes", plen);
+
+ /* data is copied in the payload with a 2 byte length header */
+ ppos[0] = (plen >> 8) & 0xff;
+ ppos[1] = (plen & 0xff);
+ memcpy (&ppos[2], data, plen);
+ size -= plen;
+ data += plen;
+
+ rtpvorbispay->payload_pos += plen + 2;
+ rtpvorbispay->payload_left -= plen + 2;
+
+ if (fragmented) {
+ if (size == 0)
+ /* last fragment, set F to 0x3. */
+ rtpvorbispay->payload_F = 0x3;
+ else
+ /* fragment continues, set F to 0x2. */
+ rtpvorbispay->payload_F = 0x2;
+ } else {
+ if (size > 0) {
+ /* fragmented packet starts, set F to 0x1, mark ourselves as
+ * fragmented. */
+ rtpvorbispay->payload_F = 0x1;
+ fragmented = TRUE;
+ }
+ }
+ if (fragmented) {
+ /* fragmented packets are always flushed and have ptks of 0 */
+ rtpvorbispay->payload_pkts = 0;
+ ret = gst_rtp_vorbis_pay_flush_packet (rtpvorbispay);
+
+ if (size > 0) {
+ /* start new packet and get pointers. VDT stays the same. */
+ gst_rtp_vorbis_pay_init_packet (rtpvorbispay,
+ rtpvorbispay->payload_VDT);
+ payload = gst_rtp_buffer_get_payload (rtpvorbispay->packet);
+ ppos = payload + rtpvorbispay->payload_pos;
+ }
+ } else {
+ /* unfragmented packet, update stats for next packet, size == 0 and we
+ * exit the while loop */
+ rtpvorbispay->payload_pkts++;
+ if (duration != GST_CLOCK_TIME_NONE)
+ rtpvorbispay->payload_duration += duration;
+ }
+ }
return ret;
+
+ /* ERRORS */
+wrong_size:
+ {
+ GST_ELEMENT_WARNING (rtpvorbispay, STREAM, DECODE,
+ ("Invalid packet size (1 < %d <= 0xffff)", size), (NULL));
+ return GST_FLOW_OK;
+ }
+parse_id_failed:
+ {
+ return GST_FLOW_ERROR;
+ }
+unknown_header:
+ {
+ GST_ELEMENT_WARNING (rtpvorbispay, STREAM, DECODE,
+ ("Ignoring unknown header received"), (NULL));
+ return GST_FLOW_OK;
+ }
}
gboolean