gstreamer: amlvideosink [1/1]

PD#SWPL-59183

Problem:
add eos detect flow & use playsink transfer mediasync iid

Solution:
add eos detect flow & use playsink transfer mediasync iid

Verify:
(detail info)

Change-Id: I9517f81a7e3072f5d711a9f224be863412e6d881
Signed-off-by: xuesong.jiang <xuesong.jiang@amlogic.com>
diff --git a/src/gstamlvideosink.c b/src/gstamlvideosink.c
index 7a76816..05760b5 100644
--- a/src/gstamlvideosink.c
+++ b/src/gstamlvideosink.c
@@ -48,7 +48,7 @@
   GST_DEBUG("dbg basesink ctxt lock | aml | %p | locking", obj); \
   g_mutex_lock(GST_OBJECT_GET_LOCK(obj)); \
   GST_DEBUG("dbg basesink ctxt lock | aml | %p | locked", obj); \
-} 
+}
 #endif
 
 #ifdef GST_OBJECT_UNLOCK
@@ -58,7 +58,7 @@
   GST_DEBUG("dbg basesink ctxt lock | aml |%p | unlocking", obj); \
   g_mutex_unlock(GST_OBJECT_GET_LOCK(obj)); \
   GST_DEBUG("dbg basesink ctxt lock | aml |%p | unlocked", obj); \
-} 
+}
 #endif
 
 /* signals */
@@ -82,11 +82,11 @@
     "RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, "     \
     "YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"
 #define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
-#define GST_USE_PLAYBIN 0
+#define GST_USE_PLAYBIN 1
 #define RENDER_DEVICE_NAME "wayland"
 #define USE_DMABUF TRUE
 
-#define DRMBP_EXTRA_BUF_SZIE_FOR_DISPLAY      10
+#define DRMBP_EXTRA_BUF_SZIE_FOR_DISPLAY      5
 #define DRMBP_LIMIT_MAX_BUFSIZE_TO_BUFSIZE    1
 #define DRMBP_UNLIMIT_MAX_BUFSIZE             0
 
@@ -99,8 +99,10 @@
     gboolean video_info_changed;
     gboolean use_dmabuf;
     gboolean is_flushing;
+    gboolean got_eos;
     gint mediasync_instanceid;
     GstSegment segment;
+
     /* property params */
     gboolean fullscreen;
     gboolean mute;
@@ -145,6 +147,8 @@
 static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink);
 #endif
 static gboolean gst_render_set_params(GstVideoSink *vsink);
+static void gst_emit_eos_signal(GstAmlVideoSink *vsink);
+static void gst_wait_eos_signal(GstAmlVideoSink *vsink);
 
 /* public interface definition */
 static void gst_aml_video_sink_class_init(GstAmlVideoSinkClass *klass)
@@ -195,9 +199,19 @@
 static void gst_aml_video_sink_init(GstAmlVideoSink *sink)
 {
     GstBaseSink *basesink = (GstBaseSink *)sink;
+
+    /* init eos detect */
+    sink->queued = 0;
+    sink->dequeued = 0;
+    sink->rendered = 0;
+    g_mutex_init (&sink->eos_lock);
+    g_cond_init (&sink->eos_cond);
+
     gst_pad_set_event_function(basesink->sinkpad, gst_aml_video_sink_pad_event);
+
     GST_AML_VIDEO_SINK_GET_PRIVATE(sink) = malloc (sizeof(GstAmlVideoSinkPrivate));
     gst_aml_video_sink_reset_private(sink);
+
     gst_base_sink_set_sync(basesink, FALSE);
 }
 
@@ -265,6 +279,10 @@
     GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
 
     GST_DEBUG_OBJECT(sink, "Finalizing aml video sink..");
+
+    g_mutex_clear (&sink->eos_lock);
+    g_cond_clear (&sink->eos_cond);
+
     gst_aml_video_sink_reset_private(sink);
     if(GST_AML_VIDEO_SINK_GET_PRIVATE(sink))
         free(GST_AML_VIDEO_SINK_GET_PRIVATE(sink));
@@ -450,9 +468,9 @@
 
     if (sink_priv->preroll_buffer && sink_priv->preroll_buffer == buffer)
     {
-        GST_LOG_OBJECT(sink, "get preroll buffer:%p 2nd time, goto done", buffer);
+        GST_LOG_OBJECT(sink, "get preroll buffer:%p 2nd time, goto ret", buffer);
         sink_priv->preroll_buffer = NULL;
-        goto done;
+        goto ret;
     }
     if (G_UNLIKELY(((GstBaseSink *)sink)->need_preroll))
     {
@@ -470,7 +488,7 @@
             goto error;
         }
         GST_DEBUG_OBJECT(sink, "in flushing flow, release the buffer directly");
-        goto done;
+        goto flushing;
     }
 
     if (sink_priv->video_info_changed)
@@ -495,20 +513,27 @@
         goto error;
     }
 
+    GST_OBJECT_UNLOCK(vsink);
+
     if (render_display_frame(sink_priv->render_device_handle, tunnel_lib_buf_wrap) == -1)
     {
         GST_ERROR_OBJECT(sink, "render lib: display frame fail");
         goto error;
     }
 
-done:
-    GST_OBJECT_UNLOCK(vsink);
+    sink->queued++;
     GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued ok", buffer);
     return ret;
+
 error:
-    GST_OBJECT_UNLOCK(vsink);
     GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued error", buffer);
     ret = GST_FLOW_CUSTOM_ERROR_2;
+    goto ret;
+flushing:
+    GST_DEBUG_OBJECT(sink, "flushing when buf:%p", buffer);
+    goto ret;
+ret:
+    GST_OBJECT_UNLOCK(vsink);
     return ret;
 }
 
@@ -532,7 +557,13 @@
     {
         GST_INFO_OBJECT(sink, "flush stop");
 
+        gst_wait_eos_signal(sink);
+
         GST_OBJECT_LOCK(sink);
+        sink->queued = 0;
+        sink->dequeued = 0;
+        sink->rendered = 0;
+        sink_priv->got_eos = FALSE;
         sink_priv->is_flushing = FALSE;
         GST_OBJECT_UNLOCK(sink);
         break;
@@ -546,6 +577,14 @@
         GST_OBJECT_UNLOCK(sink);
         break;
     }
+    case GST_EVENT_EOS:
+    {
+        GST_OBJECT_LOCK(sink);
+        sink_priv->got_eos = TRUE;
+        GST_OBJECT_UNLOCK(sink);
+
+        gst_wait_eos_signal(sink);
+    }
     default:
     {
         GST_DEBUG_OBJECT(sink, "pass to basesink");
@@ -571,28 +610,50 @@
     GstAmlVideoSink *sink = (GstAmlVideoSink *)userData;
     switch (type)
     {
+    case MSG_DISPLAYED_BUFFER:
+    {
+        GST_LOG_OBJECT(sink, "get message: MSG_DISPLAYED_BUFFER from tunnel lib");
+        GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
+        RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
+        RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
+        GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
+        if (buffer)
+        {
+            sink->rendered++;
+            if ((sink_priv->got_eos || sink_priv->is_flushing) && sink->queued == sink->rendered)
+            {
+                gst_emit_eos_signal(sink);
+            }
+        }
+        else
+        {
+            GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_DISPLAYED_BUFFER");
+        }
+
+        GST_DEBUG_OBJECT(sink, "buf out:%p\n\
+                                planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d\n\
+                                pts:%lld, buf stat | queued:%d, dequeued:%d, rendered:%d",
+                        buffer,
+                        dmabuf->planeCnt, dmabuf->fd[0], dmabuf->fd[1],
+                        buffer? GST_BUFFER_PTS(buffer):-1, sink->queued, sink->dequeued, sink->rendered);
+        break;
+    }
     case MSG_RELEASE_BUFFER:
     {
         GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib");
         GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
         RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
-        RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
         GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
 
-        GST_DEBUG_OBJECT(sink, "dbg: buf out:%p, planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d", 
-                        tunnel_lib_buf_wrap->priv, 
-                        dmabuf->planeCnt, 
-                        dmabuf->fd[0], 
-                        dmabuf->fd[1]);
-
         if (buffer)
         {
-            GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib, buffer:%p, from pool:%p", buffer, buffer->pool);
+            GST_DEBUG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib, buffer:%p, from pool:%p", buffer, buffer->pool);
             gst_buffer_unref(buffer);
+            sink->dequeued++;
         }
         else
         {
-            GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer");
+            GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_RELEASE_BUFFER");
         }
         render_free_render_buffer_wrap(sink_priv->render_device_handle, tunnel_lib_buf_wrap);
         break;
@@ -760,6 +821,11 @@
 #if GST_USE_PLAYBIN
     GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
     GstElement *asink = gst_aml_video_sink_find_audio_sink(vsink);
+    if (!asink)
+    {
+        GST_DEBUG_OBJECT(vsink, "pipeline don't have audio sink element");
+        return FALSE;
+    }
     GstClock *amlclock = gst_aml_hal_asink_get_clock((GstElement *)asink);
     gboolean ret = TRUE;
     if (amlclock)
@@ -800,6 +866,23 @@
     return ret;
 }
 
+static void gst_emit_eos_signal(GstAmlVideoSink *vsink)
+{
+    GST_DEBUG_OBJECT(vsink, "emit eos signal");
+    g_mutex_lock(&vsink->eos_lock);
+    g_cond_signal (&vsink->eos_cond);
+    g_mutex_unlock(&vsink->eos_lock);
+}
+
+static void gst_wait_eos_signal(GstAmlVideoSink *vsink)
+{
+    GST_DEBUG_OBJECT(vsink, "waitting eos signal");
+    g_mutex_lock(&vsink->eos_lock);
+    g_cond_wait (&vsink->eos_cond, &vsink->eos_lock);
+    g_mutex_unlock(&vsink->eos_lock);
+    GST_DEBUG_OBJECT(vsink, "waitted eos signal");
+}
+
 #if GST_USE_PLAYBIN
 static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink)
 {
@@ -815,14 +898,13 @@
         {
             gst_object_unref(elementPrev);
         }
-        GST_DEBUG_OBJECT(sink, "dbg-0, element:%p, parent:%p", element, gst_element_get_parent(element));
+        //TODO use this func will ref elment,but when unref these element?
         element = GST_ELEMENT_CAST(gst_element_get_parent(element));
         if (element)
         {
             elementPrev = pipeline;
             pipeline = element;
         }
-        GST_DEBUG_OBJECT(sink, "dbg-1");
     } while (element != 0);
 
     if (pipeline)
@@ -882,7 +964,7 @@
 
         gst_object_unref(pipeline);
     }
-    GST_DEBUG_OBJECT(sink, "trace out");
+    GST_DEBUG_OBJECT(sink, "trace out get audioSink:%p", audioSink);
     return audioSink;
 }
 #endif
@@ -893,14 +975,14 @@
     GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
     GstVideoInfo *video_info = &(sink_priv->video_info);
 
-    RenderWindowSize window_size = {0, 0, video_info->width, video_info->height};
+    // RenderWindowSize window_size = {0, 0, video_info->width, video_info->height};
     RenderFrameSize frame_size = {video_info->width, video_info->height};
     GstVideoFormat format = video_info->finfo? video_info->finfo->format : GST_VIDEO_FORMAT_UNKNOWN;
-    if (render_set(sink_priv->render_device_handle, KEY_WINDOW_SIZE, &window_size) == -1)
-    {
-        GST_ERROR_OBJECT(vsink, "tunnel lib: set window size error");
-        return FALSE;
-    }
+    // if (render_set(sink_priv->render_device_handle, KEY_WINDOW_SIZE, &window_size) == -1)
+    // {
+    //     GST_ERROR_OBJECT(vsink, "tunnel lib: set window size error");
+    //     return FALSE;
+    // }
     if (render_set(sink_priv->render_device_handle, KEY_FRAME_SIZE, &frame_size) == -1)
     {
         GST_ERROR_OBJECT(vsink, "tunnel lib: set frame size error");
diff --git a/src/gstamlvideosink.h b/src/gstamlvideosink.h
index b19be70..c111bc7 100644
--- a/src/gstamlvideosink.h
+++ b/src/gstamlvideosink.h
@@ -47,6 +47,14 @@
 struct _GstAmlVideoSink
 {
   GstVideoSink parent;
+
+  /* eos detect */
+  gint queued;
+  gint dequeued;
+  gint rendered;
+  GMutex eos_lock;
+  GCond eos_cond;
+
   GstAmlVideoSinkPrivate *priv;
 };