mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
rtp: port to 0.11
This commit is contained in:
parent
b0fbb1725f
commit
9a54175e9f
6 changed files with 294 additions and 255 deletions
|
@ -109,8 +109,7 @@ gst_rtp_h263_depay_class_init (GstRtpH263DepayClass * klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h263_depay_init (GstRtpH263Depay * rtph263depay,
|
gst_rtp_h263_depay_init (GstRtpH263Depay * rtph263depay)
|
||||||
GstRtpH263DepayClass * klass)
|
|
||||||
{
|
{
|
||||||
rtph263depay->adapter = gst_adapter_new ();
|
rtph263depay->adapter = gst_adapter_new ();
|
||||||
|
|
||||||
|
@ -162,6 +161,7 @@ gst_rtp_h263_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
guint SBIT, EBIT;
|
guint SBIT, EBIT;
|
||||||
gboolean F, P, M;
|
gboolean F, P, M;
|
||||||
gboolean I;
|
gboolean I;
|
||||||
|
GstRTPBuffer rtp = { NULL };
|
||||||
|
|
||||||
rtph263depay = GST_RTP_H263_DEPAY (depayload);
|
rtph263depay = GST_RTP_H263_DEPAY (depayload);
|
||||||
|
|
||||||
|
@ -174,10 +174,12 @@ gst_rtp_h263_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
rtph263depay->start = FALSE;
|
rtph263depay->start = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
payload_len = gst_rtp_buffer_get_payload_len (buf);
|
gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
|
||||||
payload = gst_rtp_buffer_get_payload (buf);
|
|
||||||
|
|
||||||
M = gst_rtp_buffer_get_marker (buf);
|
payload_len = gst_rtp_buffer_get_payload_len (&rtp);
|
||||||
|
payload = gst_rtp_buffer_get_payload (&rtp);
|
||||||
|
|
||||||
|
M = gst_rtp_buffer_get_marker (&rtp);
|
||||||
|
|
||||||
/* Let's see what mode we are using */
|
/* Let's see what mode we are using */
|
||||||
F = (payload[0] & 0x80) == 0x80;
|
F = (payload[0] & 0x80) == 0x80;
|
||||||
|
@ -282,13 +284,13 @@ gst_rtp_h263_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
GstBuffer *tmp;
|
GstBuffer *tmp;
|
||||||
|
|
||||||
/* Take the entire buffer */
|
/* Take the entire buffer */
|
||||||
tmp = gst_rtp_buffer_get_payload_subbuffer (buf, header_len, payload_len);
|
tmp = gst_rtp_buffer_get_payload_subbuffer (&rtp, header_len, payload_len);
|
||||||
gst_adapter_push (rtph263depay->adapter, tmp);
|
gst_adapter_push (rtph263depay->adapter, tmp);
|
||||||
} else {
|
} else {
|
||||||
GstBuffer *tmp;
|
GstBuffer *tmp;
|
||||||
|
|
||||||
/* Take the entire buffer except for the last byte */
|
/* Take the entire buffer except for the last byte */
|
||||||
tmp = gst_rtp_buffer_get_payload_subbuffer (buf, header_len,
|
tmp = gst_rtp_buffer_get_payload_subbuffer (&rtp, header_len,
|
||||||
payload_len - 1);
|
payload_len - 1);
|
||||||
gst_adapter_push (rtph263depay->adapter, tmp);
|
gst_adapter_push (rtph263depay->adapter, tmp);
|
||||||
|
|
||||||
|
@ -312,7 +314,7 @@ skip:
|
||||||
GstBuffer *buf = gst_buffer_new_and_alloc (1);
|
GstBuffer *buf = gst_buffer_new_and_alloc (1);
|
||||||
|
|
||||||
GST_DEBUG ("Pushing leftover in adapter");
|
GST_DEBUG ("Pushing leftover in adapter");
|
||||||
GST_BUFFER_DATA (buf)[0] = rtph263depay->leftover;
|
gst_buffer_fill (buf, 0, &rtph263depay->leftover, 1);
|
||||||
gst_adapter_push (rtph263depay->adapter, buf);
|
gst_adapter_push (rtph263depay->adapter, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +326,7 @@ skip:
|
||||||
|
|
||||||
GST_DEBUG ("Pushing out a buffer of %d bytes", avail);
|
GST_DEBUG ("Pushing out a buffer of %d bytes", avail);
|
||||||
|
|
||||||
timestamp = gst_rtp_buffer_get_timestamp (buf);
|
timestamp = gst_rtp_buffer_get_timestamp (&rtp);
|
||||||
gst_base_rtp_depayload_push_ts (depayload, timestamp, outbuf);
|
gst_base_rtp_depayload_push_ts (depayload, timestamp, outbuf);
|
||||||
rtph263depay->offset = 0;
|
rtph263depay->offset = 0;
|
||||||
rtph263depay->leftover = 0;
|
rtph263depay->leftover = 0;
|
||||||
|
@ -333,6 +335,7 @@ skip:
|
||||||
rtph263depay->start = TRUE;
|
rtph263depay->start = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,32 +395,18 @@ static void gst_rtp_h263_pay_context_destroy (GstRtpH263PayContext * context,
|
||||||
guint ind);
|
guint ind);
|
||||||
static void gst_rtp_h263_pay_package_destroy (GstRtpH263PayPackage * pack);
|
static void gst_rtp_h263_pay_package_destroy (GstRtpH263PayPackage * pack);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstRtpH263Pay, gst_rtp_h263_pay, GstBaseRTPPayload,
|
#define gst_rtp_h263_pay_parent_class parent_class
|
||||||
GST_TYPE_BASE_RTP_PAYLOAD)
|
G_DEFINE_TYPE (GstRtpH263Pay, gst_rtp_h263_pay, GST_TYPE_BASE_RTP_PAYLOAD);
|
||||||
|
|
||||||
static void gst_rtp_h263_pay_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h263_pay_src_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h263_pay_sink_template));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
|
||||||
"RTP H263 packet payloader", "Codec/Payloader/Network/RTP",
|
|
||||||
"Payload-encodes H263 video in RTP packets (RFC 2190)",
|
|
||||||
"Neil Stratford <neils@vipadia.com>"
|
|
||||||
"Dejan Sakelsak <dejan.sakelsak@marand.si>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h263_pay_class_init (GstRtpH263PayClass * klass)
|
gst_rtp_h263_pay_class_init (GstRtpH263PayClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtp_h263_pay_finalize;
|
gobject_class->finalize = gst_rtp_h263_pay_finalize;
|
||||||
|
@ -436,12 +422,23 @@ gst_rtp_h263_pay_class_init (GstRtpH263PayClass * klass)
|
||||||
"Disable packetization modes B and C", DEFAULT_MODE_A,
|
"Disable packetization modes B and C", DEFAULT_MODE_A,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h263_pay_src_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h263_pay_sink_template));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"RTP H263 packet payloader", "Codec/Payloader/Network/RTP",
|
||||||
|
"Payload-encodes H263 video in RTP packets (RFC 2190)",
|
||||||
|
"Neil Stratford <neils@vipadia.com>"
|
||||||
|
"Dejan Sakelsak <dejan.sakelsak@marand.si>");
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (rtph263pay_debug, "rtph263pay", 0,
|
GST_DEBUG_CATEGORY_INIT (rtph263pay_debug, "rtph263pay", 0,
|
||||||
"H263 RTP Payloader");
|
"H263 RTP Payloader");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h263_pay_init (GstRtpH263Pay * rtph263pay, GstRtpH263PayClass * klass)
|
gst_rtp_h263_pay_init (GstRtpH263Pay * rtph263pay)
|
||||||
{
|
{
|
||||||
rtph263pay->adapter = gst_adapter_new ();
|
rtph263pay->adapter = gst_adapter_new ();
|
||||||
|
|
||||||
|
@ -1239,8 +1236,11 @@ gst_rtp_h263_pay_push (GstRtpH263Pay * rtph263pay,
|
||||||
guint8 *header;
|
guint8 *header;
|
||||||
guint8 *payload;
|
guint8 *payload;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
GstRTPBuffer rtp = { NULL };
|
||||||
|
|
||||||
header = gst_rtp_buffer_get_payload (package->outbuf);
|
gst_rtp_buffer_map (package->outbuf, GST_MAP_WRITE, &rtp);
|
||||||
|
|
||||||
|
header = gst_rtp_buffer_get_payload (&rtp);
|
||||||
payload = header + package->mode;
|
payload = header + package->mode;
|
||||||
|
|
||||||
switch (package->mode) {
|
switch (package->mode) {
|
||||||
|
@ -1271,10 +1271,12 @@ gst_rtp_h263_pay_push (GstRtpH263Pay * rtph263pay,
|
||||||
*/
|
*/
|
||||||
GST_BUFFER_TIMESTAMP (package->outbuf) = rtph263pay->first_ts;
|
GST_BUFFER_TIMESTAMP (package->outbuf) = rtph263pay->first_ts;
|
||||||
|
|
||||||
gst_rtp_buffer_set_marker (package->outbuf, package->marker);
|
gst_rtp_buffer_set_marker (&rtp, package->marker);
|
||||||
if (package->marker)
|
if (package->marker)
|
||||||
GST_DEBUG ("Marker set!");
|
GST_DEBUG ("Marker set!");
|
||||||
|
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtph263pay),
|
gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtph263pay),
|
||||||
package->outbuf);
|
package->outbuf);
|
||||||
|
@ -1610,7 +1612,7 @@ gst_rtp_h263_pay_flush (GstRtpH263Pay * rtph263pay)
|
||||||
|
|
||||||
/* Get a pointer to all the data for the frame */
|
/* Get a pointer to all the data for the frame */
|
||||||
rtph263pay->data =
|
rtph263pay->data =
|
||||||
(guint8 *) gst_adapter_peek (rtph263pay->adapter,
|
(guint8 *) gst_adapter_map (rtph263pay->adapter,
|
||||||
rtph263pay->available_data);
|
rtph263pay->available_data);
|
||||||
|
|
||||||
/* Picture header */
|
/* Picture header */
|
||||||
|
@ -1766,7 +1768,7 @@ gst_rtp_h263_pay_flush (GstRtpH263Pay * rtph263pay)
|
||||||
end:
|
end:
|
||||||
gst_rtp_h263_pay_context_destroy (context,
|
gst_rtp_h263_pay_context_destroy (context,
|
||||||
context->piclayer->ptype_srcformat);
|
context->piclayer->ptype_srcformat);
|
||||||
gst_adapter_flush (rtph263pay->adapter, rtph263pay->available_data);
|
gst_adapter_unmap (rtph263pay->adapter, rtph263pay->available_data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,12 @@ gst_rtp_h263p_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstRtpH263PDepay *rtph263pdepay;
|
GstRtpH263PDepay *rtph263pdepay;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
|
gint payload_len;
|
||||||
|
guint8 *payload;
|
||||||
|
gboolean P, V, M;
|
||||||
|
guint header_len;
|
||||||
|
guint8 PLEN, PEBIT;
|
||||||
|
GstRTPBuffer rtp = { NULL };
|
||||||
|
|
||||||
rtph263pdepay = GST_RTP_H263P_DEPAY (depayload);
|
rtph263pdepay = GST_RTP_H263P_DEPAY (depayload);
|
||||||
|
|
||||||
|
@ -240,103 +246,100 @@ gst_rtp_h263p_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
rtph263pdepay->wait_start = TRUE;
|
rtph263pdepay->wait_start = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
|
||||||
gint payload_len;
|
|
||||||
guint8 *payload;
|
|
||||||
gboolean P, V, M;
|
|
||||||
guint header_len;
|
|
||||||
guint8 PLEN, PEBIT;
|
|
||||||
|
|
||||||
payload_len = gst_rtp_buffer_get_payload_len (buf);
|
payload_len = gst_rtp_buffer_get_payload_len (&rtp);
|
||||||
payload = gst_rtp_buffer_get_payload (buf);
|
header_len = 2;
|
||||||
|
|
||||||
header_len = 2;
|
if (payload_len < header_len)
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
if (payload_len < header_len)
|
payload = gst_rtp_buffer_get_payload (&rtp);
|
||||||
goto too_small;
|
|
||||||
|
|
||||||
M = gst_rtp_buffer_get_marker (buf);
|
M = gst_rtp_buffer_get_marker (&rtp);
|
||||||
|
|
||||||
/* 0 1
|
/* 0 1
|
||||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | RR |P|V| PLEN |PEBIT|
|
* | RR |P|V| PLEN |PEBIT|
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
*/
|
*/
|
||||||
P = (payload[0] & 0x04) == 0x04;
|
P = (payload[0] & 0x04) == 0x04;
|
||||||
V = (payload[0] & 0x02) == 0x02;
|
V = (payload[0] & 0x02) == 0x02;
|
||||||
PLEN = ((payload[0] & 0x1) << 5) | (payload[1] >> 3);
|
PLEN = ((payload[0] & 0x1) << 5) | (payload[1] >> 3);
|
||||||
PEBIT = payload[1] & 0x7;
|
PEBIT = payload[1] & 0x7;
|
||||||
|
|
||||||
GST_LOG_OBJECT (depayload, "P %d, V %d, PLEN %d, PEBIT %d", P, V, PLEN,
|
GST_LOG_OBJECT (depayload, "P %d, V %d, PLEN %d, PEBIT %d", P, V, PLEN,
|
||||||
PEBIT);
|
PEBIT);
|
||||||
|
|
||||||
if (V) {
|
if (V) {
|
||||||
header_len++;
|
header_len++;
|
||||||
}
|
}
|
||||||
if (PLEN) {
|
if (PLEN) {
|
||||||
header_len += PLEN;
|
header_len += PLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!P && payload_len < header_len) || (P && payload_len < header_len - 2))
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
|
if (P) {
|
||||||
|
/* FIXME, have to make the packet writable hear. Better to reset these
|
||||||
|
* bytes when we copy the packet below */
|
||||||
|
rtph263pdepay->wait_start = FALSE;
|
||||||
|
header_len -= 2;
|
||||||
|
payload[header_len] = 0;
|
||||||
|
payload[header_len + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtph263pdepay->wait_start)
|
||||||
|
goto waiting_start;
|
||||||
|
|
||||||
|
if (payload_len < header_len)
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
|
/* FIXME do not ignore the VRC header (See RFC 2429 section 4.2) */
|
||||||
|
/* FIXME actually use the RTP picture header when it is lost in the network */
|
||||||
|
/* for now strip off header */
|
||||||
|
payload += header_len;
|
||||||
|
payload_len -= header_len;
|
||||||
|
|
||||||
|
if (M) {
|
||||||
|
/* frame is completed: append to previous, push it out */
|
||||||
|
guint len, padlen;
|
||||||
|
guint avail;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (depayload, "Frame complete");
|
||||||
|
|
||||||
|
avail = gst_adapter_available (rtph263pdepay->adapter);
|
||||||
|
len = avail + payload_len;
|
||||||
|
padlen = (len % 4) + 4;
|
||||||
|
|
||||||
|
outbuf = gst_buffer_new_and_alloc (len + padlen);
|
||||||
|
|
||||||
|
data = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
|
||||||
|
memset (data + len, 0, padlen);
|
||||||
|
|
||||||
|
/* prepend previous data */
|
||||||
|
if (avail > 0) {
|
||||||
|
gst_adapter_copy (rtph263pdepay->adapter, data, 0, avail);
|
||||||
|
gst_adapter_flush (rtph263pdepay->adapter, avail);
|
||||||
}
|
}
|
||||||
|
memcpy (data + avail, payload, payload_len);
|
||||||
|
gst_buffer_unmap (outbuf, data, len);
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
if ((!P && payload_len < header_len) || (P && payload_len < header_len - 2))
|
return outbuf;
|
||||||
goto too_small;
|
|
||||||
|
|
||||||
if (P) {
|
} else {
|
||||||
/* FIXME, have to make the packet writable hear. Better to reset these
|
/* frame not completed: store in adapter */
|
||||||
* bytes when we copy the packet below */
|
outbuf = gst_buffer_new_and_alloc (payload_len);
|
||||||
rtph263pdepay->wait_start = FALSE;
|
|
||||||
header_len -= 2;
|
|
||||||
payload[header_len] = 0;
|
|
||||||
payload[header_len + 1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rtph263pdepay->wait_start)
|
GST_LOG_OBJECT (depayload, "Frame incomplete, storing %d", payload_len);
|
||||||
goto waiting_start;
|
gst_buffer_fill (outbuf, 0, payload, payload_len);
|
||||||
|
|
||||||
if (payload_len < header_len)
|
gst_adapter_push (rtph263pdepay->adapter, outbuf);
|
||||||
goto too_small;
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
/* FIXME do not ignore the VRC header (See RFC 2429 section 4.2) */
|
|
||||||
/* FIXME actually use the RTP picture header when it is lost in the network */
|
|
||||||
/* for now strip off header */
|
|
||||||
payload += header_len;
|
|
||||||
payload_len -= header_len;
|
|
||||||
|
|
||||||
if (M) {
|
|
||||||
/* frame is completed: append to previous, push it out */
|
|
||||||
guint len, padlen;
|
|
||||||
guint avail;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (depayload, "Frame complete");
|
|
||||||
|
|
||||||
avail = gst_adapter_available (rtph263pdepay->adapter);
|
|
||||||
|
|
||||||
len = avail + payload_len;
|
|
||||||
padlen = (len % 4) + 4;
|
|
||||||
outbuf = gst_buffer_new_and_alloc (len + padlen);
|
|
||||||
memset (GST_BUFFER_DATA (outbuf) + len, 0, padlen);
|
|
||||||
GST_BUFFER_SIZE (outbuf) = len;
|
|
||||||
|
|
||||||
/* prepend previous data */
|
|
||||||
if (avail > 0) {
|
|
||||||
gst_adapter_copy (rtph263pdepay->adapter, GST_BUFFER_DATA (outbuf), 0,
|
|
||||||
avail);
|
|
||||||
gst_adapter_flush (rtph263pdepay->adapter, avail);
|
|
||||||
}
|
|
||||||
memcpy (GST_BUFFER_DATA (outbuf) + avail, payload, payload_len);
|
|
||||||
|
|
||||||
return outbuf;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* frame not completed: store in adapter */
|
|
||||||
outbuf = gst_buffer_new_and_alloc (payload_len);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (depayload, "Frame incomplete, storing %d", payload_len);
|
|
||||||
|
|
||||||
memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
|
|
||||||
|
|
||||||
gst_adapter_push (rtph263pdepay->adapter, outbuf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -344,11 +347,13 @@ too_small:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (rtph263pdepay, STREAM, DECODE,
|
GST_ELEMENT_WARNING (rtph263pdepay, STREAM, DECODE,
|
||||||
("Packet payload was too small"), (NULL));
|
("Packet payload was too small"), (NULL));
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
waiting_start:
|
waiting_start:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (rtph263pdepay, "waiting for picture start");
|
GST_DEBUG_OBJECT (rtph263pdepay, "waiting for picture start");
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,32 +90,18 @@ static gboolean gst_rtp_h263p_pay_setcaps (GstBaseRTPPayload * payload,
|
||||||
static GstFlowReturn gst_rtp_h263p_pay_handle_buffer (GstBaseRTPPayload *
|
static GstFlowReturn gst_rtp_h263p_pay_handle_buffer (GstBaseRTPPayload *
|
||||||
payload, GstBuffer * buffer);
|
payload, GstBuffer * buffer);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstRtpH263PPay, gst_rtp_h263p_pay, GstBaseRTPPayload,
|
#define gst_rtp_h263p_pay_parent_class parent_class
|
||||||
GST_TYPE_BASE_RTP_PAYLOAD);
|
G_DEFINE_TYPE (GstRtpH263PPay, gst_rtp_h263p_pay, GST_TYPE_BASE_RTP_PAYLOAD);
|
||||||
|
|
||||||
static void
|
|
||||||
gst_rtp_h263p_pay_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h263p_pay_src_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h263p_pay_sink_template));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class, "RTP H263 payloader",
|
|
||||||
"Codec/Payloader/Network/RTP",
|
|
||||||
"Payload-encodes H263/+/++ video in RTP packets (RFC 4629)",
|
|
||||||
"Wim Taymans <wim.taymans@gmail.com>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h263p_pay_class_init (GstRtpH263PPayClass * klass)
|
gst_rtp_h263p_pay_class_init (GstRtpH263PPayClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtp_h263p_pay_finalize;
|
gobject_class->finalize = gst_rtp_h263p_pay_finalize;
|
||||||
|
@ -132,13 +118,22 @@ gst_rtp_h263p_pay_class_init (GstRtpH263PPayClass * klass)
|
||||||
DEFAULT_FRAGMENTATION_MODE,
|
DEFAULT_FRAGMENTATION_MODE,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h263p_pay_src_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h263p_pay_sink_template));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class, "RTP H263 payloader",
|
||||||
|
"Codec/Payloader/Network/RTP",
|
||||||
|
"Payload-encodes H263/+/++ video in RTP packets (RFC 4629)",
|
||||||
|
"Wim Taymans <wim.taymans@gmail.com>");
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (rtph263ppay_debug, "rtph263ppay",
|
GST_DEBUG_CATEGORY_INIT (rtph263ppay_debug, "rtph263ppay",
|
||||||
0, "rtph263ppay (RFC 4629)");
|
0, "rtph263ppay (RFC 4629)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h263p_pay_init (GstRtpH263PPay * rtph263ppay,
|
gst_rtp_h263p_pay_init (GstRtpH263PPay * rtph263ppay)
|
||||||
GstRtpH263PPayClass * klass)
|
|
||||||
{
|
{
|
||||||
rtph263ppay->adapter = gst_adapter_new ();
|
rtph263ppay->adapter = gst_adapter_new ();
|
||||||
|
|
||||||
|
@ -236,13 +231,14 @@ gst_rtp_h263p_pay_flush (GstRtpH263PPay * rtph263ppay)
|
||||||
gint header_len;
|
gint header_len;
|
||||||
guint next_gop = 0;
|
guint next_gop = 0;
|
||||||
gboolean found_gob = FALSE;
|
gboolean found_gob = FALSE;
|
||||||
|
GstRTPBuffer rtp = { NULL };
|
||||||
|
|
||||||
if (rtph263ppay->fragmentation_mode == GST_FRAGMENTATION_MODE_SYNC) {
|
if (rtph263ppay->fragmentation_mode == GST_FRAGMENTATION_MODE_SYNC) {
|
||||||
/* start after 1st gop possible */
|
/* start after 1st gop possible */
|
||||||
guint parsed_len = 3;
|
guint parsed_len = 3;
|
||||||
const guint8 *parse_data = NULL;
|
const guint8 *parse_data = NULL;
|
||||||
|
|
||||||
parse_data = gst_adapter_peek (rtph263ppay->adapter, avail);
|
parse_data = gst_adapter_map (rtph263ppay->adapter, avail);
|
||||||
|
|
||||||
/* Check if we have a gob or eos , eossbs */
|
/* Check if we have a gob or eos , eossbs */
|
||||||
/* FIXME EOS and EOSSBS packets should never contain any gobs and vice-versa */
|
/* FIXME EOS and EOSSBS packets should never contain any gobs and vice-versa */
|
||||||
|
@ -264,6 +260,7 @@ gst_rtp_h263p_pay_flush (GstRtpH263PPay * rtph263ppay)
|
||||||
}
|
}
|
||||||
parsed_len++;
|
parsed_len++;
|
||||||
}
|
}
|
||||||
|
gst_adapter_unmap (rtph263ppay->adapter, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for picture start frames (non-fragmented), we need to remove the first
|
/* for picture start frames (non-fragmented), we need to remove the first
|
||||||
|
@ -279,10 +276,12 @@ gst_rtp_h263p_pay_flush (GstRtpH263PPay * rtph263ppay)
|
||||||
payload_len = header_len + towrite;
|
payload_len = header_len + towrite;
|
||||||
|
|
||||||
outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
|
outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
|
||||||
/* last fragment gets the marker bit set */
|
|
||||||
gst_rtp_buffer_set_marker (outbuf, avail > towrite ? 0 : 1);
|
|
||||||
|
|
||||||
payload = gst_rtp_buffer_get_payload (outbuf);
|
gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
|
||||||
|
/* last fragment gets the marker bit set */
|
||||||
|
gst_rtp_buffer_set_marker (&rtp, avail > towrite ? 0 : 1);
|
||||||
|
|
||||||
|
payload = gst_rtp_buffer_get_payload (&rtp);
|
||||||
|
|
||||||
gst_adapter_copy (rtph263ppay->adapter, &payload[header_len], 0, towrite);
|
gst_adapter_copy (rtph263ppay->adapter, &payload[header_len], 0, towrite);
|
||||||
|
|
||||||
|
@ -298,6 +297,7 @@ gst_rtp_h263p_pay_flush (GstRtpH263PPay * rtph263ppay)
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = rtph263ppay->first_timestamp;
|
GST_BUFFER_TIMESTAMP (outbuf) = rtph263ppay->first_timestamp;
|
||||||
GST_BUFFER_DURATION (outbuf) = rtph263ppay->first_duration;
|
GST_BUFFER_DURATION (outbuf) = rtph263ppay->first_duration;
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
gst_adapter_flush (rtph263ppay->adapter, towrite);
|
gst_adapter_flush (rtph263ppay->adapter, towrite);
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
/* "max-rcmd-nalu-size = (string) ANY " */
|
/* "max-rcmd-nalu-size = (string) ANY " */
|
||||||
);
|
);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstRtpH264Depay, gst_rtp_h264_depay, GstBaseRTPDepayload,
|
#define gst_rtp_h264_depay_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstRtpH264Depay, gst_rtp_h264_depay,
|
||||||
GST_TYPE_BASE_RTP_DEPAYLOAD);
|
GST_TYPE_BASE_RTP_DEPAYLOAD);
|
||||||
|
|
||||||
static void gst_rtp_h264_depay_finalize (GObject * object);
|
static void gst_rtp_h264_depay_finalize (GObject * object);
|
||||||
|
@ -96,22 +97,6 @@ static GstBuffer *gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload,
|
||||||
static gboolean gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * filter,
|
static gboolean gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * filter,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
|
|
||||||
static void
|
|
||||||
gst_rtp_h264_depay_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h264_depay_src_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h264_depay_sink_template));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class, "RTP H264 depayloader",
|
|
||||||
"Codec/Depayloader/Network/RTP",
|
|
||||||
"Extracts H264 video from RTP packets (RFC 3984)",
|
|
||||||
"Wim Taymans <wim.taymans@gmail.com>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
|
gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -137,6 +122,15 @@ gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
|
||||||
"Merge NALU into AU (picture) (deprecated; use caps)",
|
"Merge NALU into AU (picture) (deprecated; use caps)",
|
||||||
DEFAULT_ACCESS_UNIT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
DEFAULT_ACCESS_UNIT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h264_depay_src_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h264_depay_sink_template));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"RTP H264 depayloader", "Codec/Depayloader/Network/RTP",
|
||||||
|
"Extracts H264 video from RTP packets (RFC 3984)",
|
||||||
|
"Wim Taymans <wim.taymans@gmail.com>");
|
||||||
gstelement_class->change_state = gst_rtp_h264_depay_change_state;
|
gstelement_class->change_state = gst_rtp_h264_depay_change_state;
|
||||||
|
|
||||||
gstbasertpdepayload_class->process = gst_rtp_h264_depay_process;
|
gstbasertpdepayload_class->process = gst_rtp_h264_depay_process;
|
||||||
|
@ -147,8 +141,7 @@ gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h264_depay_init (GstRtpH264Depay * rtph264depay,
|
gst_rtp_h264_depay_init (GstRtpH264Depay * rtph264depay)
|
||||||
GstRtpH264DepayClass * klass)
|
|
||||||
{
|
{
|
||||||
rtph264depay->adapter = gst_adapter_new ();
|
rtph264depay->adapter = gst_adapter_new ();
|
||||||
rtph264depay->picture_adapter = gst_adapter_new ();
|
rtph264depay->picture_adapter = gst_adapter_new ();
|
||||||
|
@ -282,7 +275,7 @@ gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
GstRtpH264Depay *rtph264depay;
|
GstRtpH264Depay *rtph264depay;
|
||||||
const gchar *ps, *profile;
|
const gchar *ps, *profile;
|
||||||
GstBuffer *codec_data;
|
GstBuffer *codec_data;
|
||||||
guint8 *b64;
|
guint8 *ptr, *data;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
|
||||||
rtph264depay = GST_RTP_H264_DEPAY (depayload);
|
rtph264depay = GST_RTP_H264_DEPAY (depayload);
|
||||||
|
@ -319,23 +312,25 @@ gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
}
|
}
|
||||||
/* we seriously overshoot the length, but it's fine. */
|
/* we seriously overshoot the length, but it's fine. */
|
||||||
codec_data = gst_buffer_new_and_alloc (len);
|
codec_data = gst_buffer_new_and_alloc (len);
|
||||||
b64 = GST_BUFFER_DATA (codec_data);
|
|
||||||
|
data = gst_buffer_map (codec_data, NULL, NULL, GST_MAP_WRITE);
|
||||||
|
ptr = data;
|
||||||
total = 0;
|
total = 0;
|
||||||
for (i = 0; params[i]; i++) {
|
for (i = 0; params[i]; i++) {
|
||||||
guint save = 0;
|
guint save = 0;
|
||||||
gint state = 0;
|
gint state = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (depayload, "decoding param %d (%s)", i, params[i]);
|
GST_DEBUG_OBJECT (depayload, "decoding param %d (%s)", i, params[i]);
|
||||||
memcpy (b64, sync_bytes, sizeof (sync_bytes));
|
memcpy (ptr, sync_bytes, sizeof (sync_bytes));
|
||||||
b64 += sizeof (sync_bytes);
|
ptr += sizeof (sync_bytes);
|
||||||
len =
|
len =
|
||||||
g_base64_decode_step (params[i], strlen (params[i]), b64, &state,
|
g_base64_decode_step (params[i], strlen (params[i]), ptr, &state,
|
||||||
&save);
|
&save);
|
||||||
GST_DEBUG_OBJECT (depayload, "decoded %d bytes", len);
|
GST_DEBUG_OBJECT (depayload, "decoded %d bytes", len);
|
||||||
total += len + sizeof (sync_bytes);
|
total += len + sizeof (sync_bytes);
|
||||||
b64 += len;
|
ptr += len;
|
||||||
}
|
}
|
||||||
GST_BUFFER_SIZE (codec_data) = total;
|
gst_buffer_unmap (codec_data, data, total);
|
||||||
g_strfreev (params);
|
g_strfreev (params);
|
||||||
|
|
||||||
/* keep the codec_data, we need to send it as the first buffer. We cannot
|
/* keep the codec_data, we need to send it as the first buffer. We cannot
|
||||||
|
@ -349,7 +344,6 @@ gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
guint8 **sps, **pps;
|
guint8 **sps, **pps;
|
||||||
guint len, num_sps, num_pps;
|
guint len, num_sps, num_pps;
|
||||||
gint i;
|
gint i;
|
||||||
guint8 *data;
|
|
||||||
|
|
||||||
if (ps == NULL)
|
if (ps == NULL)
|
||||||
goto incomplete_caps;
|
goto incomplete_caps;
|
||||||
|
@ -398,50 +392,51 @@ gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
}
|
}
|
||||||
|
|
||||||
codec_data = gst_buffer_new_and_alloc (len);
|
codec_data = gst_buffer_new_and_alloc (len);
|
||||||
data = GST_BUFFER_DATA (codec_data);
|
|
||||||
|
data = ptr = gst_buffer_map (codec_data, NULL, NULL, GST_MAP_WRITE);
|
||||||
|
|
||||||
/* 8 bits version == 1 */
|
/* 8 bits version == 1 */
|
||||||
*data++ = 1;
|
*ptr++ = 1;
|
||||||
if (profile) {
|
if (profile) {
|
||||||
guint32 profile_id;
|
guint32 profile_id;
|
||||||
|
|
||||||
/* hex: AVCProfileIndication:8 | profile_compat:8 | AVCLevelIndication:8 */
|
/* hex: AVCProfileIndication:8 | profile_compat:8 | AVCLevelIndication:8 */
|
||||||
sscanf (profile, "%6x", &profile_id);
|
sscanf (profile, "%6x", &profile_id);
|
||||||
*data++ = (profile_id >> 16) & 0xff;
|
*ptr++ = (profile_id >> 16) & 0xff;
|
||||||
*data++ = (profile_id >> 8) & 0xff;
|
*ptr++ = (profile_id >> 8) & 0xff;
|
||||||
*data++ = profile_id & 0xff;
|
*ptr++ = profile_id & 0xff;
|
||||||
} else {
|
} else {
|
||||||
/* extract from SPS */
|
/* extract from SPS */
|
||||||
*data++ = sps[0][3];
|
*ptr++ = sps[0][3];
|
||||||
*data++ = sps[0][4];
|
*ptr++ = sps[0][4];
|
||||||
*data++ = sps[0][5];
|
*ptr++ = sps[0][5];
|
||||||
}
|
}
|
||||||
/* 6 bits reserved | 2 bits lengthSizeMinusOn */
|
/* 6 bits reserved | 2 bits lengthSizeMinusOn */
|
||||||
*data++ = 0xff;
|
*ptr++ = 0xff;
|
||||||
/* 3 bits reserved | 5 bits numOfSequenceParameterSets */
|
/* 3 bits reserved | 5 bits numOfSequenceParameterSets */
|
||||||
*data++ = 0xe0 | (num_sps & 0x1f);
|
*ptr++ = 0xe0 | (num_sps & 0x1f);
|
||||||
|
|
||||||
/* copy all SPS */
|
/* copy all SPS */
|
||||||
for (i = 0; sps[i]; i++) {
|
for (i = 0; sps[i]; i++) {
|
||||||
len = ((sps[i][0] << 8) | sps[i][1]) + 2;
|
len = ((sps[i][0] << 8) | sps[i][1]) + 2;
|
||||||
GST_DEBUG_OBJECT (depayload, "copy SPS %d of length %d", i, len);
|
GST_DEBUG_OBJECT (depayload, "copy SPS %d of length %d", i, len);
|
||||||
memcpy (data, sps[i], len);
|
memcpy (ptr, sps[i], len);
|
||||||
g_free (sps[i]);
|
g_free (sps[i]);
|
||||||
data += len;
|
ptr += len;
|
||||||
}
|
}
|
||||||
g_free (sps);
|
g_free (sps);
|
||||||
/* 8 bits numOfPictureParameterSets */
|
/* 8 bits numOfPictureParameterSets */
|
||||||
*data++ = num_pps;
|
*ptr++ = num_pps;
|
||||||
/* copy all PPS */
|
/* copy all PPS */
|
||||||
for (i = 0; pps[i]; i++) {
|
for (i = 0; pps[i]; i++) {
|
||||||
len = ((pps[i][0] << 8) | pps[i][1]) + 2;
|
len = ((pps[i][0] << 8) | pps[i][1]) + 2;
|
||||||
GST_DEBUG_OBJECT (depayload, "copy PPS %d of length %d", i, len);
|
GST_DEBUG_OBJECT (depayload, "copy PPS %d of length %d", i, len);
|
||||||
memcpy (data, pps[i], len);
|
memcpy (ptr, pps[i], len);
|
||||||
g_free (pps[i]);
|
g_free (pps[i]);
|
||||||
data += len;
|
ptr += len;
|
||||||
}
|
}
|
||||||
g_free (pps);
|
g_free (pps);
|
||||||
GST_BUFFER_SIZE (codec_data) = data - GST_BUFFER_DATA (codec_data);
|
gst_buffer_unmap (codec_data, data, ptr - data);
|
||||||
|
|
||||||
gst_caps_set_simple (srccaps,
|
gst_caps_set_simple (srccaps,
|
||||||
"codec_data", GST_TYPE_BUFFER, codec_data, NULL);
|
"codec_data", GST_TYPE_BUFFER, codec_data, NULL);
|
||||||
|
@ -476,18 +471,16 @@ gst_rtp_h264_depay_handle_nal (GstRtpH264Depay * rtph264depay, GstBuffer * nal,
|
||||||
{
|
{
|
||||||
GstBaseRTPDepayload *depayload = GST_BASE_RTP_DEPAYLOAD (rtph264depay);
|
GstBaseRTPDepayload *depayload = GST_BASE_RTP_DEPAYLOAD (rtph264depay);
|
||||||
gint nal_type;
|
gint nal_type;
|
||||||
guint size;
|
gsize size;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
GstBuffer *outbuf = NULL;
|
GstBuffer *outbuf = NULL;
|
||||||
GstClockTime out_timestamp;
|
GstClockTime out_timestamp;
|
||||||
gboolean keyframe, out_keyframe;
|
gboolean keyframe, out_keyframe;
|
||||||
|
|
||||||
size = GST_BUFFER_SIZE (nal);
|
data = gst_buffer_map (nal, &size, NULL, GST_MAP_READ);
|
||||||
if (G_UNLIKELY (size < 5))
|
if (G_UNLIKELY (size < 5))
|
||||||
goto short_nal;
|
goto short_nal;
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (nal);
|
|
||||||
|
|
||||||
nal_type = data[4] & 0x1f;
|
nal_type = data[4] & 0x1f;
|
||||||
GST_DEBUG_OBJECT (rtph264depay, "handle NAL type %d", nal_type);
|
GST_DEBUG_OBJECT (rtph264depay, "handle NAL type %d", nal_type);
|
||||||
|
|
||||||
|
@ -544,6 +537,7 @@ gst_rtp_h264_depay_handle_nal (GstRtpH264Depay * rtph264depay, GstBuffer * nal,
|
||||||
GST_DEBUG_OBJECT (depayload, "using NAL as output");
|
GST_DEBUG_OBJECT (depayload, "using NAL as output");
|
||||||
outbuf = nal;
|
outbuf = nal;
|
||||||
}
|
}
|
||||||
|
gst_buffer_unmap (nal, data, size);
|
||||||
|
|
||||||
if (outbuf) {
|
if (outbuf) {
|
||||||
/* prepend codec_data */
|
/* prepend codec_data */
|
||||||
|
@ -553,7 +547,7 @@ gst_rtp_h264_depay_handle_nal (GstRtpH264Depay * rtph264depay, GstBuffer * nal,
|
||||||
rtph264depay->codec_data = NULL;
|
rtph264depay->codec_data = NULL;
|
||||||
out_keyframe = TRUE;
|
out_keyframe = TRUE;
|
||||||
}
|
}
|
||||||
outbuf = gst_buffer_make_metadata_writable (outbuf);
|
outbuf = gst_buffer_make_writable (outbuf);
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = out_timestamp;
|
GST_BUFFER_TIMESTAMP (outbuf) = out_timestamp;
|
||||||
|
|
||||||
|
@ -562,8 +556,6 @@ gst_rtp_h264_depay_handle_nal (GstRtpH264Depay * rtph264depay, GstBuffer * nal,
|
||||||
else
|
else
|
||||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
|
||||||
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
|
|
||||||
|
|
||||||
gst_base_rtp_depayload_push (depayload, outbuf);
|
gst_base_rtp_depayload_push (depayload, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,6 +565,7 @@ gst_rtp_h264_depay_handle_nal (GstRtpH264Depay * rtph264depay, GstBuffer * nal,
|
||||||
short_nal:
|
short_nal:
|
||||||
{
|
{
|
||||||
GST_WARNING_OBJECT (depayload, "dropping short NAL");
|
GST_WARNING_OBJECT (depayload, "dropping short NAL");
|
||||||
|
gst_buffer_unmap (nal, data, size);
|
||||||
gst_buffer_unref (nal);
|
gst_buffer_unref (nal);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -584,6 +577,7 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
GstRtpH264Depay *rtph264depay;
|
GstRtpH264Depay *rtph264depay;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
guint8 nal_unit_type;
|
guint8 nal_unit_type;
|
||||||
|
GstRTPBuffer rtp = { NULL };
|
||||||
|
|
||||||
rtph264depay = GST_RTP_H264_DEPAY (depayload);
|
rtph264depay = GST_RTP_H264_DEPAY (depayload);
|
||||||
|
|
||||||
|
@ -604,8 +598,10 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
|
|
||||||
timestamp = GST_BUFFER_TIMESTAMP (buf);
|
timestamp = GST_BUFFER_TIMESTAMP (buf);
|
||||||
|
|
||||||
payload_len = gst_rtp_buffer_get_payload_len (buf);
|
gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
|
||||||
payload = gst_rtp_buffer_get_payload (buf);
|
|
||||||
|
payload_len = gst_rtp_buffer_get_payload_len (&rtp);
|
||||||
|
payload = gst_rtp_buffer_get_payload (&rtp);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtph264depay, "receiving %d bytes", payload_len);
|
GST_DEBUG_OBJECT (rtph264depay, "receiving %d bytes", payload_len);
|
||||||
|
|
||||||
|
@ -664,7 +660,8 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
|
|
||||||
outsize = nalu_size + sizeof (sync_bytes);
|
outsize = nalu_size + sizeof (sync_bytes);
|
||||||
outbuf = gst_buffer_new_and_alloc (outsize);
|
outbuf = gst_buffer_new_and_alloc (outsize);
|
||||||
outdata = GST_BUFFER_DATA (outbuf);
|
|
||||||
|
outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
|
||||||
if (rtph264depay->byte_stream) {
|
if (rtph264depay->byte_stream) {
|
||||||
memcpy (outdata, sync_bytes, sizeof (sync_bytes));
|
memcpy (outdata, sync_bytes, sizeof (sync_bytes));
|
||||||
} else {
|
} else {
|
||||||
|
@ -677,8 +674,8 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
payload += 2;
|
payload += 2;
|
||||||
payload_len -= 2;
|
payload_len -= 2;
|
||||||
|
|
||||||
outdata += sizeof (sync_bytes);
|
memcpy (outdata + sizeof (sync_bytes), payload, nalu_size);
|
||||||
memcpy (outdata, payload, nalu_size);
|
gst_buffer_unmap (outbuf, outdata, outsize);
|
||||||
|
|
||||||
gst_adapter_push (rtph264depay->adapter, outbuf);
|
gst_adapter_push (rtph264depay->adapter, outbuf);
|
||||||
|
|
||||||
|
@ -741,10 +738,11 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
nalu_size = payload_len;
|
nalu_size = payload_len;
|
||||||
outsize = nalu_size + sizeof (sync_bytes);
|
outsize = nalu_size + sizeof (sync_bytes);
|
||||||
outbuf = gst_buffer_new_and_alloc (outsize);
|
outbuf = gst_buffer_new_and_alloc (outsize);
|
||||||
outdata = GST_BUFFER_DATA (outbuf);
|
|
||||||
outdata += sizeof (sync_bytes);
|
outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
|
||||||
memcpy (outdata, payload, nalu_size);
|
memcpy (outdata + sizeof (sync_bytes), payload, nalu_size);
|
||||||
outdata[0] = nal_header;
|
outdata[sizeof (sync_bytes)] = nal_header;
|
||||||
|
gst_buffer_unmap (outbuf, outdata, outsize);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);
|
GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);
|
||||||
|
|
||||||
|
@ -757,8 +755,10 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
|
|
||||||
outsize = payload_len;
|
outsize = payload_len;
|
||||||
outbuf = gst_buffer_new_and_alloc (outsize);
|
outbuf = gst_buffer_new_and_alloc (outsize);
|
||||||
outdata = GST_BUFFER_DATA (outbuf);
|
|
||||||
|
outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
|
||||||
memcpy (outdata, payload, outsize);
|
memcpy (outdata, payload, outsize);
|
||||||
|
gst_buffer_unmap (outbuf, outdata, outsize);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);
|
GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);
|
||||||
|
|
||||||
|
@ -772,8 +772,8 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
|
|
||||||
outsize = gst_adapter_available (rtph264depay->adapter);
|
outsize = gst_adapter_available (rtph264depay->adapter);
|
||||||
outbuf = gst_adapter_take_buffer (rtph264depay->adapter, outsize);
|
outbuf = gst_adapter_take_buffer (rtph264depay->adapter, outsize);
|
||||||
outdata = GST_BUFFER_DATA (outbuf);
|
|
||||||
|
|
||||||
|
outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
|
||||||
if (rtph264depay->byte_stream) {
|
if (rtph264depay->byte_stream) {
|
||||||
memcpy (outdata, sync_bytes, sizeof (sync_bytes));
|
memcpy (outdata, sync_bytes, sizeof (sync_bytes));
|
||||||
} else {
|
} else {
|
||||||
|
@ -782,7 +782,10 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
outdata[1] = (outsize >> 16);
|
outdata[1] = (outsize >> 16);
|
||||||
outdata[2] = (outsize >> 8);
|
outdata[2] = (outsize >> 8);
|
||||||
outdata[3] = (outsize);
|
outdata[3] = (outsize);
|
||||||
|
outsize += 4;
|
||||||
}
|
}
|
||||||
|
gst_buffer_unmap (outbuf, outdata, outsize);
|
||||||
|
|
||||||
gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
|
gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -796,7 +799,8 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
nalu_size = payload_len;
|
nalu_size = payload_len;
|
||||||
outsize = nalu_size + sizeof (sync_bytes);
|
outsize = nalu_size + sizeof (sync_bytes);
|
||||||
outbuf = gst_buffer_new_and_alloc (outsize);
|
outbuf = gst_buffer_new_and_alloc (outsize);
|
||||||
outdata = GST_BUFFER_DATA (outbuf);
|
|
||||||
|
outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
|
||||||
if (rtph264depay->byte_stream) {
|
if (rtph264depay->byte_stream) {
|
||||||
memcpy (outdata, sync_bytes, sizeof (sync_bytes));
|
memcpy (outdata, sync_bytes, sizeof (sync_bytes));
|
||||||
} else {
|
} else {
|
||||||
|
@ -804,13 +808,14 @@ gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
outdata[2] = nalu_size >> 8;
|
outdata[2] = nalu_size >> 8;
|
||||||
outdata[3] = nalu_size & 0xff;
|
outdata[3] = nalu_size & 0xff;
|
||||||
}
|
}
|
||||||
outdata += sizeof (sync_bytes);
|
memcpy (outdata + sizeof (sync_bytes), payload, nalu_size);
|
||||||
memcpy (outdata, payload, nalu_size);
|
gst_buffer_unmap (outbuf, outdata, outsize);
|
||||||
|
|
||||||
gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
|
gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -820,17 +825,20 @@ undefined_type:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (rtph264depay, STREAM, DECODE,
|
GST_ELEMENT_WARNING (rtph264depay, STREAM, DECODE,
|
||||||
(NULL), ("Undefined packet type"));
|
(NULL), ("Undefined packet type"));
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
waiting_start:
|
waiting_start:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (rtph264depay, "waiting for start");
|
GST_DEBUG_OBJECT (rtph264depay, "waiting for start");
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
not_implemented:
|
not_implemented:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (rtph264depay, STREAM, FORMAT,
|
GST_ELEMENT_ERROR (rtph264depay, STREAM, FORMAT,
|
||||||
(NULL), ("NAL unit type %d not supported yet", nal_unit_type));
|
(NULL), ("NAL unit type %d not supported yet", nal_unit_type));
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,28 +112,13 @@ static gboolean gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
static GstFlowReturn gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * pad,
|
static GstFlowReturn gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * pad,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
static gboolean gst_rtp_h264_pay_handle_event (GstPad * pad, GstEvent * event);
|
static gboolean gst_rtp_h264_pay_handle_event (GstBaseRTPPayload * payload,
|
||||||
|
GstEvent * event);
|
||||||
static GstStateChangeReturn gst_basertppayload_change_state (GstElement *
|
static GstStateChangeReturn gst_basertppayload_change_state (GstElement *
|
||||||
element, GstStateChange transition);
|
element, GstStateChange transition);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstRtpH264Pay, gst_rtp_h264_pay, GstBaseRTPPayload,
|
#define gst_rtp_h264_pay_parent_class parent_class
|
||||||
GST_TYPE_BASE_RTP_PAYLOAD);
|
G_DEFINE_TYPE (GstRtpH264Pay, gst_rtp_h264_pay, GST_TYPE_BASE_RTP_PAYLOAD);
|
||||||
|
|
||||||
static void
|
|
||||||
gst_rtp_h264_pay_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h264_pay_src_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_h264_pay_sink_template));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class, "RTP H264 payloader",
|
|
||||||
"Codec/Payloader/Network/RTP",
|
|
||||||
"Payload-encode H264 video into RTP packets (RFC 3984)",
|
|
||||||
"Laurent Glayal <spglegle@yahoo.fr>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
|
gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
|
||||||
|
@ -188,6 +173,16 @@ gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtp_h264_pay_finalize;
|
gobject_class->finalize = gst_rtp_h264_pay_finalize;
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h264_pay_src_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_h264_pay_sink_template));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class, "RTP H264 payloader",
|
||||||
|
"Codec/Payloader/Network/RTP",
|
||||||
|
"Payload-encode H264 video into RTP packets (RFC 3984)",
|
||||||
|
"Laurent Glayal <spglegle@yahoo.fr>");
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_basertppayload_change_state);
|
GST_DEBUG_FUNCPTR (gst_basertppayload_change_state);
|
||||||
|
|
||||||
|
@ -200,7 +195,7 @@ gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay, GstRtpH264PayClass * klass)
|
gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
|
||||||
{
|
{
|
||||||
rtph264pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
|
rtph264pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||||
rtph264pay->profile = 0;
|
rtph264pay->profile = 0;
|
||||||
|
@ -255,6 +250,8 @@ gst_rtp_h264_pay_set_sps_pps (GstBaseRTPPayload * basepayload)
|
||||||
GString *sprops;
|
GString *sprops;
|
||||||
guint count;
|
guint count;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
guint8 *data;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
sprops = g_string_new ("");
|
sprops = g_string_new ("");
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -263,8 +260,10 @@ gst_rtp_h264_pay_set_sps_pps (GstBaseRTPPayload * basepayload)
|
||||||
for (walk = payloader->sps; walk; walk = g_list_next (walk)) {
|
for (walk = payloader->sps; walk; walk = g_list_next (walk)) {
|
||||||
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
|
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
|
||||||
|
|
||||||
set =
|
data = gst_buffer_map (sps_buf, &size, NULL, GST_MAP_READ);
|
||||||
g_base64_encode (GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf));
|
set = g_base64_encode (data, size);
|
||||||
|
gst_buffer_unmap (sps_buf, data, size);
|
||||||
|
|
||||||
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
||||||
g_free (set);
|
g_free (set);
|
||||||
count++;
|
count++;
|
||||||
|
@ -272,8 +271,10 @@ gst_rtp_h264_pay_set_sps_pps (GstBaseRTPPayload * basepayload)
|
||||||
for (walk = payloader->pps; walk; walk = g_list_next (walk)) {
|
for (walk = payloader->pps; walk; walk = g_list_next (walk)) {
|
||||||
GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
|
GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
|
||||||
|
|
||||||
set =
|
data = gst_buffer_map (pps_buf, &size, NULL, GST_MAP_READ);
|
||||||
g_base64_encode (GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf));
|
set = g_base64_encode (data, size);
|
||||||
|
gst_buffer_unmap (pps_buf, data, size);
|
||||||
|
|
||||||
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
||||||
g_free (set);
|
g_free (set);
|
||||||
count++;
|
count++;
|
||||||
|
@ -296,8 +297,9 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
GstRtpH264Pay *rtph264pay;
|
GstRtpH264Pay *rtph264pay;
|
||||||
GstStructure *str;
|
GstStructure *str;
|
||||||
const GValue *value;
|
const GValue *value;
|
||||||
guint8 *data;
|
guint8 *data, *bdata;
|
||||||
guint size;
|
gsize size, bsize;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
|
||||||
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
||||||
|
|
||||||
|
@ -309,7 +311,6 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
|
|
||||||
/* packetized AVC video has a codec_data */
|
/* packetized AVC video has a codec_data */
|
||||||
if ((value = gst_structure_get_value (str, "codec_data"))) {
|
if ((value = gst_structure_get_value (str, "codec_data"))) {
|
||||||
GstBuffer *buffer;
|
|
||||||
guint num_sps, num_pps;
|
guint num_sps, num_pps;
|
||||||
gint i, nal_size;
|
gint i, nal_size;
|
||||||
|
|
||||||
|
@ -317,8 +318,10 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
rtph264pay->packetized = TRUE;
|
rtph264pay->packetized = TRUE;
|
||||||
|
|
||||||
buffer = gst_value_get_buffer (value);
|
buffer = gst_value_get_buffer (value);
|
||||||
data = GST_BUFFER_DATA (buffer);
|
|
||||||
size = GST_BUFFER_SIZE (buffer);
|
bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
|
||||||
|
data = bdata;
|
||||||
|
size = bsize;
|
||||||
|
|
||||||
/* parse the avcC data */
|
/* parse the avcC data */
|
||||||
if (size < 7)
|
if (size < 7)
|
||||||
|
@ -363,7 +366,7 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
|
|
||||||
/* make a buffer out of it and add to SPS list */
|
/* make a buffer out of it and add to SPS list */
|
||||||
sps_buf = gst_buffer_new_and_alloc (nal_size);
|
sps_buf = gst_buffer_new_and_alloc (nal_size);
|
||||||
memcpy (GST_BUFFER_DATA (sps_buf), data, nal_size);
|
gst_buffer_fill (sps_buf, 0, data, nal_size);
|
||||||
rtph264pay->sps = g_list_append (rtph264pay->sps, sps_buf);
|
rtph264pay->sps = g_list_append (rtph264pay->sps, sps_buf);
|
||||||
|
|
||||||
data += nal_size;
|
data += nal_size;
|
||||||
|
@ -395,7 +398,7 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
|
|
||||||
/* make a buffer out of it and add to PPS list */
|
/* make a buffer out of it and add to PPS list */
|
||||||
pps_buf = gst_buffer_new_and_alloc (nal_size);
|
pps_buf = gst_buffer_new_and_alloc (nal_size);
|
||||||
memcpy (GST_BUFFER_DATA (pps_buf), data, nal_size);
|
gst_buffer_fill (pps_buf, 0, data, nal_size);
|
||||||
rtph264pay->pps = g_list_append (rtph264pay->pps, pps_buf);
|
rtph264pay->pps = g_list_append (rtph264pay->pps, pps_buf);
|
||||||
|
|
||||||
data += nal_size;
|
data += nal_size;
|
||||||
|
@ -403,7 +406,7 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
}
|
}
|
||||||
/* and update the caps with the collected data */
|
/* and update the caps with the collected data */
|
||||||
if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
|
if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
|
||||||
return FALSE;
|
goto set_sps_pps_failed;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (rtph264pay, "have bytestream h264");
|
GST_DEBUG_OBJECT (rtph264pay, "have bytestream h264");
|
||||||
rtph264pay->packetized = FALSE;
|
rtph264pay->packetized = FALSE;
|
||||||
|
@ -414,16 +417,26 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
avcc_too_small:
|
avcc_too_small:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (rtph264pay, "avcC size %u < 7", size);
|
GST_ERROR_OBJECT (rtph264pay, "avcC size %u < 7", size);
|
||||||
return FALSE;
|
goto error;
|
||||||
}
|
}
|
||||||
wrong_version:
|
wrong_version:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (rtph264pay, "wrong avcC version");
|
GST_ERROR_OBJECT (rtph264pay, "wrong avcC version");
|
||||||
return FALSE;
|
goto error;
|
||||||
}
|
}
|
||||||
avcc_error:
|
avcc_error:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (rtph264pay, "avcC too small ");
|
GST_ERROR_OBJECT (rtph264pay, "avcC too small ");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
set_sps_pps_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (rtph264pay, "failed to set sps/pps");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
{
|
||||||
|
gst_buffer_unmap (buffer, bdata, bsize);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,13 +468,15 @@ gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
|
||||||
guint8 *nalp;
|
guint8 *nalp;
|
||||||
guint save = 0;
|
guint save = 0;
|
||||||
gint state = 0;
|
gint state = 0;
|
||||||
|
guint8 nal_type;
|
||||||
|
|
||||||
nal_len = strlen (params[i]);
|
nal_len = strlen (params[i]);
|
||||||
buf = gst_buffer_new_and_alloc (nal_len);
|
buf = gst_buffer_new_and_alloc (nal_len);
|
||||||
nalp = GST_BUFFER_DATA (buf);
|
|
||||||
|
|
||||||
|
nalp = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
|
||||||
nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
|
nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
|
||||||
GST_BUFFER_SIZE (buf) = nal_len;
|
nal_type = nalp[0];
|
||||||
|
gst_buffer_unmap (buf, nalp, nal_len);
|
||||||
|
|
||||||
if (!nal_len) {
|
if (!nal_len) {
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
@ -469,7 +484,7 @@ gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* append to the right list */
|
/* append to the right list */
|
||||||
if ((nalp[0] & 0x1f) == 7) {
|
if ((nal_type & 0x1f) == 7) {
|
||||||
GST_DEBUG_OBJECT (rtph264pay, "adding param %d as SPS %d", i, num_sps);
|
GST_DEBUG_OBJECT (rtph264pay, "adding param %d as SPS %d", i, num_sps);
|
||||||
rtph264pay->sps = g_list_append (rtph264pay->sps, buf);
|
rtph264pay->sps = g_list_append (rtph264pay->sps, buf);
|
||||||
num_sps++;
|
num_sps++;
|
||||||
|
@ -578,8 +593,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
||||||
if (payloader->sps != NULL) {
|
if (payloader->sps != NULL) {
|
||||||
sps_buf = GST_BUFFER_CAST (payloader->sps->data);
|
sps_buf = GST_BUFFER_CAST (payloader->sps->data);
|
||||||
|
|
||||||
if ((GST_BUFFER_SIZE (sps_buf) != sps_len)
|
if (gst_buffer_memcmp (sps_buf, 0, sps, sps_len)) {
|
||||||
|| memcmp (GST_BUFFER_DATA (sps_buf), sps, sps_len)) {
|
|
||||||
/* something changed, update */
|
/* something changed, update */
|
||||||
payloader->profile = (sps[1] << 16) + (sps[2] << 8) + sps[3];
|
payloader->profile = (sps[1] << 16) + (sps[2] << 8) + sps[3];
|
||||||
GST_DEBUG ("Profile level IDC = %06x", payloader->profile);
|
GST_DEBUG ("Profile level IDC = %06x", payloader->profile);
|
||||||
|
@ -592,7 +606,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
||||||
|
|
||||||
if (updated) {
|
if (updated) {
|
||||||
sps_buf = gst_buffer_new_and_alloc (sps_len);
|
sps_buf = gst_buffer_new_and_alloc (sps_len);
|
||||||
memcpy (GST_BUFFER_DATA (sps_buf), sps, sps_len);
|
gst_buffer_fill (sps_buf, 0, sps, sps_len);
|
||||||
|
|
||||||
if (payloader->sps) {
|
if (payloader->sps) {
|
||||||
/* replace old buffer */
|
/* replace old buffer */
|
||||||
|
@ -611,8 +625,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
||||||
if (payloader->pps != NULL) {
|
if (payloader->pps != NULL) {
|
||||||
pps_buf = GST_BUFFER_CAST (payloader->pps->data);
|
pps_buf = GST_BUFFER_CAST (payloader->pps->data);
|
||||||
|
|
||||||
if ((GST_BUFFER_SIZE (pps_buf) != pps_len)
|
if (gst_buffer_memcmp (pps_buf, 0, pps, pps_len)) {
|
||||||
|| memcmp (GST_BUFFER_DATA (pps_buf), pps, pps_len)) {
|
|
||||||
/* something changed, update */
|
/* something changed, update */
|
||||||
updated = TRUE;
|
updated = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +636,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
||||||
|
|
||||||
if (updated) {
|
if (updated) {
|
||||||
pps_buf = gst_buffer_new_and_alloc (pps_len);
|
pps_buf = gst_buffer_new_and_alloc (pps_len);
|
||||||
memcpy (GST_BUFFER_DATA (pps_buf), pps, pps_len);
|
gst_buffer_fill (pps_buf, 0, pps, pps_len);
|
||||||
|
|
||||||
if (payloader->pps) {
|
if (payloader->pps) {
|
||||||
/* replace old buffer */
|
/* replace old buffer */
|
||||||
|
@ -649,15 +662,18 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload,
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GList *walk;
|
GList *walk;
|
||||||
|
guint8 *data;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
|
for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
|
||||||
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
|
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
|
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
|
||||||
/* resend SPS */
|
/* resend SPS */
|
||||||
|
data = gst_buffer_map (sps_buf, &size, NULL, GST_MAP_READ);
|
||||||
ret = gst_rtp_h264_pay_payload_nal (basepayload,
|
ret = gst_rtp_h264_pay_payload_nal (basepayload,
|
||||||
GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf), timestamp,
|
data, size, timestamp, sps_buf);
|
||||||
sps_buf);
|
gst_buffer_unmap (sps_buf, data, size);
|
||||||
/* Not critical here; but throw a warning */
|
/* Not critical here; but throw a warning */
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
GST_WARNING ("Problem pushing SPS");
|
GST_WARNING ("Problem pushing SPS");
|
||||||
|
@ -667,9 +683,10 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload,
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
|
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
|
||||||
/* resend PPS */
|
/* resend PPS */
|
||||||
|
data = gst_buffer_map (pps_buf, &size, NULL, GST_MAP_READ);
|
||||||
ret = gst_rtp_h264_pay_payload_nal (basepayload,
|
ret = gst_rtp_h264_pay_payload_nal (basepayload,
|
||||||
GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf), timestamp,
|
data, size, timestamp, pps_buf);
|
||||||
pps_buf);
|
gst_buffer_unmap (pps_buf, data, size);
|
||||||
/* Not critical here; but throw a warning */
|
/* Not critical here; but throw a warning */
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
GST_WARNING ("Problem pushing PPS");
|
GST_WARNING ("Problem pushing PPS");
|
||||||
|
@ -1123,10 +1140,11 @@ caps_rejected:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_h264_pay_handle_event (GstPad * pad, GstEvent * event)
|
gst_rtp_h264_pay_handle_event (GstBaseRTPPayload * payload, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
gboolean res;
|
||||||
const GstStructure *s;
|
const GstStructure *s;
|
||||||
GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (GST_PAD_PARENT (pad));
|
GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_FLUSH_STOP:
|
case GST_EVENT_FLUSH_STOP:
|
||||||
|
@ -1146,7 +1164,10 @@ gst_rtp_h264_pay_handle_event (GstPad * pad, GstEvent * event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
res =
|
||||||
|
GST_BASE_RTP_PAYLOAD_CLASS (parent_class)->handle_event (payload, event);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
|
Loading…
Reference in a new issue