diff options
author | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2009-10-27 20:57:05 +0100 |
---|---|---|
committer | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2009-11-22 22:38:08 +0100 |
commit | 51caa55d4e0166f9816698c37cd4ba7c202b85df (patch) | |
tree | 64fb72324f6cd5461cde7bc02f3efc7addfb6f70 /sys | |
parent | 55b108f7cad4149847a5f081794c697bdac7b5b1 (diff) |
vdpauvideopostprocess: implement basic qos handling
Diffstat (limited to 'sys')
-rw-r--r-- | sys/vdpau/gstvdpvideopostprocess.c | 96 | ||||
-rw-r--r-- | sys/vdpau/gstvdpvideopostprocess.h | 4 |
2 files changed, 99 insertions, 1 deletions
diff --git a/sys/vdpau/gstvdpvideopostprocess.c b/sys/vdpau/gstvdpvideopostprocess.c index e0db37885..da7661a65 100644 --- a/sys/vdpau/gstvdpvideopostprocess.c +++ b/sys/vdpau/gstvdpvideopostprocess.c @@ -626,6 +626,9 @@ gst_vdp_vpp_start (GstVdpVideoPostProcess * vpp) vpp->interlaced = FALSE; vpp->field_duration = GST_CLOCK_TIME_NONE; + vpp->earliest_time = GST_CLOCK_TIME_NONE; + vpp->discont = FALSE; + vpp->mixer = VDP_INVALID_HANDLE; vpp->device = NULL; @@ -654,8 +657,9 @@ gst_vdp_vpp_chain (GstPad * pad, GstBuffer * buffer) GstVdpVideoPostProcess *vpp = GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad)); - GstFlowReturn ret = GST_FLOW_OK; + GstClockTime qostime; + GstFlowReturn ret = GST_FLOW_OK; GstVdpPicture current_pic; guint32 video_surfaces_past_count; @@ -664,6 +668,47 @@ gst_vdp_vpp_chain (GstPad * pad, GstBuffer * buffer) guint32 video_surfaces_future_count; VdpVideoSurface video_surfaces_future[MAX_PICTURES]; + /* can only do QoS if the segment is in TIME */ + if (vpp->segment.format != GST_FORMAT_TIME) + goto no_qos; + + /* QOS is done on the running time of the buffer, get it now */ + qostime = gst_segment_to_running_time (&vpp->segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + + if (qostime != -1) { + gboolean need_skip; + GstClockTime earliest_time; + + /* lock for getting the QoS parameters that are set (in a different thread) + * with the QOS events */ + GST_OBJECT_LOCK (vpp); + earliest_time = vpp->earliest_time; + /* check for QoS, don't perform conversion for buffers + * that are known to be late. */ + need_skip = GST_CLOCK_TIME_IS_VALID (earliest_time) && qostime != -1 && + qostime <= earliest_time; + + GST_OBJECT_UNLOCK (vpp); + + if (need_skip) { + GST_DEBUG_OBJECT (vpp, "skipping transform: qostime %" + GST_TIME_FORMAT " <= %" GST_TIME_FORMAT, + GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time)); + /* mark discont for next buffer */ + vpp->discont = TRUE; + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + } + +no_qos: + + if (vpp->discont) { + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + vpp->discont = FALSE; + } + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (vpp, "Received discont buffer"); gst_vdp_vpp_flush (vpp); @@ -903,6 +948,35 @@ video_buffer_error: } static gboolean +gst_vdp_vpp_src_event (GstPad * pad, GstEvent * event) +{ + GstVdpVideoPostProcess *vpp = + GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad)); + gboolean res; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_QOS: + { + gdouble proportion; + GstClockTimeDiff diff; + GstClockTime timestamp; + + gst_event_parse_qos (event, &proportion, &diff, ×tamp); + + GST_OBJECT_LOCK (vpp); + vpp->earliest_time = timestamp + diff; + GST_OBJECT_UNLOCK (vpp); + } + default: + res = gst_pad_event_default (pad, event); + } + + gst_object_unref (vpp); + + return res; +} + +static gboolean gst_vdp_vpp_sink_event (GstPad * pad, GstEvent * event) { GstVdpVideoPostProcess *vpp = @@ -919,6 +993,23 @@ gst_vdp_vpp_sink_event (GstPad * pad, GstEvent * event) break; } + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate, applied_rate; + GstFormat format; + gint64 start, stop, time; + + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &time); + + GST_OBJECT_LOCK (vpp); + gst_segment_set_newsegment_full (&vpp->segment, update, rate, + applied_rate, format, start, stop, time); + GST_OBJECT_UNLOCK (vpp); + + res = gst_pad_push_event (vpp->srcpad, event); + } default: res = gst_pad_event_default (pad, event); } @@ -1189,6 +1280,9 @@ gst_vdp_vpp_init (GstVdpVideoPostProcess * vpp, vpp->srcpad = gst_pad_new_from_static_template (&src_template, "src"); gst_element_add_pad (GST_ELEMENT (vpp), vpp->srcpad); + gst_pad_set_event_function (vpp->srcpad, + GST_DEBUG_FUNCPTR (gst_vdp_vpp_src_event)); + /* SINK PAD */ sink_template = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (gclass), "sink"); diff --git a/sys/vdpau/gstvdpvideopostprocess.h b/sys/vdpau/gstvdpvideopostprocess.h index cfd23a0a1..9aa57a920 100644 --- a/sys/vdpau/gstvdpvideopostprocess.h +++ b/sys/vdpau/gstvdpvideopostprocess.h @@ -77,6 +77,10 @@ struct _GstVdpVideoPostProcess gboolean interlaced; GstClockTime field_duration; + + GstSegment segment; + GstClockTime earliest_time; + gboolean discont; GstVdpDevice *device; VdpVideoMixer mixer; |