Commit 25a44f8e authored by Wim Taymans's avatar Wim Taymans
Browse files

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.
parent e4ba5018
2006-09-22 Wim Taymans <wim@fluendo.com>
* 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.
2006-09-22 Tim-Philipp Müller <tim at centricular dot net>
* gst/autodetect/gstautoaudiosink.c:
......
......@@ -2,7 +2,6 @@ plugin_LTLIBRARIES = libgstrtp.la
libgstrtp_la_SOURCES = \
gstrtp.c \
gstrtpasfdepay.c \
gstrtpdepay.c \
gstrtpmpadepay.c \
gstrtpmpapay.c \
......@@ -44,7 +43,6 @@ libgstrtp_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \
libgstrtp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = \
gstrtpasfdepay.h \
gstrtpL16depay.h \
gstrtpL16pay.h \
gstrtpamrdepay.h \
......
......@@ -21,7 +21,6 @@
#include "config.h"
#endif
#include "gstrtpasfdepay.h"
#include "gstrtpdepay.h"
#include "gstrtppcmupay.h"
#include "gstrtppcmapay.h"
......@@ -52,9 +51,6 @@
static gboolean
plugin_init (GstPlugin * plugin)
{
if (!gst_rtp_asf_depay_plugin_init (plugin))
return FALSE;
if (!gst_rtp_depay_plugin_init (plugin))
return FALSE;
......
......@@ -201,7 +201,7 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
GST_DEBUG_OBJECT (depayload, "got RTP packet of size %d", payload_len);
/* we need at least 4 bytes for the packet header */
if (payload_len < 4)
if (G_UNLIKELY (payload_len < 4))
goto packet_short;
payload = gst_rtp_buffer_get_payload (buf);
......@@ -220,7 +220,7 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
* pkts: number of packets.
*/
VDT = (header & 0x30) >> 4;
if (VDT == 3)
if (G_UNLIKELY (VDT == 3))
goto ignore_reserved;
ident = (header >> 8) & 0xffffff;
......@@ -235,8 +235,8 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
payload += 4;
payload_len -= 4;
GST_DEBUG_OBJECT (depayload, "ident: %u, F: %d, packets: %d", ident, F,
packets);
GST_DEBUG_OBJECT (depayload, "ident: %u, F: %d, VDT: %d, packets: %d", ident,
F, VDT, packets);
/* fragmented packets, assemble */
if (F != 0) {
......@@ -268,6 +268,7 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
/* construct assembled buffer */
payload_len = gst_adapter_available (rtpvorbisdepay->adapter);
payload = gst_adapter_take (rtpvorbisdepay->adapter, payload_len);
/* fix the length */
payload[0] = ((payload_len - 2) >> 8) & 0xff;
payload[1] = (payload_len - 2) & 0xff;
to_free = payload;
......@@ -307,11 +308,11 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
payload_len);
/* skip packet if something odd happens */
if (length > payload_len)
if (G_UNLIKELY (length > payload_len))
goto length_short;
/* create buffer for packet */
if (to_free) {
if (G_UNLIKELY (to_free)) {
outbuf = gst_buffer_new ();
GST_BUFFER_DATA (outbuf) = payload;
GST_BUFFER_MALLOCDATA (outbuf) = to_free;
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment