mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
parent
8f43709e00
commit
40ec22788f
2 changed files with 112 additions and 21 deletions
|
@ -90,6 +90,7 @@ gst_h264_scan_mode_get_type (void)
|
||||||
#define DEFAULT_PROFILE_LEVEL_ID NULL
|
#define DEFAULT_PROFILE_LEVEL_ID NULL
|
||||||
#define DEFAULT_SPROP_PARAMETER_SETS NULL
|
#define DEFAULT_SPROP_PARAMETER_SETS NULL
|
||||||
#define DEFAULT_SCAN_MODE GST_H264_SCAN_MODE_MULTI_NAL
|
#define DEFAULT_SCAN_MODE GST_H264_SCAN_MODE_MULTI_NAL
|
||||||
|
#define DEFAULT_BUFFER_LIST FALSE
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -97,6 +98,7 @@ enum
|
||||||
PROP_PROFILE_LEVEL_ID,
|
PROP_PROFILE_LEVEL_ID,
|
||||||
PROP_SPROP_PARAMETER_SETS,
|
PROP_SPROP_PARAMETER_SETS,
|
||||||
PROP_SCAN_MODE,
|
PROP_SCAN_MODE,
|
||||||
|
PROP_BUFFER_LIST,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,6 +167,11 @@ gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
|
||||||
GST_TYPE_H264_SCAN_MODE, DEFAULT_SCAN_MODE,
|
GST_TYPE_H264_SCAN_MODE, DEFAULT_SCAN_MODE,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST,
|
||||||
|
g_param_spec_boolean ("buffer-list", "Buffer List",
|
||||||
|
"Use Buffer Lists",
|
||||||
|
DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtp_h264_pay_finalize;
|
gobject_class->finalize = gst_rtp_h264_pay_finalize;
|
||||||
|
|
||||||
gstbasertppayload_class->set_caps = gst_rtp_h264_pay_setcaps;
|
gstbasertppayload_class->set_caps = gst_rtp_h264_pay_setcaps;
|
||||||
|
@ -181,6 +188,7 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay, GstRtpH264PayClass * klass)
|
||||||
rtph264pay->sps = NULL;
|
rtph264pay->sps = NULL;
|
||||||
rtph264pay->pps = NULL;
|
rtph264pay->pps = NULL;
|
||||||
rtph264pay->scan_mode = GST_H264_SCAN_MODE_MULTI_NAL;
|
rtph264pay->scan_mode = GST_H264_SCAN_MODE_MULTI_NAL;
|
||||||
|
rtph264pay->buffer_list = DEFAULT_BUFFER_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -550,7 +558,7 @@ gst_rtp_h264_pay_parse_sps_pps (GstBaseRTPPayload * basepayload,
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
|
gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
|
||||||
guint size, GstClockTime timestamp)
|
guint size, GstClockTime timestamp, GstBuffer * buffer_orig)
|
||||||
{
|
{
|
||||||
GstRtpH264Pay *rtph264pay;
|
GstRtpH264Pay *rtph264pay;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
@ -558,6 +566,8 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
|
||||||
guint packet_len, payload_len, mtu;
|
guint packet_len, payload_len, mtu;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
guint8 *payload;
|
guint8 *payload;
|
||||||
|
GstBufferList *list = NULL;
|
||||||
|
GstBufferListIterator *it = NULL;
|
||||||
|
|
||||||
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
||||||
mtu = GST_BASE_RTP_PAYLOAD_MTU (rtph264pay);
|
mtu = GST_BASE_RTP_PAYLOAD_MTU (rtph264pay);
|
||||||
|
@ -571,30 +581,63 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
|
||||||
GST_DEBUG_OBJECT (basepayload,
|
GST_DEBUG_OBJECT (basepayload,
|
||||||
"NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
|
"NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
|
||||||
/* will fit in one packet */
|
/* will fit in one packet */
|
||||||
outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
if (rtph264pay->buffer_list) {
|
||||||
|
/* use buffer lists
|
||||||
|
* first create buffer without payload containing only the RTP header
|
||||||
|
* and then another buffer containing the payload. both buffers will
|
||||||
|
* be then added to the list */
|
||||||
|
outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
|
||||||
|
} else {
|
||||||
|
/* use the old-fashioned way with a single buffer and memcpy */
|
||||||
|
outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* only set the marker bit on packets containing access units */
|
/* only set the marker bit on packets containing access units */
|
||||||
if (IS_ACCESS_UNIT (nalType)) {
|
if (IS_ACCESS_UNIT (nalType)) {
|
||||||
gst_rtp_buffer_set_marker (outbuf, 1);
|
gst_rtp_buffer_set_marker (outbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
payload = gst_rtp_buffer_get_payload (outbuf);
|
/* timestamp the outbuffer */
|
||||||
GST_DEBUG_OBJECT (basepayload, "Copying %d bytes to outbuf", size);
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||||
memcpy (payload, data, size);
|
|
||||||
|
|
||||||
ret = gst_basertppayload_push (basepayload, outbuf);
|
if (rtph264pay->buffer_list) {
|
||||||
|
GstBuffer *paybuf;
|
||||||
|
|
||||||
|
/* create another buffer with the payload. */
|
||||||
|
paybuf = gst_buffer_create_sub (buffer_orig, data -
|
||||||
|
GST_BUFFER_DATA (buffer_orig), size);
|
||||||
|
|
||||||
|
list = gst_buffer_list_new ();
|
||||||
|
it = gst_buffer_list_iterate (list);
|
||||||
|
|
||||||
|
/* add both buffers to the buffer list */
|
||||||
|
gst_buffer_list_iterator_add_group (it);
|
||||||
|
gst_buffer_list_iterator_add (it, outbuf);
|
||||||
|
gst_buffer_list_iterator_add (it, paybuf);
|
||||||
|
|
||||||
|
gst_buffer_list_iterator_free (it);
|
||||||
|
|
||||||
|
/* push the list to the next element in the pipe */
|
||||||
|
ret = gst_basertppayload_push_list (basepayload, list);
|
||||||
|
} else {
|
||||||
|
payload = gst_rtp_buffer_get_payload (outbuf);
|
||||||
|
GST_DEBUG_OBJECT (basepayload, "Copying %d bytes to outbuf", size);
|
||||||
|
memcpy (payload, data, size);
|
||||||
|
|
||||||
|
ret = gst_basertppayload_push (basepayload, outbuf);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Fragmentation Units FU-A */
|
/* fragmentation Units FU-A */
|
||||||
guint8 nalHeader;
|
guint8 nalHeader;
|
||||||
guint limitedSize;
|
guint limitedSize;
|
||||||
int ii = 0, start = 1, end = 0, first = 0;
|
int ii = 0, start = 1, end = 0, pos = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (basepayload,
|
GST_DEBUG_OBJECT (basepayload,
|
||||||
"NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
|
"NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
|
||||||
|
|
||||||
nalHeader = *data;
|
nalHeader = *data;
|
||||||
data++;
|
pos++;
|
||||||
size--;
|
size--;
|
||||||
|
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
|
@ -605,13 +648,29 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
|
||||||
/* We keep 2 bytes for FU indicator and FU Header */
|
/* We keep 2 bytes for FU indicator and FU Header */
|
||||||
payload_len = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
|
payload_len = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
|
||||||
|
|
||||||
|
if (rtph264pay->buffer_list) {
|
||||||
|
list = gst_buffer_list_new ();
|
||||||
|
it = gst_buffer_list_iterate (list);
|
||||||
|
}
|
||||||
|
|
||||||
while (end == 0) {
|
while (end == 0) {
|
||||||
limitedSize = size < payload_len ? size : payload_len;
|
limitedSize = size < payload_len ? size : payload_len;
|
||||||
GST_DEBUG_OBJECT (basepayload,
|
GST_DEBUG_OBJECT (basepayload,
|
||||||
"Inside FU-A fragmentation limitedSize=%d iteration=%d", limitedSize,
|
"Inside FU-A fragmentation limitedSize=%d iteration=%d", limitedSize,
|
||||||
ii);
|
ii);
|
||||||
|
|
||||||
outbuf = gst_rtp_buffer_new_allocate (limitedSize + 2, 0, 0);
|
if (rtph264pay->buffer_list) {
|
||||||
|
/* use buffer lists
|
||||||
|
* first create buffer without payload containing only the RTP header
|
||||||
|
* and then another buffer containing the payload. both buffers will
|
||||||
|
* be then added to the list */
|
||||||
|
outbuf = gst_rtp_buffer_new_allocate (2, 0, 0);
|
||||||
|
} else {
|
||||||
|
/* use the old-fashioned way with a single buffer and memcpy
|
||||||
|
* first create buffer to hold the payload */
|
||||||
|
outbuf = gst_rtp_buffer_new_allocate (limitedSize + 2, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||||
payload = gst_rtp_buffer_get_payload (outbuf);
|
payload = gst_rtp_buffer_get_payload (outbuf);
|
||||||
|
|
||||||
|
@ -629,20 +688,42 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
|
||||||
/* FU Header */
|
/* FU Header */
|
||||||
payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
|
payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
|
||||||
|
|
||||||
memcpy (&payload[2], data + first, limitedSize);
|
if (rtph264pay->buffer_list) {
|
||||||
GST_DEBUG_OBJECT (basepayload,
|
GstBuffer *paybuf;
|
||||||
"recorded %d payload bytes into packet iteration=%d", limitedSize + 2,
|
|
||||||
ii);
|
|
||||||
|
|
||||||
ret = gst_basertppayload_push (basepayload, outbuf);
|
/* create another buffer to hold the payload */
|
||||||
if (ret != GST_FLOW_OK)
|
paybuf = gst_buffer_create_sub (buffer_orig, data -
|
||||||
break;
|
GST_BUFFER_DATA (buffer_orig) + pos, limitedSize);
|
||||||
|
|
||||||
|
/* create a new group to hold the header and the payload */
|
||||||
|
gst_buffer_list_iterator_add_group (it);
|
||||||
|
|
||||||
|
/* add both buffers to the buffer list */
|
||||||
|
gst_buffer_list_iterator_add (it, outbuf);
|
||||||
|
gst_buffer_list_iterator_add (it, paybuf);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
memcpy (&payload[2], data + pos, limitedSize);
|
||||||
|
GST_DEBUG_OBJECT (basepayload,
|
||||||
|
"recorded %d payload bytes into packet iteration=%d",
|
||||||
|
limitedSize + 2, ii);
|
||||||
|
|
||||||
|
ret = gst_basertppayload_push (basepayload, outbuf);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
size -= limitedSize;
|
size -= limitedSize;
|
||||||
first += limitedSize;
|
pos += limitedSize;
|
||||||
ii++;
|
ii++;
|
||||||
start = 0;
|
start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rtph264pay->buffer_list) {
|
||||||
|
/* free iterator and push the whole buffer list at once */
|
||||||
|
gst_buffer_list_iterator_free (it);
|
||||||
|
ret = gst_basertppayload_push_list (basepayload, list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -697,7 +778,8 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp);
|
gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp,
|
||||||
|
buffer);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -765,7 +847,8 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
|
|
||||||
/* put the data in one or more RTP packets */
|
/* put the data in one or more RTP packets */
|
||||||
ret =
|
ret =
|
||||||
gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp);
|
gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp,
|
||||||
|
buffer);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -801,6 +884,9 @@ gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_SCAN_MODE:
|
case PROP_SCAN_MODE:
|
||||||
rtph264pay->scan_mode = g_value_get_enum (value);
|
rtph264pay->scan_mode = g_value_get_enum (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_BUFFER_LIST:
|
||||||
|
rtph264pay->buffer_list = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -825,6 +911,9 @@ gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_SCAN_MODE:
|
case PROP_SCAN_MODE:
|
||||||
g_value_set_enum (value, rtph264pay->scan_mode);
|
g_value_set_enum (value, rtph264pay->scan_mode);
|
||||||
break;
|
break;
|
||||||
|
case PROP_BUFFER_LIST:
|
||||||
|
g_value_set_boolean (value, rtph264pay->buffer_list);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -61,6 +61,8 @@ struct _GstRtpH264Pay
|
||||||
gchar *sprop_parameter_sets;
|
gchar *sprop_parameter_sets;
|
||||||
gboolean update_caps;
|
gboolean update_caps;
|
||||||
GstH264ScanMode scan_mode;
|
GstH264ScanMode scan_mode;
|
||||||
|
|
||||||
|
gboolean buffer_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRtpH264PayClass
|
struct _GstRtpH264PayClass
|
||||||
|
|
Loading…
Reference in a new issue