mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 02:02:26 +00:00
rtph264pay: Support STAP-A bundling
Add a new property "do-aggregate"* to the H.264 RTP payloader which enables STAP-A aggregation as per [RFC-6184][1]. With aggregation enabled, packets are bundled instead of sent immediately, up until the MTU size. Bundles also end at access unit boundaries or when packets have to be fragmented. *: The property-name is kept generic since it might apply more widely, e.g. STAP-B or MTAP. [1]: https://tools.ietf.org/html/rfc6184#section-5.7 Closes https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/issues/434
This commit is contained in:
parent
66a3db2083
commit
b46dab13d2
4 changed files with 254 additions and 4 deletions
|
@ -38,6 +38,8 @@
|
||||||
#define IDR_TYPE_ID 5
|
#define IDR_TYPE_ID 5
|
||||||
#define SPS_TYPE_ID 7
|
#define SPS_TYPE_ID 7
|
||||||
#define PPS_TYPE_ID 8
|
#define PPS_TYPE_ID 8
|
||||||
|
#define AUD_TYPE_ID 9
|
||||||
|
#define STAP_A_TYPE_ID 24
|
||||||
#define FU_A_TYPE_ID 28
|
#define FU_A_TYPE_ID 28
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (rtph264pay_debug);
|
GST_DEBUG_CATEGORY_STATIC (rtph264pay_debug);
|
||||||
|
@ -70,12 +72,14 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
|
||||||
#define DEFAULT_SPROP_PARAMETER_SETS NULL
|
#define DEFAULT_SPROP_PARAMETER_SETS NULL
|
||||||
#define DEFAULT_CONFIG_INTERVAL 0
|
#define DEFAULT_CONFIG_INTERVAL 0
|
||||||
|
#define DEFAULT_DO_AGGREGATE TRUE
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_SPROP_PARAMETER_SETS,
|
PROP_SPROP_PARAMETER_SETS,
|
||||||
PROP_CONFIG_INTERVAL,
|
PROP_CONFIG_INTERVAL,
|
||||||
|
PROP_DO_AGGREGATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gst_rtp_h264_pay_finalize (GObject * object);
|
static void gst_rtp_h264_pay_finalize (GObject * object);
|
||||||
|
@ -96,6 +100,8 @@ static gboolean gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload,
|
||||||
static GstStateChangeReturn gst_rtp_h264_pay_change_state (GstElement *
|
static GstStateChangeReturn gst_rtp_h264_pay_change_state (GstElement *
|
||||||
element, GstStateChange transition);
|
element, GstStateChange transition);
|
||||||
|
|
||||||
|
static void gst_rtp_h264_pay_reset_bundle (GstRtpH264Pay * rtph264pay);
|
||||||
|
|
||||||
#define gst_rtp_h264_pay_parent_class parent_class
|
#define gst_rtp_h264_pay_parent_class parent_class
|
||||||
G_DEFINE_TYPE (GstRtpH264Pay, gst_rtp_h264_pay, GST_TYPE_RTP_BASE_PAYLOAD);
|
G_DEFINE_TYPE (GstRtpH264Pay, gst_rtp_h264_pay, GST_TYPE_RTP_BASE_PAYLOAD);
|
||||||
|
|
||||||
|
@ -132,6 +138,15 @@ gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||||
|
PROP_DO_AGGREGATE,
|
||||||
|
g_param_spec_boolean ("do-aggregate",
|
||||||
|
"Attempt to use aggregate packets",
|
||||||
|
"Bundle suitable SPS/PPS NAL units into STAP-A "
|
||||||
|
"aggregate packets. ",
|
||||||
|
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||||
|
);
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtp_h264_pay_finalize;
|
gobject_class->finalize = gst_rtp_h264_pay_finalize;
|
||||||
|
|
||||||
gst_element_class_add_static_pad_template (gstelement_class,
|
gst_element_class_add_static_pad_template (gstelement_class,
|
||||||
|
@ -167,6 +182,7 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
|
||||||
(GDestroyNotify) gst_buffer_unref);
|
(GDestroyNotify) gst_buffer_unref);
|
||||||
rtph264pay->last_spspps = -1;
|
rtph264pay->last_spspps = -1;
|
||||||
rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
|
rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
|
||||||
|
rtph264pay->do_aggregate = DEFAULT_DO_AGGREGATE;
|
||||||
rtph264pay->delta_unit = FALSE;
|
rtph264pay->delta_unit = FALSE;
|
||||||
rtph264pay->discont = FALSE;
|
rtph264pay->discont = FALSE;
|
||||||
|
|
||||||
|
@ -195,6 +211,7 @@ gst_rtp_h264_pay_finalize (GObject * object)
|
||||||
g_free (rtph264pay->sprop_parameter_sets);
|
g_free (rtph264pay->sprop_parameter_sets);
|
||||||
|
|
||||||
g_object_unref (rtph264pay->adapter);
|
g_object_unref (rtph264pay->adapter);
|
||||||
|
gst_rtp_h264_pay_reset_bundle (rtph264pay);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -742,6 +759,11 @@ gst_rtp_h264_pay_payload_nal_fragment (GstRTPBasePayload * basepayload,
|
||||||
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
|
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
|
||||||
gboolean delta_unit, gboolean discont, guint8 nal_header);
|
gboolean delta_unit, gboolean discont, guint8 nal_header);
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_rtp_h264_pay_payload_nal_bundle (GstRTPBasePayload * basepayload,
|
||||||
|
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
|
||||||
|
gboolean delta_unit, gboolean discont, guint8 nal_header);
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
||||||
GstClockTime dts, GstClockTime pts, gboolean delta_unit, gboolean discont)
|
GstClockTime dts, GstClockTime pts, gboolean delta_unit, gboolean discont)
|
||||||
|
@ -893,6 +915,10 @@ gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
|
||||||
discont = FALSE;
|
discont = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rtph264pay->do_aggregate)
|
||||||
|
return gst_rtp_h264_pay_payload_nal_bundle (basepayload, paybuf, dts, pts,
|
||||||
|
end_of_au, delta_unit, discont, nal_header);
|
||||||
|
|
||||||
return gst_rtp_h264_pay_payload_nal_fragment (basepayload, paybuf, dts, pts,
|
return gst_rtp_h264_pay_payload_nal_fragment (basepayload, paybuf, dts, pts,
|
||||||
end_of_au, delta_unit, discont, nal_header);
|
end_of_au, delta_unit, discont, nal_header);
|
||||||
}
|
}
|
||||||
|
@ -1035,6 +1061,204 @@ gst_rtp_h264_pay_payload_nal_single (GstRTPBasePayload * basepayload,
|
||||||
return gst_rtp_base_payload_push (basepayload, outbuf);
|
return gst_rtp_base_payload_push (basepayload, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtp_h264_pay_reset_bundle (GstRtpH264Pay * rtph264pay)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&rtph264pay->bundle, gst_buffer_list_unref);
|
||||||
|
rtph264pay->bundle_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_rtp_h264_pay_send_bundle (GstRtpH264Pay * rtph264pay, gboolean end_of_au)
|
||||||
|
{
|
||||||
|
GstRTPBasePayload *basepayload;
|
||||||
|
GstBufferList *bundle;
|
||||||
|
guint length, bundle_size;
|
||||||
|
GstBuffer *first, *outbuf;
|
||||||
|
GstClockTime dts, pts;
|
||||||
|
gboolean delta, discont;
|
||||||
|
|
||||||
|
bundle_size = rtph264pay->bundle_size;
|
||||||
|
|
||||||
|
if (bundle_size == 0) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "no bundle, nothing to send");
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
basepayload = GST_RTP_BASE_PAYLOAD (rtph264pay);
|
||||||
|
bundle = rtph264pay->bundle;
|
||||||
|
length = gst_buffer_list_length (bundle);
|
||||||
|
|
||||||
|
first = gst_buffer_list_get (bundle, 0);
|
||||||
|
dts = GST_BUFFER_DTS (first);
|
||||||
|
pts = GST_BUFFER_PTS (first);
|
||||||
|
delta = GST_BUFFER_FLAG_IS_SET (first, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
discont = GST_BUFFER_FLAG_IS_SET (first, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
|
||||||
|
if (length == 1) {
|
||||||
|
/* Push unaggregated NALU */
|
||||||
|
outbuf = gst_buffer_ref (first);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay,
|
||||||
|
"sending NAL Unit unaggregated: datasize=%u", bundle_size - 2);
|
||||||
|
} else {
|
||||||
|
guint8 stap_header;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
outbuf = gst_buffer_new_allocate (NULL, sizeof stap_header, NULL);
|
||||||
|
stap_header = STAP_A_TYPE_ID;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
GstBuffer *buf = gst_buffer_list_get (bundle, i);
|
||||||
|
guint8 nal_header;
|
||||||
|
GstMemory *size_header;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_extract (buf, 0, &nal_header, sizeof nal_header);
|
||||||
|
|
||||||
|
/* Propagate F bit */
|
||||||
|
if ((nal_header & 0x80))
|
||||||
|
stap_header |= 0x80;
|
||||||
|
|
||||||
|
/* Select highest nal_ref_idc */
|
||||||
|
if ((nal_header & 0x60) > (stap_header & 0x60))
|
||||||
|
stap_header = (stap_header & 0x9f) | (nal_header & 0x60);
|
||||||
|
|
||||||
|
/* append NALU size */
|
||||||
|
size_header = gst_allocator_alloc (NULL, 2, NULL);
|
||||||
|
gst_memory_map (size_header, &map, GST_MAP_WRITE);
|
||||||
|
GST_WRITE_UINT16_BE (map.data, gst_buffer_get_size (buf));
|
||||||
|
gst_memory_unmap (size_header, &map);
|
||||||
|
gst_buffer_append_memory (outbuf, size_header);
|
||||||
|
|
||||||
|
/* append NALU data */
|
||||||
|
outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_fill (outbuf, 0, &stap_header, sizeof stap_header);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay,
|
||||||
|
"sending STAP-A bundle: n=%u header=%02x datasize=%u",
|
||||||
|
length, stap_header, bundle_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_rtp_h264_pay_reset_bundle (rtph264pay);
|
||||||
|
return gst_rtp_h264_pay_payload_nal_single (basepayload, outbuf, dts, pts,
|
||||||
|
end_of_au, delta, discont);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_rtp_h264_pay_payload_nal_bundle (GstRTPBasePayload * basepayload,
|
||||||
|
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
|
||||||
|
gboolean delta_unit, gboolean discont, guint8 nal_header)
|
||||||
|
{
|
||||||
|
GstRtpH264Pay *rtph264pay;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
guint mtu, pay_size, bundle_size;
|
||||||
|
GstBufferList *bundle;
|
||||||
|
guint8 nal_type;
|
||||||
|
gboolean start_of_au;
|
||||||
|
|
||||||
|
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
||||||
|
nal_type = nal_header & 0x1f;
|
||||||
|
mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
|
||||||
|
pay_size = 2 + gst_buffer_get_size (paybuf);
|
||||||
|
bundle = rtph264pay->bundle;
|
||||||
|
start_of_au = FALSE;
|
||||||
|
|
||||||
|
if (bundle) {
|
||||||
|
GstBuffer *first = gst_buffer_list_get (bundle, 0);
|
||||||
|
|
||||||
|
if (nal_type == AUD_TYPE_ID) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "found access delimiter");
|
||||||
|
start_of_au = TRUE;
|
||||||
|
} else if (discont) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "found discont");
|
||||||
|
start_of_au = TRUE;
|
||||||
|
} else if (!delta_unit) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "found !delta_unit");
|
||||||
|
start_of_au = TRUE;
|
||||||
|
} else if (GST_BUFFER_PTS (first) != pts || GST_BUFFER_DTS (first) != dts) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "found timestamp mismatch");
|
||||||
|
start_of_au = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_of_au) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "sending bundle before start of AU");
|
||||||
|
|
||||||
|
ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
bundle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle_size = 1 + pay_size;
|
||||||
|
|
||||||
|
if (gst_rtp_buffer_calc_packet_len (bundle_size, 0, 0) > mtu) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "NAL Unit cannot fit in a bundle");
|
||||||
|
|
||||||
|
ret = gst_rtp_h264_pay_send_bundle (rtph264pay, FALSE);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return gst_rtp_h264_pay_payload_nal_fragment (basepayload, paybuf, dts, pts,
|
||||||
|
end_of_au, delta_unit, discont, nal_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle_size = rtph264pay->bundle_size + pay_size;
|
||||||
|
|
||||||
|
if (gst_rtp_buffer_calc_packet_len (bundle_size, 0, 0) > mtu) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay,
|
||||||
|
"bundle overflows, sending: bundlesize=%u datasize=2+%u mtu=%u",
|
||||||
|
rtph264pay->bundle_size, pay_size - 2, mtu);
|
||||||
|
|
||||||
|
ret = gst_rtp_h264_pay_send_bundle (rtph264pay, FALSE);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
bundle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bundle) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "creating new STAP-A aggregate");
|
||||||
|
bundle = rtph264pay->bundle = gst_buffer_list_new ();
|
||||||
|
bundle_size = rtph264pay->bundle_size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay,
|
||||||
|
"bundling NAL Unit: bundlesize=%u datasize=2+%u mtu=%u",
|
||||||
|
rtph264pay->bundle_size, pay_size - 2, mtu);
|
||||||
|
|
||||||
|
paybuf = gst_buffer_make_writable (paybuf);
|
||||||
|
GST_BUFFER_PTS (paybuf) = pts;
|
||||||
|
GST_BUFFER_DTS (paybuf) = dts;
|
||||||
|
|
||||||
|
if (delta_unit)
|
||||||
|
GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
else
|
||||||
|
GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
|
||||||
|
if (discont)
|
||||||
|
GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
else
|
||||||
|
GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
|
||||||
|
gst_buffer_list_add (bundle, gst_buffer_ref (paybuf));
|
||||||
|
rtph264pay->bundle_size += pay_size;
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
if (end_of_au) {
|
||||||
|
GST_DEBUG_OBJECT (rtph264pay, "sending bundle at end of AU");
|
||||||
|
ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
gst_buffer_unref (paybuf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
||||||
GstBuffer * buffer)
|
GstBuffer * buffer)
|
||||||
|
@ -1358,10 +1582,12 @@ gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
|
||||||
gboolean res;
|
gboolean res;
|
||||||
const GstStructure *s;
|
const GstStructure *s;
|
||||||
GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
|
GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_FLUSH_STOP:
|
case GST_EVENT_FLUSH_STOP:
|
||||||
gst_adapter_clear (rtph264pay->adapter);
|
gst_adapter_clear (rtph264pay->adapter);
|
||||||
|
gst_rtp_h264_pay_reset_bundle (rtph264pay);
|
||||||
break;
|
break;
|
||||||
case GST_EVENT_CUSTOM_DOWNSTREAM:
|
case GST_EVENT_CUSTOM_DOWNSTREAM:
|
||||||
s = gst_event_get_structure (event);
|
s = gst_event_get_structure (event);
|
||||||
|
@ -1379,16 +1605,21 @@ gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
|
||||||
* in byte-stream mode
|
* in byte-stream mode
|
||||||
*/
|
*/
|
||||||
gst_rtp_h264_pay_handle_buffer (payload, NULL);
|
gst_rtp_h264_pay_handle_buffer (payload, NULL);
|
||||||
|
ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_EVENT_STREAM_START:
|
case GST_EVENT_STREAM_START:
|
||||||
GST_DEBUG_OBJECT (rtph264pay, "New stream detected => Clear SPS and PPS");
|
GST_DEBUG_OBJECT (rtph264pay, "New stream detected => Clear SPS and PPS");
|
||||||
gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
|
gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
|
||||||
|
ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
|
res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -1404,6 +1635,7 @@ gst_rtp_h264_pay_change_state (GstElement * element, GstStateChange transition)
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
rtph264pay->send_spspps = FALSE;
|
rtph264pay->send_spspps = FALSE;
|
||||||
gst_adapter_clear (rtph264pay->adapter);
|
gst_adapter_clear (rtph264pay->adapter);
|
||||||
|
gst_rtp_h264_pay_reset_bundle (rtph264pay);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1440,6 +1672,9 @@ gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_CONFIG_INTERVAL:
|
case PROP_CONFIG_INTERVAL:
|
||||||
rtph264pay->spspps_interval = g_value_get_int (value);
|
rtph264pay->spspps_interval = g_value_get_int (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DO_AGGREGATE:
|
||||||
|
rtph264pay->do_aggregate = 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;
|
||||||
|
@ -1461,6 +1696,9 @@ gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_CONFIG_INTERVAL:
|
case PROP_CONFIG_INTERVAL:
|
||||||
g_value_set_int (value, rtph264pay->spspps_interval);
|
g_value_set_int (value, rtph264pay->spspps_interval);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DO_AGGREGATE:
|
||||||
|
g_value_set_boolean (value, rtph264pay->do_aggregate);
|
||||||
|
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;
|
||||||
|
|
|
@ -79,6 +79,11 @@ struct _GstRtpH264Pay
|
||||||
gboolean delta_unit;
|
gboolean delta_unit;
|
||||||
/* TRUE if the next NALU processed should have the DISCONT flag */
|
/* TRUE if the next NALU processed should have the DISCONT flag */
|
||||||
gboolean discont;
|
gboolean discont;
|
||||||
|
|
||||||
|
/* aggregate buffers with STAP-A */
|
||||||
|
GstBufferList *bundle;
|
||||||
|
guint bundle_size;
|
||||||
|
gboolean do_aggregate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRtpH264PayClass
|
struct _GstRtpH264PayClass
|
||||||
|
|
|
@ -879,8 +879,10 @@ static const guint8 rtp_h264_list_lt_mtu_frame_data_avc[] =
|
||||||
0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00
|
0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NAL = 4 bytes */
|
/* Only the last NAL of each packet is computed by the strange algorithm in
|
||||||
static int rtp_h264_list_lt_mtu_bytes_sent_avc = 2 * (16 - 2 * 4);
|
* rtp_pipeline_chain_list()
|
||||||
|
*/
|
||||||
|
static int rtp_h264_list_lt_mtu_bytes_sent_avc = 7 + 3;
|
||||||
|
|
||||||
//static int rtp_h264_list_lt_mtu_mtu_size = 1024;
|
//static int rtp_h264_list_lt_mtu_mtu_size = 1024;
|
||||||
|
|
||||||
|
|
|
@ -539,6 +539,8 @@ GST_START_TEST (test_rtph264pay_reserved_nals)
|
||||||
guint8 nal_27[sizeof (h264_aud)];
|
guint8 nal_27[sizeof (h264_aud)];
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
g_object_set (h->element, "do-aggregate", FALSE, NULL);
|
||||||
|
|
||||||
gst_harness_set_src_caps_str (h,
|
gst_harness_set_src_caps_str (h,
|
||||||
"video/x-h264,alignment=nal,stream-format=byte-stream");
|
"video/x-h264,alignment=nal,stream-format=byte-stream");
|
||||||
|
|
||||||
|
@ -603,6 +605,7 @@ GST_START_TEST (test_rtph264pay_two_slices_timestamp)
|
||||||
sizeof (h264_idr_slice_2), GST_SECOND));
|
sizeof (h264_idr_slice_2), GST_SECOND));
|
||||||
fail_unless_equals_int (ret, GST_FLOW_OK);
|
fail_unless_equals_int (ret, GST_FLOW_OK);
|
||||||
|
|
||||||
|
gst_harness_push_event (h, gst_event_new_eos ());
|
||||||
|
|
||||||
fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
|
fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
|
||||||
|
|
||||||
|
@ -641,7 +644,8 @@ GST_END_TEST;
|
||||||
|
|
||||||
GST_START_TEST (test_rtph264pay_marker_for_flag)
|
GST_START_TEST (test_rtph264pay_marker_for_flag)
|
||||||
{
|
{
|
||||||
GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
|
GstHarness *h =
|
||||||
|
gst_harness_new_parse ("rtph264pay timestamp-offset=123 do-aggregate=0");
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||||
|
@ -680,7 +684,8 @@ GST_END_TEST;
|
||||||
|
|
||||||
GST_START_TEST (test_rtph264pay_marker_for_au)
|
GST_START_TEST (test_rtph264pay_marker_for_au)
|
||||||
{
|
{
|
||||||
GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
|
GstHarness *h =
|
||||||
|
gst_harness_new_parse ("rtph264pay timestamp-offset=123 do-aggregate=0");
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBuffer *slice1, *slice2, *buffer;
|
GstBuffer *slice1, *slice2, *buffer;
|
||||||
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||||
|
|
Loading…
Reference in a new issue