mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
gst/rtp/gstrtpamrdec.c: Handle multiple AMr packets per payload. Handle CRC and parse ILL/ILP.
Original commit message from CVS: * gst/rtp/gstrtpamrdec.c: (gst_rtpamrdec_sink_setcaps), (gst_rtpamrdec_chain): Handle multiple AMr packets per payload. Handle CRC and parse ILL/ILP. * gst/rtp/gstrtpamrenc.c: (gst_rtpamrenc_setcaps): Make caps params strings for easy SDP mapping. * gst/rtp/gstrtpdec.c: (gst_rtpdec_init), (gst_rtpdec_getcaps): Handle capsnego better. * gst/rtp/gstrtpmp4vdec.c: (gst_rtpmp4vdec_setcaps): * gst/rtp/gstrtpmp4venc.c: (gst_rtpmp4venc_new_caps): Generate and parse config string in the caps.
This commit is contained in:
parent
9dd3929730
commit
a297069e16
11 changed files with 373 additions and 108 deletions
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2005-09-21 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/rtp/gstrtpamrdec.c: (gst_rtpamrdec_sink_setcaps),
|
||||
(gst_rtpamrdec_chain):
|
||||
Handle multiple AMr packets per payload. Handle CRC and
|
||||
parse ILL/ILP.
|
||||
|
||||
* gst/rtp/gstrtpamrenc.c: (gst_rtpamrenc_setcaps):
|
||||
Make caps params strings for easy SDP mapping.
|
||||
|
||||
* gst/rtp/gstrtpdec.c: (gst_rtpdec_init), (gst_rtpdec_getcaps):
|
||||
Handle capsnego better.
|
||||
|
||||
* gst/rtp/gstrtpmp4vdec.c: (gst_rtpmp4vdec_setcaps):
|
||||
* gst/rtp/gstrtpmp4venc.c: (gst_rtpmp4venc_new_caps):
|
||||
Generate and parse config string in the caps.
|
||||
|
||||
2005-09-21 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/rtp/README:
|
||||
|
|
|
@ -63,9 +63,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
"clock-rate = (int) 8000, "
|
||||
"encoding-name = (string) \"AMR\", "
|
||||
"encoding-params = (string) \"1\", "
|
||||
"octet-align = (string) 1, "
|
||||
"crc = (string) 0, "
|
||||
"robust-sorting = (string) 0, " "interleaving = (string) 0"
|
||||
"octet-align = (string) \"1\", "
|
||||
"crc = (string) { \"0\", \"1\" }, "
|
||||
"robust-sorting = (string) \"0\", " "interleaving = (string) \"0\""
|
||||
/* following options are not needed for a decoder
|
||||
*
|
||||
"mode-set = (int) [ 0, 7 ], "
|
||||
|
@ -238,8 +238,6 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
return FALSE;
|
||||
if (rtpamrdec->octet_align != TRUE)
|
||||
return FALSE;
|
||||
if (rtpamrdec->crc != FALSE)
|
||||
return FALSE;
|
||||
if (rtpamrdec->robust_sorting != FALSE)
|
||||
return FALSE;
|
||||
if (rtpamrdec->interleaving != FALSE)
|
||||
|
@ -256,6 +254,12 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* -1 is invalid */
|
||||
static gint frame_size[16] = {
|
||||
12, 13, 15, 17, 19, 20, 26, 31,
|
||||
5, -1, -1, -1, -1, -1, -1, 0
|
||||
};
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
||||
{
|
||||
|
@ -275,9 +279,12 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
|||
* no robust sorting, no interleaving data is to be parsed */
|
||||
{
|
||||
gint payload_len;
|
||||
guint8 *payload;
|
||||
guint8 *payload, *p, *dp;
|
||||
guint32 timestamp;
|
||||
guint8 CMR, F, FT, Q;
|
||||
guint8 CMR;
|
||||
gint i, num_packets, num_nonempty_packets;
|
||||
gint amr_len;
|
||||
gint ILL, ILP;
|
||||
|
||||
payload_len = gst_rtpbuffer_get_payload_len (buf);
|
||||
|
||||
|
@ -287,46 +294,111 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
payload = gst_rtpbuffer_get_payload (buf);
|
||||
|
||||
/* parse header
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
|
||||
* | CMR |R|R|R|R|F| FT |Q|P|P|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
|
||||
/* parse CMR. The CMR is used by the sender to request
|
||||
* a new encoding mode.
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* | CMR |R|R|R|R|
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
CMR = (payload[0] & 0xf0) >> 4;
|
||||
F = (payload[1] & 0x80) >> 7;
|
||||
/* we only support 1 packet per RTP packet for now */
|
||||
if (F != 0)
|
||||
goto one_packet_only;
|
||||
|
||||
FT = (payload[1] & 0x78) >> 3;
|
||||
Q = (payload[1] & 0x04) >> 2;
|
||||
|
||||
/* skip packet */
|
||||
if (FT > 9 && FT < 15) {
|
||||
ret = GST_FLOW_OK;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* strip header now, leave FT in the data for the decoder */
|
||||
/* strip CMR header now, pack FT and the data for the decoder */
|
||||
payload_len -= 1;
|
||||
payload += 1;
|
||||
|
||||
if (rtpamrdec->interleaving) {
|
||||
ILL = (payload[0] & 0xf0) >> 4;
|
||||
ILP = (payload[0] & 0x0f);
|
||||
|
||||
payload_len -= 1;
|
||||
payload += 1;
|
||||
|
||||
if (ILP > ILL)
|
||||
goto bad_packet;
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
|
||||
* +-+-+-+-+-+-+-+-+..
|
||||
* |F| FT |Q|P|P| more FT..
|
||||
* +-+-+-+-+-+-+-+-+..
|
||||
*/
|
||||
/* count number of packets by counting the FTs. Also
|
||||
* count number of amr data bytes and number of non-empty
|
||||
* packets (this is also the number of CRCs if present). */
|
||||
amr_len = 0;
|
||||
num_nonempty_packets = 0;
|
||||
num_packets = 0;
|
||||
for (i = 0; i < payload_len; i++) {
|
||||
gint fr_size;
|
||||
guint8 FT;
|
||||
|
||||
FT = (payload[i] & 0x78) >> 3;
|
||||
|
||||
fr_size = frame_size[FT];
|
||||
if (fr_size == -1)
|
||||
goto bad_packet;
|
||||
|
||||
if (fr_size > 0) {
|
||||
amr_len += fr_size;
|
||||
num_nonempty_packets++;
|
||||
}
|
||||
num_packets++;
|
||||
|
||||
if ((payload[i] & 0x80) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* this is impossible */
|
||||
if (num_packets == payload_len)
|
||||
goto bad_packet;
|
||||
|
||||
if (rtpamrdec->crc) {
|
||||
/* data len + CRC len + header bytes should be smaller than payload_len */
|
||||
if (num_packets + num_nonempty_packets + amr_len > payload_len)
|
||||
goto bad_packet;
|
||||
} else {
|
||||
/* data len + header bytes should be smaller than payload_len */
|
||||
if (num_packets + amr_len > payload_len)
|
||||
goto bad_packet;
|
||||
}
|
||||
|
||||
timestamp = gst_rtpbuffer_get_timestamp (buf);
|
||||
|
||||
outbuf = gst_buffer_new_and_alloc (payload_len);
|
||||
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdec->rate;
|
||||
|
||||
memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
|
||||
/* point to destination */
|
||||
p = GST_BUFFER_DATA (outbuf);
|
||||
/* point to first data packet */
|
||||
dp = payload + num_packets;
|
||||
if (rtpamrdec->crc) {
|
||||
/* skip CRC if present */
|
||||
dp += num_nonempty_packets;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_packets; i++) {
|
||||
gint fr_size;
|
||||
|
||||
fr_size = frame_size[(payload[i] & 0x78) >> 3];
|
||||
if (fr_size > 0) {
|
||||
/* copy FT */
|
||||
*p++ = payload[i];
|
||||
/* copy data packet, FIXME, calc CRC here. */
|
||||
memcpy (p, dp, fr_size);
|
||||
|
||||
p += fr_size;
|
||||
dp += fr_size;
|
||||
}
|
||||
}
|
||||
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpamrdec->srcpad));
|
||||
|
||||
GST_DEBUG ("gst_rtpamrdec_chain: pushing buffer of size %d",
|
||||
GST_BUFFER_SIZE (outbuf));
|
||||
ret = gst_pad_push (rtpamrdec->srcpad, outbuf);
|
||||
|
||||
skip:
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
|
@ -334,21 +406,17 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
not_negotiated:
|
||||
{
|
||||
GST_DEBUG ("not_negotiated");
|
||||
GST_ELEMENT_ERROR (rtpamrdec, STREAM, NOT_IMPLEMENTED,
|
||||
("not negotiated"), (NULL));
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
bad_packet:
|
||||
{
|
||||
GST_DEBUG ("Packet did not validate");
|
||||
GST_ELEMENT_WARNING (rtpamrdec, STREAM, DECODE,
|
||||
("amr packet did not validate"), (NULL));
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
one_packet_only:
|
||||
{
|
||||
GST_DEBUG ("One packet per RTP packet only");
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_ERROR;
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
"clock-rate = (int) 8000, "
|
||||
"encoding-name = (string) \"AMR\", "
|
||||
"encoding-params = (string) \"1\", "
|
||||
"octet-align = (string) 1, "
|
||||
"crc = (string) 0, "
|
||||
"robust-sorting = (string) 0, " "interleaving = (string) 0"
|
||||
"octet-align = (string) \"1\", "
|
||||
"crc = (string) { \"0\", \"1\" }, "
|
||||
"robust-sorting = (string) \"0\", " "interleaving = (string) \"0\""
|
||||
/* following options are not needed for a decoder
|
||||
*
|
||||
"mode-set = (int) [ 0, 7 ], "
|
||||
|
@ -238,8 +238,6 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
return FALSE;
|
||||
if (rtpamrdec->octet_align != TRUE)
|
||||
return FALSE;
|
||||
if (rtpamrdec->crc != FALSE)
|
||||
return FALSE;
|
||||
if (rtpamrdec->robust_sorting != FALSE)
|
||||
return FALSE;
|
||||
if (rtpamrdec->interleaving != FALSE)
|
||||
|
@ -256,6 +254,12 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* -1 is invalid */
|
||||
static gint frame_size[16] = {
|
||||
12, 13, 15, 17, 19, 20, 26, 31,
|
||||
5, -1, -1, -1, -1, -1, -1, 0
|
||||
};
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
||||
{
|
||||
|
@ -275,9 +279,12 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
|||
* no robust sorting, no interleaving data is to be parsed */
|
||||
{
|
||||
gint payload_len;
|
||||
guint8 *payload;
|
||||
guint8 *payload, *p, *dp;
|
||||
guint32 timestamp;
|
||||
guint8 CMR, F, FT, Q;
|
||||
guint8 CMR;
|
||||
gint i, num_packets, num_nonempty_packets;
|
||||
gint amr_len;
|
||||
gint ILL, ILP;
|
||||
|
||||
payload_len = gst_rtpbuffer_get_payload_len (buf);
|
||||
|
||||
|
@ -287,46 +294,111 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
payload = gst_rtpbuffer_get_payload (buf);
|
||||
|
||||
/* parse header
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
|
||||
* | CMR |R|R|R|R|F| FT |Q|P|P|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
|
||||
/* parse CMR. The CMR is used by the sender to request
|
||||
* a new encoding mode.
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* | CMR |R|R|R|R|
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
CMR = (payload[0] & 0xf0) >> 4;
|
||||
F = (payload[1] & 0x80) >> 7;
|
||||
/* we only support 1 packet per RTP packet for now */
|
||||
if (F != 0)
|
||||
goto one_packet_only;
|
||||
|
||||
FT = (payload[1] & 0x78) >> 3;
|
||||
Q = (payload[1] & 0x04) >> 2;
|
||||
|
||||
/* skip packet */
|
||||
if (FT > 9 && FT < 15) {
|
||||
ret = GST_FLOW_OK;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* strip header now, leave FT in the data for the decoder */
|
||||
/* strip CMR header now, pack FT and the data for the decoder */
|
||||
payload_len -= 1;
|
||||
payload += 1;
|
||||
|
||||
if (rtpamrdec->interleaving) {
|
||||
ILL = (payload[0] & 0xf0) >> 4;
|
||||
ILP = (payload[0] & 0x0f);
|
||||
|
||||
payload_len -= 1;
|
||||
payload += 1;
|
||||
|
||||
if (ILP > ILL)
|
||||
goto bad_packet;
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
|
||||
* +-+-+-+-+-+-+-+-+..
|
||||
* |F| FT |Q|P|P| more FT..
|
||||
* +-+-+-+-+-+-+-+-+..
|
||||
*/
|
||||
/* count number of packets by counting the FTs. Also
|
||||
* count number of amr data bytes and number of non-empty
|
||||
* packets (this is also the number of CRCs if present). */
|
||||
amr_len = 0;
|
||||
num_nonempty_packets = 0;
|
||||
num_packets = 0;
|
||||
for (i = 0; i < payload_len; i++) {
|
||||
gint fr_size;
|
||||
guint8 FT;
|
||||
|
||||
FT = (payload[i] & 0x78) >> 3;
|
||||
|
||||
fr_size = frame_size[FT];
|
||||
if (fr_size == -1)
|
||||
goto bad_packet;
|
||||
|
||||
if (fr_size > 0) {
|
||||
amr_len += fr_size;
|
||||
num_nonempty_packets++;
|
||||
}
|
||||
num_packets++;
|
||||
|
||||
if ((payload[i] & 0x80) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* this is impossible */
|
||||
if (num_packets == payload_len)
|
||||
goto bad_packet;
|
||||
|
||||
if (rtpamrdec->crc) {
|
||||
/* data len + CRC len + header bytes should be smaller than payload_len */
|
||||
if (num_packets + num_nonempty_packets + amr_len > payload_len)
|
||||
goto bad_packet;
|
||||
} else {
|
||||
/* data len + header bytes should be smaller than payload_len */
|
||||
if (num_packets + amr_len > payload_len)
|
||||
goto bad_packet;
|
||||
}
|
||||
|
||||
timestamp = gst_rtpbuffer_get_timestamp (buf);
|
||||
|
||||
outbuf = gst_buffer_new_and_alloc (payload_len);
|
||||
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdec->rate;
|
||||
|
||||
memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
|
||||
/* point to destination */
|
||||
p = GST_BUFFER_DATA (outbuf);
|
||||
/* point to first data packet */
|
||||
dp = payload + num_packets;
|
||||
if (rtpamrdec->crc) {
|
||||
/* skip CRC if present */
|
||||
dp += num_nonempty_packets;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_packets; i++) {
|
||||
gint fr_size;
|
||||
|
||||
fr_size = frame_size[(payload[i] & 0x78) >> 3];
|
||||
if (fr_size > 0) {
|
||||
/* copy FT */
|
||||
*p++ = payload[i];
|
||||
/* copy data packet, FIXME, calc CRC here. */
|
||||
memcpy (p, dp, fr_size);
|
||||
|
||||
p += fr_size;
|
||||
dp += fr_size;
|
||||
}
|
||||
}
|
||||
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpamrdec->srcpad));
|
||||
|
||||
GST_DEBUG ("gst_rtpamrdec_chain: pushing buffer of size %d",
|
||||
GST_BUFFER_SIZE (outbuf));
|
||||
ret = gst_pad_push (rtpamrdec->srcpad, outbuf);
|
||||
|
||||
skip:
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
|
@ -334,21 +406,17 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
not_negotiated:
|
||||
{
|
||||
GST_DEBUG ("not_negotiated");
|
||||
GST_ELEMENT_ERROR (rtpamrdec, STREAM, NOT_IMPLEMENTED,
|
||||
("not negotiated"), (NULL));
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
bad_packet:
|
||||
{
|
||||
GST_DEBUG ("Packet did not validate");
|
||||
GST_ELEMENT_WARNING (rtpamrdec, STREAM, DECODE,
|
||||
("amr packet did not validate"), (NULL));
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
one_packet_only:
|
||||
{
|
||||
GST_DEBUG ("One packet per RTP packet only");
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_ERROR;
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,13 +54,13 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
|||
"clock-rate = (int) 8000, "
|
||||
"encoding-name = (string) \"AMR\", "
|
||||
"encoding-params = (string) \"1\", "
|
||||
"octet-align = (boolean) TRUE, "
|
||||
"crc = (boolean) FALSE, "
|
||||
"robust-sorting = (boolean) FALSE, "
|
||||
"interleaving = (boolean) FALSE, "
|
||||
"octet-align = (string) \"1\", "
|
||||
"crc = (string) \"0\", "
|
||||
"robust-sorting = (string) \"0\", "
|
||||
"interleaving = (string) \"0\", "
|
||||
"mode-set = (int) [ 0, 7 ], "
|
||||
"mode-change-period = (int) [ 1, MAX ], "
|
||||
"mode-change-neighbor = (boolean) { TRUE, FALSE }, "
|
||||
"mode-change-neighbor = (string) { \"0\", \"1\" }, "
|
||||
"maxptime = (int) [ 20, MAX ], " "ptime = (int) [ 20, MAX ]")
|
||||
);
|
||||
|
||||
|
@ -144,11 +144,14 @@ gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
|||
|
||||
gst_basertppayload_set_options (basepayload, "audio", TRUE, "AMR", 8000);
|
||||
gst_basertppayload_set_outcaps (basepayload,
|
||||
"encoding-params", G_TYPE_STRING, "1",
|
||||
"octet-align", G_TYPE_BOOLEAN, TRUE,
|
||||
"crc", G_TYPE_BOOLEAN, FALSE,
|
||||
"robust-sorting", G_TYPE_BOOLEAN, FALSE,
|
||||
"interleaving", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
"encoding-params", G_TYPE_STRING, "1", "octet-align", G_TYPE_STRING, "1",
|
||||
/* don't set the defaults
|
||||
*
|
||||
* "crc", G_TYPE_STRING, "0",
|
||||
* "robust-sorting", G_TYPE_STRING, "0",
|
||||
* "interleaving", G_TYPE_STRING, "0",
|
||||
*/
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -54,13 +54,13 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
|||
"clock-rate = (int) 8000, "
|
||||
"encoding-name = (string) \"AMR\", "
|
||||
"encoding-params = (string) \"1\", "
|
||||
"octet-align = (boolean) TRUE, "
|
||||
"crc = (boolean) FALSE, "
|
||||
"robust-sorting = (boolean) FALSE, "
|
||||
"interleaving = (boolean) FALSE, "
|
||||
"octet-align = (string) \"1\", "
|
||||
"crc = (string) \"0\", "
|
||||
"robust-sorting = (string) \"0\", "
|
||||
"interleaving = (string) \"0\", "
|
||||
"mode-set = (int) [ 0, 7 ], "
|
||||
"mode-change-period = (int) [ 1, MAX ], "
|
||||
"mode-change-neighbor = (boolean) { TRUE, FALSE }, "
|
||||
"mode-change-neighbor = (string) { \"0\", \"1\" }, "
|
||||
"maxptime = (int) [ 20, MAX ], " "ptime = (int) [ 20, MAX ]")
|
||||
);
|
||||
|
||||
|
@ -144,11 +144,14 @@ gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
|||
|
||||
gst_basertppayload_set_options (basepayload, "audio", TRUE, "AMR", 8000);
|
||||
gst_basertppayload_set_outcaps (basepayload,
|
||||
"encoding-params", G_TYPE_STRING, "1",
|
||||
"octet-align", G_TYPE_BOOLEAN, TRUE,
|
||||
"crc", G_TYPE_BOOLEAN, FALSE,
|
||||
"robust-sorting", G_TYPE_BOOLEAN, FALSE,
|
||||
"interleaving", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
"encoding-params", G_TYPE_STRING, "1", "octet-align", G_TYPE_STRING, "1",
|
||||
/* don't set the defaults
|
||||
*
|
||||
* "crc", G_TYPE_STRING, "0",
|
||||
* "robust-sorting", G_TYPE_STRING, "0",
|
||||
* "interleaving", G_TYPE_STRING, "0",
|
||||
*/
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ GST_STATIC_PAD_TEMPLATE ("sinkrtcp",
|
|||
static void gst_rtpdec_class_init (gpointer g_class);
|
||||
static void gst_rtpdec_init (GstRTPDec * rtpdec);
|
||||
|
||||
static GstCaps *gst_rtpdec_getcaps (GstPad * pad);
|
||||
static GstFlowReturn gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer);
|
||||
static GstFlowReturn gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer);
|
||||
|
||||
|
@ -153,6 +154,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
|||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&gst_rtpdec_sink_rtp_template), "sinkrtp");
|
||||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtp);
|
||||
gst_pad_set_getcaps_function (rtpdec->sink_rtp, gst_rtpdec_getcaps);
|
||||
gst_pad_set_chain_function (rtpdec->sink_rtp, gst_rtpdec_chain_rtp);
|
||||
|
||||
/* the input rtcp pad */
|
||||
|
@ -166,6 +168,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
|||
rtpdec->src_rtp =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&gst_rtpdec_src_rtp_template), "srcrtp");
|
||||
gst_pad_set_getcaps_function (rtpdec->src_rtp, gst_rtpdec_getcaps);
|
||||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtp);
|
||||
|
||||
/* the output rtcp pad */
|
||||
|
@ -175,6 +178,19 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
|||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtcp);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_rtpdec_getcaps (GstPad * pad)
|
||||
{
|
||||
GstRTPDec *src;
|
||||
GstPad *other;
|
||||
|
||||
src = GST_RTPDEC (GST_PAD_PARENT (pad));
|
||||
|
||||
other = pad == src->src_rtp ? src->sink_rtp : src->src_rtp;
|
||||
|
||||
return gst_pad_peer_get_caps (other);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,7 @@ GST_STATIC_PAD_TEMPLATE ("sinkrtcp",
|
|||
static void gst_rtpdec_class_init (gpointer g_class);
|
||||
static void gst_rtpdec_init (GstRTPDec * rtpdec);
|
||||
|
||||
static GstCaps *gst_rtpdec_getcaps (GstPad * pad);
|
||||
static GstFlowReturn gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer);
|
||||
static GstFlowReturn gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer);
|
||||
|
||||
|
@ -153,6 +154,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
|||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&gst_rtpdec_sink_rtp_template), "sinkrtp");
|
||||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtp);
|
||||
gst_pad_set_getcaps_function (rtpdec->sink_rtp, gst_rtpdec_getcaps);
|
||||
gst_pad_set_chain_function (rtpdec->sink_rtp, gst_rtpdec_chain_rtp);
|
||||
|
||||
/* the input rtcp pad */
|
||||
|
@ -166,6 +168,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
|||
rtpdec->src_rtp =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&gst_rtpdec_src_rtp_template), "srcrtp");
|
||||
gst_pad_set_getcaps_function (rtpdec->src_rtp, gst_rtpdec_getcaps);
|
||||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtp);
|
||||
|
||||
/* the output rtcp pad */
|
||||
|
@ -175,6 +178,19 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
|||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtcp);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_rtpdec_getcaps (GstPad * pad)
|
||||
{
|
||||
GstRTPDec *src;
|
||||
GstPad *other;
|
||||
|
||||
src = GST_RTPDEC (GST_PAD_PARENT (pad));
|
||||
|
||||
other = pad == src->src_rtp ? src->sink_rtp : src->src_rtp;
|
||||
|
||||
return gst_pad_peer_get_caps (other);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
|
|
|
@ -161,6 +161,7 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GstStructure *structure;
|
||||
GstRtpMP4VDec *rtpmp4vdec;
|
||||
GstCaps *srccaps;
|
||||
const gchar *str;
|
||||
|
||||
rtpmp4vdec = GST_RTP_MP4V_DEC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
|
@ -175,6 +176,29 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
|
|||
gst_pad_set_caps (rtpmp4vdec->srcpad, srccaps);
|
||||
gst_caps_unref (srccaps);
|
||||
|
||||
if ((str = gst_structure_get_string (structure, "config"))) {
|
||||
GValue v = { 0 };
|
||||
|
||||
g_print ("config=%s\n", str);
|
||||
|
||||
g_value_init (&v, GST_TYPE_BUFFER);
|
||||
if (gst_value_deserialize (&v, str)) {
|
||||
GstBuffer *buffer;
|
||||
|
||||
buffer = gst_value_get_buffer (&v);
|
||||
gst_buffer_ref (buffer);
|
||||
g_value_unset (&v);
|
||||
|
||||
g_print ("buf=%p\n", buffer);
|
||||
|
||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (rtpmp4vdec->srcpad));
|
||||
|
||||
gst_pad_push (rtpmp4vdec->srcpad, buffer);
|
||||
} else {
|
||||
g_warning ("cannot convert config to buffer");
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GstStructure *structure;
|
||||
GstRtpMP4VDec *rtpmp4vdec;
|
||||
GstCaps *srccaps;
|
||||
const gchar *str;
|
||||
|
||||
rtpmp4vdec = GST_RTP_MP4V_DEC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
|
@ -175,6 +176,29 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
|
|||
gst_pad_set_caps (rtpmp4vdec->srcpad, srccaps);
|
||||
gst_caps_unref (srccaps);
|
||||
|
||||
if ((str = gst_structure_get_string (structure, "config"))) {
|
||||
GValue v = { 0 };
|
||||
|
||||
g_print ("config=%s\n", str);
|
||||
|
||||
g_value_init (&v, GST_TYPE_BUFFER);
|
||||
if (gst_value_deserialize (&v, str)) {
|
||||
GstBuffer *buffer;
|
||||
|
||||
buffer = gst_value_get_buffer (&v);
|
||||
gst_buffer_ref (buffer);
|
||||
g_value_unset (&v);
|
||||
|
||||
g_print ("buf=%p\n", buffer);
|
||||
|
||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (rtpmp4vdec->srcpad));
|
||||
|
||||
gst_pad_push (rtpmp4vdec->srcpad, buffer);
|
||||
} else {
|
||||
g_warning ("cannot convert config to buffer");
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,11 +45,11 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
|||
GST_STATIC_CAPS ("application/x-rtp, "
|
||||
"media = (string) \"video\", "
|
||||
"payload = (int) [ 96, 255 ], "
|
||||
"clock-rate = (int) [1, MAX ], "
|
||||
"encoding-name = (string) \"MP4V-ES\", " "profile-level-id=[1,MAX]"
|
||||
/* All optional parameters
|
||||
"clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"MP4V-ES\""
|
||||
/* two string params
|
||||
*
|
||||
* "config="
|
||||
"profile-level-id = (string) [1,MAX]"
|
||||
"config = (string) [1,MAX]"
|
||||
*/
|
||||
)
|
||||
);
|
||||
|
@ -148,9 +148,22 @@ gst_rtpmp4venc_finalize (GObject * object)
|
|||
static void
|
||||
gst_rtpmp4venc_new_caps (GstRtpMP4VEnc * rtpmp4venc)
|
||||
{
|
||||
gchar *profile, *config;
|
||||
GValue v = { 0 };
|
||||
|
||||
profile = g_strdup_printf ("%d", rtpmp4venc->profile);
|
||||
g_value_init (&v, GST_TYPE_BUFFER);
|
||||
gst_value_set_buffer (&v, rtpmp4venc->config);
|
||||
config = gst_value_serialize (&v);
|
||||
|
||||
gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4venc),
|
||||
"profile-level-id", G_TYPE_INT, rtpmp4venc->profile,
|
||||
"config", GST_TYPE_BUFFER, rtpmp4venc->config, NULL);
|
||||
"profile-level-id", G_TYPE_STRING, profile,
|
||||
"config", G_TYPE_STRING, config, NULL);
|
||||
|
||||
g_value_unset (&v);
|
||||
|
||||
g_free (profile);
|
||||
g_free (config);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -45,11 +45,11 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
|||
GST_STATIC_CAPS ("application/x-rtp, "
|
||||
"media = (string) \"video\", "
|
||||
"payload = (int) [ 96, 255 ], "
|
||||
"clock-rate = (int) [1, MAX ], "
|
||||
"encoding-name = (string) \"MP4V-ES\", " "profile-level-id=[1,MAX]"
|
||||
/* All optional parameters
|
||||
"clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"MP4V-ES\""
|
||||
/* two string params
|
||||
*
|
||||
* "config="
|
||||
"profile-level-id = (string) [1,MAX]"
|
||||
"config = (string) [1,MAX]"
|
||||
*/
|
||||
)
|
||||
);
|
||||
|
@ -148,9 +148,22 @@ gst_rtpmp4venc_finalize (GObject * object)
|
|||
static void
|
||||
gst_rtpmp4venc_new_caps (GstRtpMP4VEnc * rtpmp4venc)
|
||||
{
|
||||
gchar *profile, *config;
|
||||
GValue v = { 0 };
|
||||
|
||||
profile = g_strdup_printf ("%d", rtpmp4venc->profile);
|
||||
g_value_init (&v, GST_TYPE_BUFFER);
|
||||
gst_value_set_buffer (&v, rtpmp4venc->config);
|
||||
config = gst_value_serialize (&v);
|
||||
|
||||
gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4venc),
|
||||
"profile-level-id", G_TYPE_INT, rtpmp4venc->profile,
|
||||
"config", GST_TYPE_BUFFER, rtpmp4venc->config, NULL);
|
||||
"profile-level-id", G_TYPE_STRING, profile,
|
||||
"config", G_TYPE_STRING, config, NULL);
|
||||
|
||||
g_value_unset (&v);
|
||||
|
||||
g_free (profile);
|
||||
g_free (config);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
Loading…
Reference in a new issue