vaapidecode: support seek actions
authorWind Yuan <feng.yuan@intel.com>
Fri, 30 Nov 2012 05:06:10 +0000 (13:06 +0800)
committerzhongcong <congx.zhong@intel.com>
Thu, 28 Feb 2013 08:16:33 +0000 (16:16 +0800)
vaapidecode need clear all decoder's buffers when
GST_EVENT_FLUSH_STOP/GST_EVENT_NEWSEGMENT happened

Change-Id: I83606f6b619c4501b43bf868bc92787b670fab88

gst-libs/gst/vaapi/gstvaapidecoder.c
gst-libs/gst/vaapi/gstvaapidecoder.h
gst/vaapi/gstvaapidecode.c
gst/vaapi/gstvaapidecode.h

index b0ad5ab..0df566d 100644 (file)
@@ -452,6 +452,22 @@ gst_vaapi_decoder_get_surface(
 }
 
 void
+gst_vaapi_decoder_clear_buffer(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    GstVaapiDecoderClass * const klass = GST_VAAPI_DECODER_GET_CLASS(decoder);
+
+    if (klass->clear_buffer)
+        klass->clear_buffer(decoder);
+
+    if (priv->buffers)
+        clear_queue(priv->buffers, (GDestroyNotify)destroy_buffer);
+
+    if (priv->surfaces)
+        clear_queue(priv->surfaces, (GDestroyNotify)g_object_unref);
+}
+
+void
 gst_vaapi_decoder_set_picture_size(
     GstVaapiDecoder    *decoder,
     guint               width,
index b5a397b..ebcead9 100644 (file)
@@ -111,6 +111,7 @@ struct _GstVaapiDecoderClass {
     GObjectClass parent_class;
 
     GstVaapiDecoderStatus (*decode)(GstVaapiDecoder *decoder, GstBuffer *buffer);
+    void                  (*clear_buffer)(GstVaapiDecoder *decoder);
 };
 
 GType
@@ -131,6 +132,9 @@ gst_vaapi_decoder_get_surface(
     GstVaapiDecoderStatus *pstatus
 );
 
+void
+gst_vaapi_decoder_clear_buffer(GstVaapiDecoder *decoder);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_DECODER_H */
index e58a31b..5e2c8ef 100644 (file)
@@ -178,6 +178,19 @@ gst_vaapidecode_release(GstVaapiDecode *decode, GObject *dead_object)
     g_mutex_unlock(&decode->decoder_mutex);
 }
 
+static gboolean
+gst_vaapidecode_is_valid_time(GstVaapiDecode *decode, gint64 time)
+{
+    if (decode->segment.format != GST_FORMAT_TIME)
+        return TRUE;
+    if (decode->segment.stop != -1 && time != -1 && time > decode->segment.stop)
+        return FALSE;
+    if (decode->segment.start != -1 && time != -1 && time < decode->segment.start)
+        return FALSE;
+
+    return TRUE;
+}
+
 static GstFlowReturn
 gst_vaapidecode_step(GstVaapiDecode *decode)
 {
@@ -227,6 +240,12 @@ gst_vaapidecode_step(GstVaapiDecode *decode)
             goto error_create_buffer;
 
         timestamp = GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
+        if (GST_CLOCK_TIME_IS_VALID(timestamp) &&
+            !gst_vaapidecode_is_valid_time(decode, (gint64)timestamp)) {
+            g_object_unref(proxy);
+            continue;
+        }
+
         if (!decode->render_time_base)
             decode->render_time_base = g_get_monotonic_time();
         decode->last_buffer_time = timestamp;
@@ -387,6 +406,32 @@ gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps)
     return gst_vaapidecode_create(decode, caps);
 }
 
+static void
+gst_vaapidecode_configure_segment(
+    GstVaapiDecode *decode,
+    GstEvent *event
+)
+{
+    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);
+    if (format == GST_FORMAT_TIME) {
+        gst_segment_set_newsegment_full(&decode->segment, update, rate, applied_rate,
+                                        format, start, stop, time);
+        GST_DEBUG("configured new segment, update %d, rate %lf, applied rate %lf, "
+                  "format GST_FORMAT_TIME, "
+                  "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT ", "
+                  "time %" GST_TIME_FORMAT,
+                  update, rate, applied_rate,
+                  GST_TIME_ARGS(start), GST_TIME_ARGS(stop),
+                  GST_TIME_ARGS(time));
+    }
+}
+
 static gboolean
 gst_vaapidecode_flush(GstVaapiDecode *decode)
 {
@@ -665,6 +710,11 @@ gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
 
     /* Propagate event downstream */
     switch (GST_EVENT_TYPE(event)) {
+    case GST_EVENT_FLUSH_STOP:
+        gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
+        if (decode->decoder)
+            gst_vaapi_decoder_clear_buffer(decode->decoder);
+        break;
     case GST_EVENT_NEWSEGMENT:
         if (decode->delayed_new_seg) {
             gst_event_unref(decode->delayed_new_seg);
@@ -674,6 +724,7 @@ gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
             decode->delayed_new_seg = gst_event_ref(event);
             return TRUE;
         }
+        gst_vaapidecode_configure_segment(decode, event);
         break;
     case GST_EVENT_EOS:
         if (!gst_vaapidecode_flush(decode)) {
@@ -730,6 +781,7 @@ gst_vaapidecode_init(GstVaapiDecode *decode)
 
     g_mutex_init(&decode->decoder_mutex);
     g_cond_init(&decode->decoder_ready);
+    gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
 
     /* Pad through which data comes in to the element */
     decode->sinkpad = gst_pad_new_from_template(
index 87e2807..c8b2583 100644 (file)
@@ -72,6 +72,7 @@ struct _GstVaapiDecode {
     GstCaps            *decoder_caps;
     GstCaps            *allowed_caps;
     GstEvent           *delayed_new_seg;
+    GstSegment          segment;
     gint64              render_time_base;
     GstClockTime        last_buffer_time;
     unsigned int        is_ready        : 1;