rtpgstpay: Add a create_from_adapter API and use a list of GstBufferList

This is necessary to fix event/caps sending. If we send a STREAM_START
packet, it will cause an error because the stream didn't receive its
caps and new-segment events, so we must wait for the first buffer before
sending the stream-start event buffer. However, the caps will be sent
at the same time and so the 'inline caps' will be set for the event.
We need to be able to payload individual packets (data, caps or events)
and only send them when we call flush.
This commit is contained in:
Youness Alaoui 2013-07-25 20:54:50 -04:00 committed by Wim Taymans
parent 0070ba76f2
commit 2d53289b6b
2 changed files with 36 additions and 7 deletions

View file

@ -120,6 +120,7 @@ static void
gst_rtp_gst_pay_init (GstRtpGSTPay * rtpgstpay) gst_rtp_gst_pay_init (GstRtpGSTPay * rtpgstpay)
{ {
rtpgstpay->adapter = gst_adapter_new (); rtpgstpay->adapter = gst_adapter_new ();
rtpgstpay->pending_buffers = NULL;
gst_rtp_base_payload_set_options (GST_RTP_BASE_PAYLOAD (rtpgstpay), gst_rtp_base_payload_set_options (GST_RTP_BASE_PAYLOAD (rtpgstpay),
"application", TRUE, "X-GST", 90000); "application", TRUE, "X-GST", 90000);
} }
@ -132,24 +133,28 @@ gst_rtp_gst_pay_finalize (GObject * obj)
rtpgstpay = GST_RTP_GST_PAY (obj); rtpgstpay = GST_RTP_GST_PAY (obj);
g_object_unref (rtpgstpay->adapter); g_object_unref (rtpgstpay->adapter);
if (rtpgstpay->pending_buffers)
g_list_free_full (rtpgstpay->pending_buffers,
(GDestroyNotify) gst_buffer_list_unref);
rtpgstpay->pending_buffers = NULL;
G_OBJECT_CLASS (parent_class)->finalize (obj); G_OBJECT_CLASS (parent_class)->finalize (obj);
} }
static GstFlowReturn static gboolean
gst_rtp_gst_pay_flush (GstRtpGSTPay * rtpgstpay, GstClockTime timestamp) gst_rtp_gst_pay_create_from_adapter (GstRtpGSTPay * rtpgstpay,
GstClockTime timestamp)
{ {
GstFlowReturn ret;
guint avail; guint avail;
guint frag_offset; guint frag_offset;
GstBufferList *list; GstBufferList *list;
frag_offset = 0;
avail = gst_adapter_available (rtpgstpay->adapter); avail = gst_adapter_available (rtpgstpay->adapter);
if (avail == 0) if (avail == 0)
return GST_FLOW_OK; return FALSE;
list = gst_buffer_list_new (); list = gst_buffer_list_new ();
frag_offset = 0;
while (avail) { while (avail) {
guint towrite; guint towrite;
@ -219,11 +224,34 @@ gst_rtp_gst_pay_flush (GstRtpGSTPay * rtpgstpay, GstClockTime timestamp)
/* and add to list */ /* and add to list */
gst_buffer_list_insert (list, -1, outbuf); gst_buffer_list_insert (list, -1, outbuf);
} }
/* push the whole buffer list at once */
ret = gst_rtp_base_payload_push_list (GST_RTP_BASE_PAYLOAD (rtpgstpay), list);
rtpgstpay->flags &= 0x70; rtpgstpay->flags &= 0x70;
rtpgstpay->etype = 0; rtpgstpay->etype = 0;
rtpgstpay->pending_buffers = g_list_append (rtpgstpay->pending_buffers, list);
return TRUE;
}
static GstFlowReturn
gst_rtp_gst_pay_flush (GstRtpGSTPay * rtpgstpay, GstClockTime timestamp)
{
GstFlowReturn ret = GST_FLOW_OK;
GList *iter, *next;
gst_rtp_gst_pay_create_from_adapter (rtpgstpay, timestamp);
for (iter = rtpgstpay->pending_buffers; iter; iter = next) {
GstBufferList *list = iter->data;
next = iter->next;
rtpgstpay->pending_buffers = g_list_remove_link (rtpgstpay->pending_buffers,
iter);
/* push the whole buffer list at once */
ret = gst_rtp_base_payload_push_list (GST_RTP_BASE_PAYLOAD (rtpgstpay),
list);
if (ret != GST_FLOW_OK)
break;
}
return ret; return ret;
} }

View file

@ -44,6 +44,7 @@ struct _GstRtpGSTPay
{ {
GstRTPBasePayload payload; GstRTPBasePayload payload;
GList *pending_buffers; // GstBufferList
GstAdapter *adapter; GstAdapter *adapter;
guint8 flags; guint8 flags;
guint8 etype; guint8 etype;