mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 09:40:37 +00:00
gst/rtp/README: Update README with new RTP variables that will be used for synchronisation.
Original commit message from CVS: * gst/rtp/README: Update README with new RTP variables that will be used for synchronisation. * gst/rtp/gstrtpvorbisdepay.c: (decode_base64), (gst_rtp_vorbis_depay_parse_configuration), (gst_rtp_vorbis_depay_process): * gst/rtp/gstrtpvorbispay.c: (encode_base64), (gst_rtp_vorbis_pay_finish_headers), (gst_rtp_vorbis_pay_handle_buffer): Update vorbis pay and depayloader to draft-04.
This commit is contained in:
parent
3e1fd61201
commit
5bc71b661d
5 changed files with 276 additions and 93 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2007-05-11 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/rtp/README:
|
||||||
|
Update README with new RTP variables that will be used for
|
||||||
|
synchronisation.
|
||||||
|
|
||||||
|
* gst/rtp/gstrtpvorbisdepay.c: (decode_base64),
|
||||||
|
(gst_rtp_vorbis_depay_parse_configuration),
|
||||||
|
(gst_rtp_vorbis_depay_process):
|
||||||
|
* gst/rtp/gstrtpvorbispay.c: (encode_base64),
|
||||||
|
(gst_rtp_vorbis_pay_finish_headers),
|
||||||
|
(gst_rtp_vorbis_pay_handle_buffer):
|
||||||
|
Update vorbis pay and depayloader to draft-04.
|
||||||
|
|
||||||
2007-05-11 Wim Taymans <wim@fluendo.com>
|
2007-05-11 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/rtsp/rtsptransport.c:
|
* gst/rtsp/rtsptransport.c:
|
||||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
||||||
Subproject commit 1b4fb5836a9e290fe13895643d41e0166de8a94c
|
Subproject commit b5971d76ccd216c27e095c02c3a369a9d05cb36d
|
|
@ -22,16 +22,41 @@ The following fields can or must (*) be specified in the structure:
|
||||||
set.
|
set.
|
||||||
|
|
||||||
* clock-rate: (int) [0 - MAXINT]
|
* clock-rate: (int) [0 - MAXINT]
|
||||||
the RTP clock rate
|
The RTP clock rate.
|
||||||
|
|
||||||
ssrc: (uint) [0 - MAXINT]
|
ssrc: (uint) [0 - MAXINT]
|
||||||
The ssrc value currently in use.
|
The ssrc value currently in use. (default = the SSRC of the first RTP
|
||||||
|
packet)
|
||||||
|
|
||||||
|
npt-start: (uint64) [0 - MAXINT]
|
||||||
|
The Normal Play Time for clock-base. This is the position in the stream and
|
||||||
|
is between 0 and the duration of the stream. This value is expressed in
|
||||||
|
nanoseconds GstClockTime. (default = 0)
|
||||||
|
|
||||||
|
npt-stop: (uint64) [0 - MAXINT]
|
||||||
|
The last position in the stream. This value is expressed in nanoseconds
|
||||||
|
GstClockTime. (default = -1, stop unknown)
|
||||||
|
|
||||||
clock-base: (uint) [0 - MAXINT]
|
clock-base: (uint) [0 - MAXINT]
|
||||||
The RTP time representing time 0
|
The RTP time representing time npt-start. (default = rtptime of first RTP
|
||||||
|
packet).
|
||||||
|
|
||||||
|
play-speed: (gdouble) [-MIN - MAX]
|
||||||
|
The intended playback speed of the stream. The client is delivered data at
|
||||||
|
the adjusted speed. The client should adjust its playback speed with this
|
||||||
|
value and thus corresponds to the GStreamer rate field in the NEWSEGMENT
|
||||||
|
event. (default = 1.0)
|
||||||
|
|
||||||
|
play-scale: (gdouble) [-MIN - MAX]
|
||||||
|
The rate already applied to the stream. The client is delivered a stream
|
||||||
|
that is scaled by this amount. This value is used to adjust position
|
||||||
|
reporting and corresponds to the GStream applied-rate field in the
|
||||||
|
NEWSEGMENT event. (default = 1.0)
|
||||||
|
|
||||||
seqnum-base: (uint) [0 - MAXINT]
|
seqnum-base: (uint) [0 - MAXINT]
|
||||||
The RTP sequence number representing the first rtp packet
|
The RTP sequence number representing the first rtp packet. When this
|
||||||
|
parameter is given, all sequence numbers below this seqnum should be
|
||||||
|
ignored. (default = seqnum of first RTP packet).
|
||||||
|
|
||||||
encoding-name: (String) ANY
|
encoding-name: (String) ANY
|
||||||
typically second part of the mime type. ex. MP4V-ES. only required if
|
typically second part of the mime type. ex. MP4V-ES. only required if
|
||||||
|
@ -50,15 +75,15 @@ The following fields can or must (*) be specified in the structure:
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
"application/x-rtp",
|
"application/x-rtp",
|
||||||
"media", G_TYPE_STRING, "audio", -]
|
"media", G_TYPE_STRING, "audio", -.
|
||||||
"payload", G_TYPE_INT, 96, ] - required
|
"payload", G_TYPE_INT, 96, | - required
|
||||||
"clock-rate", G_TYPE_INT, 8000, -]
|
"clock-rate", G_TYPE_INT, 8000, -'
|
||||||
"encoding-name", G_TYPE_STRING, "AMR", -] - required since payload >= 96
|
"encoding-name", G_TYPE_STRING, "AMR", -. - required since payload >= 96
|
||||||
"encoding-params", G_TYPE_STRING, "1", -] - optional param for AMR
|
"encoding-params", G_TYPE_STRING, "1", -' - optional param for AMR
|
||||||
"octet-align", G_TYPE_STRING, "1", -]
|
"octet-align", G_TYPE_STRING, "1", -.
|
||||||
"crc", G_TYPE_STRING, "0", ]
|
"crc", G_TYPE_STRING, "0", |
|
||||||
"robust-sorting", G_TYPE_STRING, "0", ] AMR specific params.
|
"robust-sorting", G_TYPE_STRING, "0", | AMR specific params.
|
||||||
"interleaving", G_TYPE_STRING, "0", -]
|
"interleaving", G_TYPE_STRING, "0", -'
|
||||||
|
|
||||||
Mapping of caps to and from SDP fields:
|
Mapping of caps to and from SDP fields:
|
||||||
|
|
||||||
|
@ -79,6 +104,18 @@ The following fields can or must (*) be specified in the structure:
|
||||||
always use the lowercase names so that the SDP -> caps mapping remains
|
always use the lowercase names so that the SDP -> caps mapping remains
|
||||||
possible.
|
possible.
|
||||||
|
|
||||||
|
Mapping of caps to NEWSEGMENT:
|
||||||
|
|
||||||
|
rate: <play-speed>
|
||||||
|
applied-rate: <play-scale>
|
||||||
|
format: GST_FORMAT_TIME
|
||||||
|
start: <clock-base> * GST_SECOND / <clock-rate>
|
||||||
|
stop: if <ntp-stop> != -1
|
||||||
|
<npt-stop> - <npt-start> + start
|
||||||
|
else
|
||||||
|
-1
|
||||||
|
time: <npt-start>
|
||||||
|
|
||||||
|
|
||||||
usage with UDP
|
usage with UDP
|
||||||
--------------
|
--------------
|
||||||
|
|
|
@ -30,11 +30,15 @@
|
||||||
GST_DEBUG_CATEGORY_STATIC (rtpvorbisdepay_debug);
|
GST_DEBUG_CATEGORY_STATIC (rtpvorbisdepay_debug);
|
||||||
#define GST_CAT_DEFAULT (rtpvorbisdepay_debug)
|
#define GST_CAT_DEFAULT (rtpvorbisdepay_debug)
|
||||||
|
|
||||||
|
/* references:
|
||||||
|
* http://svn.xiph.org/trunk/vorbis/doc/draft-ietf-avt-rtp-vorbis-04.txt
|
||||||
|
*/
|
||||||
|
|
||||||
/* elementfactory information */
|
/* elementfactory information */
|
||||||
static const GstElementDetails gst_rtp_vorbis_depay_details =
|
static const GstElementDetails gst_rtp_vorbis_depay_details =
|
||||||
GST_ELEMENT_DETAILS ("RTP packet depayloader",
|
GST_ELEMENT_DETAILS ("RTP packet depayloader",
|
||||||
"Codec/Depayloader/Network",
|
"Codec/Depayloader/Network",
|
||||||
"Extracts Vorbis Audio from RTP packets (draft-01 of RFC XXXX)",
|
"Extracts Vorbis Audio from RTP packets (draft-04 of RFC XXXX)",
|
||||||
"Wim Taymans <wim@fluendo.com>");
|
"Wim Taymans <wim@fluendo.com>");
|
||||||
|
|
||||||
/* RtpVorbisDepay signals and args */
|
/* RtpVorbisDepay signals and args */
|
||||||
|
@ -151,28 +155,70 @@ gst_rtp_vorbis_depay_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const guint8 a2bin[256] = {
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||||
|
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint
|
||||||
|
decode_base64 (const gchar * in, guint8 * out)
|
||||||
|
{
|
||||||
|
guint8 v1, v2;
|
||||||
|
guint len = 0;
|
||||||
|
|
||||||
|
v1 = a2bin[(gint) * in];
|
||||||
|
while (v1 <= 63) {
|
||||||
|
/* read 4 bytes, write 3 bytes, invalid base64 are zeroes */
|
||||||
|
v2 = a2bin[(gint) * ++in];
|
||||||
|
*out++ = (v1 << 2) | ((v2 & 0x3f) >> 4);
|
||||||
|
v1 = (v2 > 63 ? 64 : a2bin[(gint) * ++in]);
|
||||||
|
*out++ = (v2 << 4) | ((v1 & 0x3f) >> 2);
|
||||||
|
v2 = (v1 > 63 ? 64 : a2bin[(gint) * ++in]);
|
||||||
|
*out++ = (v1 << 6) | (v2 & 0x3f);
|
||||||
|
v1 = (v2 > 63 ? 64 : a2bin[(gint) * ++in]);
|
||||||
|
len += 3;
|
||||||
|
}
|
||||||
|
/* move to '\0' */
|
||||||
|
while (*in != '\0')
|
||||||
|
in++;
|
||||||
|
|
||||||
|
/* subtract padding */
|
||||||
|
while (len > 0 && *--in == '=')
|
||||||
|
len--;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
|
gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
|
||||||
const gchar * configuration)
|
const gchar * configuration)
|
||||||
{
|
{
|
||||||
GValue v = { 0 };
|
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
guint32 num_headers;
|
guint32 num_headers;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
guint size;
|
guint size;
|
||||||
gint i;
|
gint i, j;
|
||||||
|
|
||||||
/* deserialize base16 to buffer */
|
/* deserialize base64 to buffer */
|
||||||
g_value_init (&v, GST_TYPE_BUFFER);
|
size = strlen (configuration);
|
||||||
if (!gst_value_deserialize (&v, configuration))
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "base64 config size %u", size);
|
||||||
goto wrong_configuration;
|
|
||||||
|
|
||||||
buf = gst_value_get_buffer (&v);
|
data = g_malloc (size);
|
||||||
gst_buffer_ref (buf);
|
size = decode_base64 (configuration, data);
|
||||||
g_value_unset (&v);
|
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (buf);
|
|
||||||
size = GST_BUFFER_SIZE (buf);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpvorbisdepay, "config size %u", size);
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "config size %u", size);
|
||||||
|
|
||||||
|
@ -216,59 +262,73 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
|
||||||
for (i = 0; i < num_headers; i++) {
|
for (i = 0; i < num_headers; i++) {
|
||||||
guint32 ident;
|
guint32 ident;
|
||||||
guint16 length;
|
guint16 length;
|
||||||
|
guint8 n_headers, b;
|
||||||
GstRtpVorbisConfig *conf;
|
GstRtpVorbisConfig *conf;
|
||||||
GstTagList *list;
|
guint *h_sizes;
|
||||||
|
|
||||||
if (size < 5)
|
if (size < 6)
|
||||||
goto too_small;
|
goto too_small;
|
||||||
|
|
||||||
ident = (data[0] << 16) | (data[1] << 8) | data[2];
|
ident = (data[0] << 16) | (data[1] << 8) | data[2];
|
||||||
length = (data[3] << 8) | data[4];
|
length = (data[3] << 8) | data[4];
|
||||||
size -= 5;
|
n_headers = data[5];
|
||||||
data += 5;
|
size -= 6;
|
||||||
|
data += 6;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpvorbisdepay, "header %d, ident 0x%08x, length %u", i,
|
GST_DEBUG_OBJECT (rtpvorbisdepay,
|
||||||
ident, length);
|
"header %d, ident 0x%08x, length %u, left %u", i, ident, length, size);
|
||||||
|
|
||||||
if (size < length + VORBIS_ID_LEN)
|
if (size < length)
|
||||||
goto too_small;
|
goto too_small;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpvorbisdepay, "preparing headers");
|
/* read header sizes we read 2 sizes, the third size (for which we allocate
|
||||||
|
* space) must be derived from the total packed header length. */
|
||||||
|
h_sizes = g_newa (guint, n_headers + 1);
|
||||||
|
for (j = 0; j < n_headers; j++) {
|
||||||
|
guint h_size;
|
||||||
|
|
||||||
|
h_size = 0;
|
||||||
|
do {
|
||||||
|
if (size < 1)
|
||||||
|
goto too_small;
|
||||||
|
b = *data++;
|
||||||
|
size--;
|
||||||
|
h_size = (h_size << 7) | (b & 0x7f);
|
||||||
|
} while (b & 0x80);
|
||||||
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "headers %d: size: %u", j, h_size);
|
||||||
|
h_sizes[j] = h_size;
|
||||||
|
length -= h_size;
|
||||||
|
}
|
||||||
|
/* last header length is the remaining space */
|
||||||
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "last header size: %u", length);
|
||||||
|
h_sizes[j] = length;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "preparing headers");
|
||||||
conf = g_new0 (GstRtpVorbisConfig, 1);
|
conf = g_new0 (GstRtpVorbisConfig, 1);
|
||||||
conf->ident = ident;
|
conf->ident = ident;
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (VORBIS_ID_LEN);
|
for (j = 0; j <= n_headers; j++) {
|
||||||
memcpy (GST_BUFFER_DATA (buf), data, VORBIS_ID_LEN);
|
guint h_size;
|
||||||
conf->headers = g_list_append (conf->headers, buf);
|
|
||||||
data += VORBIS_ID_LEN;
|
|
||||||
size -= VORBIS_ID_LEN;
|
|
||||||
|
|
||||||
/* create a dummy comment */
|
h_size = h_sizes[j];
|
||||||
list = gst_tag_list_new ();
|
if (size < h_size)
|
||||||
buf =
|
goto too_small;
|
||||||
gst_tag_list_to_vorbiscomment_buffer (list, (guint8 *) "\003vorbis", 7,
|
|
||||||
"Vorbis RTP depayloader");
|
|
||||||
conf->headers = g_list_append (conf->headers, buf);
|
|
||||||
gst_tag_list_free (list);
|
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (length);
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "reading header %d, size %u", j,
|
||||||
memcpy (GST_BUFFER_DATA (buf), data, length);
|
h_size);
|
||||||
conf->headers = g_list_append (conf->headers, buf);
|
|
||||||
data += length;
|
|
||||||
size -= length;
|
|
||||||
|
|
||||||
|
buf = gst_buffer_new_and_alloc (h_size);
|
||||||
|
memcpy (GST_BUFFER_DATA (buf), data, h_size);
|
||||||
|
conf->headers = g_list_append (conf->headers, buf);
|
||||||
|
data += h_size;
|
||||||
|
size -= h_size;
|
||||||
|
}
|
||||||
rtpvorbisdepay->configs = g_list_append (rtpvorbisdepay->configs, conf);
|
rtpvorbisdepay->configs = g_list_append (rtpvorbisdepay->configs, conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
wrong_configuration:
|
|
||||||
{
|
|
||||||
GST_DEBUG_OBJECT (rtpvorbisdepay, "error parsing configuration");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
too_small:
|
too_small:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (rtpvorbisdepay, "configuration too small");
|
GST_DEBUG_OBJECT (rtpvorbisdepay, "configuration too small");
|
||||||
|
@ -421,6 +481,8 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
payload = gst_rtp_buffer_get_payload (buf);
|
payload = gst_rtp_buffer_get_payload (buf);
|
||||||
free_payload = FALSE;
|
free_payload = FALSE;
|
||||||
|
|
||||||
|
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||||
|
|
||||||
header = GST_READ_UINT32_BE (payload);
|
header = GST_READ_UINT32_BE (payload);
|
||||||
/*
|
/*
|
||||||
* 0 1 2 3
|
* 0 1 2 3
|
||||||
|
|
|
@ -32,7 +32,7 @@ GST_DEBUG_CATEGORY_STATIC (rtpvorbispay_debug);
|
||||||
#define GST_CAT_DEFAULT (rtpvorbispay_debug)
|
#define GST_CAT_DEFAULT (rtpvorbispay_debug)
|
||||||
|
|
||||||
/* references:
|
/* references:
|
||||||
* http://svn.xiph.org/trunk/vorbis/doc/draft-ietf-avt-rtp-vorbis-01.txt
|
* http://svn.xiph.org/trunk/vorbis/doc/draft-ietf-avt-rtp-vorbis-04.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* elementfactory information */
|
/* elementfactory information */
|
||||||
|
@ -208,27 +208,47 @@ gst_rtp_vorbis_pay_flush_packet (GstRtpVorbisPay * rtpvorbispay)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
encode_base64 (const guint8 * in, guint size, guint * len)
|
||||||
|
{
|
||||||
|
gchar *ret, *d;
|
||||||
|
static const gchar *v =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
*len = ((size + 2) / 3) * 4;
|
||||||
|
d = ret = (gchar *) g_malloc (*len + 1);
|
||||||
|
for (; size; in += 3) { /* process tuplets */
|
||||||
|
*d++ = v[in[0] >> 2]; /* byte 1: high 6 bits (1) */
|
||||||
|
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
||||||
|
*d++ = v[((in[0] << 4) + (--size ? (in[1] >> 4) : 0)) & 0x3f];
|
||||||
|
/* byte 3: low 4 bits (2), high 2 bits (3) */
|
||||||
|
*d++ = size ? v[((in[1] << 2) + (--size ? (in[2] >> 6) : 0)) & 0x3f] : '=';
|
||||||
|
/* byte 4: low 6 bits (3) */
|
||||||
|
*d++ = size ? v[in[2] & 0x3f] : '=';
|
||||||
|
if (size)
|
||||||
|
size--; /* count third character if processed */
|
||||||
|
}
|
||||||
|
*d = '\0'; /* tie off string */
|
||||||
|
|
||||||
|
return ret; /* return the resulting string */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_vorbis_pay_finish_headers (GstBaseRTPPayload * basepayload)
|
gst_rtp_vorbis_pay_finish_headers (GstBaseRTPPayload * basepayload)
|
||||||
{
|
{
|
||||||
GstRtpVorbisPay *rtpvorbispay = GST_RTP_VORBIS_PAY (basepayload);
|
GstRtpVorbisPay *rtpvorbispay = GST_RTP_VORBIS_PAY (basepayload);
|
||||||
GList *walk;
|
GList *walk;
|
||||||
guint length;
|
guint length, size, n_headers, configlen;
|
||||||
gchar *cstr, *configuration;
|
gchar *cstr, *configuration;
|
||||||
guint8 *data;
|
guint8 *data, *config;
|
||||||
guint32 ident;
|
guint32 ident;
|
||||||
GValue v = { 0 };
|
|
||||||
GstBuffer *config;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpvorbispay, "finish headers");
|
GST_DEBUG_OBJECT (rtpvorbispay, "finish headers");
|
||||||
|
|
||||||
if (!rtpvorbispay->headers)
|
if (!rtpvorbispay->headers)
|
||||||
goto no_headers;
|
goto no_headers;
|
||||||
|
|
||||||
/* we need exactly 2 header packets */
|
|
||||||
if (g_list_length (rtpvorbispay->headers) != 2)
|
|
||||||
goto no_headers;
|
|
||||||
|
|
||||||
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Number of packed headers |
|
* | Number of packed headers |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
@ -247,35 +267,60 @@ gst_rtp_vorbis_pay_finish_headers (GstBaseRTPPayload * basepayload)
|
||||||
* 0 1 2 3
|
* 0 1 2 3
|
||||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Ident | ..
|
* | Ident | length ..
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* .. length | Identification Header ..
|
* .. | n. of headers | length1 | length2 ..
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* .. Identification Header |
|
* .. | Identification Header ..
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* .................................................................
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* .. | Comment Header ..
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* .................................................................
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* .. Comment Header |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Setup Header ..
|
* | Setup Header ..
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* .................................................................
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* .. Setup Header |
|
* .. Setup Header |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* count the size of the headers first */
|
/* we need 4 bytes for the number of headers (which is always 1), 3 bytes for
|
||||||
|
* the ident, 2 bytes for length, 1 byte for n. of headers. */
|
||||||
|
size = 4 + 3 + 2 + 1;
|
||||||
|
|
||||||
|
/* count the size of the headers first and update the hash */
|
||||||
length = 0;
|
length = 0;
|
||||||
|
n_headers = 0;
|
||||||
ident = fnv1_hash_32_new ();
|
ident = fnv1_hash_32_new ();
|
||||||
for (walk = rtpvorbispay->headers; walk; walk = g_list_next (walk)) {
|
for (walk = rtpvorbispay->headers; walk; walk = g_list_next (walk)) {
|
||||||
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
||||||
|
guint bsize;
|
||||||
|
|
||||||
ident =
|
bsize = GST_BUFFER_SIZE (buf);
|
||||||
fnv1_hash_32_update (ident, GST_BUFFER_DATA (buf),
|
length += bsize;
|
||||||
|
n_headers++;
|
||||||
|
|
||||||
|
/* count number of bytes needed for length fields, we don't need this for
|
||||||
|
* the last header. */
|
||||||
|
if (g_list_next (walk)) {
|
||||||
|
do {
|
||||||
|
size++;
|
||||||
|
bsize >>= 7;
|
||||||
|
} while (bsize);
|
||||||
|
}
|
||||||
|
/* update hash */
|
||||||
|
ident = fnv1_hash_32_update (ident, GST_BUFFER_DATA (buf),
|
||||||
GST_BUFFER_SIZE (buf));
|
GST_BUFFER_SIZE (buf));
|
||||||
length += GST_BUFFER_SIZE (buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* total config length is 4 bytes header number + size of the
|
/* packet length is header size + packet length */
|
||||||
* headers + 2 bytes length + 3 bytes for the ident */
|
configlen = size + length;
|
||||||
config = gst_buffer_new_and_alloc (length + 4 + 2 + 3);
|
config = data = g_malloc (configlen);
|
||||||
data = GST_BUFFER_DATA (config);
|
|
||||||
|
|
||||||
/* number of packed headers, we only pack 1 header */
|
/* number of packed headers, we only pack 1 header */
|
||||||
data[0] = 0;
|
data[0] = 0;
|
||||||
|
@ -292,12 +337,44 @@ gst_rtp_vorbis_pay_finish_headers (GstBaseRTPPayload * basepayload)
|
||||||
data[5] = (ident >> 8) & 0xff;
|
data[5] = (ident >> 8) & 0xff;
|
||||||
data[6] = ident & 0xff;
|
data[6] = ident & 0xff;
|
||||||
|
|
||||||
/* store length minus the length of the fixed vorbis header */
|
/* store length of all vorbis headers */
|
||||||
data[7] = ((length - 30) >> 8) & 0xff;
|
data[7] = ((length) >> 8) & 0xff;
|
||||||
data[8] = (length - 30) & 0xff;
|
data[8] = (length) & 0xff;
|
||||||
|
|
||||||
|
/* store number of headers minus one. */
|
||||||
|
data[9] = n_headers - 1;
|
||||||
|
data += 10;
|
||||||
|
|
||||||
|
/* store length for each header */
|
||||||
|
for (walk = rtpvorbispay->headers; walk; walk = g_list_next (walk)) {
|
||||||
|
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
||||||
|
guint bsize, size, temp;
|
||||||
|
|
||||||
|
/* only need to store the length when it's not the last header */
|
||||||
|
if (!g_list_next (walk))
|
||||||
|
break;
|
||||||
|
|
||||||
|
bsize = GST_BUFFER_SIZE (buf);
|
||||||
|
|
||||||
|
/* calc size */
|
||||||
|
size = 0;
|
||||||
|
do {
|
||||||
|
size++;
|
||||||
|
bsize >>= 7;
|
||||||
|
} while (bsize);
|
||||||
|
temp = size;
|
||||||
|
|
||||||
|
bsize = GST_BUFFER_SIZE (buf);
|
||||||
|
/* write the size backwards */
|
||||||
|
while (size) {
|
||||||
|
size--;
|
||||||
|
data[size] = bsize & 0x7f;
|
||||||
|
bsize >>= 7;
|
||||||
|
}
|
||||||
|
data += temp;
|
||||||
|
}
|
||||||
|
|
||||||
/* copy header data */
|
/* copy header data */
|
||||||
data += 9;
|
|
||||||
for (walk = rtpvorbispay->headers; walk; walk = g_list_next (walk)) {
|
for (walk = rtpvorbispay->headers; walk; walk = g_list_next (walk)) {
|
||||||
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
||||||
|
|
||||||
|
@ -305,10 +382,9 @@ gst_rtp_vorbis_pay_finish_headers (GstBaseRTPPayload * basepayload)
|
||||||
data += GST_BUFFER_SIZE (buf);
|
data += GST_BUFFER_SIZE (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serialize buffer to base16 */
|
/* serialize to base64 */
|
||||||
g_value_init (&v, GST_TYPE_BUFFER);
|
configuration = encode_base64 (config, configlen, &size);
|
||||||
gst_value_take_buffer (&v, config);
|
g_free (config);
|
||||||
configuration = gst_value_serialize (&v);
|
|
||||||
|
|
||||||
/* configure payloader settings */
|
/* configure payloader settings */
|
||||||
cstr = g_strdup_printf ("%d", rtpvorbispay->channels);
|
cstr = g_strdup_printf ("%d", rtpvorbispay->channels);
|
||||||
|
@ -322,7 +398,6 @@ gst_rtp_vorbis_pay_finish_headers (GstBaseRTPPayload * basepayload)
|
||||||
NULL);
|
NULL);
|
||||||
g_free (cstr);
|
g_free (cstr);
|
||||||
g_free (configuration);
|
g_free (configuration);
|
||||||
g_value_unset (&v);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -450,12 +525,7 @@ gst_rtp_vorbis_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
|
|
||||||
if (rtpvorbispay->need_headers) {
|
if (rtpvorbispay->need_headers) {
|
||||||
/* we need to collect the headers and construct a config string from them */
|
/* we need to collect the headers and construct a config string from them */
|
||||||
if (VDT == 2) {
|
if (VDT != 0) {
|
||||||
GST_DEBUG_OBJECT (rtpvorbispay,
|
|
||||||
"discard comment packet while collecting headers");
|
|
||||||
ret = GST_FLOW_OK;
|
|
||||||
goto done;
|
|
||||||
} else if (VDT != 0) {
|
|
||||||
GST_DEBUG_OBJECT (rtpvorbispay, "collecting header");
|
GST_DEBUG_OBJECT (rtpvorbispay, "collecting header");
|
||||||
/* append header to the list of headers */
|
/* append header to the list of headers */
|
||||||
rtpvorbispay->headers = g_list_append (rtpvorbispay->headers, buffer);
|
rtpvorbispay->headers = g_list_append (rtpvorbispay->headers, buffer);
|
||||||
|
|
Loading…
Reference in a new issue