libvideorender: CB2 disconnect timeout [1/1]

PD#SWPL-138652

Problem:
1.render_disconnect take too long time, it causes
yts timeout or crash

Solution:
1.refine disconnect logic
2.add category for log debug

Verify:
ap222

Change-Id: I1920838d8d0562df6760c78cab2db52d2c6aa126
Signed-off-by: fei.deng <fei.deng@amlogic.com>
diff --git a/drm/Makefile b/drm/Makefile
index c581499..17baea2 100644
--- a/drm/Makefile
+++ b/drm/Makefile
@@ -52,6 +52,7 @@
 
 OBJ_CLIENT_LIB += \
 	$(TOOLS_PATH)/Thread.o \
+	$(TOOLS_PATH)/Poll.o \
 	$(TOOLS_PATH)/Times.o \
 	$(TOOLS_PATH)/Logger.o \
 	$(TOOLS_PATH)/Queue.o
diff --git a/drm/drm_display.cpp b/drm/drm_display.cpp
index 3ed3318..5d9abee 100644
--- a/drm/drm_display.cpp
+++ b/drm/drm_display.cpp
@@ -24,6 +24,7 @@
 #include "Logger.h"
 #include "drm_framepost.h"
 #include "drm_framerecycle.h"
+#include "ErrorCode.h"
 
 using namespace Tls;
 
@@ -32,8 +33,9 @@
 #define BLACK_FRAME_WIDTH 64
 #define BLACK_FRAME_HEIGHT 64
 
-DrmDisplay::DrmDisplay(DrmPlugin *plugin)
-    : mPlugin(plugin)
+DrmDisplay::DrmDisplay(DrmPlugin *plugin, int logcategory)
+    : mPlugin(plugin),
+    mLogCategory(logcategory)
 {
     mDrmHandle = NULL;
     mBlackFrame = 0;
@@ -52,7 +54,7 @@
     mHideVideo = false;
     mIsDropFrames = false;
     mKeepLastFrame = false;
-    mDrmMesonLib = drmMesonLoadLib();
+    mDrmMesonLib = drmMesonLoadLib(logcategory);
 }
 
 DrmDisplay::~DrmDisplay()
@@ -65,7 +67,7 @@
     }
     //free dlopen resources
     if (mDrmMesonLib) {
-        drmMesonUnloadLib(mDrmMesonLib);
+        drmMesonUnloadLib(mLogCategory, mDrmMesonLib);
         mDrmMesonLib = NULL;
     }
 }
@@ -74,13 +76,13 @@
 {
     mIsPip = pip;
 
-    DEBUG("start pip:%d",pip);
+    DEBUG(mLogCategory, "start pip:%d",pip);
     if (mDrmMesonLib) {
         mDrmHandle = mDrmMesonLib->libDrmDisplayInit();
     }
 
     if (!mDrmHandle) {
-        ERROR("drm display init failed");
+        ERROR(mLogCategory, "drm display init failed");
         return false;
     }
 #ifdef SUPPORT_DRM_FREEZEN
@@ -90,11 +92,11 @@
     } else {
         mDrmHandle->freeze = 0;
     }
-    INFO("set keep last frame %d", mDrmHandle->freeze);
+    INFO(mLogCategory, "set keep last frame %d", mDrmHandle->freeze);
 #endif
 
     if (!mDrmFramePost) {
-        mDrmFramePost = new DrmFramePost(this);
+        mDrmFramePost = new DrmFramePost(this, mLogCategory);
         mDrmFramePost->start();
         /*if window size set, we set to frame post,this needed
          when yts resize case,window size must effect when post
@@ -106,7 +108,7 @@
     }
 
     if (!mDrmFrameRecycle) {
-        mDrmFrameRecycle = new DrmFrameRecycle(this);
+        mDrmFrameRecycle = new DrmFrameRecycle(this,mLogCategory);
         mDrmFrameRecycle->start();
     }
     return true;
@@ -115,13 +117,13 @@
 bool DrmDisplay::stop()
 {
     if (mDrmFramePost) {
-        DEBUG("stop frame post thread");
+        DEBUG(mLogCategory, "stop frame post thread");
         mDrmFramePost->stop();
         delete mDrmFramePost;
         mDrmFramePost = NULL;
     }
     if (mDrmFrameRecycle) {
-        DEBUG("stop frame recycle thread");
+        DEBUG(mLogCategory, "stop frame recycle thread");
         mDrmFrameRecycle->stop();
         delete mDrmFrameRecycle;
         mDrmFrameRecycle = NULL;
@@ -163,7 +165,7 @@
                 mIsDropFrames = true;
             }
         } else {
-            WARNING("no frame post service");
+            WARNING(mLogCategory,"no frame post service");
             handleDropedFrameEntity(frameEntity);
             handleReleaseFrameEntity(frameEntity);
         }
@@ -179,8 +181,8 @@
 
 void DrmDisplay::flush()
 {
-    DEBUG("flush");
-    std::lock_guard<std::mutex> lck(mMutex);
+    DEBUG(mLogCategory,"flush");
+    Tls::Mutex::Autolock _l(mMutex);
     if (mDrmFramePost) {
         mDrmFramePost->flush();
     }
@@ -199,7 +201,7 @@
 void DrmDisplay::setVideoFormat(RenderVideoFormat videoFormat)
 {
     mVideoFormat = videoFormat;
-    DEBUG("video format:%d",mVideoFormat);
+    DEBUG(mLogCategory,"video format:%d",mVideoFormat);
 }
 
 void DrmDisplay::setWindowSize(int x, int y, int w, int h)
@@ -208,7 +210,7 @@
     mWinRect.y = y;
     mWinRect.w = w;
     mWinRect.h = h;
-    DEBUG("window size:(%dx%dx%dx%d)",x, y,w,h);
+    DEBUG(mLogCategory,"window size:(%dx%dx%dx%d)",x, y,w,h);
     if (mDrmFramePost) {
         mDrmFramePost->setWindowSize(x, y, w, h);
     }
@@ -218,7 +220,7 @@
 {
     mFrameWidth = width;
     mFrameHeight = height;
-    DEBUG("frame size:%dx%d",width, height);
+    DEBUG(mLogCategory,"frame size:%dx%d",width, height);
 }
 
 void DrmDisplay::showBlackFrame()
@@ -226,6 +228,10 @@
     int rc;
     struct drm_buf_metadata info;
 
+    if (mBlackFrame) {
+        return;
+    }
+
     memset(&info, 0 , sizeof(struct drm_buf_metadata));
 
     /* use single planar for black frame */
@@ -244,14 +250,14 @@
     }
 
     if (!mBlackFrame) {
-        ERROR("Unable to alloc drm buf");
+        ERROR(mLogCategory,"Unable to alloc drm buf");
         goto tag_error;
     }
 
     mBlackFrameAddr = mmap (NULL, info.width * info.height * 2, PROT_WRITE,
         MAP_SHARED, mBlackFrame->fd[0], mBlackFrame->offsets[0]);
     if (mBlackFrameAddr == MAP_FAILED) {
-        ERROR("mmap fail %d", errno);
+        ERROR(mLogCategory,"mmap fail %d", errno);
         mBlackFrameAddr = NULL;
     }
 
@@ -262,12 +268,15 @@
     mBlackFrame->crtc_w = -1;
     mBlackFrame->crtc_h = -1;
 
+    //disable plane
+    mBlackFrame->disable_plane = 1;
+
     //post black frame buf to drm
     if (mDrmHandle && mDrmMesonLib) {
         rc = mDrmMesonLib->libDrmPostBuf(mDrmHandle, mBlackFrame);
     }
     if (rc) {
-        ERROR("post black frame to drm failed");
+        ERROR(mLogCategory, "post black frame to drm failed");
         goto tag_error;
     }
 
@@ -295,7 +304,7 @@
 }
 
 void DrmDisplay::setHideVideo(bool hide) {
-    INFO("hide video:%d",hide);
+    INFO(mLogCategory,"hide video:%d",hide);
     mHideVideo = hide;
     mIsDropFrames = false;
 }
@@ -309,7 +318,11 @@
     if (mDrmHandle) {
         mDrmHandle->freeze = kp;
     }
-    INFO("set keep last frame %d(%d)", keep,mDrmHandle->freeze);
+    INFO(mLogCategory, "set keep last frame %d(%d)", keep,mDrmHandle->freeze);
+    if (!kp) {
+        INFO(mLogCategory, "set keep last frame %d, show black frame to drm", kp);
+        showBlackFrame();
+    }
 #endif
 }
 
@@ -321,7 +334,7 @@
 
     frame = (FrameEntity*)calloc(1, sizeof(FrameEntity));
     if (!frame) {
-        ERROR("oom calloc FrameEntity mem failed");
+        ERROR(mLogCategory,"oom calloc FrameEntity mem failed");
         goto tag_error;
     }
 
@@ -344,7 +357,7 @@
 
         default: {
             info.fourcc = DRM_FORMAT_YUYV;
-            WARNING("unknown video format, set to default YUYV format");
+            WARNING(mLogCategory,"unknown video format, set to default YUYV format");
         }
     }
 
@@ -358,7 +371,7 @@
     if not dup buf fd, fd will be double free*/
     for (int i = 0; i < buf->dma.planeCnt; i++) {
         info.fd[i] = dup(buf->dma.fd[i]);
-        TRACE("dup fd[%d]:%d->%d",i,buf->dma.fd[i],info.fd[i]);
+        TRACE(mLogCategory,"dup fd[%d]:%d->%d",i,buf->dma.fd[i],info.fd[i]);
     }
 
     if (mDrmHandle && mDrmMesonLib) {
@@ -366,7 +379,7 @@
     }
 
     if (!drmBuf) {
-        ERROR("unable drm_import_buf");
+        ERROR(mLogCategory, "unable drm_import_buf");
         goto tag_error;
     }
 
@@ -393,7 +406,7 @@
 #endif
 
     frame->drmBuf = drmBuf;
-    TRACE("crtc(%d,%d,%d,%d),src(%d,%d,%d,%d)",drmBuf->crtc_x,drmBuf->crtc_y,drmBuf->crtc_w,drmBuf->crtc_h,
+    TRACE(mLogCategory,"crtc(%d,%d,%d,%d),src(%d,%d,%d,%d)",drmBuf->crtc_x,drmBuf->crtc_y,drmBuf->crtc_w,drmBuf->crtc_h,
         drmBuf->src_x,drmBuf->src_y,drmBuf->src_w,drmBuf->src_h);
 
     return frame;
@@ -423,9 +436,9 @@
         }
 
         if (rc) {
-            WARNING("drm_free_buf free %p failed",frameEntity->drmBuf);
+            WARNING(mLogCategory, "drm_free_buf free %p failed",frameEntity->drmBuf);
         }
-        TRACE("drm_free_buf displaytime:%lld(pts:%lld ms)",frameEntity->displayTime,frameEntity->renderBuf->pts/1000000);
+        TRACE(mLogCategory,"drm_free_buf displaytime:%lld(pts:%lld ms)",frameEntity->displayTime,frameEntity->renderBuf->pts/1000000);
     }
     free(frameEntity);
 }
diff --git a/drm/drm_display.h b/drm/drm_display.h
index 4a56d21..721089c 100644
--- a/drm/drm_display.h
+++ b/drm/drm_display.h
@@ -20,7 +20,7 @@
 #include <xf86drmMode.h>
 #include <drm_fourcc.h>
 #include <linux/videodev2.h>
-#include <mutex>
+#include "Mutex.h"
 #include "Thread.h"
 #include "Queue.h"
 #include "drm_plugin.h"
@@ -40,7 +40,7 @@
 class DrmDisplay
 {
   public:
-    DrmDisplay(DrmPlugin *plugin);
+    DrmDisplay(DrmPlugin *plugin, int logCategory);
     virtual ~DrmDisplay();
     bool start(bool pip);
     bool stop();
@@ -100,10 +100,11 @@
     void destroyFrameEntity(FrameEntity * frameEntity);
 
     DrmPlugin *mPlugin;
+    int mLogCategory;
 
     DrmMesonLib *mDrmMesonLib; //libdrm meson dlopen handle
 
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mMutex;
 
     bool mIsPip;
     RenderVideoFormat mVideoFormat;
diff --git a/drm/drm_framepost.cpp b/drm/drm_framepost.cpp
index be4bc04..32ad486 100644
--- a/drm/drm_framepost.cpp
+++ b/drm/drm_framepost.cpp
@@ -18,14 +18,16 @@
 #include "Logger.h"
 #include "drm_display.h"
 #include "drm_framepost.h"
+#include "ErrorCode.h"
 
 using namespace Tls;
 
 #define TAG "rlib:drm_framepost"
 
-DrmFramePost::DrmFramePost(DrmDisplay *drmDisplay)
+DrmFramePost::DrmFramePost(DrmDisplay *drmDisplay,int logCategory)
 {
     mDrmDisplay = drmDisplay;
+    mLogCategory = logCategory;
     mPaused = false;
     mStop = false;
     mImmediatelyOutput = false;
@@ -40,7 +42,7 @@
 {
     if (isRunning()) {
         mStop = true;
-        DEBUG("stop frame post thread");
+        DEBUG(mLogCategory,"stop frame post thread");
         requestExitAndWait();
     }
 
@@ -53,17 +55,17 @@
 
 bool DrmFramePost::start()
 {
-    DEBUG("start frame post thread");
+    DEBUG(mLogCategory,"start frame post thread");
     run("frame post thread");
     return true;
 }
 
 bool DrmFramePost::stop()
 {
-    DEBUG("stop frame post thread");
+    DEBUG(mLogCategory,"stop frame post thread");
     if (isRunning()) {
         mStop = true;
-        DEBUG("stop frame post thread");
+        DEBUG(mLogCategory,"stop frame post thread");
         requestExitAndWait();
     }
     flush();
@@ -72,16 +74,16 @@
 
 bool DrmFramePost::readyPostFrame(FrameEntity * frameEntity)
 {
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     mQueue->push(frameEntity);
-    TRACE("queue cnt:%d",mQueue->getCnt());
+    TRACE(mLogCategory,"queue cnt:%d",mQueue->getCnt());
     return true;
 }
 
 void DrmFramePost::flush()
 {
     FrameEntity *entity;
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     while (mQueue->pop((void **)&entity) == Q_OK)
     {
         mDrmDisplay->handleDropedFrameEntity(entity);
@@ -102,7 +104,7 @@
 void DrmFramePost::setImmediatelyOutout(bool on)
 {
     mImmediatelyOutput = on;
-    DEBUG("set immediately output:%d",on);
+    DEBUG(mLogCategory,"set immediately output:%d",on);
 }
 
 void DrmFramePost::setWindowSize(int x, int y, int w, int h)
@@ -134,7 +136,7 @@
     }
 
     if (!drmHandle) {
-        ERROR("drm handle is NULL");
+        ERROR(mLogCategory,"drm handle is NULL");
         return false;
     }
 
@@ -147,7 +149,7 @@
     //drmWaitBland need link libdrm.so
     rc = drmWaitVBlank(drmHandle->drm_fd, &vbl);
     if (rc) {
-        ERROR("drmWaitVBlank error %d", rc);
+        ERROR(mLogCategory,"drmWaitVBlank error %d", rc);
         usleep(4000);
         return true;
     }
@@ -160,7 +162,7 @@
     vBlankTime = vbl.reply.tval_sec*1000000LL + vbl.reply.tval_usec;
     vBlankTime += refreshInterval; //check next blank time
 
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     //if queue is empty or paused, loop next
     if (mQueue->isEmpty() || mPaused) {
         //TRACE(mLogCategory,"empty or paused");
@@ -176,7 +178,7 @@
 
     while (mQueue->peek((void **)&curFrameEntity, 0) == Q_OK)
     {
-        TRACE("vBlankTime:%lld,frame time:%lld(pts:%lld ms),refreshInterval:%lld",vBlankTime,curFrameEntity->displayTime,curFrameEntity->renderBuf->pts/1000000,refreshInterval);
+        TRACE(mLogCategory,"vBlankTime:%lld,frame time:%lld(pts:%lld ms),refreshInterval:%lld",vBlankTime,curFrameEntity->displayTime,curFrameEntity->renderBuf->pts/1000000,refreshInterval);
         //no frame expired,loop next
         if (vBlankTime < curFrameEntity->displayTime) {
             break;
@@ -187,20 +189,20 @@
 
         //drop last expired frame,got a new expired frame
         if (expiredFrameEntity) {
-            DEBUG("drop frame,vBlankTime:%lld,frame time:%lld(pts:%lld ms)",vBlankTime,expiredFrameEntity->displayTime,expiredFrameEntity->renderBuf->pts/1000000);
+            DEBUG(mLogCategory,"drop frame,vBlankTime:%lld,frame time:%lld(pts:%lld ms)",vBlankTime,expiredFrameEntity->displayTime,expiredFrameEntity->renderBuf->pts/1000000);
             mDrmDisplay->handleDropedFrameEntity(expiredFrameEntity);
             mDrmDisplay->handleReleaseFrameEntity(expiredFrameEntity);
             expiredFrameEntity = NULL;
         }
 
         expiredFrameEntity = curFrameEntity;
-        TRACE("expire,frame time:%lld(pts:%lld ms)",expiredFrameEntity->displayTime,expiredFrameEntity->renderBuf->pts/1000000);
+        TRACE(mLogCategory,"expire,frame time:%lld(pts:%lld ms)",expiredFrameEntity->displayTime,expiredFrameEntity->renderBuf->pts/1000000);
     }
 
 tag_post:
     //no frame will be posted to drm display
     if (!expiredFrameEntity) {
-        TRACE("no frame expire");
+        TRACE(mLogCategory,"no frame expire");
         goto tag_next;
     }
 
@@ -211,7 +213,7 @@
         drmBuf->crtc_y = mWinRect.y;
         drmBuf->crtc_w = mWinRect.w;
         drmBuf->crtc_h = mWinRect.h;
-        TRACE("postBuf crtc(%d,%d,%d,%d),src(%d,%d,%d,%d)",drmBuf->crtc_x,drmBuf->crtc_y,drmBuf->crtc_w,drmBuf->crtc_h,
+        TRACE(mLogCategory,"postBuf crtc(%d,%d,%d,%d),src(%d,%d,%d,%d)",drmBuf->crtc_x,drmBuf->crtc_y,drmBuf->crtc_w,drmBuf->crtc_h,
         drmBuf->src_x,drmBuf->src_y,drmBuf->src_w,drmBuf->src_h);
     }
 
@@ -220,13 +222,13 @@
     }
 
     if (rc) {
-        ERROR("drm_post_buf error %d", rc);
+        ERROR(mLogCategory, "drm_post_buf error %d", rc);
         mDrmDisplay->handleDropedFrameEntity(expiredFrameEntity);
         mDrmDisplay->handleReleaseFrameEntity(expiredFrameEntity);
         goto tag_next;
     }
 
-    TRACE("drm_post_buf,frame time:%lld(pts:%lld ms)",expiredFrameEntity->displayTime,expiredFrameEntity->renderBuf->pts/1000000);
+    TRACE(mLogCategory,"drm_post_buf,frame time:%lld(pts:%lld ms)",expiredFrameEntity->displayTime,expiredFrameEntity->renderBuf->pts/1000000);
     mDrmDisplay->handlePostedFrameEntity(expiredFrameEntity);
     mDrmDisplay->handleDisplayedFrameEntity(expiredFrameEntity);
 tag_next:
diff --git a/drm/drm_framepost.h b/drm/drm_framepost.h
index a4c5a75..90fda5b 100644
--- a/drm/drm_framepost.h
+++ b/drm/drm_framepost.h
@@ -15,7 +15,7 @@
  */
 #ifndef __DRM_FRAME_POST_H__
 #define __DRM_FRAME_POST_H__
-#include <mutex>
+#include "Mutex.h"
 #include "Thread.h"
 #include "Queue.h"
 
@@ -25,7 +25,7 @@
 class DrmFramePost : public Tls::Thread
 {
   public:
-    DrmFramePost(DrmDisplay *drmDisplay);
+    DrmFramePost(DrmDisplay *drmDisplay,int logCategory);
     virtual ~DrmFramePost();
     bool start();
     bool stop();
@@ -46,10 +46,11 @@
       int h;
     } WinRect;
     DrmDisplay *mDrmDisplay;
+    int mLogCategory;
 
     bool mPaused;
     bool mStop;
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mMutex;
     Tls::Queue *mQueue;
 
     /*immediately output video frame to display*/
diff --git a/drm/drm_framerecycle.cpp b/drm/drm_framerecycle.cpp
index bfb2da2..3e37e35 100644
--- a/drm/drm_framerecycle.cpp
+++ b/drm/drm_framerecycle.cpp
@@ -23,9 +23,10 @@
 
 #define TAG "rlib:drm_framerecycle"
 
-DrmFrameRecycle::DrmFrameRecycle(DrmDisplay *drmDisplay)
+DrmFrameRecycle::DrmFrameRecycle(DrmDisplay *drmDisplay, int logCategory)
 {
     mDrmDisplay = drmDisplay;
+    mLogCategory = logCategory;
     mStop = false;
     mWaitVideoFence = false;
     mQueue = new Tls::Queue();
@@ -35,7 +36,7 @@
 {
     if (isRunning()) {
         mStop = true;
-        DEBUG("stop frame recycle thread");
+        DEBUG(mLogCategory,"stop frame recycle thread");
         requestExitAndWait();
     }
 
@@ -48,7 +49,7 @@
 
 bool DrmFrameRecycle::start()
 {
-    DEBUG("start frame recycle thread");
+    DEBUG(mLogCategory,"start frame recycle thread");
     mStop = false;
     run("frame recycle thread");
     return true;
@@ -58,24 +59,24 @@
 {
     if (isRunning()) {
         mStop = true;
-        DEBUG("stop frame recycle thread");
+        DEBUG(mLogCategory,"stop frame recycle thread");
         requestExitAndWait();
     }
     mWaitVideoFence = false;
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     mQueue->flushAndCallback(this, DrmFrameRecycle::queueFlushCallback);
     return true;
 }
 
 bool DrmFrameRecycle::recycleFrame(FrameEntity * frameEntity)
 {
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     if (mStop) {
         mDrmDisplay->handleReleaseFrameEntity(frameEntity);
         return true;
     }
     mQueue->push(frameEntity);
-    TRACE("queue cnt:%d",mQueue->getCnt());
+    TRACE(mLogCategory,"queue cnt:%d",mQueue->getCnt());
     /* when two frame are posted, fence can be retrieved.
      * So waiting video fence starts
      */
@@ -115,13 +116,13 @@
         return true;
     }
 
-    TRACE("wait video fence for frame:%lld(pts:%lld)",frameEntity->displayTime,frameEntity->renderBuf->pts);
+    TRACE(mLogCategory,"wait video fence for frame:%lld(pts:%lld)",frameEntity->displayTime,frameEntity->renderBuf->pts);
     if (drmMesonLib) {
         rc = drmMesonLib->libDrmWaitVideoFence(frameEntity->drmBuf->fd[0]);
     }
 
     if (rc <= 0) {
-        WARNING("wait fence error %d", rc);
+        WARNING(mLogCategory, "wait fence error %d", rc);
     }
 
     mDrmDisplay->handleReleaseFrameEntity(frameEntity);
diff --git a/drm/drm_framerecycle.h b/drm/drm_framerecycle.h
index a783ccf..dbccf3f 100644
--- a/drm/drm_framerecycle.h
+++ b/drm/drm_framerecycle.h
@@ -15,7 +15,7 @@
  */
 #ifndef __DRM_FRAME_RECYCLE_H__
 #define __DRM_FRAME_RECYCLE_H__
-#include <mutex>
+#include "Mutex.h"
 #include "Thread.h"
 #include "Queue.h"
 
@@ -25,7 +25,7 @@
 class DrmFrameRecycle : public Tls::Thread
 {
   public:
-    DrmFrameRecycle(DrmDisplay *drmDisplay);
+    DrmFrameRecycle(DrmDisplay *drmDisplay, int logCategory);
     virtual ~DrmFrameRecycle();
     bool start();
     bool stop();
@@ -36,10 +36,11 @@
     static void queueFlushCallback(void *userdata,void *data);
   private:
     DrmDisplay *mDrmDisplay;
+    int mLogCategory;
 
     bool mStop;
     bool mWaitVideoFence;
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mMutex;
     Tls::Queue *mQueue;
 };
 
diff --git a/drm/drm_lib_wrap.cpp b/drm/drm_lib_wrap.cpp
index a2a8388..542cb4e 100644
--- a/drm/drm_lib_wrap.cpp
+++ b/drm/drm_lib_wrap.cpp
@@ -18,102 +18,103 @@
 #include <stdlib.h>
 #include "drm_lib_wrap.h"
 #include "Logger.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:drm_lib_wrap"
 
 #define DRM_MESON_LIB_NAME "libdrm_meson.so"
 
-DrmMesonLib * drmMesonLoadLib()
+DrmMesonLib * drmMesonLoadLib(int logCategory)
 {
-    INFO("load libdrm meson so symbol");
+    INFO(logCategory, "load libdrm meson so symbol");
 
     DrmMesonLib *handle = (DrmMesonLib*)calloc( 1, sizeof(DrmMesonLib));
     if (!handle) {
-        ERROR("calloc DrmMesonLib struct fail");
+        ERROR(logCategory, "calloc DrmMesonLib struct fail");
         goto err_labal;
     }
 
     handle->libHandle = dlopen(DRM_MESON_LIB_NAME, RTLD_NOW);
     if (handle->libHandle == NULL) {
-        ERROR("unable to dlopen %s : %s",DRM_MESON_LIB_NAME, dlerror());
+        ERROR(logCategory, "unable to dlopen %s : %s",DRM_MESON_LIB_NAME, dlerror());
         goto err_labal;
     }
 
     handle->libDrmDisplayInit = (lib_drm_display_init)dlsym(handle->libHandle, "drm_display_init");
     if (handle->libDrmDisplayInit == NULL) {
-        ERROR("dlsym drm_display_init failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_display_init failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmDisplayDestroy = (lib_drm_destroy_display)dlsym(handle->libHandle, "drm_destroy_display");
     if (handle->libDrmDisplayDestroy == NULL) {
-        ERROR("dlsym drm_destroy_display failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_destroy_display failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmDisplayRegisterDonCb = (lib_drm_display_register_done_cb)dlsym(handle->libHandle, "drm_display_register_done_cb");
     if (handle->libDrmDisplayRegisterDonCb == NULL) {
-        ERROR("dlsym drm_display_register_done_cb failed, err=%s \n", dlerror());
+        ERROR(logCategory, "dlsym drm_display_register_done_cb failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmDisplayRegisterResCb = (lib_drm_display_register_res_cb)dlsym(handle->libHandle, "drm_display_register_res_cb");
     if (handle->libDrmDisplayRegisterResCb == NULL) {
-        ERROR("dlsym drm_display_register_res_cb failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_display_register_res_cb failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmSetAllocOnlyFlag = (lib_drm_set_alloc_only_flag)dlsym(handle->libHandle, "drm_set_alloc_only_flag");
     if (handle->libDrmSetAllocOnlyFlag == NULL) {
-        ERROR("dlsym drm_set_alloc_only_flag failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_set_alloc_only_flag failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmAllocBufs = (lib_drm_alloc_bufs)dlsym(handle->libHandle, "drm_alloc_bufs");
     if (handle->libDrmAllocBufs == NULL) {
-        ERROR("dlsym drm_alloc_bufs failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_alloc_bufs failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmFreeBufs = (lib_drm_free_bufs)dlsym(handle->libHandle, "drm_free_bufs");
     if (handle->libDrmFreeBufs == NULL) {
-        ERROR("dlsym drm_free_bufs failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_free_bufs failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmAllocBuf = (lib_drm_alloc_buf)dlsym(handle->libHandle, "drm_alloc_buf");
     if (handle->libDrmAllocBuf == NULL) {
-        ERROR("dlsym drm_alloc_buf failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_alloc_buf failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmImportBuf = (lib_drm_import_buf)dlsym(handle->libHandle, "drm_import_buf");
     if (handle->libDrmImportBuf == NULL) {
-        ERROR("dlsym drm_import_buf failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_import_buf failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmFreeBuf = (lib_drm_free_buf)dlsym(handle->libHandle, "drm_free_buf");
     if (handle->libDrmFreeBuf == NULL) {
-        ERROR("dlsym drm_free_buf failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_free_buf failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmPostBuf = (lib_drm_post_buf)dlsym(handle->libHandle, "drm_post_buf");
     if (handle->libDrmPostBuf == NULL) {
-        ERROR("dlsym drm_post_buf failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_post_buf failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmModeAsyncAtomicCommit = (lib_drmModeAsyncAtomicCommit)dlsym(handle->libHandle, "drmModeAsyncAtomicCommit");
     if (handle->libDrmModeAsyncAtomicCommit == NULL) {
-        ERROR("dlsym drmModeAsyncAtomicCommit failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drmModeAsyncAtomicCommit failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->libDrmWaitVideoFence = (lib_drm_waitvideoFence)dlsym(handle->libHandle, "drm_waitvideoFence");
     if (handle->libDrmWaitVideoFence == NULL) {
-        ERROR("dlsym drm_waitvideoFence failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym drm_waitvideoFence failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
@@ -128,14 +129,14 @@
     return NULL;
 }
 
-int drmMesonUnloadLib(DrmMesonLib *drmMesonLib)
+int drmMesonUnloadLib(int logCategory,DrmMesonLib *drmMesonLib)
 {
     if (drmMesonLib) {
         if (drmMesonLib->libHandle) {
-            INFO("dlclose libdrm meson so symbol");
+            INFO(logCategory, "dlclose libdrm meson so symbol");
             dlclose(drmMesonLib->libHandle);
         }
         free(drmMesonLib);
     }
-    return 0;
+    return NO_ERROR;
 }
diff --git a/drm/drm_lib_wrap.h b/drm/drm_lib_wrap.h
index af3b05d..be99199 100644
--- a/drm/drm_lib_wrap.h
+++ b/drm/drm_lib_wrap.h
@@ -58,7 +58,7 @@
 } DrmMesonLib;
 
 
-DrmMesonLib * drmMesonLoadLib();
-int drmMesonUnloadLib(DrmMesonLib *drmMesonLib);
+DrmMesonLib * drmMesonLoadLib(int logCategory);
+int drmMesonUnloadLib(int logCategory,DrmMesonLib *drmMesonLib);
 
 #endif /*__DRM_LIB_WRAP_H__*/
\ No newline at end of file
diff --git a/drm/drm_plugin.cpp b/drm/drm_plugin.cpp
index 22e38a5..f2ebcaf 100644
--- a/drm/drm_plugin.cpp
+++ b/drm/drm_plugin.cpp
@@ -16,14 +16,16 @@
 #include "drm_plugin.h"
 #include "Logger.h"
 #include "drm_display.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:drm_plugin"
 
-DrmPlugin::DrmPlugin()
+DrmPlugin::DrmPlugin(int logCategory)
+    : mLogCategory(logCategory)
 {
     mVideoFormat = VIDEO_FORMAT_UNKNOWN;
     mIsPip = false;
-    mDrmDisplay = new DrmDisplay(this);
+    mDrmDisplay = new DrmDisplay(this,logCategory);
 }
 
 DrmPlugin::~DrmPlugin()
@@ -36,7 +38,7 @@
 
 void DrmPlugin::init()
 {
-    INFO("\n--------------------------------\n"
+    INFO(mLogCategory,"\n--------------------------------\n"
             "plugin      : drmmeson\n"
             "ARCH        : %s\n"
             "branch name : %s\n"
@@ -76,65 +78,67 @@
 {
     int ret;
 
-    DEBUG("openDisplay");
+    DEBUG(mLogCategory,"openDisplay");
 
+    DEBUG(mLogCategory,"openDisplay end");
     return ret;
 }
 
 int DrmPlugin::openWindow()
 {
-    int ret = 0;
+    int ret = NO_ERROR;
 
-    DEBUG("openWindow");
+    DEBUG(mLogCategory,"openWindow");
 
     bool rc = mDrmDisplay->start(mIsPip);
     if (!rc) {
-        ERROR("drm window open failed");
-        return -1;
+        ret = ERROR_OPEN_FAIL;
+        ERROR(mLogCategory,"drm window open failed");
+        return ret;
     }
 
-    DEBUG("openWindow,end");
+    DEBUG(mLogCategory,"openWindow,end");
     return ret;
 }
 
 int DrmPlugin::prepareFrame(RenderBuffer *buffer)
 {
-
+    return NO_ERROR;
 }
 
 int DrmPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
 {
     mDrmDisplay->displayFrame(buffer, displayTime);
-    return 0;
+    return NO_ERROR;
 }
 
 int DrmPlugin::flush()
 {
     mDrmDisplay->flush();
-    return 0;
+    return NO_ERROR;
 }
 
 int DrmPlugin::pause()
 {
     mDrmDisplay->pause();
-    return 0;
+    return NO_ERROR;
 }
 int DrmPlugin::resume()
 {
     mDrmDisplay->resume();
-    return 0;
+    return NO_ERROR;
 }
 
 int DrmPlugin::closeDisplay()
 {
-    return 0;
+    return NO_ERROR;
 }
 
 int DrmPlugin::closeWindow()
 {
     int ret;
     mDrmDisplay->stop();
-    return 0;
+    return NO_ERROR;
 }
 
 
@@ -143,7 +147,7 @@
     switch (key) {
         case PLUGIN_KEY_VIDEO_FORMAT: {
             *(int *)value = mVideoFormat;
-            TRACE("get video format:%d",*(int *)value);
+            TRACE(mLogCategory,"get video format:%d",*(int *)value);
         } break;
         case PLUGIN_KEY_VIDEO_PIP: {
             *(int *)value = (mIsPip == true) ? 1 : 0;
@@ -154,11 +158,11 @@
                 isHide = mDrmDisplay->isHideVideo();
             }
             *(int *)value = isHide == true? 1: 0;
-            TRACE("get hide video:%d",*(int *)value);
+            TRACE(mLogCategory,"get hide video:%d",*(int *)value);
         } break;
     }
 
-    return 0;
+    return NO_ERROR;
 }
 
 int DrmPlugin::setValue(PluginKey key, void *value)
@@ -179,7 +183,7 @@
         case PLUGIN_KEY_VIDEO_FORMAT: {
             int format = *(int *)(value);
             mVideoFormat = (RenderVideoFormat) format;
-            DEBUG("Set video format :%d",mVideoFormat);
+            DEBUG(mLogCategory,"Set video format :%d",mVideoFormat);
             if (mDrmDisplay) {
                 mDrmDisplay->setVideoFormat(mVideoFormat);
             }
@@ -190,7 +194,7 @@
         };
         case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
             bool immediately = (*(int *)(value)) > 0? true: false;
-            DEBUG( "Set immediately output:%d",immediately);
+            DEBUG(mLogCategory, "Set immediately output:%d",immediately);
             if (mDrmDisplay) {
                 mDrmDisplay->setImmediatelyOutout(immediately);
             }
@@ -204,13 +208,13 @@
         case PLUGIN_KEY_KEEP_LAST_FRAME: {
             int keep = *(int *) (value);
             bool keepLastFrame = keep > 0? true:false;
-            DEBUG("Set keep last frame :%d",keepLastFrame);
+            DEBUG(mLogCategory, "Set keep last frame :%d",keepLastFrame);
             if (mDrmDisplay) {
                 mDrmDisplay->setKeepLastFrame(keepLastFrame);
             }
         } break;
     }
-    return 0;
+    return NO_ERROR;
 }
 
 void DrmPlugin::handleBufferRelease(RenderBuffer *buffer)
@@ -243,18 +247,23 @@
 
 void *makePluginInstance(int id)
 {
+    int category =Logger_init(id);
     char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
     if (env) {
         int level = atoi(env);
         Logger_set_level(level);
-        INFO("VIDEO_RENDER_LOG_LEVEL=%d",level);
+        INFO(category,"VIDEO_RENDER_LOG_LEVEL=%d",level);
     }
-    DrmPlugin *drmPlugin = new DrmPlugin();
+    DrmPlugin *drmPlugin = new DrmPlugin(category);
     return static_cast<void *>(drmPlugin);
 }
 
 void destroyPluginInstance(void * plugin)
 {
+    int category;
+
     DrmPlugin *pluginInstance = static_cast<DrmPlugin *>(plugin);
+    category = pluginInstance->getLogCategory();
     delete pluginInstance;
+    Logger_exit(category);
 }
diff --git a/drm/drm_plugin.h b/drm/drm_plugin.h
index 889bb22..8511dbb 100644
--- a/drm/drm_plugin.h
+++ b/drm/drm_plugin.h
@@ -22,7 +22,7 @@
 class DrmPlugin : public RenderPlugin
 {
   public:
-    DrmPlugin();
+    DrmPlugin(int category);
     virtual ~DrmPlugin();
     virtual void init();
     virtual void release();
@@ -46,9 +46,15 @@
     virtual void handleFrameDropped(RenderBuffer *buffer);
     //handle msg to render core
     void handleMsgNotify(int type, void *detail);
+    int getLogCategory() {
+        return mLogCategory;
+    };
   private:
     PluginCallback *mCallback;
     DrmDisplay *mDrmDisplay;
+
+    int mLogCategory;
+
     bool mIsPip;
 
     RenderVideoFormat mVideoFormat;
diff --git a/tools/Condition.h b/tools/Condition.h
new file mode 100644
index 0000000..ba1c67a
--- /dev/null
+++ b/tools/Condition.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2021 Amlogic Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _TOOLS_CONDITION_H_
+#define _TOOLS_CONDITION_H_
+
+#include <limits.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+#include <pthread.h>
+#include "Mutex.h"
+
+namespace Tls {
+class Condition {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+
+    enum WakeUpType {
+        WAKE_UP_ONE = 0,
+        WAKE_UP_ALL = 1
+    };
+
+    Condition();
+    explicit Condition(int type);
+    ~Condition();
+    // Wait on the condition variable.  Lock the mutex before calling.
+    // Note that spurious wake-ups may happen.
+    int wait(Mutex& mutex);
+    // same with relative timeout , microsecond time
+    int waitRelative(Mutex& mutex, int64_t reltime);
+    // same with relative timeout , us time
+    int waitRelativeUs(Mutex& mutex, int64_t reltime/*us*/);
+    // Signal the condition variable, allowing one thread to continue.
+    void signal();
+    // Signal the condition variable, allowing one or all threads to continue.
+    void signal(WakeUpType type) {
+        if (type == WAKE_UP_ONE) {
+            signal();
+        } else {
+            broadcast();
+        }
+    }
+    // Signal the condition variable, allowing all threads to continue.
+    void broadcast();
+
+private:
+    pthread_cond_t mCond;
+};
+
+inline Condition::Condition() : Condition(PRIVATE) {
+}
+inline Condition::Condition(int type) {
+    pthread_condattr_t attr;
+    pthread_condattr_init(&attr);
+    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+
+    if (type == SHARED) {
+        pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+    }
+
+    pthread_cond_init(&mCond, &attr);
+    pthread_condattr_destroy(&attr);
+
+}
+inline Condition::~Condition() {
+    pthread_cond_destroy(&mCond);
+}
+
+/**
+ * wait relative nanosecond time
+ * return 0 if wait success, non 0 if timeout or other
+*/
+inline int Condition::wait(Mutex& mutex) {
+    return -pthread_cond_wait(&mCond, &mutex.mMutex);
+}
+
+/**
+ * wait relative microsecond time
+ * return 0 if wait success, non 0 if timeout or other
+ * ETIMEDOUT timeout,
+*/
+inline int Condition::waitRelative(Mutex& mutex, int64_t reltime/*microsecnd*/) {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+
+    // On 32-bit devices, tv_sec is 32-bit, but `reltime` is 64-bit.
+    int64_t reltime_sec = reltime/1000;
+
+    ts.tv_nsec += static_cast<long>(reltime*1000*1000%1000000000);
+    if (reltime_sec < INT64_MAX && ts.tv_nsec >= 1000000000) {
+        ts.tv_nsec -= 1000000000;
+        ++reltime_sec;
+    }
+
+    int64_t time_sec = ts.tv_sec;
+    if (time_sec > INT64_MAX - reltime_sec) {
+        time_sec = INT64_MAX;
+    } else {
+        time_sec += reltime_sec;
+    }
+
+    ts.tv_sec = (time_sec > LONG_MAX) ? LONG_MAX : static_cast<long>(time_sec);
+
+    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
+}
+
+/**
+ * wait relative us time
+ * return 0 if wait success, non 0 if timeout or other
+ * ETIMEDOUT timeout,
+*/
+inline int Condition::waitRelativeUs(Mutex& mutex, int64_t reltime/*us*/) {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+
+    // On 32-bit devices, tv_sec is 32-bit, but `reltime` is 64-bit.
+    int64_t reltime_sec = reltime/1000000;
+
+    ts.tv_nsec += static_cast<long>(reltime*1000%1000000000);
+    if (reltime_sec < INT64_MAX && ts.tv_nsec >= 1000000000) {
+        ts.tv_nsec -= 1000000000;
+        ++reltime_sec;
+    }
+
+    int64_t time_sec = ts.tv_sec;
+    if (time_sec > INT64_MAX - reltime_sec) {
+        time_sec = INT64_MAX;
+    } else {
+        time_sec += reltime_sec;
+    }
+
+    ts.tv_sec = (time_sec > LONG_MAX) ? LONG_MAX : static_cast<long>(time_sec);
+
+    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
+}
+
+inline void Condition::signal() {
+    pthread_cond_signal(&mCond);
+}
+inline void Condition::broadcast() {
+    pthread_cond_broadcast(&mCond);
+}
+
+}
+
+#endif // _TOOLS_CONDITION_H_
diff --git a/tools/ErrorCode.h b/tools/ErrorCode.h
new file mode 100644
index 0000000..0f749ba
--- /dev/null
+++ b/tools/ErrorCode.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+#ifndef _TOOLS_ERRORS_CODE_H_
+#define _TOOLS_ERRORS_CODE_H_
+
+#include <sys/types.h>
+#include <errno.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+
+enum ErrorCode {
+    NO_ERROR          = 0,    // No errors.
+
+    ERROR_UNKNOWN             = (-2147483647-1), // INT32_MIN value
+
+    ERROR_NO_MEMORY           = -ENOMEM,
+    ERROR_INVALID_OPERATION   = -ENOSYS,
+    ERROR_BAD_VALUE           = -EINVAL,
+    ERROR_BAD_TYPE            = (ERROR_UNKNOWN + 1),
+    ERROR_NOT_FOUND           = -ENOENT,
+    ERROR_PERMISSION_DENIED   = -EPERM,
+    ERROR_NO_INIT             = -ENODEV,
+    ERROR_ALREADY_EXISTS      = -EEXIST,
+    ERROR_DEAD_OBJECT         = -EPIPE,
+    ERROR_FAILED_TRANSACTION  = (ERROR_UNKNOWN + 2),
+
+    ERROR_BAD_INDEX           = -E2BIG,
+    ERROR_NOT_ENOUGH_DATA     = (ERROR_UNKNOWN + 3),
+    ERROR_WOULD_BLOCK         = (ERROR_UNKNOWN + 4),
+    ERROR_TIMED_OUT           = (ERROR_UNKNOWN + 5),
+    ERROR_UNKNOWN_TRANSACTION = (ERROR_UNKNOWN + 6),
+
+    ERROR_FDS_NOT_ALLOWED     = (ERROR_UNKNOWN + 7),
+    ERROR_UNEXPECTED_NULL     = (ERROR_UNKNOWN + 8),
+    ERROR_OPEN_FAIL           = (ERROR_UNKNOWN + 9),
+    ERROR_PARAM_NULL          = (ERROR_UNKNOWN + 10),
+    ERROR_DESTROY_FAIL        = (ERROR_UNKNOWN + 11),
+    ERROR_IOCTL_FAIL          = (ERROR_UNKNOWN + 12),
+};
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif // _TOOLS_ERRORS_CODE_H_
diff --git a/tools/Logger.cpp b/tools/Logger.cpp
index 197601e..e3a8946 100644
--- a/tools/Logger.cpp
+++ b/tools/Logger.cpp
@@ -30,16 +30,60 @@
 #include <cutils/log.h>
 #include "Logger.h"
 
+#define MAX_USER_TAG 8
 #define MAX_TAG_LENGTH 64
 #define MAX_FILENAME_LENGTH 128
 #define MAX_LOG_BUFFER 1024
 
 static long long getCurrentTimeMillis(void);
+typedef struct {
+    char tag[MAX_TAG_LENGTH]; //user print tag
+    bool active;
+} UserTag;
 
 static int g_activeLevel= 2;
 static FILE * g_fd = stderr;
-static char g_fileName[MAX_FILENAME_LENGTH] = {0};
+static char g_fileName[MAX_FILENAME_LENGTH];
+static UserTag g_userTag[MAX_USER_TAG];
+static int g_activeUserTag = 0;
 static std::mutex g_mutext;
+static int g_init = 0;
+
+int Logger_init(int id)
+{
+    int category = NO_CAT;
+
+    g_mutext.lock();
+    if (g_init == 0) {
+        g_init = 1;
+        memset(g_fileName, 0 , MAX_FILENAME_LENGTH);
+        for (int i = 0; i < MAX_USER_TAG; i++) {
+            g_userTag[i].active = false;
+        }
+    }
+    for (int i = 0; i < MAX_USER_TAG; i++) {
+        if (g_userTag[i].active == false) {
+            g_userTag[i].active = true;
+            category = i;
+            memset(g_userTag[i].tag, 0, MAX_TAG_LENGTH);
+            sprintf(g_userTag[i].tag,"%s-%d","rlib",id);
+            ++g_activeUserTag;
+            break;
+        }
+    }
+    g_mutext.unlock();
+    return category;
+}
+
+void Logger_exit(int category)
+{
+    g_mutext.lock();
+    if (category >= 0 && category < MAX_USER_TAG) {
+        g_userTag[category].active = false;
+        --g_activeUserTag;
+    }
+    g_mutext.unlock();
+}
 
 void Logger_set_level(int setLevel)
 {
@@ -73,9 +117,10 @@
             return;
         }
         if (g_fd != stderr && strlen(g_fileName) > 0) {
-            printf("render_client log file:%s \n",g_fileName);
+            fprintf(stderr, "libvideorender log file:%s \n",g_fileName);
             return;
         }
+        fprintf(stderr, "libvideorender log file:%s \n",g_fileName);
         memset(g_fileName, 0 , MAX_FILENAME_LENGTH);
         strcpy(g_fileName, filepath);
         if (g_fd != stderr) {
@@ -106,7 +151,7 @@
     return (char *) " U ";
 }
 
-void logPrint(int level, const char *fmt, ... )
+void logPrint(int category ,int level, const char *fmt, ... )
 {
     if ( level <= g_activeLevel )
     {
@@ -116,10 +161,12 @@
             int len = 0;
 
             len = sprintf(buf, "%lld ",getCurrentTimeMillis());
-            int tlen = len > 0? len:0;
-            tlen = sprintf( buf+tlen, "%d ", getpid());
-            if (tlen >= 0) {
-                len += tlen;
+            if (g_activeUserTag && category >= 0 && category < MAX_USER_TAG && g_userTag[category].active) {
+                int tlen = len > 0? len:0;
+                tlen = sprintf( buf+tlen, "%s ", g_userTag[category].tag);
+                if (tlen >= 0) {
+                    len += tlen;
+                }
             }
             va_start( argptr, fmt );
             if (len > 0) {
@@ -132,7 +179,11 @@
         } else if (g_fd != stderr) { //set output log to file
             va_list argptr;
             fprintf( g_fd, "%lld ", getCurrentTimeMillis());
-            fprintf( g_fd, "%d ", getpid());
+            if (g_activeUserTag && category >= 0 && category < MAX_USER_TAG && g_userTag[category].active) {
+                fprintf( g_fd, "%s ", g_userTag[category].tag);
+            } else {
+                fprintf( g_fd, "%d:%lu ", getpid(),pthread_self());
+            }
             //print log level tag
             fprintf( g_fd, "%s ",logLevelToString(level));
             va_start( argptr, fmt );
diff --git a/tools/Logger.h b/tools/Logger.h
index b0c4b4b..8977a0c 100644
--- a/tools/Logger.h
+++ b/tools/Logger.h
@@ -23,7 +23,25 @@
 #define LOG_LEVEL_DEBUG   3
 #define LOG_LEVEL_TRACE   4
 
-void logPrint(int level, const char *fmt, ... );
+#define NO_CAT -1
+
+/**
+ * @brief init logger print
+ * @param id plugin instance id
+ *
+ * @return category id
+ */
+int Logger_init(int id);
+
+/**
+ * @brief exit logger print
+ * @param category category id
+ *
+ * @return
+ */
+void Logger_exit(int category);
+
+void logPrint(int category, int level, const char *fmt, ... );
 
 /**
  * @brief set log level
@@ -52,16 +70,16 @@
  */
 void Logger_set_file(char *filepath);
 
-#define INT_ERROR(FORMAT, ...)      logPrint(LOG_LEVEL_ERROR,  "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
-#define INT_WARNING(FORMAT, ...)    logPrint(LOG_LEVEL_WARNING,"%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
-#define INT_INFO(FORMAT, ...)       logPrint(LOG_LEVEL_INFO,   "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
-#define INT_DEBUG(FORMAT, ...)      logPrint(LOG_LEVEL_DEBUG,  "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
-#define INT_TRACE(FORMAT, ...)      logPrint(LOG_LEVEL_TRACE, "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
+#define INT_ERROR(CAT,FORMAT, ...)      logPrint(CAT,LOG_LEVEL_ERROR,  "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
+#define INT_WARNING(CAT,FORMAT, ...)    logPrint(CAT,LOG_LEVEL_WARNING,"%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
+#define INT_INFO(CAT,FORMAT, ...)       logPrint(CAT,LOG_LEVEL_INFO,   "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
+#define INT_DEBUG(CAT,FORMAT, ...)      logPrint(CAT,LOG_LEVEL_DEBUG,  "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
+#define INT_TRACE(CAT,FORMAT, ...)      logPrint(CAT,LOG_LEVEL_TRACE, "%s,%s:%d " FORMAT "\n",TAG,__func__, __LINE__, __VA_ARGS__)
 
-#define ERROR(...)                  INT_ERROR(__VA_ARGS__, "")
-#define WARNING(...)                INT_WARNING(__VA_ARGS__, "")
-#define INFO(...)                   INT_INFO(__VA_ARGS__, "")
-#define DEBUG(...)                  INT_DEBUG(__VA_ARGS__, "")
-#define TRACE(...)                  INT_TRACE(__VA_ARGS__, "")
+#define ERROR(CAT,...)                  INT_ERROR(CAT,__VA_ARGS__, "")
+#define WARNING(CAT,...)                INT_WARNING(CAT,__VA_ARGS__, "")
+#define INFO(CAT,...)                   INT_INFO(CAT,__VA_ARGS__, "")
+#define DEBUG(CAT,...)                  INT_DEBUG(CAT,__VA_ARGS__, "")
+#define TRACE(CAT,...)                  INT_TRACE(CAT,__VA_ARGS__, "")
 
 #endif /*__TOOLS_LOGGER_H__*/
\ No newline at end of file
diff --git a/tools/Mutex.h b/tools/Mutex.h
new file mode 100644
index 0000000..8d72ce8
--- /dev/null
+++ b/tools/Mutex.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2021 Amlogic Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _TOOS_MUTEX_H_
+#define _TOOS_MUTEX_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+#include <pthread.h>
+
+namespace Tls {
+
+// Enable thread safety attributes only with clang.
+// The attributes can be safely erased when compiling with other compilers.
+#if defined(__clang__) && (!defined(SWIG))
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x)  // no-op
+#endif
+
+#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+
+#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+
+#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+
+#define ACQUIRED_BEFORE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+
+#define ACQUIRED_AFTER(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+#define REQUIRES(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+
+#define REQUIRES_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+
+#define ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+
+#define ACQUIRE_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+
+#define RELEASE(...) THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+
+#define RELEASE_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE_SHARED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+
+#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+
+#define ASSERT_SHARED_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+
+#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+#define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+
+class Condition;
+
+/*
+ * NOTE: This class is for code that builds on Win32.  Its usage is
+ * deprecated for code which doesn't build for Win32.  New code which
+ * doesn't build for Win32 should use std::mutex and std::lock_guard instead.
+ *
+ * Simple mutex class.  The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it.  They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class CAPABILITY("mutex") Mutex {
+  public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+
+    Mutex();
+    explicit Mutex(const char* name);
+    explicit Mutex(int type, const char* name = NULL);
+    ~Mutex();
+
+    // lock or unlock the mutex
+    int lock() ACQUIRE();
+    void unlock() RELEASE();
+
+    // lock if possible; returns 0 on success, error otherwise
+    int tryLock() TRY_ACQUIRE(true);
+
+    // Manages the mutex automatically. It'll be locked when Autolock is
+    // constructed and released when Autolock goes out of scope.
+    class SCOPED_CAPABILITY Autolock {
+      public:
+        inline explicit Autolock(Mutex& mutex) ACQUIRE(mutex) : mLock(mutex) { mLock.lock(); }
+        inline explicit Autolock(Mutex* mutex) ACQUIRE(mutex) : mLock(*mutex) { mLock.lock(); }
+        inline ~Autolock() RELEASE() { mLock.unlock(); }
+
+      private:
+        Mutex& mLock;
+        // Cannot be copied or moved - declarations only
+        Autolock(const Autolock&);
+        Autolock& operator=(const Autolock&);
+    };
+
+  private:
+    friend class Condition;
+
+    // A mutex cannot be copied
+    Mutex(const Mutex&);
+    Mutex& operator=(const Mutex&);
+    pthread_mutex_t mMutex;
+};
+
+inline Mutex::Mutex() {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(__attribute__((unused)) const char* name) {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
+    if (type == SHARED) {
+        pthread_mutexattr_t attr;
+        pthread_mutexattr_init(&attr);
+        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_mutex_init(&mMutex, &attr);
+        pthread_mutexattr_destroy(&attr);
+    } else {
+        pthread_mutex_init(&mMutex, NULL);
+    }
+}
+inline Mutex::~Mutex() {
+    pthread_mutex_destroy(&mMutex);
+}
+inline int Mutex::lock() {
+    return -pthread_mutex_lock(&mMutex);
+}
+inline void Mutex::unlock() {
+    pthread_mutex_unlock(&mMutex);
+}
+inline int Mutex::tryLock() {
+    return -pthread_mutex_trylock(&mMutex);
+}
+
+
+typedef Mutex::Autolock AutoMutex;
+
+}
+#endif // _TOOS_MUTEX_H_
+
diff --git a/tools/Poll.cpp b/tools/Poll.cpp
new file mode 100644
index 0000000..46d306f
--- /dev/null
+++ b/tools/Poll.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2021 Amlogic Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/time.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <string.h>
+
+#include <unistd.h>
+#include "Times.h"
+#include "Poll.h"
+#include "Logger.h"
+
+#define TAG "Poll"
+
+namespace Tls {
+
+#define INCREASE_ACTIVE_FDS 8
+
+Poll::Poll(bool controllable)
+      : mControllable(controllable)
+{
+    mFds = NULL;
+    mFdsCnt = 0;
+    mFdsMaxCnt = 0;
+
+    mWaiting.store(0);
+    mControlPending.store(0);
+    mFlushing.store(0);
+
+    //init control sockets
+    int control_sock[2];
+
+    if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0) {
+        mControlReadFd = -1;
+        mControlWriteFd = -1;
+    } else {
+        mControlReadFd = control_sock[0];
+        mControlWriteFd = control_sock[1];
+    }
+    addFd(mControlReadFd);
+    setFdReadable(mControlReadFd,true);
+}
+
+Poll::~Poll()
+{
+    if (mControlWriteFd >= 0) {
+        close (mControlWriteFd);
+        mControlWriteFd = -1;
+    }
+
+    if (mControlReadFd >= 0) {
+        close (mControlReadFd);
+        mControlReadFd = -1;
+    }
+
+    if (mFds) {
+        free(mFds);
+        mFds = NULL;
+    }
+}
+
+int Poll::addFd(int fd)
+{
+    Tls::Mutex::Autolock _l(mMutex);
+    struct pollfd *pfd = findFd(fd);
+    if (pfd) {
+        return 0;
+    }
+
+    if ((mFdsCnt + 1) > mFdsMaxCnt) {
+        mFdsMaxCnt += INCREASE_ACTIVE_FDS;
+        mFds = (struct pollfd *)realloc(mFds,mFdsMaxCnt*sizeof(struct pollfd));
+        if (!mFds) {
+            ERROR(NO_CAT,"NO memory");
+            return -1;
+        }
+    }
+    mFds[mFdsCnt].fd = fd;
+    mFds[mFdsCnt].events = POLLERR | POLLNVAL | POLLHUP;
+    mFds[mFdsCnt].revents = 0;
+    mFdsCnt++;
+
+    //DEBUG("mFds:%p,maxcnt:%d,cnt:%d",mFds,mFdsMaxCnt,mFdsCnt);
+    return 0;
+}
+
+int Poll::removeFd(int fd)
+{
+    Tls::Mutex::Autolock _l(mMutex);
+    for (int i = 0; i < mFdsCnt; i++) {
+        struct pollfd *pfd = &mFds[i];
+        if (pfd->fd == fd) {
+            memmove(mFds+i*sizeof(struct pollfd),mFds+(i+1)*sizeof(struct pollfd), 1);
+            mFdsCnt--;
+            return 0;
+        }
+    }
+    return 0;
+}
+
+int Poll::setFdReadable(int fd, bool readable)
+{
+    Tls::Mutex::Autolock _l(mMutex);
+    struct pollfd * pfd = findFd(fd);
+    if (!pfd) {
+        return -1;
+    }
+    if (readable) {
+        pfd->events |= POLLIN | POLLPRI | POLLRDNORM;
+    } else {
+        pfd->events &= ~POLLIN;
+    }
+
+    return 0;
+}
+
+int Poll::setFdWritable(int fd, bool writable)
+{
+    Tls::Mutex::Autolock _l(mMutex);
+    struct pollfd * pfd = findFd(fd);
+    if (!pfd) {
+        return -1;
+    }
+    if (writable) {
+        pfd->events |= POLLOUT;
+    } else {
+        pfd->events &= ~POLLOUT;
+    }
+
+    return 0;
+}
+
+int Poll::wait(int64_t timeoutMs /*millisecond*/)
+{
+    int oldwaiting;
+    int activecnt = 0;
+
+    oldwaiting = mWaiting.load();
+
+    mWaiting.fetch_add(1);
+
+    if (oldwaiting > 0) { //had other thread waiting
+        goto tag_already_waiting;
+    }
+
+    if (mFlushing.load()) {
+        goto tag_flushing;
+    }
+
+    do {
+        int64_t t = -1; //nanosecond
+        if (timeoutMs >= 0) {
+            t = timeoutMs;
+        }
+        //DEBUG("waiting");
+        activecnt = poll(mFds, mFdsCnt, t);
+        //DEBUG("waiting end");
+        if (mFlushing.load()) {
+            goto tag_flushing;
+        }
+    } while(0);
+
+tag_success:
+    mWaiting.fetch_sub(1);
+    return activecnt;
+tag_already_waiting:
+    mWaiting.fetch_sub(1);
+    errno = EPERM;
+    return -1;
+tag_flushing:
+    mWaiting.fetch_sub(1);
+    errno = EBUSY;
+    return -1;
+}
+
+void Poll::setFlushing(bool flushing)
+{
+    /* update the new state first */
+    if (flushing) {
+        mFlushing.store(1);
+    } else {
+        mFlushing.store(0);
+    }
+
+    if (mFlushing.load() && mControllable && mWaiting.load() > 0) {
+        /* we are flushing, controllable and waiting, wake up the waiter. When we
+        * stop the flushing operation we don't clear the wakeup fd here, this will
+        * happen in the _wait() thread. */
+        raiseWakeup();
+    }
+}
+
+bool Poll::isReadable(int fd)
+{
+    for (int i = 0; i < mFdsCnt; i++) {
+        if (mFds[i].fd == fd && ((mFds[i].revents & (POLLIN|POLLRDNORM)) != 0)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool Poll::isWritable(int fd)
+{
+    for (int i = 0; i < mFdsCnt; i++) {
+        if (mFds[i].fd == fd && ((mFds[i].revents & POLLOUT) != 0)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+struct pollfd * Poll::findFd(int fd)
+{
+    for (int i = 0; i < mFdsCnt; i++) {
+        struct pollfd *pfd = &mFds[i];
+        if (pfd->fd == fd) {
+            return pfd;
+        }
+    }
+    return NULL;
+}
+
+bool Poll::wakeEvent()
+{
+    ssize_t num_written;
+    while ((num_written = write (mControlWriteFd, "W", 1)) != 1) {
+        if (num_written == -1 && errno != EAGAIN && errno != EINTR) {
+            ERROR(NO_CAT,"failed to wake event: %s", strerror (errno));
+            return false;
+        }
+    }
+    return true;
+}
+
+bool Poll::releaseEvent()
+{
+    char buf[1] = { '\0' };
+    ssize_t num_read;
+    while ((num_read = read (mControlReadFd, buf, 1)) != 1) {
+        if (num_read == -1 && errno != EAGAIN && errno != EINTR) {
+            ERROR(NO_CAT,"failed to release event: %s", strerror (errno));
+            return false;
+        }
+    }
+     return true;
+}
+bool Poll::raiseWakeup()
+{
+    bool result = true;
+
+    /* makes testing control_pending and WAKE_EVENT() atomic. */
+    Tls::Mutex::Autolock _l(mMutex);
+    //DEBUG("mControlPending:%d",mControlPending.load());
+    if (mControlPending.load() == 0) {
+        /* raise when nothing pending */
+        //GST_LOG ("%p: raise", set);
+        result = wakeEvent();
+    }
+
+    if (result) {
+        mControlPending.fetch_add(1);
+    }
+
+     return result;
+}
+
+bool Poll::releaseWakeup()
+{
+    bool result = false;
+
+    /* makes testing/modifying control_pending and RELEASE_EVENT() atomic. */
+    Tls::Mutex::Autolock _l(mMutex);
+
+    if (mControlPending.load() > 0) {
+        /* release, only if this was the last pending. */
+        if (mControlPending.load() == 1) {
+            //GST_LOG ("%p: release", set);
+            result = releaseEvent();
+        } else {
+            result = true;
+        }
+
+        if (result) {
+            mControlPending.fetch_sub(1);
+        }
+    } else {
+        errno = EWOULDBLOCK;
+    }
+
+    return result;
+}
+
+bool Poll::releaseAllWakeup()
+{
+    bool result = false;
+
+    /* makes testing/modifying control_pending and RELEASE_EVENT() atomic. */
+    Tls::Mutex::Autolock _l(mMutex);
+
+    if (mControlPending.load() > 0) {
+        //GST_LOG ("%p: release", set);
+        result = releaseEvent();
+        if (result) {
+            mControlPending.store(0);
+        }
+    } else {
+        errno = EWOULDBLOCK;
+    }
+
+    return result;
+}
+
+}
\ No newline at end of file
diff --git a/tools/Poll.h b/tools/Poll.h
new file mode 100644
index 0000000..23d2944
--- /dev/null
+++ b/tools/Poll.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2021 Amlogic Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _TOOS_POLL_H_
+#define _TOOS_POLL_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <list>
+#include <atomic>
+#include <poll.h>
+
+#include "Mutex.h"
+
+/**
+ * @brief Poll is a implement wrap about
+ * poll,but Poll can wakeup when poll is waiting
+ * for ever,if set flushing
+ * the sequence api is
+ * 1.poll = new Poll(true)
+ * 2.poll->addfd(fd)
+ * 3.poll->setFdReadable(fd,true)/poll->setFdWritable(fd,true)
+ * 4.poll->wait(waittime)
+ * ........
+ * 5.if (poll->isReadable(fd))
+ * 6. read data from fd
+ * 7.if (poll->isReadable(fd))
+ * 8. write data to fd
+ * if want to destroy poll,call
+ * 9.poll->setFlushing
+ * 10.delete poll
+ */
+namespace Tls {
+class Poll {
+  public:
+    Poll(bool controllable);
+    virtual ~Poll();
+    /**
+     * @brief add a fd to poll
+     *
+     * @param fd
+     * @return int
+     */
+    int addFd(int fd);
+    /**
+     * @brief remove fd from poll
+     *
+     * @param fd
+     * @return int
+     */
+    int removeFd(int fd);
+    /**
+     * @brief Set the Fd Readable ,poll will
+     * check readable event
+     * @param fd
+     * @param readable
+     * @return int 0 success, -1 fail
+     */
+    int setFdReadable(int fd, bool readable);
+    /**
+     * @brief Set the Fd Writable,poll will
+     * check writable event
+     * @param fd
+     * @param writable
+     * @return int 0 success, -1 fail
+     */
+    int setFdWritable(int fd, bool writable);
+    /**
+     * @brief wait fd event
+     *
+     * @param timeoutMs wait millisecond time, -1 will wait for ever
+     * otherwise wait the special nanasecond time
+     * @return int active fd count
+     */
+    int wait(int64_t timeoutMs /*millisecond*/);
+    /**
+     * @brief Set the Flushing if poll wait had called
+     * and waiting, this func will send a raise event to
+     * wakeup poll wait
+     * @param flushing
+     */
+    void setFlushing(bool flushing);
+    /**
+     * @brief check this fd if had data to read
+     *
+     * @param fd file fd
+     * @return true
+     * @return false
+     */
+    bool isReadable(int fd);
+    /**
+     * @brief check this fd if can write
+     *
+     * @param fd file fd
+     * @return true
+     * @return false
+     */
+    bool isWritable(int fd);
+  private:
+    struct pollfd * findFd(int fd);
+    bool wakeEvent();
+    bool releaseEvent();
+    bool raiseWakeup();
+    bool releaseWakeup();
+    bool releaseAllWakeup();
+    Tls::Mutex mMutex;
+    int mControlReadFd;
+    int mControlWriteFd;
+    struct pollfd * mFds;
+    int mFdsMaxCnt;
+    int mFdsCnt;
+    bool mControllable;
+    std::atomic<int> mControlPending;
+    std::atomic<int> mFlushing;
+    std::atomic<int> mWaiting; //store waiting thread count
+};
+
+}
+
+#endif /*_TOOS_POLL_H_*/
diff --git a/tools/Thread.cpp b/tools/Thread.cpp
index b472a80..1e9ba9a 100644
--- a/tools/Thread.cpp
+++ b/tools/Thread.cpp
@@ -27,6 +27,7 @@
 
 Thread::Thread()
     :mThread(pthread_t(-1)),
+    mLock("Thread::mLock"),
     mStatus(0),
     mExitPending(false),
     mRunning(false),
@@ -55,12 +56,14 @@
 
 int Thread::run(const char* name)
 {
-    std::unique_lock<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mLock);
     if (mRunning) {
         // thread already started
         return -1;
     }
 
+    // reset status and exitPending to their default value, so we can
+    // try again after an error happened (either below, or in readyToRun())
     mStatus = 0;
     mExitPending = false;
     mThread = pthread_t(-1);
@@ -85,9 +88,10 @@
         mStatus = -1;   // something happened!
         mRunning = false;
         mThread = pthread_t(-1);
-        mCond.notify_all();
+        mCondition.broadcast();
         return -1;
     }
+
     return 0;
 }
 
@@ -148,7 +152,7 @@
 exit:
     //must call readyToExit before set mRunning to false
     self->readyToExit();
-    std::unique_lock<std::mutex> lck(self->mMutex);
+    Tls::Mutex::Autolock _l(self->mLock);
     self->mExitPending = true;
     // clear thread ID so that requestExitAndWait() does not exit if
     // called by a new thread using the same thread ID as this one.
@@ -156,55 +160,59 @@
     self->mRunning = false;
     // note that interested observers blocked in requestExitAndWait are
     // awoken by broadcast, but blocked on mLock until break exits scope
-    self->mCond.notify_all();
+    self->mCondition.broadcast();
+
     return 0;
 }
 
 void Thread::requestExit()
 {
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mLock);
     mExitPending = true;
 }
 
 int Thread::requestExitAndWait()
 {
-    std::unique_lock<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mLock);
     if (mThread == getThreadId()) {
+
         return -1;
     }
 
     mExitPending = true;
 
     while (mRunning == true) {
-        mCond.wait(lck);
+        mCondition.wait(mLock);
     }
-    // This next line is probably not needed any more, but is being left for
-    // historical reference. Note that each interested party will clear flag.
+
     mExitPending = false;
+
     return mStatus;
 }
 
 int Thread::join()
 {
-    std::unique_lock<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mLock);
     if (mThread == getThreadId()) {
+
         return -1;
     }
 
     while (mRunning == true) {
-        mCond.wait(lck);
+        mCondition.wait(mLock);
     }
+
     return mStatus;
 }
 
 bool Thread::isRunning() const {
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mLock);
     return mRunning;
 }
 
 bool Thread::isExitPending() const
 {
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mLock);
     return mExitPending;
 }
 }
\ No newline at end of file
diff --git a/tools/Thread.h b/tools/Thread.h
index 2a8e297..c87e9f7 100644
--- a/tools/Thread.h
+++ b/tools/Thread.h
@@ -20,8 +20,8 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <pthread.h>
-#include <mutex>
-#include <condition_variable>
+#include "Mutex.h"
+#include "Condition.h"
 
 typedef void* (*pthread_entry_func)(void*);
 #define MAX_THREAD_NAME_LEN 128
@@ -74,14 +74,14 @@
     static  void* _threadLoop(void* user);
     int _createThread(pthread_entry_func entryFunction);
     // always hold mLock when reading or writing
-    pthread_t mThread;
+    pthread_t       mThread;
     char    mThreadName[MAX_THREAD_NAME_LEN];
-    mutable std::mutex mMutex;
-    std::condition_variable mCond;
+    mutable Tls::Mutex   mLock;
+    Tls::Condition       mCondition;
     int        mStatus;
     // note that all accesses of mExitPending and mRunning need to hold mLock
-    volatile bool mExitPending;
-    volatile bool mRunning;
+    volatile bool           mExitPending;
+    volatile bool           mRunning;
     int mPriority;
 };
 }
diff --git a/videotunnel/Makefile b/videotunnel/Makefile
index a1f4d55..e5cf0f1 100644
--- a/videotunnel/Makefile
+++ b/videotunnel/Makefile
@@ -36,6 +36,7 @@
 
 OBJ_CLIENT_LIB += \
 	$(TOOLS_PATH)/Thread.o \
+	$(TOOLS_PATH)/Poll.o \
 	$(TOOLS_PATH)/Times.o \
 	$(TOOLS_PATH)/Logger.o
 
diff --git a/videotunnel/videotunnel.h b/videotunnel/videotunnel.h
new file mode 100644
index 0000000..e616988
--- /dev/null
+++ b/videotunnel/videotunnel.h
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * drivers/amlogic/media/video_processor/videotunnel/uapi/videotunnel.h
+ *
+ * Copyright (C) 2020 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __UAPI_VIDEO_TUNNEL_H
+#define __UAPI_VIDEO_TUNNEL_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define MAX_VIDEO_TUNNEL 16
+
+enum vt_role_e {
+	VT_ROLE_PRODUCER,
+	VT_ROLE_CONSUMER,
+	VT_ROLE_INVALID,
+};
+
+enum vt_ctrl_cmd_e {
+	VT_CTRL_CONNECT,
+	VT_CTRL_DISCONNECT,
+	VT_CTRL_SEND_CMD,
+	VT_CTRL_RECV_CMD,
+	VT_CTRL_SET_BLOCK_MODE,
+	VT_CTRL_SET_NONBLOCK_MODE,
+	VT_CTRL_REPLY_CMD,
+	VT_CTRL_POLL_CMD,
+	VT_CTRL_CANCEL_BUFFER,
+};
+
+enum vt_video_cmd_e {
+	VT_VIDEO_SET_STATUS,
+	VT_VIDEO_GET_STATUS,
+	VT_VIDEO_SET_GAME_MODE,
+	VT_VIDEO_SET_SOURCE_CROP,
+};
+
+struct vt_alloc_id_data {
+	int tunnel_id;
+};
+
+struct vt_krect {
+	int left;
+	int top;
+	int right;
+	int bottom;
+};
+
+struct vt_ctrl_data {
+	int tunnel_id;
+	enum vt_role_e role;
+	enum vt_ctrl_cmd_e ctrl_cmd;
+	enum vt_video_cmd_e video_cmd;
+	int video_cmd_data;
+	int client_id;
+	struct vt_krect source_crop;
+};
+
+/**
+ * struct vt_buffer_data - vframe buffer metadata
+ * buffer data transfer between producer and consumer
+ */
+struct vt_buffer_data {
+	int tunnel_id;
+	int buffer_fd;
+	int fence_fd;
+	int buffer_status;
+	int64_t time_stamp;
+};
+
+/*
+ * struct vt_display_vsync
+ * display vsync info transfer between producer and consumer
+ */
+struct vt_display_vsync {
+	int tunnel_id;
+	uint64_t timestamp;
+	uint32_t period;
+};
+
+#define VT_IOC_MAGIC 'V'
+
+/**
+ * VT_IOC_ALLOC_ID - allocate tunnel id
+ *
+ * takes an vt_alloc_id_data struct and returns it with tunnel_id
+ * field populated
+ */
+#define VT_IOC_ALLOC_ID _IOWR(VT_IOC_MAGIC, 0, \
+				       struct vt_alloc_id_data)
+
+/**
+ * VT_IOC_FREE_ID - free tunnel id
+ *
+ * takes an vt_alloc_id_data struct and no return
+ * free the videotunnel_instance
+ */
+#define VT_IOC_FREE_ID _IOWR(VT_IOC_MAGIC, 1, \
+				      struct vt_alloc_id_data)
+
+/**
+ * VT_IOC_CTRL - control tunnel on and off
+ * takes an vt_ctrl_data struct and no return
+ * control the tunnel switch
+ */
+#define VT_IOC_CTRL	_IOWR(VT_IOC_MAGIC, 2, \
+				      struct vt_ctrl_data)
+
+/**
+ * VT_IOC_QUEUE_BUFFER - producer queue the vframe info
+ * takes an vt_buffer_item and no return
+ */
+#define VT_IOC_QUEUE_BUFFER	_IOWR(VT_IOC_MAGIC, 3, \
+				      struct vt_buffer_data)
+
+/**
+ * VT_IOC_DEQUEUE_BUFFER - producer dequeue the vframe info
+ * takes an vt_buffer_item and returns it with index field
+ * populated
+ */
+#define VT_IOC_DEQUEUE_BUFFER	_IOWR(VT_IOC_MAGIC, 4, \
+				      struct vt_buffer_data)
+
+/**
+ * VT_IOC_RELEASE_BUFFER - consumer release the vframe info
+ * takes an vt_buffer_data and no return
+ * the vt_buffer_item should contain the fence
+ */
+#define VT_IOC_RELEASE_BUFFER	_IOWR(VT_IOC_MAGIC, 5, \
+				      struct vt_buffer_data)
+
+/**
+ * VT_IOC_ACQUIRE_BUFFER - consumer dequeue the vframe info
+ * takes an vt_buffer_data and returns it with buffer_item field
+ * populated
+ */
+#define VT_IOC_ACQUIRE_BUFFER	_IOWR(VT_IOC_MAGIC, 6, \
+				      struct vt_buffer_data)
+
+/**
+ * VT_IOC_GET_VSYNCTIME - producer get display vsync timestamp
+ * and period from videotunnel.
+ */
+#define VT_IOC_GET_VSYNCTIME	_IOWR(VT_IOC_MAGIC, 7, \
+				      struct vt_display_vsync)
+
+/**
+ * VT_IOC_SET_VSYNCTIME - consumer set display vsync timestamp
+ * and period to videotunnel.
+ */
+#define VT_IOC_SET_VSYNCTIME	_IOWR(VT_IOC_MAGIC, 8, \
+				      struct vt_display_vsync)
+#endif
diff --git a/videotunnel/videotunnel_impl.cpp b/videotunnel/videotunnel_impl.cpp
index e824108..2fc6b6c 100644
--- a/videotunnel/videotunnel_impl.cpp
+++ b/videotunnel/videotunnel_impl.cpp
@@ -29,8 +29,9 @@
 #define UNDER_FLOW_EXPIRED_TIME_MS 83
 
 
-VideoTunnelImpl::VideoTunnelImpl(VideoTunnelPlugin *plugin)
-    : mPlugin(plugin)
+VideoTunnelImpl::VideoTunnelImpl(VideoTunnelPlugin *plugin, int logcategory)
+    : mPlugin(plugin),
+    mLogCategory(logcategory)
 {
     mFd = -1;
     mInstanceId = 0;
@@ -42,17 +43,22 @@
     mFrameWidth = 0;
     mFrameHeight = 0;
     mUnderFlowDetect = false;
+    mPoll = new Tls::Poll(true);
 }
 
 VideoTunnelImpl::~VideoTunnelImpl()
 {
+    if (mPoll) {
+        delete mPoll;
+        mPoll = NULL;
+    }
 }
 
 bool VideoTunnelImpl::init()
 {
-    mVideotunnelLib = videotunnelLoadLib();
+    mVideotunnelLib = videotunnelLoadLib(mLogCategory);
     if (!mVideotunnelLib) {
-        ERROR("videotunnelLoadLib load symbol fail");
+        ERROR(mLogCategory,"videotunnelLoadLib load symbol fail");
         return false;
     }
     return true;
@@ -61,7 +67,7 @@
 bool VideoTunnelImpl::release()
 {
     if (mVideotunnelLib) {
-        videotunnelUnloadLib(mVideotunnelLib);
+        videotunnelUnloadLib(mLogCategory, mVideotunnelLib);
         mVideotunnelLib = NULL;
     }
     return true;
@@ -70,7 +76,7 @@
 bool VideoTunnelImpl::connect()
 {
     int ret;
-    DEBUG("in");
+    DEBUG(mLogCategory,"in");
     mRequestStop = false;
     mSignalFirstFrameDiplayed = false;
     if (mVideotunnelLib && mVideotunnelLib->vtOpen) {
@@ -85,36 +91,39 @@
         }
         mIsVideoTunnelConnected = true;
     } else {
-        ERROR("open videotunnel fail or alloc id fail");
+        ERROR(mLogCategory,"open videotunnel fail or alloc id fail");
         return false;
     }
-    INFO("vt fd:%d, instance id:%d",mFd,mInstanceId);
-    DEBUG("out");
+    INFO(mLogCategory,"vt fd:%d, instance id:%d",mFd,mInstanceId);
+    DEBUG(mLogCategory,"out");
     return true;
 }
 
 bool VideoTunnelImpl::disconnect()
 {
     mRequestStop = true;
-    DEBUG("in");
+    DEBUG(mLogCategory,"in");
     if (isRunning()) {
+        if (mPoll) {
+            mPoll->setFlushing(true);
+        }
         requestExitAndWait();
         mStarted = false;
     }
 
     if (mFd > 0) {
         if (mIsVideoTunnelConnected) {
-            INFO("instance id:%d",mInstanceId);
+            INFO(mLogCategory,"instance id:%d",mInstanceId);
             if (mVideotunnelLib && mVideotunnelLib->vtDisconnect) {
                 mVideotunnelLib->vtDisconnect(mFd, mInstanceId, VT_ROLE_PRODUCER);
             }
             mIsVideoTunnelConnected = false;
         }
         if (mInstanceId >= 0) {
-            INFO("free instance id:%d",mInstanceId);
+            INFO(mLogCategory,"free instance id:%d",mInstanceId);
             //meson_vt_free_id(mFd, mInstanceId);
         }
-        INFO("close vt fd:%d",mFd);
+        INFO(mLogCategory,"close vt fd:%d",mFd);
         if (mVideotunnelLib && mVideotunnelLib->vtClose) {
             mVideotunnelLib->vtClose(mFd);
         }
@@ -122,15 +131,15 @@
     }
 
     //flush all buffer those do not displayed
-    DEBUG("release all posted to videotunnel buffers");
-    std::lock_guard<std::mutex> lck(mMutex);
+    DEBUG(mLogCategory,"release all posted to videotunnel buffers");
+    Tls::Mutex::Autolock _l(mMutex);
     for (auto item = mQueueRenderBufferMap.begin(); item != mQueueRenderBufferMap.end(); ) {
         RenderBuffer *renderbuffer = (RenderBuffer*) item->second;
         mQueueRenderBufferMap.erase(item++);
         mPlugin->handleFrameDropped(renderbuffer);
         mPlugin->handleBufferRelease(renderbuffer);
     }
-    DEBUG("out");
+    DEBUG(mLogCategory,"out");
     return true;
 }
 
@@ -138,7 +147,7 @@
 {
     int ret;
     if (mStarted == false) {
-        DEBUG("to run VideoTunnelImpl");
+        DEBUG(mLogCategory,"to run VideoTunnelImpl");
         run("VideoTunnelImpl");
         mStarted = true;
         mSignalFirstFrameDiplayed = true;
@@ -153,11 +162,11 @@
         }
     }
 
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     std::pair<int, RenderBuffer *> item(fd0, buf);
     mQueueRenderBufferMap.insert(item);
     ++mQueueFrameCnt;
-    TRACE("***fd:%d,w:%d,h:%d,displaytime:%lld,commitCnt:%d",buf->dma.fd[0],buf->dma.width,buf->dma.height,displayTime,mQueueFrameCnt);
+    TRACE(mLogCategory,"***fd:%d,w:%d,h:%d,displaytime:%lld,commitCnt:%d",buf->dma.fd[0],buf->dma.width,buf->dma.height,displayTime,mQueueFrameCnt);
     mPlugin->handleFrameDisplayed(buf);
     mLastDisplayTime = Tls::Times::getSystemTimeMs();
     return true;
@@ -165,8 +174,8 @@
 
 void VideoTunnelImpl::flush()
 {
-    DEBUG("flush");
-    std::lock_guard<std::mutex> lck(mMutex);
+    DEBUG(mLogCategory,"flush");
+    Tls::Mutex::Autolock _l(mMutex);
     if (mVideotunnelLib && mVideotunnelLib->vtCancelBuffer) {
         mVideotunnelLib->vtCancelBuffer(mFd, mInstanceId);
     }
@@ -177,14 +186,14 @@
         mPlugin->handleBufferRelease(renderbuffer);
     }
     mQueueFrameCnt = 0;
-    DEBUG("after flush,commitCnt:%d",mQueueFrameCnt);
+    DEBUG(mLogCategory,"after flush,commitCnt:%d",mQueueFrameCnt);
 }
 
 void VideoTunnelImpl::setFrameSize(int width, int height)
 {
     mFrameWidth = width;
     mFrameHeight = height;
-    DEBUG("set frame size, width:%d, height:%d",mFrameWidth,mFrameHeight);
+    DEBUG(mLogCategory, "set frame size, width:%d, height:%d",mFrameWidth,mFrameHeight);
 }
 
 void VideoTunnelImpl::setVideotunnelId(int id)
@@ -194,14 +203,11 @@
 
 void VideoTunnelImpl::waitFence(int fence) {
     if (fence > 0) {
-        struct pollfd fds;
-
-        fds.fd = fence;
-        fds.events = POLLERR | POLLNVAL | POLLHUP |POLLIN | POLLPRI | POLLRDNORM;
-        fds.revents = 0;
+        mPoll->addFd(fence);
+        mPoll->setFdReadable(fence, true);
 
         for ( ; ; ) {
-            int rc = poll(&fds, 1, 3000);
+            int rc = mPoll->wait(3000); //3 sec
             if ((rc == -1) && ((errno == EINTR) || (errno == EAGAIN))) {
                 continue;
             } else if (rc <= 0) {
@@ -209,6 +215,7 @@
             }
             break;
         }
+        mPoll->removeFd(fence);
         close(fence);
         fence = -1;
     }
@@ -237,7 +244,7 @@
     RenderBuffer *buffer = NULL;
 
     if (mRequestStop) {
-        DEBUG("request stop");
+        DEBUG(mLogCategory,"request stop");
         return false;
     }
     //if last frame expired,and not send frame to compositor for under flow expired time
@@ -255,13 +262,13 @@
 
     if (ret != 0) {
         if (mRequestStop) {
-            DEBUG("request stop");
+            DEBUG(mLogCategory,"request stop");
             return false;
         }
         return true;
     }
     if (mRequestStop) {
-        DEBUG("request stop");
+        DEBUG(mLogCategory,"request stop");
         return false;
     }
 
@@ -269,22 +276,22 @@
     waitFence(fenceId);
 
     {
-        std::lock_guard<std::mutex> lck(mMutex);
+        Tls::Mutex::Autolock _l(mMutex);
         auto item = mQueueRenderBufferMap.find(bufferId);
         if (item == mQueueRenderBufferMap.end()) {
-            ERROR("Not found in mQueueRenderBufferMap bufferId:%d",bufferId);
+            ERROR(mLogCategory,"Not found in mQueueRenderBufferMap bufferId:%d",bufferId);
             return true;
         }
         // try locking when removing item from mQueueRenderBufferMap
         buffer = (RenderBuffer*) item->second;
         mQueueRenderBufferMap.erase(bufferId);
         --mQueueFrameCnt;
-        TRACE("***dq buffer fd:%d,commitCnt:%d",bufferId,mQueueFrameCnt);
+        TRACE(mLogCategory,"***dq buffer fd:%d,commitCnt:%d",bufferId,mQueueFrameCnt);
     }
     //send first frame displayed msg
     if (mSignalFirstFrameDiplayed) {
         mSignalFirstFrameDiplayed = false;
-        INFO("send first frame displayed msg");
+        INFO(mLogCategory,"send first frame displayed msg");
         mPlugin->handleMsgNotify(MSG_FIRST_FRAME,(void*)&buffer->pts);
     }
     mPlugin->handleBufferRelease(buffer);
diff --git a/videotunnel/videotunnel_impl.h b/videotunnel/videotunnel_impl.h
index 72b1625..3b9a4bf 100644
--- a/videotunnel/videotunnel_impl.h
+++ b/videotunnel/videotunnel_impl.h
@@ -16,7 +16,9 @@
 #ifndef __VIDEO_TUNNEL_IMPLEMENT_H__
 #define __VIDEO_TUNNEL_IMPLEMENT_H__
 #include <unordered_map>
+#include "Mutex.h"
 #include "Thread.h"
+#include "Poll.h"
 #include "videotunnel_lib_wrap.h"
 
 class VideoTunnelPlugin;
@@ -24,7 +26,7 @@
 class VideoTunnelImpl : public Tls::Thread
 {
   public:
-    VideoTunnelImpl(VideoTunnelPlugin *plugin);
+    VideoTunnelImpl(VideoTunnelPlugin *plugin, int logCategory);
     virtual ~VideoTunnelImpl();
     bool init();
     bool release();
@@ -45,8 +47,11 @@
   private:
     void waitFence(int fence);
     VideoTunnelPlugin *mPlugin;
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mMutex;
     VideotunnelLib *mVideotunnelLib;
+
+    int mLogCategory;
+
     int mFd;
     int mInstanceId;
     bool mIsVideoTunnelConnected;
@@ -59,6 +64,7 @@
 
     int mFrameWidth;
     int mFrameHeight;
+    Tls::Poll *mPoll;
     int64_t mLastDisplayTime;
     bool mSignalFirstFrameDiplayed;
     bool mUnderFlowDetect;
diff --git a/videotunnel/videotunnel_lib_wrap.cpp b/videotunnel/videotunnel_lib_wrap.cpp
index 3f55dfa..7bdd96d 100644
--- a/videotunnel/videotunnel_lib_wrap.cpp
+++ b/videotunnel/videotunnel_lib_wrap.cpp
@@ -18,107 +18,108 @@
 #include <stdlib.h>
 #include "videotunnel_lib_wrap.h"
 #include "Logger.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:videotunnel_lib_wrap"
 
 #define VIDEOTUNNEL_LIB_NAME "libvideotunnel.so"
 
-VideotunnelLib * videotunnelLoadLib()
+VideotunnelLib * videotunnelLoadLib(int logCategory)
 {
-    INFO("load videotunel so symbol");
+    INFO(logCategory, "load videotunel so symbol");
 
     VideotunnelLib *handle = (VideotunnelLib*)calloc( 1, sizeof(VideotunnelLib));
     if (!handle) {
-        ERROR("calloc VideotunnelLib struct fail");
+        ERROR(logCategory, "calloc VideotunnelLib struct fail");
         goto err_labal;
     }
     handle->libHandle = dlopen(VIDEOTUNNEL_LIB_NAME, RTLD_NOW);
     if (handle->libHandle == NULL) {
-        ERROR("unable to dlopen %s : %s",VIDEOTUNNEL_LIB_NAME, dlerror());
+        ERROR(logCategory, "unable to dlopen %s : %s",VIDEOTUNNEL_LIB_NAME, dlerror());
         goto err_labal;
     }
 
     handle->vtOpen = (vt_open)dlsym(handle->libHandle, "meson_vt_open");
     if (handle->vtOpen == NULL) {
-        ERROR("dlsym meson_vt_open failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_open failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtClose = (vt_close)dlsym(handle->libHandle, "meson_vt_close");
     if (handle->vtClose == NULL) {
-        ERROR("dlsym meson_vt_close failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_close failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtAllocId = (vt_alloc_id)dlsym(handle->libHandle, "meson_vt_alloc_id");
     if (handle->vtAllocId == NULL) {
-        ERROR("dlsym meson_vt_alloc_id failed, err=%s \n", dlerror());
+        ERROR(logCategory, "dlsym meson_vt_alloc_id failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtFreeId = (vt_free_id)dlsym(handle->libHandle, "meson_vt_free_id");
     if (handle->vtFreeId == NULL) {
-        ERROR("dlsym meson_vt_free_id failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_free_id failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtConnect = (vt_connect)dlsym(handle->libHandle, "meson_vt_connect");
     if (handle->vtConnect == NULL) {
-        ERROR("dlsym meson_vt_connect failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_connect failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtDisconnect = (vt_disconnect)dlsym(handle->libHandle, "meson_vt_disconnect");
     if (handle->vtDisconnect == NULL) {
-        ERROR("dlsym meson_vt_disconnect failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_disconnect failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtQueueBuffer = (vt_queue_buffer)dlsym(handle->libHandle, "meson_vt_queue_buffer");
     if (handle->vtQueueBuffer == NULL) {
-        ERROR("dlsym meson_vt_queue_buffer failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_queue_buffer failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtDequeueBuffer = (vt_dequeue_buffer)dlsym(handle->libHandle, "meson_vt_dequeue_buffer");
     if (handle->vtDequeueBuffer == NULL) {
-        ERROR("dlsym meson_vt_dequeue_buffer failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_dequeue_buffer failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtCancelBuffer = (vt_cancel_buffer)dlsym(handle->libHandle, "meson_vt_cancel_buffer");
     if (handle->vtCancelBuffer == NULL) {
-        ERROR("dlsym meson_vt_cancel_buffer failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_cancel_buffer failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtSetSourceCrop = (vt_set_sourceCrop)dlsym(handle->libHandle, "meson_vt_set_sourceCrop");
     if (handle->vtSetSourceCrop == NULL) {
-        ERROR("dlsym meson_vt_set_sourceCrop failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_set_sourceCrop failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtGetDisplayVsyncAndPeriod = (vt_getDisplayVsyncAndPeriod)dlsym(handle->libHandle, "meson_vt_getDisplayVsyncAndPeriod");
     if (handle->vtGetDisplayVsyncAndPeriod == NULL) {
-        ERROR("dlsym meson_vt_getDisplayVsyncAndPeriod failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_getDisplayVsyncAndPeriod failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtSetMode = (vt_set_mode)dlsym(handle->libHandle, "meson_vt_set_mode");
     if (handle->vtSetMode == NULL) {
-        ERROR("dlsym meson_vt_set_mode failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_set_mode failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtSendCmd = (vt_send_cmd)dlsym(handle->libHandle, "meson_vt_send_cmd");
     if (handle->vtSendCmd == NULL) {
-        ERROR("dlsym meson_vt_send_cmd failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_send_cmd failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
     handle->vtRecvCmd = (vt_recv_cmd)dlsym(handle->libHandle, "meson_vt_recv_cmd");
     if (handle->vtRecvCmd == NULL) {
-        ERROR("dlsym meson_vt_recv_cmd failed, err=%s \n", dlerror());
+        ERROR(logCategory,"dlsym meson_vt_recv_cmd failed, err=%s \n", dlerror());
         goto err_labal;
     }
 
@@ -132,14 +133,14 @@
     }
     return NULL;
 }
-int videotunnelUnloadLib(VideotunnelLib *vt)
+int videotunnelUnloadLib(int logCategory,VideotunnelLib *vt)
 {
-    INFO("unload videotunel so symbol");
+    INFO(logCategory, "unload videotunel so symbol");
     if (vt) {
         if (vt->libHandle) {
             dlclose(vt->libHandle);
         }
         free(vt);
     }
-    return 0;
+    return NO_ERROR;
 }
\ No newline at end of file
diff --git a/videotunnel/videotunnel_lib_wrap.h b/videotunnel/videotunnel_lib_wrap.h
index a32d681..bfdb21f 100644
--- a/videotunnel/videotunnel_lib_wrap.h
+++ b/videotunnel/videotunnel_lib_wrap.h
@@ -55,7 +55,7 @@
 } VideotunnelLib;
 
 
-VideotunnelLib * videotunnelLoadLib();
-int videotunnelUnloadLib(VideotunnelLib *vt);
+VideotunnelLib * videotunnelLoadLib(int logCategory);
+int videotunnelUnloadLib(int logCategory,VideotunnelLib *vt);
 
 #endif /*__VIDEO_TUNNEL_LIB_WRAP_H__*/
\ No newline at end of file
diff --git a/videotunnel/videotunnel_plugin.cpp b/videotunnel/videotunnel_plugin.cpp
index 2c189d3..c44b1f7 100644
--- a/videotunnel/videotunnel_plugin.cpp
+++ b/videotunnel/videotunnel_plugin.cpp
@@ -16,16 +16,20 @@
 #include "videotunnel_plugin.h"
 #include "Logger.h"
 #include "video_tunnel.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:videotunnel_plugin"
 
-VideoTunnelPlugin::VideoTunnelPlugin()
+VideoTunnelPlugin::VideoTunnelPlugin(int logCategory)
+    : mDisplayLock("displaylock"),
+    mLogCategory(logCategory),
+    mRenderLock("renderlock")
 {
     mWinRect.x = 0;
     mWinRect.y = 0;
     mWinRect.w = 0;
     mWinRect.h = 0;
-    mVideoTunnel = new VideoTunnelImpl(this);
+    mVideoTunnel = new VideoTunnelImpl(this,logCategory);
 }
 
 VideoTunnelPlugin::~VideoTunnelPlugin()
@@ -38,7 +42,7 @@
 
 void VideoTunnelPlugin::init()
 {
-    INFO("\n--------------------------------\n"
+    INFO(mLogCategory,"\n--------------------------------\n"
             "plugin      : videotunnel\n"
             "ARCH        : %s\n"
             "branch name : %s\n"
@@ -78,53 +82,53 @@
 
 int VideoTunnelPlugin::openDisplay()
 {
-    DEBUG("openDisplay");
-    return 0;
+    DEBUG(mLogCategory,"openDisplay");
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::openWindow()
 {
-    DEBUG("openWindow");
+    DEBUG(mLogCategory,"openWindow");
     mVideoTunnel->connect();
-    DEBUG("openWindow,end");
-    return 0;
+    DEBUG(mLogCategory,"openWindow,end");
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::prepareFrame(RenderBuffer *buffer)
 {
-
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
 {
     mVideoTunnel->displayFrame(buffer, displayTime);
-    return 0;
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::flush()
 {
     mVideoTunnel->flush();
-    return 0;
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::pause()
 {
-    return 0;
+    return NO_ERROR;
 }
 int VideoTunnelPlugin::resume()
 {
-    return 0;
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::closeDisplay()
 {
-    return 0;
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::closeWindow()
 {
     mVideoTunnel->disconnect();
-    return 0;
+    return NO_ERROR;
 }
 
 
@@ -136,7 +140,7 @@
         } break;
     }
 
-    return 0;
+    return NO_ERROR;
 }
 
 int VideoTunnelPlugin::setValue(PluginKey key, void *value)
@@ -155,23 +159,23 @@
         } break;
         case PLUGIN_KEY_VIDEO_FORMAT: {
             int videoFormat = *(int *)(value);
-            DEBUG("Set video format :%d",videoFormat);
+            DEBUG(mLogCategory,"Set video format :%d",videoFormat);
         } break;
         case PLUGIN_KEY_VIDEOTUNNEL_ID: {
             int videotunnelId = *(int *)(value);
-            DEBUG("Set videotunnel id :%d",videotunnelId);
+            DEBUG(mLogCategory,"Set videotunnel id :%d",videotunnelId);
             mVideoTunnel->setVideotunnelId(videotunnelId);
         } break;
         case PLUGIN_KEY_VIDEO_PIP: {
             int pip = *(int *) (value);
             if (pip > 0) {
                 int videotunnelId = 1; //videotunnel id 1 be used to pip
-                DEBUG("Set pip ,videotunnel id :%d",videotunnelId);
+                DEBUG(mLogCategory,"Set pip ,videotunnel id :%d",videotunnelId);
                 mVideoTunnel->setVideotunnelId(videotunnelId);
             }
         } break;
     }
-    return 0;
+    return NO_ERROR;
 }
 
 void VideoTunnelPlugin::handleBufferRelease(RenderBuffer *buffer)
@@ -204,18 +208,23 @@
 
 void *makePluginInstance(int id)
 {
+    int category =Logger_init(id);
     char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
     if (env) {
         int level = atoi(env);
         Logger_set_level(level);
-        INFO("VIDEO_RENDER_LOG_LEVEL=%d",level);
+        INFO(category,"VIDEO_RENDER_LOG_LEVEL=%d",level);
     }
-    VideoTunnelPlugin *plugin = new VideoTunnelPlugin();
+    VideoTunnelPlugin *plugin = new VideoTunnelPlugin(category);
     return static_cast<void *>(plugin);
 }
 
 void destroyPluginInstance(void * plugin)
 {
+    int category;
+
     VideoTunnelPlugin *pluginInstance = static_cast<VideoTunnelPlugin *>(plugin);
+    category = pluginInstance->getLogCategory();
     delete pluginInstance;
+    Logger_exit(category);
 }
diff --git a/videotunnel/videotunnel_plugin.h b/videotunnel/videotunnel_plugin.h
index f8509f0..8974e2e 100644
--- a/videotunnel/videotunnel_plugin.h
+++ b/videotunnel/videotunnel_plugin.h
@@ -17,11 +17,12 @@
 #define __VIDEO_TUNNEL_PLUGIN_H__
 #include "render_plugin.h"
 #include "videotunnel_impl.h"
+#include "Mutex.h"
 
 class VideoTunnelPlugin : public RenderPlugin
 {
   public:
-    VideoTunnelPlugin();
+    VideoTunnelPlugin(int category);
     virtual ~VideoTunnelPlugin();
     virtual void init();
     virtual void release();
@@ -45,11 +46,18 @@
     virtual void handleFrameDropped(RenderBuffer *buffer);
     //plugin msg callback
     void handleMsgNotify(int type, void *detail);
+    int getLogCategory() {
+        return mLogCategory;
+    };
   private:
     PluginCallback *mCallback;
     VideoTunnelImpl *mVideoTunnel;
     RenderRect mWinRect;
 
+    int mLogCategory;
+
+    mutable Tls::Mutex mDisplayLock;
+    mutable Tls::Mutex mRenderLock;
     void *mUserData;
 };
 
diff --git a/westeros/Makefile b/westeros/Makefile
index 11f3754..9f5ddd2 100644
--- a/westeros/Makefile
+++ b/westeros/Makefile
@@ -80,6 +80,9 @@
 
 OBJ_CLIENT_LIB += \
 	$(TOOLS_PATH)/Thread.o \
+	$(TOOLS_PATH)/Poll.o \
+	$(TOOLS_PATH)/Times.o \
+	$(TOOLS_PATH)/Utils.o \
 	$(TOOLS_PATH)/Logger.o
 
 LOCAL_CFLAGS += -fPIC -O -Wcpp -g
diff --git a/westeros/wst_essos.cpp b/westeros/wst_essos.cpp
index 6cc9268..c1e2a0a 100644
--- a/westeros/wst_essos.cpp
+++ b/westeros/wst_essos.cpp
@@ -16,7 +16,7 @@
 {
    WstEssRMgrOps *rMgrOps = static_cast<WstEssRMgrOps *>(userData);
 
-   DEBUG("resMgrNotify: enter");
+   DEBUG(rMgrOps->mLogCategory,"resMgrNotify: enter");
    switch ( type )
    {
         case EssRMgrResType_videoDecoder:
@@ -27,9 +27,9 @@
                     memset( &rMgrOps->mResCurrCaps, 0, sizeof(EssRMgrCaps) );
                     if ( !rMgrOps->EssRMgrResourceGetCaps( rMgrOps->mEssRmgr, EssRMgrResType_videoDecoder, rMgrOps->mResAssignedId, &rMgrOps->mResCurrCaps ) )
                     {
-                        ERROR("resMgrNotify: failed to get caps of assigned decoder");
+                        ERROR(rMgrOps->mLogCategory,"resMgrNotify: failed to get caps of assigned decoder");
                     }
-                    DEBUG("async assigned id %d caps %X (%dx%d)",
+                    DEBUG(rMgrOps->mLogCategory,"async assigned id %d caps %X (%dx%d)",
                             rMgrOps->mResAssignedId,
                             rMgrOps->mResCurrCaps.capabilities,
                             rMgrOps->mResCurrCaps.info.video.maxWidth,
@@ -38,10 +38,10 @@
                 case EssRMgrEvent_revoked:
                 {
                     memset( &rMgrOps->mResCurrCaps, 0, sizeof(EssRMgrCaps) );
-                    WARNING("releasing video decoder %d", id);
+                    WARNING(rMgrOps->mLogCategory,"releasing video decoder %d", id);
                     rMgrOps->EssRMgrReleaseResource( rMgrOps->mEssRmgr, EssRMgrResType_videoDecoder, id );
                     rMgrOps->mResAssignedId = -1;
-                    WARNING("done releasing video decoder %d,request again", id);
+                    WARNING(rMgrOps->mLogCategory,"done releasing video decoder %d,request again", id);
                 } break;
             default:
                 break;
@@ -50,16 +50,17 @@
         default:
             break;
    }
-   DEBUG("resMgrNotify: exit");
+   DEBUG(rMgrOps->mLogCategory,"resMgrNotify: exit");
 }
 
-WstEssRMgrOps::WstEssRMgrOps(WstClientPlugin *plugin) {
+WstEssRMgrOps::WstEssRMgrOps(WstClientPlugin *plugin,int logCategory) {
     mPlugin = plugin;
     mLibHandle = NULL;
     mResPriority = 0;
     mResAssignedId = -1;
     mResUsage = DEFAULT_USAGE;
     mEssRmgr = NULL;
+    mLogCategory = logCategory;
 };
 
 WstEssRMgrOps::~WstEssRMgrOps() {
@@ -71,7 +72,7 @@
     if (mLibHandle == NULL) {
         mLibHandle = dlopen(ESSRES_LIB_NAME, RTLD_NOW);
         if (mLibHandle == NULL) {
-            ERROR("unable to dlopen %s : %s",ESSRES_LIB_NAME, dlerror());
+            ERROR(mLogCategory,"unable to dlopen %s : %s",ESSRES_LIB_NAME, dlerror());
             goto err_tag;
         }
     }
@@ -79,66 +80,66 @@
     EssRMgrCreate =
         (essRMgrCreate)dlsym(mLibHandle, "EssRMgrCreate");
     if (EssRMgrCreate == NULL) {
-        ERROR("dlsym EssRMgrCreate failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrCreate failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrDestroy =
         (essRMgrDestroy)dlsym(mLibHandle, "EssRMgrDestroy");
     if (EssRMgrDestroy == NULL) {
-        ERROR("dlsym EssRMgrDestroy failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrDestroy failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrRequestResource =
         (essRMgrRequestResource)dlsym(mLibHandle, "EssRMgrRequestResource");
     if (EssRMgrRequestResource == NULL) {
-        ERROR("dlsym EssRMgrRequestResource failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrRequestResource failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrReleaseResource =
         (essRMgrReleaseResource)dlsym(mLibHandle, "EssRMgrReleaseResource");
     if (EssRMgrReleaseResource == NULL) {
-        ERROR("dlsym EssRMgrReleaseResource failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrReleaseResource failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrDumpState =
         (essRMgrDumpStates)dlsym(mLibHandle, "EssRMgrDumpState");
     if (EssRMgrDumpState == NULL) {
-        ERROR("dlsym EssRMgrDumpState failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrDumpState failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrResourceGetCaps =
         (essRMgrResourceGetCaps)dlsym(mLibHandle, "EssRMgrResourceGetCaps");
     if (EssRMgrResourceGetCaps == NULL) {
-        ERROR("dlsym EssRMgrResourceGetCaps failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrResourceGetCaps failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrGetPolicyPriorityTie =
         (essRMgrGetPolicyPriorityTie)dlsym(mLibHandle, "EssRMgrGetPolicyPriorityTie");
     if (EssRMgrGetPolicyPriorityTie == NULL) {
-        ERROR("dlsym EssRMgrGetPolicyPriorityTie failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrGetPolicyPriorityTie failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     EssRMgrResourceSetState =
         (essRMgrResourceSetState)dlsym(mLibHandle, "EssRMgrResourceSetState");
     if (EssRMgrResourceSetState == NULL) {
-        ERROR("dlsym EssRMgrResourceSetState failed, err=%s \n", dlerror());
+        ERROR(mLogCategory,"dlsym EssRMgrResourceSetState failed, err=%s \n", dlerror());
         goto err_tag;
     }
 
     mEssRmgr = EssRMgrCreate();
     if (!mEssRmgr) {
-        ERROR("EssRMgrCreate failed");
+        ERROR(mLogCategory,"EssRMgrCreate failed");
         goto err_tag;
     }
     memset( &mResCurrCaps, 0, sizeof(EssRMgrCaps) );
-    INFO("resMgrInit,ok");
+    INFO(mLogCategory,"resMgrInit,ok");
     return;
 err_tag:
     if (mLibHandle) {
@@ -160,7 +161,7 @@
         dlclose(mLibHandle);
         mLibHandle = NULL;
     }
-    INFO("resMgrTerm, ok");
+    INFO(mLogCategory,"resMgrTerm, ok");
 }
 
 void WstEssRMgrOps::resMgrRequestDecoder(bool pip)
@@ -182,24 +183,24 @@
 
     if (!mEssRmgr)
     {
-        WARNING("EssRMgrCreate failed");
+        WARNING(mLogCategory,"EssRMgrCreate failed");
         return;
     }
 
-    DEBUG("request resource resUsage %d priority %X", mResUsage, mResPriority);
+    DEBUG(mLogCategory,"request resource resUsage %d priority %X", mResUsage, mResPriority);
     result = EssRMgrRequestResource(mEssRmgr, EssRMgrResType_videoDecoder, &mResReq);
     if ( result )
     {
         if ( mResReq.assignedId >= 0 )
         {
-            DEBUG("assigned id %d caps %X", mResReq.assignedId, mResReq.assignedCaps);
+            DEBUG(mLogCategory,"assigned id %d caps %X", mResReq.assignedId, mResReq.assignedCaps);
             mResAssignedId = mResReq.assignedId;
             memset( &mResCurrCaps, 0, sizeof(EssRMgrCaps) );
             if ( !EssRMgrResourceGetCaps( mEssRmgr, EssRMgrResType_videoDecoder, mResAssignedId, &mResCurrCaps ) )
             {
-               ERROR("resMgrRequestDecoder: failed to get caps of assigned decoder");
+               ERROR(mLogCategory,"resMgrRequestDecoder: failed to get caps of assigned decoder");
             }
-            DEBUG("done assigned id %d caps %X (%dx%d)",
+            DEBUG(mLogCategory,"done assigned id %d caps %X (%dx%d)",
                     mResAssignedId,
                     mResCurrCaps.capabilities,
                     mResCurrCaps.info.video.maxWidth,
@@ -207,12 +208,12 @@
         }
         else
         {
-            DEBUG("async grant pending" );
+            DEBUG(mLogCategory,"async grant pending" );
         }
     }
     else
     {
-        ERROR("resMgrRequestDecoder: request failed");
+        ERROR(mLogCategory,"resMgrRequestDecoder: request failed");
     }
 }
 
@@ -220,13 +221,13 @@
 {
     if (!mEssRmgr)
     {
-        WARNING("EssRMgrCreate failed");
+        WARNING(mLogCategory,"EssRMgrCreate failed");
         return;
     }
-    DEBUG("EssRMgrReleaseResource assigned id %d",mResAssignedId);
+    DEBUG(mLogCategory,"EssRMgrReleaseResource assigned id %d",mResAssignedId);
     if (mResAssignedId >= 0) {
         EssRMgrReleaseResource( mEssRmgr, EssRMgrResType_videoDecoder, mResAssignedId );
-        DEBUG("EssRMgrReleaseResource done");
+        DEBUG(mLogCategory,"EssRMgrReleaseResource done");
         mResReq.assignedId = -1;
         mResAssignedId = -1;
     }
@@ -236,7 +237,7 @@
 {
     if (!mEssRmgr)
     {
-        WARNING("EssRMgrCreate failed");
+        WARNING(mLogCategory,"EssRMgrCreate failed");
         return;
     }
     if ( mResAssignedId >= 0 )
diff --git a/westeros/wst_essos.h b/westeros/wst_essos.h
index 2785274..d2cc643 100644
--- a/westeros/wst_essos.h
+++ b/westeros/wst_essos.h
@@ -116,7 +116,7 @@
 
 class WstEssRMgrOps {
 public:
-   WstEssRMgrOps(WstClientPlugin *plugin);
+   WstEssRMgrOps(WstClientPlugin *plugin,int logCategory);
    virtual ~WstEssRMgrOps();
 
    void resMgrInit();
@@ -127,6 +127,7 @@
 
    static void resMgrNotify( EssRMgr *rm, int event, int type, int id, void* userData );
 private:
+   int mLogCategory;
    WstClientPlugin *mPlugin;
    void *mLibHandle;
    EssRMgr *mEssRmgr;
diff --git a/westeros/wstclient_plugin.cpp b/westeros/wstclient_plugin.cpp
index 370dd8d..6845dbb 100644
--- a/westeros/wstclient_plugin.cpp
+++ b/westeros/wstclient_plugin.cpp
@@ -17,19 +17,21 @@
 #include "wstclient_wayland.h"
 #include "wstclient_plugin.h"
 #include "Logger.h"
+#include "ErrorCode.h"
 
 #define TAG  "rlib:wstClient_plugin"
 #define DEFAULT_VIDEO_SERVER "video"
 
-WstClientPlugin::WstClientPlugin()
-    : mFullscreen(true)
+WstClientPlugin::WstClientPlugin(int logCategory)
+    : mFullscreen(true),
+    mLogCategory(logCategory)
 {
     mIsVideoPip = false;
     mBufferFormat = VIDEO_FORMAT_UNKNOWN;
     mNumDroppedFrames = 0;
     mCommitFrameCnt = 0;
     mReadyDisplayFrameCnt = 0;
-    mWayland = new WstClientWayland(this);
+    mWayland = new WstClientWayland(this, logCategory);
     mWstClientSocket = NULL;
     mKeepLastFrame.isSet = false;
     mKeepLastFrame.value = 0;
@@ -38,7 +40,7 @@
     mFirstFramePts = -1;
     mImmediatelyOutput = false;
     mSetCropFrameRect = false;
-    mWstEssRMgrOps = new WstEssRMgrOps(this);
+    mWstEssRMgrOps = new WstEssRMgrOps(this,logCategory);
 }
 
 WstClientPlugin::~WstClientPlugin()
@@ -52,12 +54,12 @@
         mWstEssRMgrOps = NULL;
     }
 
-    TRACE("deconstruct");
+    TRACE(mLogCategory,"deconstruct");
 }
 
 void WstClientPlugin::init()
 {
-    INFO("\n--------------------------------\n"
+    INFO(mLogCategory,"\n--------------------------------\n"
             "plugin      : westeros\n"
             "ARCH        : %s\n"
             "branch name : %s\n"
@@ -85,6 +87,7 @@
 
 void WstClientPlugin::release()
 {
+    DEBUG(mLogCategory,"release");
 }
 
 void WstClientPlugin::setCallback(void *userData, PluginCallback *callback)
@@ -97,7 +100,7 @@
 {
     int ret = 0;
 
-    DEBUG("openDisplay");
+    DEBUG(mLogCategory,"openDisplay");
 
     mWstEssRMgrOps->resMgrInit();
     mWstEssRMgrOps->resMgrRequestDecoder(mIsVideoPip);
@@ -105,13 +108,13 @@
     //connect video server first
     if (!mWstClientSocket) {
         bool rc;
-        mWstClientSocket = new WstClientSocket(this);
+        mWstClientSocket = new WstClientSocket(this, mLogCategory);
         rc = mWstClientSocket->connectToSocket(DEFAULT_VIDEO_SERVER);
         if (!rc) {
-            ERROR("Error connect to video server fail");
+            ERROR(mLogCategory,"Error connect to video server fail");
             delete mWstClientSocket;
             mWstClientSocket = NULL;
-            return -1;
+            return ERROR_OPEN_FAIL;
         }
     }
 
@@ -121,23 +124,23 @@
     }
 
     ret =  mWayland->connectToWayland();
-    if (ret != 0) {
-        ERROR("Error open display");
+    if (ret != NO_ERROR) {
+        ERROR(mLogCategory,"Error open display");
     } else {
         //run wl display queue dispatch
-        DEBUG("To run wl display dispatch queue");
+        DEBUG(mLogCategory,"To run wl display dispatch queue");
         mWayland->run("display queue");
     }
 
-    DEBUG("openDisplay end");
-    return 0;
+    DEBUG(mLogCategory,"openDisplay end");
+    return NO_ERROR;
 }
 
 int WstClientPlugin::openWindow()
 {
     int ret;
 
-    DEBUG("openWindow");
+    DEBUG(mLogCategory,"openWindow");
     mCommitFrameCnt = 0;
     mNumDroppedFrames = 0;
     mReadyDisplayFrameCnt = 0;
@@ -166,13 +169,13 @@
         setCropFrameRect();
     }
 
-    DEBUG("openWindow,end");
+    DEBUG(mLogCategory,"openWindow,end");
     return ret;
 }
 
 int WstClientPlugin::prepareFrame(RenderBuffer *buffer)
 {
-    return 0;
+    return NO_ERROR;
 }
 
 int WstClientPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
@@ -194,12 +197,12 @@
 
     wstBufferInfo.bufferId = buffer->id;
     wstBufferInfo.planeCount = buffer->dma.planeCnt;
-    TRACE("buffer width:%d,height:%d",buffer->dma.width,buffer->dma.height);
+    TRACE(mLogCategory,"buffer width:%d,height:%d",buffer->dma.width,buffer->dma.height);
     for (int i = 0; i < buffer->dma.planeCnt; i++) {
         wstBufferInfo.planeInfo[i].fd = buffer->dma.fd[i];
         wstBufferInfo.planeInfo[i].stride = buffer->dma.stride[i];
         wstBufferInfo.planeInfo[i].offset = buffer->dma.offset[i];
-        DEBUG("buffer id:%d,plane[%d],fd:%d,stride:%d,offset:%d",buffer->id,i,buffer->dma.fd[i],buffer->dma.stride[i],buffer->dma.offset[i]);
+        DEBUG(mLogCategory,"buffer id:%d,plane[%d],fd:%d,stride:%d,offset:%d",buffer->id,i,buffer->dma.fd[i],buffer->dma.stride[i],buffer->dma.offset[i]);
     }
 
     wstBufferInfo.frameWidth = buffer->dma.width;
@@ -212,7 +215,7 @@
     } else if (mBufferFormat == VIDEO_FORMAT_NV21) {
         wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV21;
     } else {
-        ERROR("unknown video buffer format:%d",mBufferFormat);
+        ERROR(mLogCategory,"unknown video buffer format:%d",mBufferFormat);
     }
 
     wstRect.x = x;
@@ -223,10 +226,10 @@
     if (mWstClientSocket) {
         ret = mWstClientSocket->sendFrameVideoClientConnection(&wstBufferInfo, &wstRect);
         if (!ret) {
-            ERROR("send video frame to server fail");
+            ERROR(mLogCategory,"send video frame to server fail");
             handleFrameDropped(buffer);
             handleBufferRelease(buffer);
-            return -1;
+            return ERROR_FAILED_TRANSACTION;
         }
     }
 
@@ -236,7 +239,7 @@
     mRenderBuffersMap.insert(item);
     ++mCommitFrameCnt;
     ++mReadyDisplayFrameCnt;
-    TRACE("committed to westeros cnt:%d,readyDisplayFramesCnt:%d",mCommitFrameCnt,mReadyDisplayFrameCnt);
+    TRACE(mLogCategory,"committed to westeros cnt:%d,readyDisplayFramesCnt:%d",mCommitFrameCnt,mReadyDisplayFrameCnt);
 
     //storage displayed render buffer
     std::pair<int, int64_t> displayitem(buffer->id, displayTime);
@@ -245,13 +248,13 @@
         mFirstFramePts = buffer->pts;
     }
 
-    return 0;
+    return NO_ERROR;
 }
 
 int WstClientPlugin::flush()
 {
     int ret;
-    INFO("flush");
+    INFO(mLogCategory,"flush");
     if (mWstClientSocket) {
         mWstClientSocket->sendFlushVideoClientConnection();
     }
@@ -270,13 +273,13 @@
         }
     }
 
-    return 0;
+    return NO_ERROR;
 }
 
 int WstClientPlugin::pause()
 {
     int ret;
-    INFO("pause");
+    INFO(mLogCategory,"pause");
     if (mWstClientSocket) {
         int waitCnt = 20; //we wait about 10 vsync duration
         while (mReadyDisplayFrameCnt != 0 && waitCnt > 0) {
@@ -289,34 +292,34 @@
         }
     }
     mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_paused);
-    return 0;
+    return NO_ERROR;
 }
 
 int WstClientPlugin::resume()
 {
     int ret;
-    INFO("resume");
+    INFO(mLogCategory,"resume");
     std::lock_guard<std::mutex> lck(mRenderLock);
     if (mWstClientSocket) {
         mWstClientSocket->sendPauseVideoClientConnection(false);
     }
     mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_active);
-    return 0;
+    return NO_ERROR;
 }
 
 int WstClientPlugin::closeDisplay()
 {
-    INFO("closeDisplay, in");
+    INFO(mLogCategory,"closeDisplay, in");
     mWayland->disconnectFromWayland();
     mWstEssRMgrOps->resMgrReleaseDecoder();
     mWstEssRMgrOps->resMgrTerm();
-    INFO("closeDisplay, out");
-    return 0;
+    INFO(mLogCategory,"closeDisplay, out");
+    return NO_ERROR;
 }
 
 int WstClientPlugin::closeWindow()
 {
-    DEBUG("closeWindow, in");
+    DEBUG(mLogCategory,"closeWindow, in");
     if (mWstClientSocket) {
         mWstClientSocket->disconnectFromSocket();
         delete mWstClientSocket;
@@ -352,8 +355,8 @@
     mNumDroppedFrames = 0;
     mReadyDisplayFrameCnt = 0;
     mImmediatelyOutput = false;
-    DEBUG("out");
-    return 0;
+    DEBUG(mLogCategory,"out");
+    return NO_ERROR;
 }
 
 int WstClientPlugin::getValue(PluginKey key, void *value)
@@ -361,11 +364,11 @@
     switch (key) {
         case PLUGIN_KEY_KEEP_LAST_FRAME: {
             *(int *)value = mKeepLastFrame.value;
-            TRACE("get keep last frame:%d",*(int *)value);
+            TRACE(mLogCategory,"get keep last frame:%d",*(int *)value);
         } break;
         case PLUGIN_KEY_HIDE_VIDEO: {
             *(int *)value = mHideVideo.value;
-            TRACE("get hide video:%d",*(int *)value);
+            TRACE(mLogCategory,"get hide video:%d",*(int *)value);
         } break;
         case PLUGIN_KEY_CROP_FRAME_SIZE: {
             RenderRect* rect = static_cast<RenderRect*>(value);
@@ -375,7 +378,7 @@
             rect->h = mCropFrameRect.h;
         } break;
     }
-    return 0;
+    return NO_ERROR;
 }
 
 int WstClientPlugin::setValue(PluginKey key, void *value)
@@ -401,7 +404,7 @@
         case PLUGIN_KEY_VIDEO_FORMAT: {
             int format = *(int *)(value);
             mBufferFormat = (RenderVideoFormat) format;
-            DEBUG("Set video format :%d",mBufferFormat);
+            DEBUG(mLogCategory,"Set video format :%d",mBufferFormat);
         } break;
         case PLUGIN_KEY_VIDEO_PIP: {
             int pip = *(int *) (value);
@@ -411,7 +414,7 @@
             int keep = *(int *) (value);
             mKeepLastFrame.value = keep > 0? true:false;
             mKeepLastFrame.isSet = true;
-            DEBUG( "Set keep last frame :%d",mKeepLastFrame.value);
+            DEBUG(mLogCategory, "Set keep last frame :%d",mKeepLastFrame.value);
             if (mWstClientSocket) {
                 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
             }
@@ -420,7 +423,7 @@
             int hide = *(int *)(value);
             mHideVideo.value = hide > 0? true:false;
             mHideVideo.isSet = true;
-            DEBUG( "Set hide video:%d",mHideVideo.value);
+            DEBUG(mLogCategory, "Set hide video:%d",mHideVideo.value);
             if (mWstClientSocket) {
                 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
             }
@@ -434,7 +437,7 @@
         case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
             int immediately = *(int *)(value);
             mImmediatelyOutput = immediately > 0? true: false;
-            DEBUG("Set immediately output:%d",mImmediatelyOutput);
+            DEBUG(mLogCategory,"Set immediately output:%d",mImmediatelyOutput);
             if (mImmediatelyOutput && mWstClientSocket) {
                 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
             }
@@ -446,18 +449,18 @@
             mCropFrameRect.w = rect->w;
             mCropFrameRect.h = rect->h;
             mSetCropFrameRect = true;
-            INFO("crop params (%d,%d,%d,%d)",rect->x,rect->y,rect->w,rect->h);
+            INFO(mLogCategory,"crop params (%d,%d,%d,%d)",rect->x,rect->y,rect->w,rect->h);
             setCropFrameRect();
         } break;
         case PLUGIN_KEY_PIXEL_ASPECT_RATIO: {
             double ratio = *(double *)(value);
-            INFO("pixel aspect ratio :%f",ratio);
+            INFO(mLogCategory,"pixel aspect ratio :%f",ratio);
             if (mWayland) {
                 mWayland->setPixelAspectRatio((double)ratio);
             }
         } break;
     }
-    return 0;
+    return NO_ERROR;
 }
 
 void WstClientPlugin::handleBufferRelease(RenderBuffer *buffer)
@@ -497,16 +500,16 @@
 
 void WstClientPlugin::onWstSocketEvent(WstEvent *event)
 {
-    std::lock_guard<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     switch (event->event)
     {
         case WST_REFRESH_RATE: {
             int rate = event->param;
-            INFO("refresh rate:%d",rate);
+            INFO(mLogCategory,"refresh rate:%d",rate);
         } break;
         case WST_BUFFER_RELEASE: {
             int bufferid = event->param;
-            TRACE("Buffer release id:%d",bufferid);
+            TRACE(mLogCategory,"Buffer release id:%d",bufferid);
             RenderBuffer *renderbuffer = NULL;
             bool isDropped = false;
             int64_t displaytime = 0;
@@ -514,7 +517,7 @@
                 std::lock_guard<std::mutex> lck(mRenderLock);
                 auto renderBufferItem = mRenderBuffersMap.find(bufferid);
                 if (renderBufferItem == mRenderBuffersMap.end()) {
-                    WARNING("can't find map Renderbuffer");
+                    WARNING(mLogCategory,"can't find map Renderbuffer");
                     return ;
                 }
                 --mCommitFrameCnt;
@@ -535,32 +538,32 @@
                 this buffer is dropped by westeros server,so we
                 must call displayed callback*/
                 if (isDropped) {
-                    WARNING("Frame droped,pts:%lld us,displaytime:%lld,readyDisplayFramesCnt:%d",\
+                    WARNING(mLogCategory,"Frame droped,pts:%lld us,displaytime:%lld,readyDisplayFramesCnt:%d",\
                             renderbuffer->pts/1000,displaytime,mReadyDisplayFrameCnt);
                     handleFrameDropped(renderbuffer);
                 }
                 handleBufferRelease(renderbuffer);
             }
-            TRACE("remain commit to westeros cnt:%d",mCommitFrameCnt);
+            TRACE(mLogCategory,"remain on westeros cnt:%d",mCommitFrameCnt);
         } break;
         case WST_STATUS: {
             int dropframes = event->param;
             int64_t frameTime = event->lparam;
-            TRACE("WST_STATUS,dropframes:%d,frameTime:%lld",dropframes,frameTime);
+            TRACE(mLogCategory,"WST_STATUS,dropframes:%d,frameTime:%lld",dropframes,frameTime);
             RenderBuffer *renderbuffer = NULL;
             if (mNumDroppedFrames != event->param) {
                 mNumDroppedFrames = event->param;
-                WARNING("frame dropped cnt:%d",mNumDroppedFrames);
+                WARNING(mLogCategory,"frame dropped cnt:%d",mNumDroppedFrames);
             }
             //update status,if frameTime isn't equal -1LL
             //this buffer had displayed
             if (frameTime != -1LL) {
                 std::lock_guard<std::mutex> lck(mRenderLock);
                 --mReadyDisplayFrameCnt;
-                TRACE("displayed frame time:%lld,readyDisplayFramesCnt:%d",frameTime,mReadyDisplayFrameCnt);
+                TRACE(mLogCategory,"displayed frame time:%lld,readyDisplayFramesCnt:%d",frameTime,mReadyDisplayFrameCnt);
                 int bufferId = getDisplayFrameBufferId(frameTime);
                 if (bufferId < 0) {
-                    WARNING("can't find map displayed frame:%lld",frameTime);
+                    WARNING(mLogCategory,"can't find map displayed frame:%lld",frameTime);
                     return ;
                 }
                 auto displayItem = mDisplayedFrameMap.find(bufferId);
@@ -582,7 +585,7 @@
         } break;
         case WST_UNDERFLOW: {
             uint64_t frameTime = event->lparam;
-            TRACE("under flow frametime:%lld",frameTime);
+            TRACE(mLogCategory,"under flow frametime:%lld",frameTime);
             //under flow event sended must be after sending first frame to westeros
             if (mFirstFramePts != -1) {
                 handleMsgNotify(MSG_UNDER_FLOW, NULL);
@@ -621,7 +624,7 @@
         int frameWidth,frameHeight;
         mWayland->getFrameSize(&frameWidth, &frameHeight);
         if (frameWidth <= 0 || frameHeight <= 0) {
-            WARNING( "no set video frame size,set crop params later");
+            WARNING(mLogCategory, "no set video frame size,set crop params later");
             goto bad_param;
         }
 
@@ -631,10 +634,10 @@
                 int oriX = mCropFrameRect.x;
                 int oriW = mCropFrameRect.w;
                 mCropFrameRect.w = frameWidth - mCropFrameRect.x;
-                WARNING( "correct crop x:%d, w:%d to x:%d, w:%d", \
+                WARNING(mLogCategory, "correct crop x:%d, w:%d to x:%d, w:%d", \
                     oriX,oriW,mCropFrameRect.x,mCropFrameRect.w);
             } else {
-                ERROR( "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
+                ERROR(mLogCategory, "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
                     mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
                 goto bad_param;
             }
@@ -644,15 +647,15 @@
                 int oriY = mCropFrameRect.x;
                 int oriH = mCropFrameRect.w;
                 mCropFrameRect.h = frameHeight - mCropFrameRect.y;
-                WARNING( "correct crop y:%d, h:%d to y:%d, h:%d", \
+                WARNING(mLogCategory, "correct crop y:%d, h:%d to y:%d, h:%d", \
                     oriY,oriH,mCropFrameRect.y,mCropFrameRect.h);
             } else {
-                ERROR( "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
+                ERROR(mLogCategory, "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
                     mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
                 goto bad_param;
             }
         }
-        INFO( "crop (%d,%d,%d,%d)", \
+        INFO(mLogCategory, "crop (%d,%d,%d,%d)", \
             mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h);
     }
     if (mWstClientSocket && mSetCropFrameRect) {
@@ -666,18 +669,23 @@
 
 void *makePluginInstance(int id)
 {
+    int category =Logger_init(id);
     char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
     if (env) {
         int level = atoi(env);
         Logger_set_level(level);
-        INFO("VIDEO_RENDER_LOG_LEVEL=%d",level);
+        INFO(category,"VIDEO_RENDER_LOG_LEVEL=%d",level);
     }
-    WstClientPlugin *pluginInstance = new WstClientPlugin();
+    WstClientPlugin *pluginInstance = new WstClientPlugin(category);
     return static_cast<void *>(pluginInstance);
 }
 
 void destroyPluginInstance(void * plugin)
 {
+    int category;
+
     WstClientPlugin *pluginInstance = static_cast<WstClientPlugin *>(plugin);
+    category = pluginInstance->getLogCategory();
     delete pluginInstance;
+    Logger_exit(category);
 }
\ No newline at end of file
diff --git a/westeros/wstclient_plugin.h b/westeros/wstclient_plugin.h
index e3b8379..798179d 100644
--- a/westeros/wstclient_plugin.h
+++ b/westeros/wstclient_plugin.h
@@ -25,7 +25,7 @@
 class WstClientPlugin : public RenderPlugin
 {
   public:
-    WstClientPlugin();
+    WstClientPlugin(int logCategory);
     virtual ~WstClientPlugin();
     virtual void init();
     virtual void release();
@@ -53,6 +53,9 @@
     void onWstSocketEvent(WstEvent *event);
 
     void setVideoRect(int videoX, int videoY, int videoWidth, int videoHeight);
+    int getLogCategory() {
+        return mLogCategory;
+    };
   private:
     typedef struct {
         bool isSet;
@@ -76,6 +79,7 @@
     RenderRect mWinRect;
     bool mSetCropFrameRect;
     RenderRect mCropFrameRect; //set frame crop size
+    int mLogCategory;
 
     ConfigValue mKeepLastFrame;
     ConfigValue mHideVideo;
@@ -94,7 +98,7 @@
     std::unordered_map<int, int64_t> mDisplayedFrameMap;
 
     bool mIsVideoPip;
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mMutex;
     void *mUserData;
 
     /*immediately output video frame to display*/
diff --git a/westeros/wstclient_socket.cpp b/westeros/wstclient_socket.cpp
index d168c6a..bd49421 100644
--- a/westeros/wstclient_socket.cpp
+++ b/westeros/wstclient_socket.cpp
@@ -26,69 +26,26 @@
 #include <limits.h>
 #include <time.h>
 #include <errno.h>
-#include <poll.h>
 #include "wstclient_socket.h"
 #include "wstclient_plugin.h"
 #include "Logger.h"
+#include "Utils.h"
 
 #define TAG "rlib:wstclient_socket"
 
-static int putU32( unsigned char *p, unsigned n )
+WstClientSocket::WstClientSocket(WstClientPlugin *plugin, int logCategory)
 {
-   p[0]= (n>>24);
-   p[1]= (n>>16);
-   p[2]= (n>>8);
-   p[3]= (n&0xFF);
-
-   return 4;
-}
-
-static unsigned int getU32( unsigned char *p )
-{
-   unsigned n;
-
-   n= (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|(p[3]);
-
-   return n;
-}
-
-static int64_t getS64( unsigned char *p )
-{
-    int64_t n;
-
-    n= ((((int64_t)(p[0]))<<56) |
-       (((int64_t)(p[1]))<<48) |
-       (((int64_t)(p[2]))<<40) |
-       (((int64_t)(p[3]))<<32) |
-       (((int64_t)(p[4]))<<24) |
-       (((int64_t)(p[5]))<<16) |
-       (((int64_t)(p[6]))<<8) |
-       (p[7]) );
-
-   return n;
-}
-
-static int putS64( unsigned char *p,  int64_t n )
-{
-   p[0]= (((uint64_t)n)>>56);
-   p[1]= (((uint64_t)n)>>48);
-   p[2]= (((uint64_t)n)>>40);
-   p[3]= (((uint64_t)n)>>32);
-   p[4]= (((uint64_t)n)>>24);
-   p[5]= (((uint64_t)n)>>16);
-   p[6]= (((uint64_t)n)>>8);
-   p[7]= (((uint64_t)n)&0xFF);
-
-   return 8;
-}
-
-WstClientSocket::WstClientSocket(WstClientPlugin *plugin)
-{
+    mLogCategory = logCategory;
     mPlugin = plugin;
+    mPoll = new Tls::Poll(true);
 }
 
 WstClientSocket::~WstClientSocket()
 {
+    if (mPoll) {
+        delete mPoll;
+        mPoll = NULL;
+    }
 }
 
 bool WstClientSocket::connectToSocket(const char *name)
@@ -105,16 +62,16 @@
     if ( !workingDir )
     {
         workingDir = "/run";
-        ERROR("wstCreateVideoClientConnection: XDG_RUNTIME_DIR is not set,set default %s",workingDir);
+        ERROR(mLogCategory,"wstCreateVideoClientConnection: XDG_RUNTIME_DIR is not set,set default %s",workingDir);
     }
 
-    DEBUG("XDG_RUNTIME_DIR=%s",workingDir);
+    INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",workingDir);
 
     pathNameLen = strlen(workingDir)+strlen("/")+strlen(mName) + 1;
     if ( pathNameLen > (int)sizeof(mAddr.sun_path) )
     {
-        ERROR("wstCreateVideoClientConnection: name for server unix domain socket is too long: %d versus max %d", \
-            pathNameLen, (int)sizeof(mAddr.sun_path) );
+        ERROR(mLogCategory,"wstCreateVideoClientConnection: name for server unix domain socket is too long: %d versus max %d",
+                pathNameLen, (int)sizeof(mAddr.sun_path) );
         goto exit;
     }
 
@@ -126,7 +83,7 @@
     mSocketFd = socket( PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0 );
     if ( mSocketFd < 0 )
     {
-        ERROR("wstCreateVideoClientConnection: unable to open socket: errno %d", errno );
+        ERROR(mLogCategory,"wstCreateVideoClientConnection: unable to open socket: errno %d", errno );
         goto exit;
     }
 
@@ -135,11 +92,11 @@
     rc = connect(mSocketFd, (struct sockaddr *)&mAddr, addressSize );
     if ( rc < 0 )
     {
-        ERROR("wstCreateVideoClientConnection: connect failed for socket: errno %d,path:%s", errno,mAddr.sun_path );
+        ERROR(mLogCategory,"wstCreateVideoClientConnection: connect failed for socket: errno %d,path:%s", errno,mAddr.sun_path );
         goto exit;
     }
 
-    INFO("wstclient socket connected,path:%s",mAddr.sun_path);
+    INFO(mLogCategory,"wstclient socket connected,path:%s",mAddr.sun_path);
 
     run("wstclientsocket");
     return true;
@@ -158,13 +115,17 @@
 bool WstClientSocket::disconnectFromSocket()
 {
     if (isRunning()) {
+        INFO(mLogCategory,"try stop socket thread");
+        if (mPoll) {
+            mPoll->setFlushing(true);
+        }
         requestExitAndWait();
     }
 
     if ( mSocketFd >= 0 )
     {
         mAddr.sun_path[0]= '\0';
-        INFO("close socket");
+        INFO(mLogCategory,"close socket");
         close( mSocketFd );
         mSocketFd = -1;
     }
@@ -205,7 +166,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent pip %d to video server", pip);
+        INFO(mLogCategory,"sent pip %d to video server", pip);
     }
 }
 
@@ -244,7 +205,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent resource id %d (0:primary,1:pip) to video server", resourceId);
+        INFO(mLogCategory,"sent resource id %d (0:primary,1:pip) to video server", resourceId);
     }
 }
 
@@ -281,7 +242,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent flush to video server");
+        INFO(mLogCategory,"sent flush to video server");
     }
 }
 
@@ -319,7 +280,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent pause %d to video server", pause);
+        INFO(mLogCategory,"sent pause %d to video server", pause);
     }
 }
 
@@ -357,7 +318,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent hide %d to video server", hide);
+        INFO(mLogCategory,"sent hide %d to video server", hide);
     }
 }
 
@@ -396,7 +357,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent session info: synctype %d sessionId %d to video server", syncType, sessionId);
+        INFO(mLogCategory,"sent session info: synctype %d sessionId %d to video server", syncType, sessionId);
     }
 }
 
@@ -433,7 +394,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent frame adavnce to video server");
+        INFO(mLogCategory,"sent frame adavnce to video server");
     }
 }
 
@@ -480,7 +441,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent position to video server,vx:%d,vy:%d,vw:%d,vh:%d",videoX,videoY,videoWidth,videoHeight);
+        INFO(mLogCategory,"sent position to video server,vx:%d,vy:%d,vw:%d,vh:%d",videoX,videoY,videoWidth,videoHeight);
     }
 }
 
@@ -519,7 +480,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent frame rate to video server: %d/%d", fpsNum, fpsDenom);
+        INFO(mLogCategory,"sent frame rate to video server: %d/%d", fpsNum, fpsDenom);
     }
 }
 
@@ -588,7 +549,7 @@
         fdToSend0 = fcntl( frameFd0, F_DUPFD_CLOEXEC, 0 );
         if ( fdToSend0 < 0 )
         {
-            ERROR("wstSendFrameVideoClientConnection: failed to dup fd0");
+            ERROR(mLogCategory,"wstSendFrameVideoClientConnection: failed to dup fd0");
             goto exit;
         }
         if ( frameFd1 >= 0 )
@@ -596,7 +557,7 @@
             fdToSend1 = fcntl( frameFd1, F_DUPFD_CLOEXEC, 0 );
             if ( fdToSend1 < 0 )
             {
-                ERROR("wstSendFrameVideoClientConnection: failed to dup fd1");
+                ERROR(mLogCategory,"wstSendFrameVideoClientConnection: failed to dup fd1");
                 goto exit;
             }
             ++numFdToSend;
@@ -606,7 +567,7 @@
             fdToSend2 = fcntl( frameFd2, F_DUPFD_CLOEXEC, 0 );
             if ( fdToSend2 < 0 )
             {
-                ERROR("wstSendFrameVideoClientConnection: failed to dup fd2");
+                ERROR(mLogCategory,"wstSendFrameVideoClientConnection: failed to dup fd2");
                 goto exit;
             }
             ++numFdToSend;
@@ -617,7 +578,7 @@
         vw = wstRect->w;
         vh = wstRect->h;
 
-        TRACE("send frame:resolution(%dx%d),rect x:%d,y:%d,w:%d,h:%d", \
+        TRACE(mLogCategory,"send frame:resolution(%dx%d),rect x:%d,y:%d,w:%d,h:%d", \
             wstBufferInfo->frameWidth,wstBufferInfo->frameHeight, vx, vy, vw, vh);
 
         i = 0;
@@ -668,7 +629,7 @@
             fd[2] = fdToSend2;
         }
 
-        TRACE("send frame:bufferid %d, fd (%d, %d, %d [%d, %d, %d]),realtmUs:%lld", bufferId, frameFd0, frameFd1, frameFd2, fdToSend0, fdToSend1, fdToSend2,wstBufferInfo->frameTime);
+        TRACE(mLogCategory,"send frame:bufferid %d, fd (%d, %d, %d [%d, %d, %d]),realtmUs:%lld", bufferId, frameFd0, frameFd1, frameFd2, fdToSend0, fdToSend1, fdToSend2,wstBufferInfo->frameTime);
 
         do
         {
@@ -681,7 +642,7 @@
         }
         else
         {
-            ERROR("out: failed(%s) %d, sentLen(%d)%d, send frame %lld buffer %d ", \
+            ERROR(mLogCategory,"out: failed(%s) %d, sentLen(%d)%d, send frame %lld buffer %d ", \
                  strerror(errno), errno, sentLen, iov[0].iov_len, wstBufferInfo->frameTime, bufferId);
         }
     }
@@ -743,7 +704,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent crop frame size to video server,x:%d,y:%d,w:%d,h:%d",x,y,w,h);
+        INFO(mLogCategory,"sent crop frame size to video server,x:%d,y:%d,w:%d,h:%d",x,y,w,h);
     }
 }
 
@@ -781,7 +742,7 @@
 
     if ( sentLen == len )
     {
-        INFO("sent keep last frame %d to video server", keep);
+        INFO(mLogCategory,"sent keep last frame %d to video server", keep);
     }
 }
 
@@ -825,7 +786,7 @@
                     if ( mlen >= 5)
                     {
                         int rate = getU32( &m[4] );
-                        DEBUG("out: got rate %d from video server", rate);
+                        DEBUG(mLogCategory,"out: got rate %d from video server", rate);
                         mServerRefreshRate = rate;
                         if ( mPlugin )
                         {
@@ -840,7 +801,7 @@
                     if ( mlen >= 5)
                     {
                         int bid= getU32( &m[4] );
-                        TRACE("out: release received for buffer %d", bid);
+                        TRACE(mLogCategory,"out: release received for buffer %d", bid);
                         if ( mPlugin )
                         {
                             WstEvent wstEvent;
@@ -856,7 +817,7 @@
                         /* set position from frame currently presented by the video server */
                         uint64_t frameTime = getS64( &m[4] );
                         uint32_t numDropped = getU32( &m[12] );
-                        TRACE("out: status received: frameTime %lld numDropped %d", frameTime, numDropped);
+                        TRACE(mLogCategory,"out: status received: frameTime %lld numDropped %d", frameTime, numDropped);
                         if ( mPlugin )
                         {
                             WstEvent wstEvent;
@@ -871,7 +832,7 @@
                     if ( mlen >= 9 )
                     {
                         uint64_t frameTime = getS64( &m[4] );
-                        TRACE("out: underflow received: frameTime %lld", frameTime);
+                        TRACE(mLogCategory,"out: underflow received: frameTime %lld", frameTime);
                         if ( mPlugin )
                         {
                             WstEvent wstEvent;
@@ -887,7 +848,7 @@
                         int globalZoomActive= getU32( &m[4] );
                         int allow4kZoom = getU32( &m[8] );
                         int zoomMode= getU32( &m[12] );
-                        DEBUG("out: got zoom-mode %d from video server (globalZoomActive %d allow4kZoom %d)", zoomMode, globalZoomActive, allow4kZoom);
+                        DEBUG(mLogCategory,"out: got zoom-mode %d from video server (globalZoomActive %d allow4kZoom %d)", zoomMode, globalZoomActive, allow4kZoom);
                         if ( mPlugin )
                         {
                             WstEvent wstEvent;
@@ -903,7 +864,7 @@
                     if ( mlen >= 5)
                     {
                         int debugLevel = getU32( &m[4] );
-                        DEBUG("out: got video-debug-level %d from video server", debugLevel);
+                        DEBUG(mLogCategory,"out: got video-debug-level %d from video server", debugLevel);
                         if ( (debugLevel >= 0) && (debugLevel <= 7) )
                         {
                             if ( mPlugin )
@@ -936,20 +897,18 @@
 
 void WstClientSocket::readyToRun()
 {
+    if (mPoll && mSocketFd > 0) {
+        mPoll->addFd(mSocketFd);
+        mPoll->setFdReadable(mSocketFd, true);
+    }
 }
 
 bool WstClientSocket::threadLoop()
 {
     int ret;
-    struct pollfd fds;
-
-    fds.fd = mSocketFd;
-    fds.events = POLLERR | POLLNVAL | POLLHUP |POLLIN | POLLPRI | POLLRDNORM;
-    fds.revents = 0;
-
-    ret = poll(&fds, 1, 500);
+    ret = mPoll->wait(-1); //wait for ever
     if (ret < 0) { //poll error
-        WARNING("poll error");
+        WARNING(mLogCategory,"poll error");
         return false;
     } else if (ret == 0) { //poll time out
         return true; //run loop
diff --git a/westeros/wstclient_socket.h b/westeros/wstclient_socket.h
index cd387c4..d6915b9 100644
--- a/westeros/wstclient_socket.h
+++ b/westeros/wstclient_socket.h
@@ -20,6 +20,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include "Thread.h"
+#include "Poll.h"
 
 #ifdef  __cplusplus
 extern "C" {
@@ -98,7 +99,7 @@
 
 class WstClientSocket : public Tls::Thread{
   public:
-    WstClientSocket(WstClientPlugin *plugin);
+    WstClientSocket(WstClientPlugin *plugin, int logCategory);
     virtual ~WstClientSocket();
     bool connectToSocket(const char *name);
     bool disconnectFromSocket();
@@ -126,6 +127,7 @@
     void readyToRun();
     virtual bool threadLoop();
   private:
+    int mLogCategory;
     const char *mName;
     struct sockaddr_un mAddr;
     int mSocketFd;
@@ -133,6 +135,7 @@
     int64_t mServerRefreshPeriod;
     int mZoomMode;
     WstClientPlugin *mPlugin;
+    Tls::Poll *mPoll;
 };
 
 #endif /*_WST_SOCKET_CLIENT_H_*/
diff --git a/westeros/wstclient_wayland.cpp b/westeros/wstclient_wayland.cpp
index d9f8976..62da083 100644
--- a/westeros/wstclient_wayland.cpp
+++ b/westeros/wstclient_wayland.cpp
@@ -15,10 +15,9 @@
  */
 #include <cstring>
 #include "wstclient_wayland.h"
-#include "wstclient_plugin.h"
+#include "ErrorCode.h"
 #include "Logger.h"
-
-#define TAG "rlib:wstclient_wayland"
+#include "wstclient_plugin.h"
 
 #ifndef MAX
 #  define MAX(a,b)  ((a) > (b)? (a) : (b))
@@ -27,6 +26,8 @@
 
 #define WESTEROS_UNUSED(x) ((void)(x))
 
+#define TAG "rlib:wstclient_wayland"
+
 #define DEFAULT_WINDOW_X (0)
 #define DEFAULT_WINDOW_Y (0)
 #define DEFAULT_WINDOW_WIDTH (1920)
@@ -129,7 +130,7 @@
     WESTEROS_UNUSED(width);
     WESTEROS_UNUSED(height);
 
-    INFO("opacity: %d,zorder:%d", opacity,zorder);
+    INFO(self->mLogCategory,"opacity: %d,zorder:%d", opacity,zorder);
     self->mWindowChange = true;
     self->mOpacity = opacity;
     self->mZorder = zorder;
@@ -157,7 +158,7 @@
     WESTEROS_UNUSED(wl_vpc_surface);
     WstClientWayland *self = static_cast<WstClientWayland *>(data);
 
-    INFO("new pathway: %d\n", new_pathway);
+    INFO(self->mLogCategory,"new pathway: %d\n", new_pathway);
     self->setVideoPath(new_pathway == WL_VPC_SURFACE_PATHWAY_GRAPHICS);
 }
 
@@ -175,9 +176,9 @@
     WESTEROS_UNUSED(wl_vpc_surface);
     WstClientWayland *self = static_cast<WstClientWayland *>(data);
 
-    TRACE("x_trans:%d,y_trans:%d,x_scale_num:%d,x_scale_denom:%d,y_scale_num:%d,y_scale_denom:%d",\
+    TRACE(self->mLogCategory,"x_trans:%d,y_trans:%d,x_scale_num:%d,x_scale_denom:%d,y_scale_num:%d,y_scale_denom:%d",\
             x_translation,y_translation,x_scale_num,x_scale_denom,y_scale_num,y_scale_denom);
-    TRACE("output_width:%d,output_height:%d",output_width,output_height);
+    TRACE(self->mLogCategory,"output_width:%d,output_height:%d",output_width,output_height);
     self->mTransX= x_translation;
     self->mTransY= y_translation;
     if ( x_scale_denom )
@@ -193,7 +194,7 @@
     self->mOutputWidth= (int)output_width;
     self->mOutputHeight= (int)output_height;
 
-    std::lock_guard<std::mutex> lck(self->mMutex);
+    Tls::Mutex::Autolock _l(self->mMutex);
     self->updateVideoPosition();
 }
 
@@ -239,17 +240,17 @@
         //output resolution is a fixed value(1920x1080)
         width = DEFAULT_OUTPUT_WIDTH;
         height = DEFAULT_OUTPUT_HEIGHT;
-        std::lock_guard<std::mutex> lck(self->mMutex);
+        Tls::Mutex::Autolock _l(self->mMutex);
         self->mDisplayWidth = width;
         self->mDisplayHeight = height;
-        DEBUG("compositor sets window to (%dx%d)\n", width, height);
+        DEBUG(self->mLogCategory,"compositor sets window to (%dx%d)\n", width, height);
         if (!self->mWindowSet)
         {
             self->mWindowWidth = width;
             self->mWindowHeight = height;
             if (self->mWlVpcSurface)
             {
-                TRACE("set window geometry:x:%d,y:%d,w:%d,h:%d",self->mWindowX,self->mWindowY,self->mWindowWidth,self->mWindowHeight);
+                TRACE(self->mLogCategory,"set window geometry:x:%d,y:%d,w:%d,h:%d",self->mWindowX,self->mWindowY,self->mWindowWidth,self->mWindowHeight);
                 wl_vpc_surface_set_geometry(self->mWlVpcSurface, self->mWindowX, self->mWindowY, self->mWindowWidth, self->mWindowHeight);
             }
         }
@@ -284,7 +285,7 @@
     WstClientWayland *self = static_cast<WstClientWayland *>(data);
     WESTEROS_UNUSED(wl_sb);
     WESTEROS_UNUSED(data);
-    TRACE("registry: sbFormat: %X\n", format);
+    TRACE(self->mLogCategory,"registry: sbFormat: %X\n", format);
 }
 
 static const struct wl_sb_listener sbListener = {
@@ -296,31 +297,31 @@
     uint32_t id, const char *interface, uint32_t version)
 {
     WstClientWayland *self = static_cast<WstClientWayland *>(data);
-    TRACE("registryHandleGlobal,interface:%s,version:%d",interface,version);
+    TRACE(self->mLogCategory,"registryHandleGlobal,interface:%s,version:%d",interface,version);
 
     if (strcmp (interface, "wl_compositor") == 0) {
         self->mWlCompositor = (struct wl_compositor *)wl_registry_bind (registry, id, &wl_compositor_interface, 1/*MIN (version, 3)*/);
         wl_proxy_set_queue((struct wl_proxy*)self->mWlCompositor, self->mWlQueue);
-        TRACE("registry: compositor %p\n", (void*)self->mWlCompositor);
+        TRACE(self->mLogCategory,"registry: compositor %p\n", (void*)self->mWlCompositor);
     } else if (strcmp (interface, "wl_simple_shell") == 0) {
         self->mWlShell = (struct wl_simple_shell*)wl_registry_bind(registry, id, &wl_simple_shell_interface, 1);
         wl_proxy_set_queue((struct wl_proxy*)self->mWlShell, self->mWlQueue);
         wl_simple_shell_add_listener(self->mWlShell, &shellListener, (void *)self);
-        TRACE("registry: simple shell %p\n", (void*)self->mWlShell);
+        TRACE(self->mLogCategory,"registry: simple shell %p\n", (void*)self->mWlShell);
     } else if (strcmp (interface, "wl_vpc") == 0) {
         self->mWlVpc = (struct wl_vpc*)wl_registry_bind(registry, id, &wl_vpc_interface, 1);
         wl_proxy_set_queue((struct wl_proxy*)self->mWlVpc, self->mWlQueue);
-        TRACE("registry: vpc %p\n", (void*)self->mWlVpc);
+        TRACE(self->mLogCategory,"registry: vpc %p\n", (void*)self->mWlVpc);
     } else if (strcmp (interface, "wl_output") == 0) {
         self->mWlOutput = (struct wl_output*)wl_registry_bind(registry, id, &wl_output_interface, 2);
         wl_proxy_set_queue((struct wl_proxy*)self->mWlOutput, self->mWlQueue);
         wl_output_add_listener(self->mWlOutput, &outputListener, (void *)self);
-        TRACE("registry: output %p\n", (void*)self->mWlOutput);
+        TRACE(self->mLogCategory,"registry: output %p\n", (void*)self->mWlOutput);
     } else if (strcmp (interface, "wl_sb") == 0) {
         self->mWlSb = (struct wl_sb*)wl_registry_bind(registry, id, &wl_sb_interface, version);
         wl_proxy_set_queue((struct wl_proxy*)self->mWlSb, self->mWlQueue);
         wl_sb_add_listener(self->mWlSb, &sbListener, (void *)self);
-        TRACE("registry: sb %p\n", (void*)self->mWlSb);
+        TRACE(self->mLogCategory,"registry: sb %p\n", (void*)self->mWlSb);
     }
 }
 
@@ -329,7 +330,7 @@
 {
     WstClientWayland *self = static_cast<WstClientWayland *>(data);
     /* temporarily do nothing */
-    DEBUG("wayland display remove registry handle global");
+    DEBUG(self->mLogCategory,"wayland display remove registry handle global");
 }
 
 static const struct wl_registry_listener registry_listener = {
@@ -337,10 +338,12 @@
     WstClientWayland::registryHandleGlobalRemove
 };
 
-WstClientWayland::WstClientWayland(WstClientPlugin *plugin)
-    :mPlugin(plugin)
+WstClientWayland::WstClientWayland(WstClientPlugin *plugin, int logCategory)
+    :mMutex("bufferMutex"),
+    mPlugin(plugin),
+    mLogCategory(logCategory)
 {
-    TRACE("construct WstClientWayland");
+    TRACE(mLogCategory,"construct WstClientWayland");
     mWlDisplay = NULL;
     mWlQueue = NULL;
     mWlRegistry = NULL;
@@ -375,11 +378,16 @@
     mScaleXDenom = 0;
     mScaleYDenom = 0;
     mForceFullScreen = false;
+    mPoll = new Tls::Poll(true);
 }
 
 WstClientWayland::~WstClientWayland()
 {
-    TRACE("deconstruct WstClientWayland");
+    TRACE(mLogCategory,"deconstruct WstClientWayland");
+    if (mPoll) {
+        delete mPoll;
+        mPoll = NULL;
+    }
 }
 
 int WstClientWayland::connectToWayland()
@@ -388,40 +396,40 @@
     const char *displayEnv = NULL;
     const char *displayName = "rlib-display";
     const char *fullScreenEnV = NULL;
-    DEBUG("in");
+    DEBUG(mLogCategory,"in");
     xdgEnv = getenv("XDG_RUNTIME_DIR");
-    INFO("XDG_RUNTIME_DIR:%s",xdgEnv != NULL?xdgEnv:"NULL");
+    INFO(mLogCategory,"XDG_RUNTIME_DIR:%s",xdgEnv != NULL?xdgEnv:"NULL");
     if (!xdgEnv) {
         xdgEnv = "/run";
-        ERROR("XDG_RUNTIME_DIR is not set,set default %s",xdgEnv);
+        ERROR(mLogCategory,"XDG_RUNTIME_DIR is not set,set default %s",xdgEnv);
     }
     displayEnv= getenv("WAYLAND_DISPLAY");
-    INFO("WAYLAND_DISPLAY:%s",displayEnv != NULL?displayEnv:"NULL");
+    INFO(mLogCategory,"WAYLAND_DISPLAY:%s",displayEnv != NULL?displayEnv:"NULL");
 
     fullScreenEnV= getenv("VIDEO_RENDER_FORCE_FULLSCREEN");
-    INFO("VIDEO_RENDER_FORCE_FULLSCREEN:%s",fullScreenEnV != NULL?fullScreenEnV:"NULL");
+    INFO(mLogCategory,"VIDEO_RENDER_FORCE_FULLSCREEN:%s",fullScreenEnV != NULL?fullScreenEnV:"NULL");
     if (fullScreenEnV) {
         int force = atoi(fullScreenEnV);
         mForceFullScreen = force != 0? true: false;
-        INFO("VIDEO_RENDER_FORCE_FULLSCREEN:%d",mForceFullScreen);
+        INFO(mLogCategory,"VIDEO_RENDER_FORCE_FULLSCREEN:%d",mForceFullScreen);
     }
 
     mWlDisplay = wl_display_connect(NULL);
     if (!mWlDisplay) {
         char waylandDisplay[64];
-        ERROR("Failed connect to default wayland display");
+        ERROR(mLogCategory,"Failed connect to default wayland display");
         memset(waylandDisplay, 0, 64);
         strcpy(waylandDisplay, xdgEnv);
         strcat(waylandDisplay, "/" );
         strcat(waylandDisplay, displayName);
-        INFO("detect rlib wayland display %s",waylandDisplay);
+        INFO(mLogCategory,"detect rlib wayland display %s",waylandDisplay);
         if (access(waylandDisplay,F_OK) == 0) {
-            INFO("try to connect to %s",waylandDisplay);
+            INFO(mLogCategory,"try to connect to %s",waylandDisplay);
             mWlDisplay = wl_display_connect(displayName);
         }
         /*try to create wayland display my self*/
         if (!mWlDisplay && xdgEnv) {
-            WARNING("try to create and connect rlib-display display");
+            WARNING(mLogCategory,"try to create and connect rlib-display display");
             std::string cmdCreateDisplay = R"(curl 'http://127.0.0.1:9998/jsonrpc' -d '{"jsonrpc": "2.0","id": 4,"method":
                 "org.rdk.RDKShell.1.createDisplay","params": { "client": "rlib-display", "displayName": "rlib-display" }}';echo)";
             std::string cmdMoveDisplay = R"(curl 'http://127.0.0.1:9998/jsonrpc' -d '{"jsonrpc": "2.0","id": 4,"method":
@@ -434,10 +442,10 @@
         }
 
         if (!mWlDisplay) {
-            ERROR( "wayland connect rlib-display fail");
-            return -1;
+            ERROR(mLogCategory, "wayland connect rlib-display fail");
+            return ERROR_OPEN_FAIL;
         }
-        INFO("wayland connected to rlib-display");
+        INFO(mLogCategory,"wayland connected to rlib-display");
     }
 
     mWlQueue = wl_display_create_queue (mWlDisplay);
@@ -449,8 +457,8 @@
     /* we need exactly 2 roundtrips to discover global objects and their state */
     for (int i = 0; i < 2; i++) {
         if (wl_display_roundtrip_queue (mWlDisplay, mWlQueue) < 0) {
-            ERROR("Error communicating with the wayland display");
-            return -1;
+            ERROR(mLogCategory,"Error communicating with the wayland display");
+            return ERROR_OPEN_FAIL;
         }
     }
 
@@ -471,16 +479,19 @@
         }
     }
 
-    DEBUG("out");
-    return 0;
+    INFO(mLogCategory,"out");
+    return NO_ERROR;
 }
 
 void WstClientWayland::disconnectFromWayland()
 {
-    DEBUG("in");
+    INFO(mLogCategory,"in");
 
    if (isRunning()) {
-        TRACE("try stop dispatch thread");
+        TRACE(mLogCategory,"try stop dispatch thread");
+        if (mPoll) {
+            mPoll->setFlushing(true);
+        }
         requestExitAndWait();
     }
 
@@ -532,16 +543,17 @@
     if (mWlDisplay) {
         wl_display_flush (mWlDisplay);
         wl_display_disconnect (mWlDisplay);
+        INFO(mLogCategory,"wl display disconnect");
         mWlDisplay = NULL;
     }
 
-    DEBUG("out");
+    INFO(mLogCategory,"out");
 }
 
 void WstClientWayland::setWindowSize(int x, int y, int w, int h)
 {
     if (x == 0 && y == 0 && w == 0 && h == 0) {
-        WARNING( "set full screen? %dx%dx%dx%d",x,y,w,h);
+        WARNING(mLogCategory, "set full screen? %dx%dx%dx%d",x,y,w,h);
         return;
     }
     mWindowX = x;
@@ -551,9 +563,9 @@
     mWindowChange = true;
     mWindowSet = true;
     mWindowSizeOverride = true;
-    DEBUG("set window size:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
+    DEBUG(mLogCategory,"set window size:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
     if (mWlVpcSurface) {
-        DEBUG( "wl_vpc_surface_set_geometry(%d,%d,%d,%d)",mWindowX,mWindowY,mWindowWidth,mWindowHeight);
+        DEBUG(mLogCategory, "wl_vpc_surface_set_geometry(%d,%d,%d,%d)",mWindowX,mWindowY,mWindowWidth,mWindowHeight);
         wl_vpc_surface_set_geometry(mWlVpcSurface, mWindowX, mWindowY, mWindowWidth, mWindowHeight);
     }
     //if window size is updated, update video position
@@ -566,11 +578,11 @@
 void WstClientWayland::setFrameSize(int frameWidth, int frameHeight) {
     mFrameWidth = frameWidth;
     mFrameHeight = frameHeight;
-    DEBUG( "set frame size:%dx%d",mFrameWidth, mFrameHeight);
+    DEBUG(mLogCategory, "set frame size:%dx%d",mFrameWidth, mFrameHeight);
 }
 
 void WstClientWayland::setZoomMode(int zoomMode, bool globalZoomActive, bool allow4kZoom) {
-    DEBUG( "zoomMode:%d, globalZoomActive:%d, allow4kZoom:%d",zoomMode,globalZoomActive,allow4kZoom);
+    DEBUG(mLogCategory, "zoomMode:%d, globalZoomActive:%d, allow4kZoom:%d",zoomMode,globalZoomActive,allow4kZoom);
     mZoomModeGlobal = globalZoomActive;
     if ( !globalZoomActive )
     {
@@ -585,7 +597,7 @@
             mPixelAspectRatioChanged = true;
         }
     } else {
-        DEBUG( "global zoom disabled: ignore server value");
+        DEBUG(mLogCategory, "global zoom disabled: ignore server value");
     }
 }
 
@@ -605,7 +617,7 @@
         *y = mWindowY;
         *w = mWindowWidth;
         *h = mWindowHeight;
-        TRACE( "no wldisplay, %d,%d,%d,%d",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
+        TRACE(mLogCategory, "no wldisplay, %d,%d,%d,%d",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
         return;
     }
 
@@ -620,14 +632,14 @@
     vw = mVideoWidth;
     vh = mVideoHeight;
 
-    TRACE( "videoX:%d,videoY:%d,videoW:%d,videoH:%d",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
+    TRACE(mLogCategory, "videoX:%d,videoY:%d,videoW:%d,videoH:%d",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
     //if the window size is smaller than display size,we scall video to map window size
     if (mWindowWidth != mDisplayWidth || mWindowHeight != mDisplayHeight) {
         *x= vx;
         *y= vy;
         *w= vw;
         *h= vh;
-        TRACE("small window vrect %d, %d, %d, %d", vx, vy, vw, vh);
+        TRACE(mLogCategory, "small window vrect %d, %d, %d, %d", vx, vy, vw, vh);
         return;
     }
     if (mForceFullScreen) {
@@ -635,7 +647,7 @@
         *y= vy;
         *w= vw;
         *h= vh;
-        TRACE("force window vrect %d, %d, %d, %d", vx, vy, vw, vh);
+        TRACE(mLogCategory, "force window vrect %d, %d, %d, %d", vx, vy, vw, vh);
         return;
     }
 
@@ -645,12 +657,12 @@
     contentHeight = frameHeight;
 
     if (mPixelAspectRatioChanged)
-        DEBUG("pixelAspectRatio: %f zoom-mode %d", mPixelAspectRatio, mZoomMode);
+        DEBUG(mLogCategory,"pixelAspectRatio: %f zoom-mode %d", mPixelAspectRatio, mZoomMode);
 
     ard = (double)mVideoWidth/(double)mVideoHeight;
     arf = (double)contentWidth/(double)contentHeight;
 
-    TRACE( "frameWidth:%d,frameHeight:%d,contentWidth:%f,contentHeight:%f",frameWidth,frameHeight,contentWidth,contentHeight);
+    TRACE(mLogCategory, "frameWidth:%d,frameHeight:%d,contentWidth:%f,contentHeight:%f",frameWidth,frameHeight,contentWidth,contentHeight);
 
     /* Establish region of interest */
     roix = 0;
@@ -664,7 +676,7 @@
         zoomMode= ZOOM_NORMAL;
     }
     //if (mPixelAspectRatioChanged )
-        TRACE("ard %f arf %f", ard, arf);
+        TRACE(mLogCategory, "ard %f arf %f", ard, arf);
     switch ( zoomMode )
     {
         case ZOOM_NORMAL:
@@ -707,7 +719,7 @@
                 /* For 16:9 content on a 16:9 display, stretch as though 4:3 */
                 hfactor= 4.0/3.0;
                 if (mPixelAspectRatioChanged )
-                    DEBUG("stretch apply vfactor %f hfactor %f", vfactor, hfactor);
+                    DEBUG(mLogCategory, "stretch apply vfactor %f hfactor %f", vfactor, hfactor);
             }
             vh = mVideoHeight * (1.0);
             vw = vh*hfactor*16/9;
@@ -733,7 +745,7 @@
                     vfactor= 4.0/3.0;
                     hfactor= 1.0;
                     if (mPixelAspectRatioChanged )
-                        DEBUG("zoom apply vfactor %f hfactor %f", vfactor, hfactor);
+                        DEBUG(mLogCategory, "zoom apply vfactor %f hfactor %f", vfactor, hfactor);
                 }
                 vh = mVideoHeight * vfactor * (1.0);
                 vw = (roiw * vh) * hfactor / roih;
@@ -750,7 +762,7 @@
         }
         break;
     }
-    if (mPixelAspectRatioChanged) DEBUG("vrect %d, %d, %d, %d", vx, vy, vw, vh);
+    if (mPixelAspectRatioChanged) DEBUG(mLogCategory, "vrect %d, %d, %d, %d", vx, vy, vw, vh);
     if (mPixelAspectRatioChanged)
     {
         if (mWlDisplay && mWlVpcSurface )
@@ -764,12 +776,12 @@
     *y= vy;
     *w= vw;
     *h= vh;
-    TRACE("vrect %d, %d, %d, %d", vx, vy, vw, vh);
+    TRACE(mLogCategory, "vrect %d, %d, %d, %d", vx, vy, vw, vh);
 }
 
 void WstClientWayland::setTextureCrop(int vx, int vy, int vw, int vh)
 {
-    DEBUG("vx %d vy %d vw %d vh %d window(%d, %d, %d, %d) display(%dx%d)", \
+    DEBUG(mLogCategory, "vx %d vy %d vw %d vh %d window(%d, %d, %d, %d) display(%dx%d)", \
              vx, vy, vw, vh, mWindowX, mWindowY, mWindowWidth, mWindowHeight, mDisplayWidth, mDisplayHeight);
     if ( (mDisplayWidth != -1) && (mDisplayHeight != -1) &&
         ( (vx < 0) || (vx+vw > mDisplayWidth) ||
@@ -869,7 +881,7 @@
         cropy= (cropy*WL_VPC_SURFACE_CROP_DENOM)/mWindowHeight;
         cropw= (cropw*WL_VPC_SURFACE_CROP_DENOM)/mWindowWidth;
         croph= (croph*WL_VPC_SURFACE_CROP_DENOM)/mWindowHeight;
-        DEBUG("%d, %d, %d, %d - %d, %d, %d, %d", vx, vy, vw, vh, cropx, cropy, cropw, croph);
+        DEBUG(mLogCategory,"%d, %d, %d, %d - %d, %d, %d, %d", vx, vy, vw, vh, cropx, cropy, cropw, croph);
         if (mWlVpcSurface) {
             wl_vpc_surface_set_geometry_with_crop(mWlVpcSurface, vx, vy, vw, vh, cropx, cropy, cropw, croph );
         }
@@ -884,7 +896,7 @@
 
 void WstClientWayland::setForceAspectRatio(bool force)
 {
-    DEBUG( "force aspect ratio:%d",force);
+    DEBUG(mLogCategory, "force aspect ratio:%d",force);
     mForceAspectRatio = force;
 }
 
@@ -892,7 +904,7 @@
 {
     mPixelAspectRatio = ratio;
     mPixelAspectRatioChanged = true;
-    INFO( "set aspect ratio:%f",ratio);
+    INFO(mLogCategory, "set aspect ratio:%f",ratio);
 }
 
 void WstClientWayland::updateVideoPosition()
@@ -910,7 +922,7 @@
         mVideoY= ((mWindowY*mScaleYNum)/mScaleYDenom) + mTransY;
         mVideoWidth= (mWindowWidth*mScaleXNum)/mScaleXDenom;
         mVideoHeight= (mWindowHeight*mScaleYNum)/mScaleYDenom;
-        DEBUG( "window override video rectangle(%d,%d,%d,%d)",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
+        DEBUG(mLogCategory, "window override video rectangle(%d,%d,%d,%d)",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
     }
     else
     {
@@ -918,7 +930,7 @@
         mVideoY = mTransY;
         mVideoWidth = (mOutputWidth*mScaleXNum)/mScaleXDenom;
         mVideoHeight = (mOutputHeight*mScaleYNum)/mScaleYDenom;
-        DEBUG( "video rectangle(%d,%d,%d,%d)",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
+        DEBUG(mLogCategory, "video rectangle(%d,%d,%d,%d)",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
     }
 
     if (vx == mVideoX && vy == mVideoY && vw == mVideoWidth && vh == mVideoHeight) {
@@ -950,7 +962,7 @@
 
 void WstClientWayland::setVideoPath(bool useGfxPath )
 {
-    INFO("useGfxPath:%d",useGfxPath);
+    INFO(mLogCategory,"useGfxPath:%d",useGfxPath);
     if ( needBounds() && mWlVpcSurface )
     {
         /* Use nominal display size provided to us by
@@ -968,7 +980,7 @@
         mVideoWidth = mWindowWidth;
         mVideoHeight = mWindowHeight;
 
-        DEBUG( "video rect (%d,%d,%d,%d)",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
+        DEBUG(mLogCategory, "video rect (%d,%d,%d,%d)",mVideoX,mVideoY,mVideoWidth,mVideoHeight);
 
         if (mFrameWidth > 0 && mFrameHeight > 0) {
             getVideoBounds(&vx, &vy, &vw, &vh);
@@ -1005,6 +1017,10 @@
 void WstClientWayland::readyToRun()
 {
     mFd = wl_display_get_fd (mWlDisplay);
+    if (mPoll) {
+        mPoll->addFd(mFd);
+        mPoll->setFdReadable(mFd, true);
+    }
 }
 
 bool WstClientWayland::threadLoop()
@@ -1016,16 +1032,13 @@
       wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
     }
 
-    pfd.fd = mFd;
-    pfd.events = POLLERR | POLLNVAL | POLLHUP |POLLIN | POLLPRI | POLLRDNORM;
-    pfd.revents = 0;
-
     wl_display_flush (mWlDisplay);
 
-    /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed*/
-    ret = poll(&pfd, 1, 500);
+    /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed,
+     so do use -1 to wait for ever*/
+    ret = mPoll->wait(-1); //wait for ever
     if (ret < 0) { //poll error
-        WARNING("poll error");
+        WARNING(mLogCategory,"poll error");
         wl_display_cancel_read(mWlDisplay);
         return false;
     } else if (ret == 0) { //poll time out
@@ -1039,15 +1052,15 @@
     wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
     return true;
 tag_error:
-    ERROR("Error communicating with the wayland server");
+    ERROR(mLogCategory,"Error communicating with the wayland server");
     return false;
 }
 
 void WstClientWayland::executeCmd(const char *cmd) {
-    INFO("%s", cmd);
+    INFO(mLogCategory,"%s", cmd);
     FILE* pFile = popen(cmd, "r");
     char buf[128];
     char* retStr = fgets(buf, sizeof(buf), pFile);
-    INFO("ret= %s", retStr);
+    INFO(mLogCategory,"ret= %s", retStr);
     pclose(pFile);
 }
\ No newline at end of file
diff --git a/westeros/wstclient_wayland.h b/westeros/wstclient_wayland.h
index f2aa317..a831c5e 100644
--- a/westeros/wstclient_wayland.h
+++ b/westeros/wstclient_wayland.h
@@ -19,7 +19,6 @@
 #include <stdlib.h>
 #include <pthread.h>
 #include <poll.h>
-#include <mutex>
 #include <list>
 #include <wayland-client.h>
 #include "xdg-shell-client-protocol.h"
@@ -31,6 +30,7 @@
 #include "vpc-client-protocol.h"
 #include "simplebuffer-client-protocol.h"
 #include "Thread.h"
+#include "Poll.h"
 #include "render_common.h"
 #include "wstclient_socket.h"
 
@@ -40,7 +40,7 @@
 
 class WstClientWayland : public Tls::Thread{
   public:
-    WstClientWayland(WstClientPlugin *plugin);
+    WstClientWayland(WstClientPlugin *plugin, int logCategory);
     virtual ~WstClientWayland();
     /**
      * @brief connet client to compositor server
@@ -176,6 +176,8 @@
     struct wl_registry *mWlRegistry;
     struct wl_compositor *mWlCompositor;
 
+    int mLogCategory;
+
     int mTransX;
     int mTransY;
     int mScaleXNum;
@@ -216,8 +218,9 @@
     bool mZoomModeGlobal;
     bool mAllow4kZoom;
 
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mMutex;
     int mFd;
+    Tls::Poll *mPoll;
 
     bool mForceFullScreen;
 };
diff --git a/weston/Makefile b/weston/Makefile
index bb79817..f74b3dc 100644
--- a/weston/Makefile
+++ b/weston/Makefile
@@ -87,6 +87,7 @@
 
 OBJ_CLIENT_LIB += \
 	$(TOOLS_PATH)/Thread.o \
+	$(TOOLS_PATH)/Poll.o \
 	$(TOOLS_PATH)/Queue.o \
 	$(TOOLS_PATH)/Times.o \
 	$(TOOLS_PATH)/Utils.o \
diff --git a/weston/wayland_buffer.cpp b/weston/wayland_buffer.cpp
index b5e260f..3ccdb78 100644
--- a/weston/wayland_buffer.cpp
+++ b/weston/wayland_buffer.cpp
@@ -33,11 +33,13 @@
 #include "wayland_dma.h"
 #include "wayland_shm.h"
 #include "Utils.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:wayland_buffer"
 
-WaylandBuffer::WaylandBuffer(WaylandDisplay *display)
-    : mDisplay(display)
+WaylandBuffer::WaylandBuffer(WaylandDisplay *display, int logCategory)
+    : mDisplay(display),
+    mLogCategory(logCategory)
 {
     mRenderBuffer = NULL;
     mWaylandWlWrap = NULL;
@@ -66,7 +68,7 @@
 void WaylandBuffer::bufferRelease (void *data, struct wl_buffer *wl_buffer)
 {
     WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
-    TRACE("--wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
+    TRACE(waylandBuffer->mLogCategory,"--wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
     waylandBuffer->mUsedByCompositor = false;
     //sometimes this callback be called twice
     //this cause double free,so check mRenderBuffer
@@ -79,7 +81,7 @@
 void WaylandBuffer::bufferdroped (void *data, struct wl_buffer *wl_buffer)
 {
     WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
-    WARNING("--droped wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
+    WARNING(waylandBuffer->mLogCategory,"--droped wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
     waylandBuffer->mUsedByCompositor = false;
 
     if (waylandBuffer->mRenderBuffer) {
@@ -122,16 +124,16 @@
 
     mRenderBuffer = buf;
     if (mWaylandWlWrap) {
-        return 0;
+        return NO_ERROR;
     }
 
     if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
-        WaylandDmaBuffer *waylanddma = new WaylandDmaBuffer(mDisplay);
+        WaylandDmaBuffer *waylanddma = new WaylandDmaBuffer(mDisplay, mLogCategory);
         wlbuffer = waylanddma->constructWlBuffer(&buf->dma, mBufferFormat);
         if (!wlbuffer) {
             delete waylanddma;
-            ERROR("create wl_buffer fail");
-            return -1;
+            ERROR(mLogCategory,"create wl_buffer fail");
+            return ERROR_INVALID_OPERATION;
         }
         mWaylandWlWrap = waylanddma;
         mFrameWidth = buf->dma.width;
@@ -141,7 +143,7 @@
     /*register buffer release listen*/
     wl_buffer_add_listener (wlbuffer, &buffer_listener, this);
 
-    return 0;
+    return NO_ERROR;
 }
 
 struct wl_buffer *WaylandBuffer::getWlBuffer()
@@ -158,7 +160,7 @@
     struct wl_callback *callback;
     struct wl_buffer *wlbuffer = NULL;
     if (mUsedByCompositor) {
-        DEBUG("buffer used by compositor");
+        DEBUG(mLogCategory,"buffer used by compositor");
         return;
     }
 
diff --git a/weston/wayland_buffer.h b/weston/wayland_buffer.h
index 785d989..a8ec92e 100644
--- a/weston/wayland_buffer.h
+++ b/weston/wayland_buffer.h
@@ -15,8 +15,8 @@
  */
 #ifndef __WAYLAND_BUFFER_H__
 #define __WAYLAND_BUFFER_H__
-#include <mutex>
-#include "render_plugin.h"
+#include "Mutex.h"
+#include "Condition.h"
 #include "wayland_wlwrap.h"
 
 class WaylandDisplay;
@@ -35,7 +35,7 @@
  */
 class WaylandBuffer {
   public:
-    WaylandBuffer(WaylandDisplay *display);
+    WaylandBuffer(WaylandDisplay *display, int logCategory);
     virtual ~WaylandBuffer();
     int constructWlBuffer(RenderBuffer *buf);
     void forceRedrawing() {
@@ -77,6 +77,7 @@
     static void bufferdroped (void *data, struct wl_buffer *wl_buffer);
     static void frameDisplayedCallback(void *data, struct wl_callback *callback, uint32_t time);
   private:
+    int mLogCategory;
     WaylandDisplay *mDisplay;
     RenderBuffer *mRenderBuffer;
     WaylandWLWrap *mWaylandWlWrap; //wl_buffer wrapper
@@ -85,7 +86,7 @@
     RenderVideoFormat mBufferFormat;
     int mFrameWidth;
     int mFrameHeight;
-    mutable std::mutex mLock;
+    mutable Tls::Mutex mLock;
     bool mRedrawingPending;
 };
 
diff --git a/weston/wayland_display.cpp b/weston/wayland_display.cpp
index 039ed71..7d7429e 100644
--- a/weston/wayland_display.cpp
+++ b/weston/wayland_display.cpp
@@ -15,6 +15,7 @@
  */
 #include <string>
 #include "wayland_display.h"
+#include "ErrorCode.h"
 #include "Logger.h"
 #include "wayland_plugin.h"
 #include "wayland_videoformat.h"
@@ -35,9 +36,9 @@
          uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
 {
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
-    std::lock_guard<std::mutex> lck(self->mMutex);
+    Tls::Mutex::Autolock _l(self->mMutex);
     if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
-        TRACE("regist dmabuffer format:%d (%s) hi:%x,lo:%x",format,print_dmabuf_format_name(format),modifier_hi,modifier_lo);
+        TRACE(self->mLogCategory,"regist dmabuffer format:%d (%s) hi:%x,lo:%x",format,print_dmabuf_format_name(format),modifier_hi,modifier_lo);
         uint64_t modifier = ((uint64_t)modifier_hi << 32) | modifier_lo;
         auto item = self->mDmaBufferFormats.find(format);
         if (item == self->mDmaBufferFormats.end()) {
@@ -105,9 +106,9 @@
     UNUSED_PARAM(model);
 
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
-    DEBUG("wl_output %p x:%d,y:%d,physicalWidth:%d,physicalHeight:%d,subPixel:%d,trans:%d",
-            output,x, y,physicalWidth, physicalHeight,subPixel,transform);;
-    std::lock_guard<std::mutex> lck(self->mMutex);
+    DEBUG(self->mLogCategory,"wl_output %p x:%d,y:%d,physicalWidth:%d,physicalHeight:%d,subPixel:%d,trans:%d",
+            output,x, y,physicalWidth, physicalHeight,subPixel,transform);
+    Tls::Mutex::Autolock _l(self->mMutex);
     for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
         if (output == self->mOutput[i].wlOutput) {
             self->mOutput[i].offsetX = x;
@@ -126,7 +127,7 @@
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
 
     if ( flags & WL_OUTPUT_MODE_CURRENT ) {
-        std::lock_guard<std::mutex> lck(self->mMutex);
+        Tls::Mutex::Autolock _l(self->mMutex);
         for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
             if (output == self->mOutput[i].wlOutput) {
                 self->mOutput[i].width = width;
@@ -136,7 +137,7 @@
         }
         //if a displayoutput had been selected,set this rectangle to wayland
         int selectOutput = self->mActiveOutput;
-        DEBUG("wl_output: %p (%dx%d) refreshrate:%d,active output index %d\n",output, width, height,refreshRate,selectOutput);
+        DEBUG(self->mLogCategory,"wl_output: %p (%dx%d) refreshrate:%d,active output index %d\n",output, width, height,refreshRate,selectOutput);
         if (selectOutput >= 0 && selectOutput < DEFAULT_DISPLAY_OUTPUT_NUM) {
             if (self->mOutput[selectOutput].width > 0 && self->mOutput[selectOutput].height > 0) {
                 self->setRenderRectangle(self->mOutput[selectOutput].offsetX,
@@ -197,7 +198,7 @@
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
     int x = wl_fixed_to_int(sx);
     int y = wl_fixed_to_int(sy);
-    DEBUG("pointer motion fixed[%d, %d] to-int: x[%d] y[%d]\n", sx, sy, x, y);
+    DEBUG(self->mLogCategory,"pointer motion fixed[%d, %d] to-int: x[%d] y[%d]\n", sx, sy, x, y);
 }
 
 void WaylandDisplay::pointerHandleButton(void *data, struct wl_pointer *wl_pointer,
@@ -378,7 +379,7 @@
 {
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
 
-    INFO("XDG toplevel got a close event.");
+    INFO(self->mLogCategory,"XDG toplevel got a close event.");
 }
 
 void WaylandDisplay::handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
@@ -387,7 +388,7 @@
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
     uint32_t *state;
 
-    INFO("XDG toplevel got a configure event, width:height [ %d, %d ].", width, height);
+    INFO(self->mLogCategory, "XDG toplevel got a configure event, width:height [ %d, %d ].", width, height);
     /*
     wl_array_for_each (state, states) {
         switch (*state) {
@@ -425,11 +426,11 @@
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
     xdg_surface_ack_configure (xdg_surface, serial);
 
-    TRACE("handleXdgSurfaceConfigure");
-    std::lock_guard<std::mutex> lck(self->mConfigureMutex);
+    TRACE(self->mLogCategory,"handleXdgSurfaceConfigure");
+    Tls::Mutex::Autolock _l(self->mConfigureMutex);
     self->mXdgSurfaceConfigured = true;
     if (self->mRenderRect.w > 0 && self->mRenderRect.h) {
-        DEBUG("set xdg surface geometry(%d,%d,%d,%d)",self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
+        DEBUG(self->mLogCategory,"set xdg surface geometry(%d,%d,%d,%d)",self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
         xdg_surface_set_window_geometry(self->mXdgSurface,self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
     }
 }
@@ -443,7 +444,7 @@
     uint32_t id, const char *interface, uint32_t version)
 {
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
-    TRACE("registryHandleGlobal,interface:%s,version:%d",interface,version);
+    TRACE(self->mLogCategory,"registryHandleGlobal,interface:%s,version:%d",interface,version);
 
     if (strcmp (interface, "wl_compositor") == 0) {
         self->mCompositor = (struct wl_compositor *)wl_registry_bind (registry, id, &wl_compositor_interface, 1/*MIN (version, 3)*/);
@@ -484,7 +485,7 @@
 {
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
     /* temporarily do nothing */
-    DEBUG("wayland display remove registry handle global");
+    DEBUG(self->mLogCategory,"wayland display remove registry handle global");
 }
 
 static const struct wl_registry_listener registry_listener = {
@@ -492,10 +493,12 @@
   WaylandDisplay::registryHandleGlobalRemove
 };
 
-WaylandDisplay::WaylandDisplay(WaylandPlugin *plugin)
-    :mWaylandPlugin(plugin)
+WaylandDisplay::WaylandDisplay(WaylandPlugin *plugin, int logCategory)
+    :mBufferMutex("bufferMutex"),
+    mWaylandPlugin(plugin),
+    mLogCategory(logCategory)
 {
-    TRACE("construct WaylandDisplay");
+    TRACE(mLogCategory,"construct WaylandDisplay");
     mWlDisplay = NULL;
     mWlDisplayWrapper = NULL;
     mWlQueue = NULL;
@@ -511,6 +514,7 @@
     mKeyboard = NULL;
     mNextOutput = 0;
     mActiveOutput = 0; //default is primary output
+    mPoll = new Tls::Poll(true);
     //window
     mVideoWidth = 0;
     mVideoHeight = 0;
@@ -540,10 +544,10 @@
         int isSet = atoi(env);
         if (isSet > 0) {
             mIsSendPtsToWeston = true;
-            INFO("set send pts to weston");
+            INFO(mLogCategory,"set send pts to weston");
         } else {
             mIsSendPtsToWeston = false;
-            INFO("do not send pts to weston");
+            INFO(mLogCategory,"do not send pts to weston");
         }
     }
     env = getenv("VIDEO_RENDER_SEND_VIDEO_PLANE_ID_TO_WESTON");
@@ -551,10 +555,10 @@
         int isSet = atoi(env);
         if (isSet == 0) {
             mIsSendVideoPlaneId = false;
-            INFO("do not send video plane id to weston");
+            INFO(mLogCategory,"do not send video plane id to weston");
         } else {
             mIsSendVideoPlaneId = true;
-            INFO("send video plane id to weston");
+            INFO(mLogCategory,"send video plane id to weston");
         }
     }
     for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
@@ -570,13 +574,17 @@
 
 WaylandDisplay::~WaylandDisplay()
 {
-    TRACE("desconstruct WaylandDisplay");
+    TRACE(mLogCategory,"desconstruct WaylandDisplay");
+    if (mPoll) {
+        delete mPoll;
+        mPoll = NULL;
+    }
 }
 
 char *WaylandDisplay::require_xdg_runtime_dir()
 {
     char *val = getenv("XDG_RUNTIME_DIR");
-    INFO("XDG_RUNTIME_DIR=%s",val);
+    INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",val);
 
     return val;
 }
@@ -585,12 +593,12 @@
 {
     char *name = require_xdg_runtime_dir();
     //DEBUG(mLogCategory,"name:%s",name);
-    DEBUG("openDisplay in");
+    DEBUG(mLogCategory,"openDisplay in");
     mWlDisplay = wl_display_connect(NULL);
     if (!mWlDisplay) {
-        ERROR("Failed to connect to the wayland display, XDG_RUNTIME_DIR='%s'",
+        ERROR(mLogCategory,"Failed to connect to the wayland display, XDG_RUNTIME_DIR='%s'",
         name ? name : "NULL");
-        return -1;
+        return ERROR_OPEN_FAIL;
     }
 
     mWlDisplayWrapper = (struct wl_display *)wl_proxy_create_wrapper ((void *)mWlDisplay);
@@ -603,20 +611,20 @@
     /* we need exactly 2 roundtrips to discover global objects and their state */
     for (int i = 0; i < 2; i++) {
         if (wl_display_roundtrip_queue (mWlDisplay, mWlQueue) < 0) {
-            ERROR("Error communicating with the wayland display");
-            return -1;
+            ERROR(mLogCategory,"Error communicating with the wayland display");
+            return ERROR_OPEN_FAIL;
         }
     }
 
     if (!mCompositor) {
-        ERROR("Could not bind to wl_compositor. Either it is not implemented in " \
+        ERROR(mLogCategory,"Could not bind to wl_compositor. Either it is not implemented in " \
         "the compositor, or the implemented version doesn't match");
-        return -1;
+        return ERROR_OPEN_FAIL;
     }
 
     if (!mDmabuf) {
-        ERROR("Could not bind to zwp_linux_dmabuf_v1");
-        return -1;
+        ERROR(mLogCategory,"Could not bind to zwp_linux_dmabuf_v1");
+        return ERROR_OPEN_FAIL;
     }
 
     if (!mXdgWmBase) {
@@ -624,9 +632,9 @@
         * wl_shell, xdg_shell and zwp_fullscreen_shell are not used.
         * In this case is correct to continue.
         */
-        ERROR("Could not bind to either wl_shell, xdg_wm_base or "
+        ERROR(mLogCategory,"Could not bind to either wl_shell, xdg_wm_base or "
             "zwp_fullscreen_shell, video display may not work properly.");
-        return -1;
+        return ERROR_OPEN_FAIL;
     }
 
     //create window surface
@@ -635,25 +643,28 @@
 
     //config weston video plane
     if (mIsSendVideoPlaneId) {
-        INFO("set weston video plane:%d",mPip);
+        INFO(mLogCategory,"set weston video plane:%d",mPip);
         wl_surface_set_video_plane(mVideoSurfaceWrapper, mPip);
     }
 
     //run wl display queue dispatch
-    DEBUG("To run wl display dispatch queue");
+    DEBUG(mLogCategory,"To run wl display dispatch queue");
     run("display queue");
     mRedrawingPending = false;
 
-    DEBUG("openDisplay out");
-    return 0;
+    DEBUG(mLogCategory,"openDisplay out");
+    return NO_ERROR;
 }
 
 void WaylandDisplay::closeDisplay()
 {
-    DEBUG("closeDisplay in");
+    DEBUG(mLogCategory,"closeDisplay in");
 
    if (isRunning()) {
-        TRACE("try stop dispatch thread");
+        TRACE(mLogCategory,"try stop dispatch thread");
+        if (mPoll) {
+            mPoll->setFlushing(true);
+        }
         requestExitAndWait();
     }
 
@@ -706,14 +717,14 @@
         mWlDisplay = NULL;
     }
 
-    DEBUG("closeDisplay out");
+    DEBUG(mLogCategory,"closeDisplay out");
 }
 
 int WaylandDisplay::toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/)
 {
     if (!outDmaformat || !outDmaformatModifiers) {
-        WARNING("NULL params");
-        return -1;
+        WARNING(mLogCategory,"NULL params");
+        return ERROR_PARAM_NULL;
     }
 
     *outDmaformat = 0;
@@ -721,63 +732,63 @@
 
     uint32_t dmaformat = video_format_to_wl_dmabuf_format (format);
     if (dmaformat == -1) {
-        ERROR("Error not found render video format:%d to wl dmabuf format",format);
-        return -1;
+        ERROR(mLogCategory,"Error not found render video format:%d to wl dmabuf format",format);
+        return ERROR_NOT_FOUND;
     }
 
-    TRACE("render video format:%d -> dmabuf format:%d",format,dmaformat);
+    TRACE(mLogCategory,"render video format:%d -> dmabuf format:%d",format,dmaformat);
     *outDmaformat = (uint32_t)dmaformat;
 
     /*get dmaformat and modifiers*/
     auto item = mDmaBufferFormats.find(dmaformat);
     if (item == mDmaBufferFormats.end()) { //not found
-        WARNING("Not found dmabuf for render video format :%d",format);
+        WARNING(mLogCategory,"Not found dmabuf for render video format :%d",format);
         *outDmaformatModifiers = 0;
-        return 0;
+        return NO_ERROR;
     }
 
     *outDmaformatModifiers = (uint64_t)item->second;
 
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandDisplay::toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat)
 {
     if (!outformat) {
-        WARNING("NULL params");
-        return -1;
+        WARNING(mLogCategory,"NULL params");
+        return ERROR_PARAM_NULL;
     }
 
     *outformat = 0;
 
     int shmformat = (int)video_format_to_wl_shm_format(format);
     if (shmformat < 0) {
-        ERROR("Error not found render video format:%d to wl shmbuf format",format);
-        return -1;
+        ERROR(mLogCategory,"Error not found render video format:%d to wl shmbuf format",format);
+        return ERROR_NOT_FOUND;
     }
 
     for (auto item = mShmFormats.begin(); item != mShmFormats.end(); ++item) {
         uint32_t  registFormat = (uint32_t)*item;
         if (registFormat == (uint32_t)shmformat) {
             *outformat = registFormat;
-            return 0;
+            return NO_ERROR;
         }
     }
 
-    return -1;
+    return ERROR_NOT_FOUND;
 }
 
 void WaylandDisplay::setVideoBufferFormat(RenderVideoFormat format)
 {
-    TRACE("set video buffer format: %d",format);
+    TRACE(mLogCategory,"set video buffer format: %d",format);
     mBufferFormat = format;
 };
 
 void WaylandDisplay::setDisplayOutput(int output)
 {
-    TRACE("select display output: %d",output);
+    TRACE(mLogCategory,"select display output: %d",output);
     if (output < 0 || output >= DEFAULT_DISPLAY_OUTPUT_NUM) {
-        ERROR( "display output index error,please set 0:primary or 1:extend,now:%d",output);
+        ERROR(mLogCategory, "display output index error,please set 0:primary or 1:extend,now:%d",output);
         return;
     }
     if (mActiveOutput != output) {
@@ -794,7 +805,7 @@
 
 void WaylandDisplay::setPip(int pip)
 {
-    INFO("set pip:%d",pip);
+    INFO(mLogCategory,"set pip:%d",pip);
     mPip = pip;
 }
 
@@ -836,7 +847,7 @@
         /* First create the XDG surface */
         mXdgSurface= xdg_wm_base_get_xdg_surface (mXdgWmBase, mAreaSurface);
         if (!mXdgSurface) {
-            ERROR("Unable to get xdg_surface");
+            ERROR(mLogCategory,"Unable to get xdg_surface");
             return;
         }
         xdg_surface_add_listener (mXdgSurface, &xdg_surface_listener,(void *)this);
@@ -844,7 +855,7 @@
         /* Then the toplevel */
         mXdgToplevel= xdg_surface_get_toplevel (mXdgSurface);
         if (!mXdgSurface) {
-            ERROR("Unable to get xdg_toplevel");
+            ERROR(mLogCategory,"Unable to get xdg_toplevel");
             return;
         }
         xdg_toplevel_add_listener (mXdgToplevel, &xdg_toplevel_listener, this);
@@ -856,14 +867,14 @@
         /* we need exactly 3 roundtrips to discover global objects and their state */
         for (int i = 0; i < 3; i++) {
             if (wl_display_roundtrip_queue(mWlDisplay, mWlQueue) < 0) {
-                ERROR("Error communicating with the wayland display");
+                ERROR(mLogCategory,"Error communicating with the wayland display");
             }
         }
 
         if (mXdgSurfaceConfigured) {
-            INFO("xdg surface had configured");
+            INFO(mLogCategory,"xdg surface had configured");
         } else {
-            WARNING("xdg surface not configured");
+            WARNING(mLogCategory,"xdg surface not configured");
         }
 
         //full screen show
@@ -877,7 +888,7 @@
         //     setRenderRectangle(mRenderRect.x, mRenderRect.y, mRenderRect.w, mRenderRect.h);
         // }
     } else {
-        ERROR("Unable to use xdg_wm_base ");
+        ERROR(mLogCategory,"Unable to use xdg_wm_base ");
         return;
     }
 }
@@ -932,7 +943,7 @@
 void WaylandDisplay::ensureFullscreen(bool fullscreen)
 {
     if (mXdgWmBase) {
-        DEBUG("full screen : %d",fullscreen);
+        DEBUG(mLogCategory,"full screen : %d",fullscreen);
         if (fullscreen) {
             xdg_toplevel_set_fullscreen (mXdgToplevel, mOutput[mActiveOutput].wlOutput);
         } else {
@@ -943,10 +954,10 @@
 
 void WaylandDisplay::setRenderRectangle(int x, int y, int w, int h)
 {
-    DEBUG("set render rect:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
+    DEBUG(mLogCategory,"set render rect:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
 
     if (w <= 0 || h <= 0) {
-        WARNING( "wrong render width or height %dx%d",w,h);
+        WARNING(mLogCategory, "wrong render width or height %dx%d",w,h);
         return;
     }
 
@@ -956,7 +967,7 @@
     mRenderRect.h = h;
 
     if (!mXdgSurfaceConfigured) {
-        WARNING("Not configured xdg");
+        WARNING(mLogCategory,"Not configured xdg");
         return;
     }
 
@@ -984,7 +995,7 @@
 {
     mVideoWidth = w;
     mVideoHeight = h;
-    TRACE("frame w:%d,h:%d",mVideoWidth,mVideoHeight);
+    TRACE(mLogCategory,"frame w:%d,h:%d",mVideoWidth,mVideoHeight);
     if (mRenderRect.w > 0 && mVideoSurface) {
         resizeVideoSurface(true);
     }
@@ -996,7 +1007,7 @@
     mWindowRect.y = y;
     mWindowRect.w = w;
     mWindowRect.h = h;
-    TRACE("window size:x:%d,y:%d,w:%d,h:%d",mWindowRect.x,mWindowRect.y,mWindowRect.w,mWindowRect.h);
+    TRACE(mLogCategory,"window size:x:%d,y:%d,w:%d,h:%d",mWindowRect.x,mWindowRect.y,mWindowRect.w,mWindowRect.h);
     if (mWindowRect.w > 0 && mVideoWidth > 0 && mVideoSurface) {
         //if had full screen, unset it and set window size
         if (mFullScreen) {
@@ -1025,7 +1036,7 @@
         dst.w = mWindowRect.w;
         dst.h = mWindowRect.h;
         if (mWindowRect.w > mRenderRect.w && mWindowRect.h > mRenderRect.h) {
-            WARNING("Error window size:%dx%d, but render size:%dx%d,reset to render size",
+            WARNING(mLogCategory,"Error window size:%dx%d, but render size:%dx%d,reset to render size",
                 mWindowRect.w,mWindowRect.h,mRenderRect.w,mRenderRect.h);
             dst.x = mRenderRect.x;
             dst.y = mRenderRect.y;
@@ -1072,7 +1083,7 @@
 
     //to scale video surface to full screen
     wp_viewport_set_destination(mVideoViewport, res.w, res.h);
-    TRACE("video rectangle,x:%d,y:%d,w:%d,h:%d",mVideoRect.x, mVideoRect.y, mVideoRect.w, mVideoRect.h);
+    TRACE(mLogCategory,"video rectangle,x:%d,y:%d,w:%d,h:%d",mVideoRect.x, mVideoRect.y, mVideoRect.w, mVideoRect.h);
 }
 
 void WaylandDisplay::setOpaque()
@@ -1093,23 +1104,23 @@
 
     waylandBuf = findWaylandBuffer(buf);
     if (waylandBuf == NULL) {
-        waylandBuf = new WaylandBuffer(this);
+        waylandBuf = new WaylandBuffer(this, mLogCategory);
         waylandBuf->setBufferFormat(mBufferFormat);
         ret = waylandBuf->constructWlBuffer(buf);
-        if (ret != 0) {
-            WARNING("dmabufConstructWlBuffer fail,release waylandbuf");
+        if (ret != NO_ERROR) {
+            WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
             //delete waylanBuf,WaylandBuffer object destruct will call release callback
             goto waylandbuf_fail;
         } else {
             addWaylandBuffer(buf, waylandBuf);
         }
     }
-    return 0;
+    return NO_ERROR;
 waylandbuf_fail:
     //delete waylandbuf
     delete waylandBuf;
     waylandBuf = NULL;
-    return -1;
+    return ERROR_UNKNOWN;
 }
 
 void WaylandDisplay::displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime)
@@ -1119,7 +1130,7 @@
     int ret;
 
     if (!buf) {
-        ERROR("Error input params, waylandbuffer is null");
+        ERROR(mLogCategory,"Error input params, waylandbuffer is null");
         return;
     }
 
@@ -1130,7 +1141,7 @@
         wl_surface_commit (mAreaSurface);
     }
 
-    TRACE("display renderBuffer:%p,PTS:%lld,realtime:%lld",buf, buf->pts, realDisplayTime);
+    TRACE(mLogCategory,"display renderBuffer:%p,PTS:%lld,realtime:%lld",buf, buf->pts, realDisplayTime);
 
     if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
         if (buf->dma.width <=0 || buf->dma.height <=0) {
@@ -1141,13 +1152,13 @@
         if (waylandBuf) {
             waylandBuf->setRenderRealTime(realDisplayTime);
             ret = waylandBuf->constructWlBuffer(buf);
-            if (ret != 0) {
-                WARNING("dmabufConstructWlBuffer fail,release waylandbuf");
+            if (ret != NO_ERROR) {
+                WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
                 //delete waylanBuf,WaylandBuffer object destruct will call release callback
                 goto waylandbuf_fail;
             }
         } else {
-            ERROR("NOT found wayland buffer,please prepare buffer first");
+            ERROR(mLogCategory,"NOT found wayland buffer,please prepare buffer first");
             goto waylandbuf_fail;
         }
     }
@@ -1156,16 +1167,16 @@
         wlbuffer = waylandBuf->getWlBuffer();
     }
     if (wlbuffer) {
-        std::lock_guard<std::mutex> lck(mRenderMutex);
+        Tls::Mutex::Autolock _l(mRenderMutex);
         ++mCommitCnt;
         uint32_t hiPts = realDisplayTime >> 32;
         uint32_t lowPts = realDisplayTime & 0xFFFFFFFF;
         //attach this wl_buffer to weston
-        TRACE("++attach,renderbuf:%p,wl_buffer:%p(0,0,%d,%d),pts:%lld,commitCnt:%d",buf,wlbuffer,mVideoRect.w,mVideoRect.h,buf->pts,mCommitCnt);
+        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) {
-            TRACE("display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
+            TRACE(mLogCategory,"display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
             wl_surface_set_pts(mVideoSurfaceWrapper, hiPts, lowPts);
         }
 
@@ -1175,7 +1186,7 @@
         std::pair<int64_t, WaylandBuffer *> item(buf->pts, waylandBuf);
         mCommittedBufferMap.insert(item);
     } else {
-        WARNING("wlbuffer is NULL");
+        WARNING(mLogCategory,"wlbuffer is NULL");
         /* clear both video and parent surfaces */
         cleanSurface();
     }
@@ -1197,7 +1208,7 @@
 void WaylandDisplay::handleBufferReleaseCallback(WaylandBuffer *buf)
 {
     {
-        std::lock_guard<std::mutex> lck(mRenderMutex);
+        Tls::Mutex::Autolock _l(mRenderMutex);
         --mCommitCnt;
         //remove buffer if this buffer is ready to release
         RenderBuffer *renderBuffer = buf->getRenderBuffer();
@@ -1205,26 +1216,26 @@
         if (item != mCommittedBufferMap.end()) {
             mCommittedBufferMap.erase(item);
         } else {
-            WARNING("Can't find WaylandBuffer in buffer map");
+            WARNING(mLogCategory,"Can't find WaylandBuffer in buffer map");
             return;
         }
     }
     RenderBuffer *renderBuffer = buf->getRenderBuffer();
-    TRACE("handle release renderBuffer :%p,priv:%p,PTS:%lld,realtime:%lld us,commitCnt:%d",renderBuffer,renderBuffer->priv,renderBuffer->pts/1000,buf->getRenderRealTime(),mCommitCnt);
+    TRACE(mLogCategory,"handle release renderBuffer :%p,priv:%p,PTS:%lld,realtime:%lld us,commitCnt:%d",renderBuffer,renderBuffer->priv,renderBuffer->pts/1000,buf->getRenderRealTime(),mCommitCnt);
     mWaylandPlugin->handleBufferRelease(renderBuffer);
 }
 
 void WaylandDisplay::handleFrameDisplayedCallback(WaylandBuffer *buf)
 {
     RenderBuffer *renderBuffer = buf->getRenderBuffer();
-    TRACE("handle displayed renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
+    TRACE(mLogCategory,"handle displayed renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
     mWaylandPlugin->handleFrameDisplayed(renderBuffer);
 }
 
 void WaylandDisplay::handleFrameDropedCallback(WaylandBuffer *buf)
 {
     RenderBuffer *renderBuffer = buf->getRenderBuffer();
-    TRACE("handle droped renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
+    TRACE(mLogCategory,"handle droped renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
     mWaylandPlugin->handleFrameDropped(renderBuffer);
 }
 
@@ -1232,16 +1243,15 @@
 void WaylandDisplay::readyToRun()
 {
     mFd = wl_display_get_fd (mWlDisplay);
+    if (mPoll) {
+        mPoll->addFd(mFd);
+        mPoll->setFdReadable(mFd, true);
+    }
 }
 
 bool WaylandDisplay::threadLoop()
 {
     int ret;
-    struct pollfd pfd;
-
-    pfd.fd = mFd;
-    pfd.events = POLLERR | POLLNVAL | POLLHUP |POLLIN | POLLPRI | POLLRDNORM;
-    pfd.revents = 0;
 
     while (wl_display_prepare_read_queue (mWlDisplay, mWlQueue) != 0) {
       wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
@@ -1251,9 +1261,9 @@
 
     /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed,
      so do use -1 to wait for ever*/
-    ret = poll(&pfd, 1, 500);
+    ret = mPoll->wait(-1); //wait for ever
     if (ret < 0) { //poll error
-        WARNING("poll error");
+        WARNING(mLogCategory,"poll error");
         wl_display_cancel_read(mWlDisplay);
         return false;
     } else if (ret == 0) { //poll time out
@@ -1267,7 +1277,7 @@
     wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
     return true;
 tag_error:
-    ERROR("Error communicating with the wayland server");
+    ERROR(mLogCategory,"Error communicating with the wayland server");
     return false;
 }
 
@@ -1279,7 +1289,7 @@
         result->y = dst.y;
         result->w = dst.w;
         result->h = dst.h;
-        TRACE("small window source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
+        TRACE(mLogCategory,"small window source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
         src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
         return;
     }
@@ -1312,7 +1322,7 @@
         }
     }
 
-    TRACE("source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
+    TRACE(mLogCategory,"source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
         src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
 }
 
@@ -1332,7 +1342,7 @@
     }
 
     RenderVideoFormat format = VIDEO_FORMAT_BGRA;
-    mAreaShmBuffer = new WaylandShmBuffer(this);
+    mAreaShmBuffer = new WaylandShmBuffer(this, mLogCategory);
     struct wl_buffer *wlbuf = mAreaShmBuffer->constructWlBuffer(width, height, format);
     if (wlbuf == NULL) {
         delete mAreaShmBuffer;
@@ -1354,7 +1364,7 @@
     }
 
     std::size_t hashval = std::hash<std::string>()(hashString);
-    //TRACE("hashstr:%s,val:%zu",hashString.c_str(),hashval);
+    //TRACE(mLogCategory,"hashstr:%s,val:%zu",hashString.c_str(),hashval);
     return hashval;
 }
 
@@ -1363,7 +1373,7 @@
     if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
         std::size_t hashval = calculateDmaBufferHash(buf->dma);
         std::pair<std::size_t, WaylandBuffer *> item(hashval, waylandbuf);
-        //TRACE("fd:%d,w:%d,h:%d,%p,hash:%zu",buf->dma.fd[0],buf->dma.width,buf->dma.height,waylandbuf,hashval);
+        //TRACE(mLogCategory,"fd:%d,w:%d,h:%d,%p,hash:%zu",buf->dma.fd[0],buf->dma.width,buf->dma.height,waylandbuf,hashval);
         mWaylandBuffersMap.insert(item);
     }
 
@@ -1373,7 +1383,7 @@
         if ((waylandbuf->getFrameWidth() != buf->dma.width ||
             waylandbuf->getFrameHeight() != buf->dma.height) &&
             waylandbuf->isFree()) {
-            TRACE("delete wayland buffer,width:%d(%d),height:%d(%d)",
+            TRACE(mLogCategory,"delete wayland buffer,width:%d(%d),height:%d(%d)",
                 waylandbuf->getFrameWidth(),buf->dma.width,
                 waylandbuf->getFrameHeight(),buf->dma.height);
             mWaylandBuffersMap.erase(item++);
@@ -1382,7 +1392,7 @@
             item++;
         }
     }
-    TRACE("mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
+    TRACE(mLogCategory,"mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
 }
 
 WaylandBuffer* WaylandDisplay::findWaylandBuffer(RenderBuffer * buf)
@@ -1408,8 +1418,8 @@
 
 void WaylandDisplay::flushBuffers()
 {
-    INFO("flushBuffers");
-    std::lock_guard<std::mutex> lck(mRenderMutex);
+    INFO(mLogCategory,"flushBuffers");
+    Tls::Mutex::Autolock _l(mRenderMutex);
     for (auto item = mCommittedBufferMap.begin(); item != mCommittedBufferMap.end(); item++) {
         WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
         waylandbuf->forceRedrawing();
diff --git a/weston/wayland_display.h b/weston/wayland_display.h
index ed8685b..06e7664 100644
--- a/weston/wayland_display.h
+++ b/weston/wayland_display.h
@@ -20,7 +20,6 @@
 #include <pthread.h>
 #include <poll.h>
 #include <list>
-#include <mutex>
 #include <unordered_map>
 #include <wayland-client-protocol.h>
 #include <wayland-client.h>
@@ -31,6 +30,7 @@
 #include "viewporter-client-protocol.h"
 #include "wayland-cursor.h"
 #include "Thread.h"
+#include "Poll.h"
 #include "render_plugin.h"
 
 using namespace std;
@@ -43,7 +43,7 @@
 
 class WaylandDisplay : public Tls::Thread{
   public:
-    WaylandDisplay(WaylandPlugin *plugin);
+    WaylandDisplay(WaylandPlugin *plugin, int logCategory);
     virtual ~WaylandDisplay();
     /**
      * @brief connet client to compositor server
@@ -257,16 +257,19 @@
     int mNextOutput; //the count of wl_output,
     int mActiveOutput; //default is primary output
 
+    int mLogCategory;
+
     std::list<uint32_t> mShmFormats;
     std::unordered_map<uint32_t, uint64_t> mDmaBufferFormats;
     RenderVideoFormat mBufferFormat;
 
-    mutable std::mutex mBufferMutex;
-    mutable std::mutex mMutex;
+    mutable Tls::Mutex mBufferMutex;
+    mutable Tls::Mutex mMutex;
     int mFd;
+    Tls::Poll *mPoll;
 
     /*the followed is windows variable*/
-    mutable std::mutex mRenderMutex;
+    mutable Tls::Mutex mRenderMutex;
     struct wl_surface *mAreaSurface;
     struct wl_surface *mAreaSurfaceWrapper;
     struct wl_surface *mVideoSurface;
@@ -278,7 +281,8 @@
     struct wp_viewport *mVideoViewport;
     WaylandShmBuffer *mAreaShmBuffer;
     bool mXdgSurfaceConfigured;
-    std::mutex mConfigureMutex;
+    Tls::Condition mConfigureCond;
+    Tls::Mutex mConfigureMutex;
     bool mFullScreen; //default full screen
 
     bool mIsSendPtsToWeston;
diff --git a/weston/wayland_dma.cpp b/weston/wayland_dma.cpp
index bf3f080..a972dc1 100644
--- a/weston/wayland_dma.cpp
+++ b/weston/wayland_dma.cpp
@@ -21,7 +21,6 @@
 #include <sys/epoll.h>
 #include <string.h>
 #include <stdlib.h>
-#include <chrono>
 
 #include <wayland-client.h>
 #include "xdg-shell-client-protocol.h"
@@ -31,11 +30,13 @@
 #include "wayland_dma.h"
 #include "Logger.h"
 #include "wayland_display.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:wayland_dma"
 
-WaylandDmaBuffer::WaylandDmaBuffer(WaylandDisplay *display)
-    : mDisplay(display)
+WaylandDmaBuffer::WaylandDmaBuffer(WaylandDisplay *display, int logCategory)
+    : mDisplay(display),
+    mLogCategory(logCategory)
 {
     mRenderDmaBuffer = {0,};
     mWlBuffer = NULL;
@@ -47,7 +48,7 @@
 {
     //release wl_buffer
     if (mWlBuffer) {
-        TRACE("destroy wl_buffer %p",mWlBuffer);
+        TRACE(mLogCategory,"destroy wl_buffer %p",mWlBuffer);
         wl_buffer_destroy(mWlBuffer);
         mWlBuffer = NULL;
     }
@@ -58,20 +59,20 @@
             struct wl_buffer *new_buffer)
 {
     WaylandDmaBuffer *waylandDma = static_cast<WaylandDmaBuffer*>(data);
-    TRACE("++create dma wl_buffer:%p ",new_buffer);
-    std::lock_guard<std::mutex> lck(waylandDma->mMutex);
+    TRACE(waylandDma->mLogCategory,"++create dma wl_buffer:%p ",new_buffer);
+    Tls::Mutex::Autolock _l(waylandDma->mMutex);
     waylandDma->mWlBuffer = new_buffer;
-    waylandDma->mCondition.notify_one();
+    waylandDma->mCondition.signal();
 }
 
 void WaylandDmaBuffer::dmabufCreateFail(void *data,
             struct zwp_linux_buffer_params_v1 *params)
 {
     WaylandDmaBuffer *waylandDma = static_cast<WaylandDmaBuffer*>(data);
-    std::lock_guard<std::mutex> lck(waylandDma->mMutex);
-    TRACE("!!!create dma wl_buffer fail");
+    Tls::Mutex::Autolock _l(waylandDma->mMutex);
+    TRACE(waylandDma->mLogCategory,"!!!create dma wl_buffer fail");
     waylandDma->mWlBuffer = NULL;
-    waylandDma->mCondition.notify_one();
+    waylandDma->mCondition.signal();
 }
 
 static const struct zwp_linux_buffer_params_v1_listener dmabuf_params_listener = {
@@ -89,19 +90,19 @@
     uint32_t dmabufferFormat;
 
     ret = mDisplay->toDmaBufferFormat(format, &dmabufferFormat, &formatModifier);
-    if (ret != 0) {
-        ERROR("Error change render video format to dmabuffer format fail");
+    if (ret != NO_ERROR) {
+        ERROR(mLogCategory,"Error change render video format to dmabuffer format fail");
         return NULL;
     }
 
     //check dma buffer
     if (dmabuf->planeCnt < 0) {
-        ERROR("Error dmabuf plane count is 0");
+        ERROR(mLogCategory,"Error dmabuf plane count is 0");
         return NULL;
     }
     for (int i = 0; i < dmabuf->planeCnt; i++) {
         if (dmabuf->fd[i] <= 0) {
-            ERROR("Error dmabuf plane fd is 0");
+            ERROR(mLogCategory,"Error dmabuf plane fd is 0");
             return NULL;
         }
     }
@@ -110,11 +111,11 @@
 
     params = zwp_linux_dmabuf_v1_create_params (mDisplay->getDmaBuf());
     if (!params) {
-        ERROR("zwp_linux_dmabuf_v1_create_params fail");
+        ERROR(mLogCategory, "zwp_linux_dmabuf_v1_create_params fail");
         return NULL;
     }
     for (int i = 0; i < dmabuf->planeCnt; i++) {
-        TRACE("dma buf index:%d,fd:%d,stride:%d,offset:%d",i, dmabuf->fd[i],dmabuf->stride[i], dmabuf->offset[i]);
+        TRACE(mLogCategory,"dma buf index:%d,fd:%d,stride:%d,offset:%d",i, dmabuf->fd[i],dmabuf->stride[i], dmabuf->offset[i]);
         zwp_linux_buffer_params_v1_add(params,
                    dmabuf->fd[i],
                    i, /*plane_idx*/
@@ -126,17 +127,17 @@
 
     /* Request buffer creation */
     zwp_linux_buffer_params_v1_add_listener (params, &dmabuf_params_listener, (void *)this);
-    TRACE("zwp_linux_buffer_params_v1_create,dma width:%d,height:%d,dmabufferformat:%d",dmabuf->width,dmabuf->height,dmabufferFormat);
+    TRACE(mLogCategory,"zwp_linux_buffer_params_v1_create,dma width:%d,height:%d,dmabufferformat:%d",dmabuf->width,dmabuf->height,dmabufferFormat);
     zwp_linux_buffer_params_v1_create (params, dmabuf->width, dmabuf->height, dmabufferFormat, flags);
 
     /* Wait for the request answer */
     wl_display_flush (mDisplay->getWlDisplay());
-    std::unique_lock<std::mutex> lck(mMutex);
+    Tls::Mutex::Autolock _l(mMutex);
     if (!mWlBuffer) { //if this wlbuffer had created,don't wait zwp linux buffer callback
         mWlBuffer =(struct wl_buffer *)0xffffffff;
         while (mWlBuffer == (struct wl_buffer *)0xffffffff) { //try wait for 1000 ms
-            if (std::cv_status::timeout == mCondition.wait_for(lck, std::chrono::seconds(1))) {
-                WARNING("zwp_linux_buffer_params_v1_create timeout");
+            if (ERROR_TIMED_OUT == mCondition.waitRelative(mMutex, 1000/*microsecond*/)) {
+                WARNING(mLogCategory,"zwp_linux_buffer_params_v1_create timeout");
                 mWlBuffer = NULL;
             }
         }
diff --git a/weston/wayland_dma.h b/weston/wayland_dma.h
index e5aa4a4..32dea3e 100644
--- a/weston/wayland_dma.h
+++ b/weston/wayland_dma.h
@@ -15,8 +15,8 @@
  */
 #ifndef __WAYLAND_DMA_H__
 #define __WAYLAND_DMA_H__
-#include <mutex>
-#include <condition_variable>
+#include "Mutex.h"
+#include "Condition.h"
 #include "wayland_wlwrap.h"
 #include "render_plugin.h"
 
@@ -25,7 +25,7 @@
 class WaylandDmaBuffer : public WaylandWLWrap
 {
   public:
-    WaylandDmaBuffer(WaylandDisplay *display);
+    WaylandDmaBuffer(WaylandDisplay *display, int logCategory);
     virtual ~WaylandDmaBuffer();
     virtual struct wl_buffer *getWlBuffer() {
         return mWlBuffer;
@@ -46,9 +46,11 @@
     WaylandDisplay *mDisplay;
     RenderDmaBuffer mRenderDmaBuffer;
     struct wl_buffer *mWlBuffer;
-    mutable std::mutex mMutex;
-    std::condition_variable mCondition;
+    mutable Tls::Mutex mMutex;
+    Tls::Condition mCondition;
     void *mData;
     int mSize;
+
+    int mLogCategory;
 };
 #endif /*__WAYLAND_DMA_H__*/
\ No newline at end of file
diff --git a/weston/wayland_plugin.cpp b/weston/wayland_plugin.cpp
index 66603a0..7221488 100644
--- a/weston/wayland_plugin.cpp
+++ b/weston/wayland_plugin.cpp
@@ -17,12 +17,15 @@
 #include "wayland_display.h"
 #include "Logger.h"
 #include "Times.h"
+#include "ErrorCode.h"
 
 #define TAG "rlib:wayland_plugin"
 
-WaylandPlugin::WaylandPlugin()
+WaylandPlugin::WaylandPlugin(int logCatgory)
+    : mRenderLock("renderlock"),
+    mLogCategory(logCatgory)
 {
-    mDisplay = new WaylandDisplay(this);
+    mDisplay = new WaylandDisplay(this, logCatgory);
     mQueue = new Tls::Queue();
     mPaused = false;
     mImmediatelyOutput = false;
@@ -38,12 +41,12 @@
         delete mQueue;
         mQueue = NULL;
     }
-    TRACE("desconstruct");
+    TRACE(mLogCategory,"desconstruct");
 }
 
 void WaylandPlugin::init()
 {
-    INFO("\n--------------------------------\n"
+    INFO(mLogCategory,"\n--------------------------------\n"
             "plugin      : weston\n"
             "ARCH        : %s\n"
             "branch name : %s\n"
@@ -83,36 +86,36 @@
 {
     int ret;
 
-    std::lock_guard<std::mutex> lck(mRenderLock);
-    DEBUG("openDisplay");
+    Tls::Mutex::Autolock _l(mRenderLock);
+    DEBUG(mLogCategory,"openDisplay");
     ret =  mDisplay->openDisplay();
-    if (ret != 0) {
-        ERROR("Error open display");
-        return -1;
+    if (ret != NO_ERROR) {
+        ERROR(mLogCategory,"Error open display");
+        return ret;
     }
-    DEBUG("openDisplay end");
-    return 0;
+    DEBUG(mLogCategory,"openDisplay end");
+    return ret;
 }
 
 int WaylandPlugin::openWindow()
 {
-    std::lock_guard<std::mutex> lck(mRenderLock);
+    Tls::Mutex::Autolock _l(mRenderLock);
     /* if weston can't support pts feature,
      * we should create a post buffer thread to
      * send buffer by mono time
      */
     if (!mDisplay->isSentPtsToWeston()) {
-        DEBUG("run frame post thread");
+            DEBUG(mLogCategory,"run frame post thread");
         setThreadPriority(50);
         run("waylandPostThread");
     }
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandPlugin::prepareFrame(RenderBuffer *buffer)
 {
     mDisplay->prepareFrameBuffer(buffer);
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
@@ -124,11 +127,11 @@
     if (!mDisplay->isSentPtsToWeston()) {
         buffer->time = displayTime;
         mQueue->push(buffer);
-        DEBUG("queue size:%d",mQueue->getCnt());
+            DEBUG(mLogCategory,"queue size:%d",mQueue->getCnt());
     } else {
         mDisplay->displayFrameBuffer(buffer, displayTime);
     }
-    return 0;
+    return NO_ERROR;
 }
 
 void WaylandPlugin::queueFlushCallback(void *userdata,void *data)
@@ -143,41 +146,41 @@
     RenderBuffer *entity;
     mQueue->flushAndCallback(this, WaylandPlugin::queueFlushCallback);
     mDisplay->flushBuffers();
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandPlugin::pause()
 {
     mPaused = true;
-    return 0;
+    return NO_ERROR;
 }
 int WaylandPlugin::resume()
 {
     mPaused = false;
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandPlugin::closeDisplay()
 {
     RenderBuffer *entity;
-    std::lock_guard<std::mutex> lck(mRenderLock);
+    Tls::Mutex::Autolock _l(mRenderLock);
     mDisplay->closeDisplay();
     while (mQueue->pop((void **)&entity) == Q_OK)
     {
         handleBufferRelease(entity);
     }
 
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandPlugin::closeWindow()
 {
-    std::lock_guard<std::mutex> lck(mRenderLock);
+    Tls::Mutex::Autolock _l(mRenderLock);
     if (isRunning()) {
-        DEBUG("stop frame post thread");
+        DEBUG(mLogCategory,"stop frame post thread");
         requestExitAndWait();
     }
-    return 0;
+    return NO_ERROR;
 }
 
 
@@ -186,10 +189,10 @@
     switch (key) {
         case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
             *(int *)(value) = mDisplay->getDisplayOutput();
-            TRACE("get select display output:%d",*(int *)value);
+            TRACE(mLogCategory,"get select display output:%d",*(int *)value);
         } break;
     }
-    return 0;
+    return NO_ERROR;
 }
 
 int WaylandPlugin::setValue(PluginKey key, void *value)
@@ -209,12 +212,12 @@
         } break;
         case PLUGIN_KEY_VIDEO_FORMAT: {
             int videoFormat = *(int *)(value);
-            DEBUG("Set video format :%d",videoFormat);
+            DEBUG(mLogCategory,"Set video format :%d",videoFormat);
             mDisplay->setVideoBufferFormat((RenderVideoFormat)videoFormat);
         } break;
         case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
             int outputIndex = *(int *)(value);
-            DEBUG("Set select display output :%d",outputIndex);
+            DEBUG(mLogCategory,"Set select display output :%d",outputIndex);
             mDisplay->setDisplayOutput(outputIndex);
         } break;
         case PLUGIN_KEY_VIDEO_PIP: {
@@ -224,7 +227,7 @@
         } break;
         case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
             bool mImmediatelyOutput = (*(int *)(value)) > 0? true: false;
-            DEBUG("Set immediately output:%d",mImmediatelyOutput);
+            DEBUG(mLogCategory, "Set immediately output:%d",mImmediatelyOutput);
         } break;
     }
     return 0;
@@ -290,7 +293,7 @@
 
         //drop last expired frame,got a new expired frame
         if (expiredFrameEntity) {
-            WARNING("drop,now:%lld,display:%lld(pts:%lld ms),n-d:%lld ms",
+            WARNING(mLogCategory,"drop,now:%lld,display:%lld(pts:%lld ms),n-d:%lld ms",
                 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
                 (nowMonotime - expiredFrameEntity->time)/1000);
             handleFrameDropped(expiredFrameEntity);
@@ -308,7 +311,7 @@
     }
 
     if (mDisplay) {
-        TRACE("post,now:%lld,display:%lld(pts:%lld ms),n-d::%lld ms",
+        TRACE(mLogCategory,"post,now:%lld,display:%lld(pts:%lld ms),n-d::%lld ms",
             nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
             (nowMonotime - expiredFrameEntity->time)/1000);
         mDisplay->displayFrameBuffer(expiredFrameEntity, expiredFrameEntity->time);
@@ -321,18 +324,23 @@
 
 void *makePluginInstance(int id)
 {
+    int category =Logger_init(id);
     char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
     if (env) {
         int level = atoi(env);
         Logger_set_level(level);
-        INFO("VIDEO_RENDER_LOG_LEVEL=%d",level);
+        INFO(category,"VIDEO_RENDER_LOG_LEVEL=%d",level);
     }
-    WaylandPlugin *pluginInstance = new WaylandPlugin();
+    WaylandPlugin *pluginInstance = new WaylandPlugin(category);
     return static_cast<void *>(pluginInstance);
 }
 
 void destroyPluginInstance(void * plugin)
 {
+    int category;
+
     WaylandPlugin *pluginInstance = static_cast<WaylandPlugin *>(plugin);
+    category = pluginInstance->getLogCategory();
     delete pluginInstance;
+    Logger_exit(category);
 }
\ No newline at end of file
diff --git a/weston/wayland_plugin.h b/weston/wayland_plugin.h
index adb9ae7..2371145 100644
--- a/weston/wayland_plugin.h
+++ b/weston/wayland_plugin.h
@@ -15,7 +15,6 @@
  */
 #ifndef __WAYLAND_PLUGIN_H__
 #define __WAYLAND_PLUGIN_H__
-#include <mutex>
 #include "render_plugin.h"
 #include "wayland_display.h"
 #include "Thread.h"
@@ -24,7 +23,7 @@
 class WaylandPlugin : public RenderPlugin, public Tls::Thread
 {
   public:
-    WaylandPlugin();
+    WaylandPlugin(int logCatgory);
     virtual ~WaylandPlugin();
     virtual void init();
     virtual void release();
@@ -40,6 +39,9 @@
     virtual int closeWindow();
     virtual int getValue(PluginKey key, void *value);
     virtual int setValue(PluginKey key, void *value);
+    int getLogCategory() {
+        return mLogCategory;
+    };
     //thread func
     void readyToRun();
     virtual bool threadLoop();
@@ -54,7 +56,9 @@
     PluginCallback *mCallback;
     WaylandDisplay *mDisplay;
 
-    mutable std::mutex mRenderLock;
+    int mLogCategory;
+
+    mutable Tls::Mutex mRenderLock;
     int mFrameWidth;
     int mFrameHeight;
 
diff --git a/weston/wayland_shm.cpp b/weston/wayland_shm.cpp
index 5af5c2d..bf221ec 100644
--- a/weston/wayland_shm.cpp
+++ b/weston/wayland_shm.cpp
@@ -25,11 +25,12 @@
 #include "wayland_shm.h"
 #include "Logger.h"
 #include "wayland_display.h"
+#include "ErrorCode.h"
 #include "Utils.h"
 
 #define TAG "rlib:wayland_shm"
 
-WaylandShmBuffer::WaylandShmBuffer(WaylandDisplay *display)
+WaylandShmBuffer::WaylandShmBuffer(WaylandDisplay *display, int logCategory)
 {
     mDisplay = display;
     mWlBuffer = NULL;
@@ -39,6 +40,7 @@
     mWidth = 0;
     mHeight = 0;
     mFormat = VIDEO_FORMAT_UNKNOWN;
+    mLogCategory = logCategory;
 }
 
 WaylandShmBuffer::~WaylandShmBuffer()
@@ -87,33 +89,33 @@
     }
 
     if (mStride <= 0 || mSize <= 0) {
-        WARNING("Unsupport format");
+        WARNING(mLogCategory,"Unsupport format");
         goto tag_err;
     }
 
     fd = createAnonymousFile(mSize);
     if (fd < 0) {
-        ERROR("create anonymous file fail");
+        ERROR(mLogCategory,"create anonymous file fail");
         return NULL;
     }
 
     mData = mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (mData == MAP_FAILED) {
-        ERROR("mmap failed: %s",strerror(errno));
+        ERROR(mLogCategory,"mmap failed: %s",strerror(errno));
         goto tag_err;
     }
     //init buffer data,set alpha transparent
     memset(mData, 0x00, mSize);
 
     if (mDisplay->getShm() == NULL) {
-        ERROR("Shm is null");
+        ERROR(mLogCategory,"Shm is null");
         goto tag_err;
     }
 
     uint32_t shmFormat;
     ret = mDisplay->toShmBufferFormat(format, &shmFormat);
-    if (ret != 0) {
-        ERROR("video format to shm format fail");
+    if (ret != NO_ERROR) {
+        ERROR(mLogCategory,"video format to shm format fail");
         goto tag_err;
     }
 
@@ -145,7 +147,7 @@
 
     path = getenv("XDG_RUNTIME_DIR");
     if (!path) {
-        WARNING("not set XDG_RUNTIME_DIR env");
+        WARNING(mLogCategory,"not set XDG_RUNTIME_DIR env");
         goto tag_err;
     }
 
@@ -154,7 +156,7 @@
 
     fd = mkstemp(filename);
     if (fd < 0) {
-        ERROR("make anonymous file fail");
+        ERROR(mLogCategory,"make anonymous file fail");
         goto tag_err;
     }
 
diff --git a/weston/wayland_shm.h b/weston/wayland_shm.h
index a78da4e..1504fe6 100644
--- a/weston/wayland_shm.h
+++ b/weston/wayland_shm.h
@@ -24,7 +24,7 @@
 class WaylandShmBuffer : public WaylandWLWrap
 {
   public:
-    WaylandShmBuffer(WaylandDisplay *display);
+    WaylandShmBuffer(WaylandDisplay *display, int logCategory);
     virtual ~WaylandShmBuffer();
     virtual struct wl_buffer *getWlBuffer() {
         return mWlBuffer;
@@ -55,6 +55,8 @@
     int mWidth;
     int mHeight;
     RenderVideoFormat mFormat;
+
+    int mLogCategory;
 };
 
 #endif /*__WAYLAND_SHM_H__*/
\ No newline at end of file
diff --git a/weston/wayland_videoformat.cpp b/weston/wayland_videoformat.cpp
index a18addc..31be7d6 100644
--- a/weston/wayland_videoformat.cpp
+++ b/weston/wayland_videoformat.cpp
@@ -76,7 +76,7 @@
             return wl_formats[i].dma_format;
     }
 
-    TRACE("wl dmabuf format not found");
+    TRACE(NO_CAT,"wl dmabuf format not found");
     return 0;
 }