libvideorender: CF2 add keep last frame for weston [1/1]

PD#TV-114757

Problem:
open source code of weston don't keep last frame when
playback end

Solution:
1.add aml config api for weston
2.add keep last frame feature

Verify:
ap222

Change-Id: I8368d5395160c8e4a0803bd9e21a7f85ef002985
Signed-off-by: fei.deng <fei.deng@amlogic.com>
diff --git a/weston/Makefile b/weston/Makefile
index 4065490..fc9e286 100644
--- a/weston/Makefile
+++ b/weston/Makefile
@@ -60,7 +60,9 @@
 	$(PROTOCOL_PATH)/simpleshell-server-protocol.h \
 	$(PROTOCOL_PATH)/wayland-client-protocol.h \
 	$(PROTOCOL_PATH)/weston-direct-display-protocol.c \
-	$(PROTOCOL_PATH)/weston-direct-display-client-protocol.h
+	$(PROTOCOL_PATH)/weston-direct-display-client-protocol.h \
+	$(PROTOCOL_PATH)/aml-config-protocol.c \
+	$(PROTOCOL_PATH)/aml-config-client-protocol.h
 
 OBJ_WESTON_DISPLAY = \
 	wayland_display.o \
diff --git a/weston/wayland-protocol/aml-config.xml b/weston/wayland-protocol/aml-config.xml
new file mode 100644
index 0000000..96293c6
--- /dev/null
+++ b/weston/wayland-protocol/aml-config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="aml_config">
+
+  <copyright>
+    Copyright © 2019 Collabora Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <interface name="aml_config" version="1">
+    <description summary="aml config for client">
+      Weston extension to inform the clients of the new interface added by amlogic.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy factory object">
+        Destroys the factory object, but does not affect any other objects.
+      </description>
+    </request>
+
+    <event name="aml_config_list">
+      <description summary="aml config list">
+  The aml_config_list event inform the clients of the new interface add by amlogic
+      </description>
+      <arg name="list" type="string"
+     summary="the new interface added by amlogic"/>
+    </event>
+  </interface>
+</protocol>
diff --git a/weston/wayland-protocol/wayland.xml b/weston/wayland-protocol/wayland.xml
index ed7b151..e5f4730 100644
--- a/weston/wayland-protocol/wayland.xml
+++ b/weston/wayland-protocol/wayland.xml
@@ -414,13 +414,11 @@
 	optimization for GL(ES) compositors with wl_shm clients.
       </description>
     </event>
-    <!--
     <event name="drop">
       <description summary="compositor drop buffer">
       Sent when this wl_buffer is dropped by the compositor.
       </description>
     </event>
-    -->
   </interface>
 
   <interface name="wl_data_offer" version="3">
@@ -1694,6 +1692,15 @@
       <arg name="pts_hi" type="uint" summary="high 32 bits of frame pts"/>
       <arg name="pts_lo" type="uint" summary="low 32 bits of frame pts"/>
     </request>
+    <request name="keep_last_frame">
+      <description summary="keep last frame or not">
+    This request sets a value for current surface.
+    The value is uesd to inform server to keep the last frame or not for
+    current surface when the video is over. The value will not change until
+    next different value is committed.
+      </description>
+      <arg name="keep_last_frame" type="uint" summary="keep last frame or not"/>
+    </request>
    </interface>
 
   <interface name="wl_seat" version="7">
diff --git a/weston/wayland_buffer.cpp b/weston/wayland_buffer.cpp
index 3ccdb78..fc17408 100644
--- a/weston/wayland_buffer.cpp
+++ b/weston/wayland_buffer.cpp
@@ -91,13 +91,14 @@
     }
 }
 
-//static const struct wl_buffer_listener buffer_listener = {
-//    WaylandBuffer::bufferRelease,
-//    WaylandBuffer::bufferdroped
-//};
- static const struct wl_buffer_listener buffer_listener = {
-     WaylandBuffer::bufferRelease
- };
+static const struct wl_buffer_listener buffer_with_drop_listener = {
+   WaylandBuffer::bufferRelease,
+   WaylandBuffer::bufferdroped,
+};
+
+static const struct wl_buffer_listener buffer_listener = {
+    WaylandBuffer::bufferRelease
+};
 
 /*if we commit buffers to weston too fast,it causes weston can't invoke this callback*/
 void WaylandBuffer::frameDisplayedCallback(void *data, struct wl_callback *callback, uint32_t time)
@@ -121,6 +122,7 @@
 int WaylandBuffer::constructWlBuffer(RenderBuffer *buf)
 {
     struct wl_buffer * wlbuffer = NULL;
+    WaylandDisplay::AmlConfigAPIList *amlConfigAPI = mDisplay->getAmlConfigAPIList();
 
     mRenderBuffer = buf;
     if (mWaylandWlWrap) {
@@ -141,7 +143,11 @@
     }
 
     /*register buffer release listen*/
-    wl_buffer_add_listener (wlbuffer, &buffer_listener, this);
+    if (amlConfigAPI->enableDropFrame) {
+        wl_buffer_add_listener (wlbuffer, &buffer_with_drop_listener, this);
+    } else {
+        wl_buffer_add_listener (wlbuffer, &buffer_listener, this);
+    }
 
     return NO_ERROR;
 }
diff --git a/weston/wayland_display.cpp b/weston/wayland_display.cpp
index 36f2583..90a1608 100644
--- a/weston/wayland_display.cpp
+++ b/weston/wayland_display.cpp
@@ -179,6 +179,7 @@
     }
 }
 
+//aml weston always add crtcIndex in callbacks.
 static const struct wl_output_listener outputListener = {
     WaylandDisplay::outputHandleGeometry,
     WaylandDisplay::outputHandleMode,
@@ -451,6 +452,33 @@
     WaylandDisplay::handleXdgSurfaceConfigure,
 };
 
+void WaylandDisplay::amlConfigure(void *data, struct aml_config *config, const char *list) {
+    WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
+    TRACE(self->mLogCategory,"aml_config:%s",list);
+    if (list && strlen(list) > 0) {
+        if (strstr(list, "set_video_plane")) {
+            TRACE(self->mLogCategory,"weston enable set_video_plane");
+            self->mAmlConfigAPIList.enableSetVideoPlane = true;
+        }
+        if (strstr(list, "set_pts")) {
+            TRACE(self->mLogCategory,"weston enable set_pts");
+            self->mAmlConfigAPIList.enableSetPts = true;
+        }
+        if (strstr(list, "drop")) {
+            TRACE(self->mLogCategory,"weston enable drop");
+            self->mAmlConfigAPIList.enableDropFrame = true;
+        }
+        if (strstr(list, "keep_last_frame")) {
+            TRACE(self->mLogCategory,"weston enable keep_last_frame");
+            self->mAmlConfigAPIList.enableKeepLastFrame = true;
+        }
+    }
+}
+
+static const struct aml_config_listener aml_config_listener = {
+    WaylandDisplay::amlConfigure,
+};
+
 void
 WaylandDisplay::registryHandleGlobal (void *data, struct wl_registry *registry,
     uint32_t name, const char *interface, uint32_t version)
@@ -522,6 +550,9 @@
         //wl_seat_add_listener(self->mSeat, &seat_listener, (void *)self);
     } else if (strcmp(interface, "weston_direct_display_v1") == 0) {
         self->mDirect_display = (struct weston_direct_display_v1 *)wl_registry_bind(registry,name, &weston_direct_display_v1_interface, 1);
+    } else if (strcmp(interface, "aml_config") == 0) {
+        self->mAmlConfig = (struct aml_config*)wl_registry_bind(registry, name, &aml_config_interface, 1);
+        aml_config_add_listener(self->mAmlConfig, &aml_config_listener, (void *)self);
     }
 }
 
@@ -602,7 +633,6 @@
     mNoBorderUpdate = false;
     mAreaShmBuffer = NULL;
     mCommitCnt = 0;
-    mIsSendPtsToWeston = false;
     mReCommitAreaSurface = false;
     mAreaSurface = NULL;
     mAreaSurfaceWrapper = NULL;
@@ -610,35 +640,20 @@
     mVideoSubSurface = NULL;
     mXdgSurfaceConfigured = false;
     mPip = 0;
-    mIsSendVideoPlaneId = true;
     mCurrentDisplayOutput = &mOutput[0];
     mUpdateRenderRectangle = false;
     memset(&mRenderRect, 0, sizeof(struct Rectangle));
     memset(&mVideoRect, 0, sizeof(struct Rectangle));
     memset(&mWindowRect, 0, sizeof(struct Rectangle));
     mFullScreen = true; //default is full screen
-    char *env = getenv("VIDEO_RENDER_SEND_PTS_TO_WESTON");
-    if (env) {
-        int isSet = atoi(env);
-        if (isSet > 0) {
-            mIsSendPtsToWeston = true;
-            INFO(mLogCategory,"set send pts to weston");
-        } else {
-            mIsSendPtsToWeston = false;
-            INFO(mLogCategory,"do not send pts to weston");
-        }
-    }
-    env = getenv("VIDEO_RENDER_SEND_VIDEO_PLANE_ID_TO_WESTON");
-    if (env) {
-        int isSet = atoi(env);
-        if (isSet == 0) {
-            mIsSendVideoPlaneId = false;
-            INFO(mLogCategory,"do not send video plane id to weston");
-        } else {
-            mIsSendVideoPlaneId = true;
-            INFO(mLogCategory,"send video plane id to weston");
-        }
-    }
+    mAmlConfig = NULL;
+    mKeepLastFrame = 0; //default is off keep last frame
+    //weston config private api
+    mAmlConfigAPIList.enableDropFrame = false;
+    mAmlConfigAPIList.enableKeepLastFrame = false;
+    mAmlConfigAPIList.enableSetPts = false;
+    mAmlConfigAPIList.enableSetVideoPlane = false;
+
     for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
         mOutput[i].wlOutput = NULL;
         mOutput[i].offsetX = 0;
@@ -722,11 +737,15 @@
     createXdgShellWindowSurface();
 
     //config weston video plane
-    if (mIsSendVideoPlaneId) {
+    if (mAmlConfigAPIList.enableSetVideoPlane) {
         INFO(mLogCategory,"set weston video plane:%d",mPip);
         wl_surface_set_video_plane(mVideoSurfaceWrapper, mPip);
     }
 
+    if (mKeepLastFrame) {
+        setKeepLastFrame(mKeepLastFrame);
+    }
+
     //run wl display queue dispatch
     DEBUG(mLogCategory,"To run wl display dispatch queue");
     run("display queue");
@@ -786,6 +805,11 @@
         mWlDisplayWrapper = NULL;
     }
 
+    if (mAmlConfig) {
+        aml_config_destroy(mAmlConfig);
+        mAmlConfig = NULL;
+    }
+
     if (mWlQueue) {
         wl_event_queue_destroy (mWlQueue);
         mWlQueue = NULL;
@@ -1291,7 +1315,7 @@
         TRACE(mLogCategory,"++attach,renderbuf:%p,wl_buffer:%p(0,0,%d,%d),pts:%lld,commitCnt:%d",buf,wlbuffer,mVideoRect.w,mVideoRect.h,buf->pts,mCommitCnt);
         waylandBuf->attach(mVideoSurfaceWrapper);
 
-        if (mIsSendPtsToWeston) {
+        if (mAmlConfigAPIList.enableSetPts) {
             TRACE(mLogCategory,"display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
             wl_surface_set_pts(mVideoSurfaceWrapper, hiPts, lowPts);
         }
@@ -1550,4 +1574,13 @@
     wl_surface_commit (mVideoSurfaceWrapper);
     wl_surface_attach (mAreaSurfaceWrapper, NULL, 0, 0);
     wl_surface_commit (mAreaSurfaceWrapper);
+}
+
+void WaylandDisplay::setKeepLastFrame(int keep)
+{
+    mKeepLastFrame = keep;
+    if (mVideoSurfaceWrapper && mAmlConfigAPIList.enableKeepLastFrame) {
+        INFO(mLogCategory,"keep last frame:%d",keep);
+        wl_surface_keep_last_frame(mVideoSurfaceWrapper, keep);
+    }
 }
\ No newline at end of file
diff --git a/weston/wayland_display.h b/weston/wayland_display.h
index 300bcfc..de07fcd 100644
--- a/weston/wayland_display.h
+++ b/weston/wayland_display.h
@@ -29,6 +29,7 @@
 #include "linux-explicit-synchronization-unstable-v1-client-protocol.h"
 #include "viewporter-client-protocol.h"
 #include "weston-direct-display-client-protocol.h"
+#include "aml-config-client-protocol.h"
 #include "wayland-cursor.h"
 #include "Thread.h"
 #include "Poll.h"
@@ -44,6 +45,13 @@
 
 class WaylandDisplay : public Tls::Thread{
   public:
+    typedef struct {
+        bool enableSetVideoPlane;
+        bool enableSetPts;
+        bool enableDropFrame;
+        bool enableKeepLastFrame;
+    } AmlConfigAPIList;
+
     WaylandDisplay(WaylandPlugin *plugin, int logCategory);
     virtual ~WaylandDisplay();
     /**
@@ -103,6 +111,15 @@
         return NULL;
     };
     /**
+     * @brief Set the Keep Last Frame when playback end
+     * #param  keep 1:keep last frame, 0:do not keep
+     */
+    void setKeepLastFrame(int keep);
+    AmlConfigAPIList *getAmlConfigAPIList()
+    {
+        return &mAmlConfigAPIList;
+    };
+    /**
      * @brief Set the Select Display Output index
      *
      * @param output selected display output index
@@ -129,10 +146,6 @@
     */
     void setPip(int pip);
 
-    bool isSentPtsToWeston() {
-        return mIsSendPtsToWeston;
-    }
-
     void setRedrawingPending(bool val) {
         mRedrawingPending = val;
     };
@@ -229,6 +242,7 @@
     static void handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
                                     int32_t width, int32_t height, struct wl_array *states);
     static void handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface, uint32_t serial);
+    static void amlConfigure(void *data, struct aml_config *config, const char *list);
   private:
     typedef struct DisplayOutput {
         struct wl_output *wlOutput;
@@ -277,6 +291,7 @@
     struct wl_touch *mTouch;
     struct wl_keyboard *mKeyboard;
     struct weston_direct_display_v1 *mDirect_display;
+    struct aml_config *mAmlConfig;
 
     /*primary output will signal first,so 0 index is primary wl_output, 1 index is extend wl_output*/
     DisplayOutput mOutput[DEFAULT_DISPLAY_OUTPUT_NUM]; //info about wl_output
@@ -311,8 +326,6 @@
     Tls::Mutex mConfigureMutex;
     bool mFullScreen; //default full screen
 
-    bool mIsSendPtsToWeston;
-
     bool mReCommitAreaSurface;
 
     bool mUpdateRenderRectangle;
@@ -341,8 +354,9 @@
     std::unordered_map<int64_t, WaylandBuffer *> mCommittedBufferMap;
 
     int mPip; //pip video, 1->pip, 0: main video(default)
-    bool mIsSendVideoPlaneId; //default true,otherwise false if set
     bool mRedrawingPending;//it will be true when weston obtains a buffer rendering,otherwise false when rendered
+    AmlConfigAPIList mAmlConfigAPIList;
+    int mKeepLastFrame; //keep last frame when playback end
 };
 
 #endif /*__WAYLAND_DISPLAY_H__*/
\ No newline at end of file
diff --git a/weston/wayland_plugin.cpp b/weston/wayland_plugin.cpp
index 37fcace..015b07a 100644
--- a/weston/wayland_plugin.cpp
+++ b/weston/wayland_plugin.cpp
@@ -104,7 +104,8 @@
      * we should create a post buffer thread to
      * send buffer by mono time
      */
-    if (!mDisplay->isSentPtsToWeston()) {
+    WaylandDisplay::AmlConfigAPIList *amlconfig = mDisplay->getAmlConfigAPIList();
+    if (!amlconfig->enableSetPts) {
             DEBUG(mLogCategory,"run frame post thread");
         setThreadPriority(50);
         run("waylandPostThread");
@@ -124,10 +125,11 @@
      * push buffer to queue, the buffer will send to
      * weston in post thread
      */
-    if (!mDisplay->isSentPtsToWeston()) {
+    WaylandDisplay::AmlConfigAPIList *amlconfig = mDisplay->getAmlConfigAPIList();
+    if (!amlconfig->enableSetPts) {
         buffer->time = displayTime;
         mQueue->push(buffer);
-            DEBUG(mLogCategory,"queue size:%d",mQueue->getCnt());
+        DEBUG(mLogCategory,"queue size:%d",mQueue->getCnt());
     } else {
         mDisplay->displayFrameBuffer(buffer, displayTime);
     }
@@ -233,6 +235,11 @@
             bool mImmediatelyOutput = (*(int *)(value)) > 0? true: false;
             DEBUG(mLogCategory, "Set immediately output:%d",mImmediatelyOutput);
         } break;
+        case PLUGIN_KEY_KEEP_LAST_FRAME: {
+            int keep = *(int *) (value);
+            DEBUG(mLogCategory, "Set keep last frame:%d",keep);
+            mDisplay->setKeepLastFrame(keep);
+        } break;
     }
     return 0;
 }