[SCM] libyami-utils/upstream: New upstream version 1.2.0

sramacher at users.alioth.debian.org sramacher at users.alioth.debian.org
Mon Aug 28 18:54:04 UTC 2017


The following commit has been merged in the upstream branch:
commit 22541275482784cba5e744ec36ae7869631d0048
Author: Sebastian Ramacher <sramacher at debian.org>
Date:   Mon Aug 28 20:25:53 2017 +0200

    New upstream version 1.2.0

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1be0a9d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,96 @@
+dist: xenial
+sudo: required
+
+language: c++
+compiler: g++
+os: linux
+
+before_install:
+  - test "${TRAVIS_BRANCH}" != 'coverity_scan' -o "${TRAVIS_JOB_NUMBER##*.}" = '1' || exit 0
+  - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
+  - pip install --user cpp-coveralls
+  - sudo apt-get -qq update
+  - sudo apt-get install -y build-essential
+  - sudo apt-get install -y autoconf
+  - sudo apt-get install -y automake
+  - sudo apt-get install -y libtool
+  - sudo apt-get install -y m4 
+  - sudo apt-get install -y lcov
+  - sudo apt-get install -y perl
+  - sudo apt-get install -y pkg-config
+  - sudo apt-get install -y libdrm-dev
+  - sudo apt-get install -y autoconf
+  - sudo apt-get install -y libegl1-mesa-dev
+  - sudo apt-get install -y libgl1-mesa-dev
+  - sudo apt-get install -y libwayland-dev
+  - sudo apt-get install -y libx11-dev
+  - sudo apt-get install -y libxext-dev
+  - sudo apt-get install -y libxfixes-dev
+  - sudo apt-get install -y intel-gpu-tools
+  - sudo apt-get install -y cifs-utils
+  - sudo apt-get install -y yasm
+  - sudo apt-get install -y libghc-x11-dev
+  - sudo apt-get install -y libxmuu-dev 
+  - sudo apt-get install -y libxfixes-dev
+  - sudo apt-get install -y libxcb-glx0-dev 
+  - sudo apt-get install -y libgegl-dev
+  - sudo apt-get install -y libcogl-gles2-dev
+  - sudo apt-get install -y libv4l-0
+  - sudo apt-get install -y libv4l-dev
+
+  
+  
+  - git clone https://github.com/01org/libva.git
+  - (cd libva && ./autogen.sh && ./configure  && sudo make install)
+  - git clone https://github.com/01org/libyami.git
+  - (cd libyami && ./autogen.sh  && make -j8 && sudo make install)
+
+
+ 
+install:
+  - git clone https://github.com/01org/libyami-utils.git
+  - (cd libyami-utils && ./autogen.sh  && make -j8 && sudo make install)
+
+addons:
+  coverity_scan:
+    project:
+      name: "01org/libyami-utils"
+      description: "Build submitted via Travis CI"
+    notification_email: 531669721 at sjtu.edu.cn
+    build_command_prepend: "./autogen.sh; ./configure --prefix=/opt/yami"
+    build_command:   "make -j8"
+    branch_pattern: coverity_scan
+
+script:
+  - if [[ "${COVERITY_SCAN_BRANCH}" == 1 ]];
+      then
+        echo "Don't build on coverty_scan branch.";
+        exit 0;
+    fi
+  - ./autogen.sh --prefix=/opt/yami
+  - make -j8 ; sudo make install
+
+#after_success:
+ #       - coveralls --exclude lib --exclude tests --gcov-options '\-lp'
+
+notifications:
+# Emails are sent to the committer's git-configured email address by default,
+# but only if they have access to the repository.  To enable Travis on your
+# public project, just go to travis-ci.org and flip the switch on for
+# your project.  To configure your git email address, use:
+#     git config --global user.email me at example.com
+  email:
+    on_success: always
+    on_failure: always
+
+# Slack notifications
+#
+
+
+# IRC notifications disabled by default.
+# Uncomment next 5 lines to send notifications to chat.freenode.net#caffe
+#   irc:
+#     channels:
+#       - "chat.freenode.net#intel-media"
+#     template:
+#       - "%{repository}/%{branch} (%{commit} - %{author}): %{message}"
diff --git a/README.md b/README.md
index 540a86d..5811656 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,14 @@
-#libyami-utils
+[![Build Status](https://travis-ci.org/01org/libyami-utils.svg?branch=master)](https://travis-ci.org/01org/libyami-utils)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/11605/badge.svg)](https://scan.coverity.com/projects/01org-libyami-utils)
+
+
+libyami-utils
+-------------
 Applications and Scripts for libyami.
+
 You can find libyami in https://github.com/01org/libyami
+  * Copyright (C) 2011-2016 Intel Corporation
 
-* Copyright (C) 2011-2016 Intel Corporation
 
 License
 -------
@@ -14,15 +20,14 @@ Overview
 --------
 libyami-utils consists of directories
 
-    * 'tests': sample decoder/encoder/vpp applications
-    * 'testscripts': conformance test scripts
-    * 'examples': simpleplayer and video wall demo
+  * `tests`: sample decoder/encoder/vpp applications
+  * `testscripts`: conformance test scripts
+  * `examples`: simpleplayer and video wall demo
 
 
 Requirements
 ------------
 Hardware requirements
-
   * Intel (core) Sandybridge, Ivybridge, Haswell, Broadwell, Skylake, Kabylake
   * Intel (atom) Baytrail, Braswell, Apollolake
 
diff --git a/configure.ac b/configure.ac
index 8d51d78..dc4a125 100755
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@ m4_define([libyamiutils_lt_version], [libyamiutils_lt_current.libyamiutils_lt_re
 
 # package version (lib name suffix), usually sync with git tag
 m4_define([libyamiutils_major_version], 1)
-m4_define([libyamiutils_minor_version], 1)
+m4_define([libyamiutils_minor_version], 2)
 # even number of micro_version means a release after full validation cycle
 m4_define([libyamiutils_micro_version], 0)
 m4_define([libyamiutils_version],
@@ -71,10 +71,6 @@ if test "$enable_debug" = "yes"; then
         [Defined to 1 if --enable-debug="yes"])
 fi
 
-GTEST_LIB_CHECK([1.7.0], [:], [:])
-AM_CONDITIONAL([ENABLE_UNITTESTS],
-[test "x$HAVE_GTEST" = "xyes"])
-
 AC_ARG_ENABLE(dmabuf,
     [AC_HELP_STRING([--enable-dmabuf],
         [support dma_buf buffer sharing @<:@default=no@:>@])],
@@ -260,7 +256,7 @@ if test "$enable_md5" = "yes"; then
         [])
 fi
 
-PKG_CHECK_MODULES([LIBYAMI], [libyami >= 0.3.6])
+PKG_CHECK_MODULES([LIBYAMI], [libyami >= 0.4.2])
 
 AM_CONDITIONAL(ENABLE_MD5, test "x$enable_md5" = "xyes")
 
@@ -287,7 +283,6 @@ AC_MSG_RESULT([
     libyami - libyamiutils_version
 
     Build utils ...................... : $APPS
-    Build gtest unit tests ........... : $HAVE_GTEST
     Enable debug ..................... : $enable_debug
     Installation prefix .............. : $prefix
 ])
diff --git a/m4/gtest.m4 b/m4/gtest.m4
deleted file mode 100644
index 03dca84..0000000
--- a/m4/gtest.m4
+++ /dev/null
@@ -1,105 +0,0 @@
-dnl Copyright 2008, Google Inc.
-dnl All rights reserved.
-dnl
-dnl Redistribution and use in source and binary forms, with or without
-dnl modification, are permitted provided that the following conditions are
-dnl met:
-dnl
-dnl     * Redistributions of source code must retain the above copyright
-dnl notice, this list of conditions and the following disclaimer.
-dnl     * Redistributions in binary form must reproduce the above
-dnl copyright notice, this list of conditions and the following disclaimer
-dnl in the documentation and/or other materials provided with the
-dnl distribution.
-dnl     * Neither the name of Google Inc. nor the names of its
-dnl contributors may be used to endorse or promote products derived from
-dnl this software without specific prior written permission.
-dnl
-dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-dnl
-dnl
-dnl
-dnl GTEST_LIB_CHECK([minimum version [,
-dnl                  action if found [,action if not found]]])
-dnl
-dnl Check for the presence of the Google Test library, optionally at a minimum
-dnl version, and indicate a viable version with the HAVE_GTEST flag. It defines
-dnl standard variables for substitution including GTEST_CPPFLAGS,
-dnl GTEST_CXXFLAGS, GTEST_LDFLAGS, and GTEST_LIBS. It also defines
-dnl GTEST_VERSION as the version of Google Test found. Finally, it provides
-dnl optional custom action slots in the event GTEST is found or not.
-AC_DEFUN([GTEST_LIB_CHECK],
-[
-dnl Provide a flag to enable or disable Google Test usage.
-AC_ARG_ENABLE([gtest],
-  [AS_HELP_STRING([--enable-gtest],
-                  [Enable tests using the Google C++ Testing Framework.
-                  @<:@default=no@:>@])],
-  [],
-  [enable_gtest=no])
-AC_ARG_VAR([GTEST_CONFIG],
-           [The exact path of Google Test's 'gtest-config' script.])
-AC_ARG_VAR([GTEST_CPPFLAGS],
-           [C-like preprocessor flags for Google Test.])
-AC_ARG_VAR([GTEST_CXXFLAGS],
-           [C++ compile flags for Google Test.])
-AC_ARG_VAR([GTEST_LDFLAGS],
-           [Linker path and option flags for Google Test.])
-AC_ARG_VAR([GTEST_LIBS],
-           [Library linking flags for Google Test.])
-AC_ARG_VAR([GTEST_VERSION],
-           [The version of Google Test available.])
-HAVE_GTEST="no"
-AS_IF([test "x${enable_gtest}" != "xno"],
-  [AC_MSG_CHECKING([for 'gtest-config'])
-   AS_IF([test "x${enable_gtest}" != "xyes"],
-     [AS_IF([test -x "${enable_gtest}/scripts/gtest-config"],
-        [GTEST_CONFIG="${enable_gtest}/scripts/gtest-config"],
-        [GTEST_CONFIG="${enable_gtest}/bin/gtest-config"])
-      AS_IF([test -x "${GTEST_CONFIG}"], [],
-        [AC_MSG_RESULT([no])
-         AC_MSG_ERROR([dnl
-Unable to locate either a built or installed Google Test.
-The specific location '${enable_gtest}' was provided for a built or installed
-Google Test, but no 'gtest-config' script could be found at this location.])
-         ])],
-     [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])])
-   AS_IF([test -x "${GTEST_CONFIG}"],
-     [AC_MSG_RESULT([${GTEST_CONFIG}])
-      m4_ifval([$1],
-        [_gtest_min_version="--min-version=$1"
-         AC_MSG_CHECKING([for Google Test at least version >= $1])],
-        [_gtest_min_version="--min-version=0"
-         AC_MSG_CHECKING([for Google Test])])
-      AS_IF([${GTEST_CONFIG} ${_gtest_min_version}],
-        [AC_MSG_RESULT([yes])
-         HAVE_GTEST='yes'],
-        [AC_MSG_RESULT([no])])],
-     [AC_MSG_RESULT([no])])
-   AS_IF([test "x${HAVE_GTEST}" = "xyes"],
-     [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags`
-      GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags`
-      GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags`
-      GTEST_LIBS=`${GTEST_CONFIG} --libs`
-      GTEST_VERSION=`${GTEST_CONFIG} --version`
-      AC_DEFINE([HAVE_GTEST],[1],[Defined when Google Test is available.])],
-     [AS_IF([test "x${enable_gtest}" = "xyes"],
-        [AC_MSG_ERROR([dnl
-Google Test was enabled, but no viable version could be found.])
-         ])])])
-AC_SUBST([HAVE_GTEST])
-AM_CONDITIONAL([HAVE_GTEST],[test "x$HAVE_GTEST" = "xyes"])
-AS_IF([test "x$HAVE_GTEST" = "xyes"],
-  [m4_ifval([$2], [$2])],
-  [m4_ifval([$3], [$3])])
-])
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4ff2a09..8705660 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -106,7 +106,7 @@ yamiencode_SOURCES  = encode.cpp encodeinput.cpp encodeInputCamera.cpp encodeInp
 
 v4l2decode_LDADD   = $(V4L2_DECODE_LIBS)
 v4l2decode_LDFLAGS = $(V4L2_DECODE_LDFLAGS)
-v4l2decode_SOURCES = v4l2decode.cpp decodehelp.cpp $(DECODE_INPUT_SOURCES)
+v4l2decode_SOURCES = v4l2decode.cpp V4L2Renderer.cpp V4L2Device.cpp decodehelp.cpp $(DECODE_INPUT_SOURCES)
 
 if ENABLE_TESTS_GLES
 v4l2decode_SOURCES += ./egl/gles2_help.c
diff --git a/tests/V4L2Device.cpp b/tests/V4L2Device.cpp
new file mode 100644
index 0000000..5cd7dbe
--- /dev/null
+++ b/tests/V4L2Device.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "V4L2Device.h"
+
+#include "common/log.h"
+#include "common/common_def.h"
+#include <string.h>
+#include <inttypes.h>
+
+#ifdef __ENABLE_V4L2_OPS__
+
+#include "v4l2codec_device_ops.h"
+#include <dlfcn.h>
+#include <fcntl.h>
+
+#define SIMULATE_V4L2_OP(OP, ...)                      \
+    do {                                               \
+        if (!m_ops.m##OP##Func)                        \
+            return -1;                                 \
+        return m_ops.m##OP##Func(m_fd, ##__VA_ARGS__); \
+    } while (0)
+
+struct TypeEntry {
+    VideoDataMemoryType type;
+    const char* str;
+};
+
+const static TypeEntry g_entrys[] = {
+    { VIDEO_DATA_MEMORY_TYPE_DRM_NAME, "drm-name" },
+    { VIDEO_DATA_MEMORY_TYPE_DMA_BUF, "dma-buf" },
+    { VIDEO_DATA_MEMORY_TYPE_ANDROID_BUFFER_HANDLE, "android-buffer-handle" },
+    { VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF, "external-dma-buf" }
+
+};
+
+const char* frameTypeToString(VideoDataMemoryType type)
+{
+    for (size_t i = 0; i < N_ELEMENTS(g_entrys); i++) {
+        if (type == g_entrys[i].type)
+            return g_entrys[i].str;
+    }
+    ASSERT(0 && "not support yet");
+    return NULL;
+}
+
+class V4L2DeviceOps : public V4L2Device {
+public:
+    bool open(const char* name, int32_t flags)
+    {
+        if (!m_ops.mOpenFunc)
+            return false;
+        m_fd = m_ops.mOpenFunc(name, flags);
+        return m_fd != -1;
+    }
+
+    int32_t close()
+    {
+        SIMULATE_V4L2_OP(Close);
+    }
+
+    int32_t ioctl(int32_t cmd, void* arg)
+    {
+        SIMULATE_V4L2_OP(Ioctl, cmd, arg);
+    }
+
+    int32_t poll(bool pollDevice, bool* eventPending)
+    {
+        SIMULATE_V4L2_OP(Poll, pollDevice, eventPending);
+    }
+
+    int32_t setDevicePollInterrupt()
+    {
+        SIMULATE_V4L2_OP(SetDevicePollInterrupt);
+    }
+
+    int32_t clearDevicePollInterrupt()
+    {
+        SIMULATE_V4L2_OP(ClearDevicePollInterrupt);
+    }
+
+    void* mmap(void* addr, size_t length, int32_t prot,
+        int32_t flags, unsigned int offset)
+    {
+        if (!m_ops.mMmapFunc)
+            return NULL;
+
+        return m_ops.mMmapFunc(addr, length, prot, flags, m_fd, offset);
+    }
+
+    int32_t munmap(void* addr, size_t length)
+    {
+        if (!m_ops.mMunmapFunc)
+            return -1;
+
+        return m_ops.mMunmapFunc(addr, length);
+    }
+
+    int32_t setFrameMemoryType(VideoDataMemoryType type)
+    {
+        const char* str = frameTypeToString(type);
+        if (str)
+            SIMULATE_V4L2_OP(SetParameter, "frame-memory-type", str);
+        return -1;
+    }
+
+#if __ENABLE_TESTS_GLES__
+    int32_t useEglImage(/*EGLDisplay*/ void* eglDisplay, /*EGLContext*/ void* eglContext,
+        uint32_t bufferIndex, void* eglImage)
+    {
+        SIMULATE_V4L2_OP(UseEglImage, eglDisplay, eglContext, bufferIndex, eglImage);
+    }
+
+    int32_t setDrmFd(int drmFd)
+    {
+        ASSERT(0 && "not supported yet");
+        return -1;
+    }
+#endif
+
+#if __ENABLE_WAYLAND__
+    int32_t setWaylandDisplay(struct wl_display* wlDisplay)
+    {
+        char displayStr[32];
+        sprintf(displayStr, "%" PRIu64 "", (uint64_t)(wlDisplay));
+        SIMULATE_V4L2_OP(SetParameter, "wayland-display", displayStr);
+    }
+#endif
+
+#if __ENABLE_X11__
+    /// it should be called before driver initialization (immediate after _Open()).
+    int32_t setXDisplay(Display* x11Display)
+    {
+        char displayStr[32];
+        sprintf(displayStr, "%" PRIu64 "", (uint64_t)x11Display);
+        SIMULATE_V4L2_OP(SetParameter, "x11-display", displayStr);
+    }
+#endif
+
+    V4L2DeviceOps()
+        : m_handle(NULL)
+    {
+        memset(&m_ops, 0, sizeof(m_ops));
+    }
+
+    ~V4L2DeviceOps()
+    {
+        if (m_handle)
+            dlclose(m_handle);
+    }
+
+protected:
+    bool init()
+    {
+        const char* libName = "libyami_v4l2.so";
+        m_handle = dlopen(libName, RTLD_NOW | RTLD_GLOBAL);
+        if (!m_handle) {
+            ERROR("dlopen failed for %s", libName);
+            return false;
+        }
+
+        V4l2codecOperationInitFunc initFunc = NULL;
+        initFunc = (V4l2codecOperationInitFunc)dlsym(RTLD_DEFAULT, "v4l2codecOperationInit");
+
+        if (!initFunc) {
+            ERROR("fail to dlsym v4l2codecOperationInit\n");
+            return false;
+        }
+
+        INIT_V4L2CODEC_OPS_SIZE_VERSION(&m_ops);
+        if (!initFunc(&m_ops)) {
+            ERROR("fail to init v4l2 device operation func pointers\n");
+            return false;
+        }
+
+        int isVersionMatch = 0;
+        IS_V4L2CODEC_OPS_VERSION_MATCH(m_ops.mVersion, isVersionMatch);
+        if (!isVersionMatch) {
+            ERROR("V4l2CodecOps interface version doesn't match\n");
+            return false;
+        }
+        if (m_ops.mSize != sizeof(V4l2CodecOps)) {
+            ERROR("V4l2CodecOps interface data structure size doesn't match\n");
+            return false;
+        }
+        return true;
+    }
+
+private:
+    void* m_handle;
+    V4l2CodecOps m_ops;
+};
+#undef SIMULATE_V4L2_OP
+
+#else
+
+#include "common/v4l2_wrapper.h"
+
+class V4L2DeviceYami : public V4L2Device {
+public:
+    bool open(const char* name, int32_t flags)
+    {
+        m_fd = YamiV4L2_Open(name, flags);
+        return m_fd != -1;
+    }
+    int32_t close()
+    {
+        return YamiV4L2_Close(m_fd);
+    }
+    int32_t ioctl(int32_t cmd, void* arg)
+    {
+        return YamiV4L2_Ioctl(m_fd, cmd, arg);
+    }
+    int32_t poll(bool pollDevice, bool* eventPending)
+    {
+        return YamiV4L2_Poll(m_fd, pollDevice, eventPending);
+    }
+    int32_t setDevicePollInterrupt()
+    {
+        return YamiV4L2_SetDevicePollInterrupt(m_fd);
+    }
+    int32_t clearDevicePollInterrupt()
+    {
+        return YamiV4L2_ClearDevicePollInterrupt(m_fd);
+    }
+    void* mmap(void* addr, size_t length, int32_t prot,
+        int32_t flags, unsigned int offset)
+    {
+        return YamiV4L2_Mmap(addr, length, prot, flags, m_fd, offset);
+    }
+    int32_t munmap(void* addr, size_t length)
+    {
+        return YamiV4L2_Munmap(addr, length);
+    }
+    int32_t setFrameMemoryType(VideoDataMemoryType type)
+    {
+        return YamiV4L2_FrameMemoryType(m_fd, type);
+    }
+
+#if __ENABLE_TESTS_GLES__
+    int32_t useEglImage(/*EGLDisplay*/ void* eglDisplay, /*EGLContext*/ void* eglContext,
+        uint32_t bufferIndex, void* eglImage)
+    {
+        return YamiV4L2_UseEglImage(m_fd, eglDisplay, eglContext, bufferIndex, eglImage);
+    }
+    int32_t setDrmFd(int drmFd)
+    {
+        return YamiV4L2_SetDrmFd(m_fd, drmFd);
+    }
+#endif
+
+#if __ENABLE_WAYLAND__
+    int32_t setWaylandDisplay(struct wl_display* wlDisplay)
+    {
+        return YamiV4L2_SetWaylandDisplay(m_fd, wlDisplay);
+    }
+#endif
+
+#if __ENABLE_X11__
+    /// it should be called before driver initialization (immediate after _Open()).
+    int32_t setXDisplay(Display* x11Display)
+    {
+        return YamiV4L2_SetXDisplay(m_fd, x11Display);
+    }
+#endif
+
+protected:
+    bool init()
+    {
+        return true;
+    }
+};
+#endif //__ENABLE_V4L2_OPS__
+
+SharedPtr<V4L2Device> V4L2Device::Create()
+{
+    SharedPtr<V4L2Device> device;
+#ifdef __ENABLE_V4L2_OPS__
+    device.reset(new V4L2DeviceOps);
+#else
+    device.reset(new V4L2DeviceYami);
+#endif
+    if (!device->init())
+        device.reset();
+    return device;
+}
diff --git a/tests/V4L2Device.h b/tests/V4L2Device.h
new file mode 100644
index 0000000..f54ac7f
--- /dev/null
+++ b/tests/V4L2Device.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * 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 V4L2Device_h
+#define V4L2Device_h
+
+#include <VideoCommonDefs.h>
+#if __ENABLE_X11__
+#include <X11/Xlib.h>
+#endif
+
+#if __ENABLE_TESTS_GLES__
+#include <EGL/egl.h>
+#endif
+
+class V4L2Device {
+public:
+    static SharedPtr<V4L2Device> Create();
+    virtual bool open(const char* name, int32_t flags) = 0;
+    virtual int32_t close() = 0;
+    virtual int32_t ioctl(int32_t cmd, void* arg) = 0;
+    virtual int32_t poll(bool pollDevice, bool* eventPending) = 0;
+    virtual int32_t setDevicePollInterrupt() = 0;
+    virtual int32_t clearDevicePollInterrupt() = 0;
+    virtual void* mmap(void* addr, size_t length, int32_t prot,
+        int32_t flags, unsigned int offset)
+        = 0;
+    virtual int32_t munmap(void* addr, size_t length) = 0;
+    virtual int32_t setFrameMemoryType(VideoDataMemoryType memory_type) = 0;
+
+#if __ENABLE_TESTS_GLES__
+    virtual int32_t useEglImage(/*EGLDisplay*/ void* eglDisplay, /*EGLContext*/ void* eglContext,
+        uint32_t bufferIndex, void* eglImage)
+        = 0;
+    virtual int32_t setDrmFd(int drmFd) = 0;
+#endif
+
+#if __ENABLE_WAYLAND__
+    virtual int32_t setWaylandDisplay(struct wl_display* wlDisplay) = 0;
+#endif
+
+#if __ENABLE_X11__
+    /// it should be called before driver initialization (immediate after _Open()).
+    virtual int32_t setXDisplay(Display* x11Display) = 0;
+#endif
+protected:
+    virtual bool init() = 0;
+    int m_fd;
+};
+
+#endif
diff --git a/tests/V4L2Renderer.cpp b/tests/V4L2Renderer.cpp
new file mode 100644
index 0000000..3233d0d
--- /dev/null
+++ b/tests/V4L2Renderer.cpp
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "V4L2Device.h"
+#include "common/log.h"
+#include "vaapi/vaapidisplay.h"
+#include "common/VaapiUtils.h"
+
+#include <vector>
+#include <deque>
+#include <algorithm>
+#include <string.h>
+#include <linux/videodev2.h>
+
+#include "V4L2Renderer.h"
+
+const static uint32_t kExtraOutputFrameCount = 2;
+const static uint32_t kOutputPlaneCount = 2;
+const static uint32_t kMaxOutputPlaneCount = 3;
+
+using namespace YamiMediaCodec;
+
+V4L2Renderer::V4L2Renderer(const SharedPtr<V4L2Device>& device, VideoDataMemoryType memoryType)
+    : m_device(device)
+    , m_memoryType(memoryType)
+{
+}
+
+bool V4L2Renderer::renderOneFrame()
+{
+    uint32_t index;
+    bool ret;
+    ret = dequeBuffer(index);
+    if (!ret)
+        return false;
+    ret = render(index);
+    ASSERT(ret && "render failed");
+    ret = queueBuffer(index);
+    ASSERT(ret && "queue buffer failed");
+    return true;
+}
+
+bool V4L2Renderer::queueBuffer(uint32_t index, unsigned long userptr)
+{
+    struct v4l2_buffer buf;
+    struct v4l2_plane planes[kMaxOutputPlaneCount]; // YUV output, in fact, we use NV12 of 2 planes
+    int ioctlRet = -1;
+
+    memset(&buf, 0, sizeof(buf));
+    memset(&planes, 0, sizeof(planes));
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; //it indicates output buffer type
+    buf.memory = V4L2_MEMORY_MMAP;
+    buf.index = index;
+    buf.m.planes = planes;
+    buf.m.userptr = userptr;
+    buf.length = kOutputPlaneCount;
+    ioctlRet = m_device->ioctl(VIDIOC_QBUF, &buf);
+    ASSERT(ioctlRet != -1);
+    return true;
+}
+
+bool V4L2Renderer::dequeBuffer(uint32_t& index)
+{
+    struct v4l2_buffer buf;
+    struct v4l2_plane planes[kMaxOutputPlaneCount]; // YUV output, in fact, we use NV12 of 2 planes
+    int ioctlRet = -1;
+
+    memset(&buf, 0, sizeof(buf));
+    memset(&planes, 0, sizeof(planes));
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; //it indicates output buffer type
+    buf.memory = V4L2_MEMORY_MMAP;
+    buf.m.planes = planes;
+    buf.length = kOutputPlaneCount;
+
+    ioctlRet = m_device->ioctl(VIDIOC_DQBUF, &buf);
+    if (ioctlRet == -1)
+        return false;
+    index = buf.index;
+    return true;
+}
+
+bool V4L2Renderer::getDpbSize(uint32_t& dpbSize)
+{
+    // setup output buffers
+    // Number of output buffers we need.
+    struct v4l2_control ctrl;
+    memset(&ctrl, 0, sizeof(ctrl));
+    ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
+    int32_t ioctlRet = m_device->ioctl(VIDIOC_G_CTRL, &ctrl);
+    ASSERT(ioctlRet != -1);
+    dpbSize = ctrl.value;
+    return true;
+}
+
+bool V4L2Renderer::requestBuffers(uint32_t& count)
+{
+    struct v4l2_requestbuffers reqbufs;
+
+    memset(&reqbufs, 0, sizeof(reqbufs));
+    reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    reqbufs.memory = V4L2_MEMORY_MMAP;
+    reqbufs.count = count;
+    int32_t ioctlRet = m_device->ioctl(VIDIOC_REQBUFS, &reqbufs);
+    ASSERT(ioctlRet != -1);
+    ASSERT(reqbufs.count > 0);
+    count = reqbufs.count;
+    return true;
+}
+
+#ifdef __ENABLE_X11__
+#include <X11/Xlib.h>
+class X11Renderer : public V4L2Renderer {
+public:
+    X11Renderer(const SharedPtr<V4L2Device>& device, VideoDataMemoryType memoryType)
+        : V4L2Renderer(device, memoryType)
+        , m_x11Display(NULL)
+        , m_x11Window(0)
+    {
+    }
+    bool setDisplay()
+    {
+        XInitThreads();
+        m_x11Display = XOpenDisplay(NULL);
+        ASSERT(m_x11Display);
+        DEBUG("x11display: %p", m_x11Display);
+        int32_t ioctlRet = m_device->setXDisplay(m_x11Display);
+        return ioctlRet != -1;
+    }
+    bool queueOutputBuffersAtStart(uint32_t count)
+    {
+        for (uint32_t i = 0; i < count; i++) {
+            if (!queueBuffer(i)) {
+                ASSERT(0);
+            }
+        }
+        return true;
+    }
+
+protected:
+    bool createWindow(uint32_t width, uint32_t height)
+    {
+        if (m_x11Window)
+            return true;
+        m_x11Window = XCreateSimpleWindow(m_x11Display, DefaultRootWindow(m_x11Display), 0, 0, width, height, 0, 0, WhitePixel(m_x11Display, 0));
+        if (m_x11Window <= 0)
+            return false;
+        XMapWindow(m_x11Display, m_x11Window);
+        return true;
+    }
+    Display* m_x11Display;
+    Window m_x11Window;
+};
+
+#include <va/va.h>
+#include <va/va_drmcommon.h>
+class ExternalDmaBufRenderer : public X11Renderer {
+    const static uint32_t kFrontSize = 3;
+
+public:
+    ExternalDmaBufRenderer(const SharedPtr<V4L2Device>& device, VideoDataMemoryType memoryType)
+        : X11Renderer(device, memoryType)
+        , m_width(0)
+        , m_height(0)
+    {
+    }
+    bool setDisplay()
+    {
+        XInitThreads();
+        m_x11Display = XOpenDisplay(NULL);
+        ASSERT(m_x11Display);
+        DEBUG("x11display: %p", m_x11Display);
+
+        NativeDisplay native;
+        memset(&native, 0, sizeof(native));
+        native.handle = (intptr_t)m_x11Display;
+        native.type = NATIVE_DISPLAY_X11;
+        m_display = VaapiDisplay::create(native);
+        ASSERT(bool(m_display));
+        return true;
+    }
+
+    bool setupOutputBuffers(uint32_t width, uint32_t height)
+    {
+        if (!createWindow(width, height)) {
+            ERROR("Create window failed");
+            return false;
+        }
+        uint32_t dpbSize;
+        if (!getDpbSize(dpbSize)) {
+            ERROR("get dpb size failed");
+            return false;
+        }
+        uint32_t count = dpbSize + kExtraOutputFrameCount + kFrontSize;
+        if (!requestBuffers(count)) {
+            ERROR("requestBuffers failed");
+            return false;
+        }
+        m_width = width;
+        m_height = height;
+        return setupOutputBuffers(width, height, count) && queueOutputBuffersAtStart(count);
+    }
+
+    bool queueOutputBuffersAtStart(uint32_t count)
+    {
+        for (uint32_t i = 0; i < count; i++) {
+            if (!queueBuffer(i, (unsigned long)m_dmabuf[i])) {
+                ASSERT(0);
+            }
+            releaseBufferHandle(m_images[i]);
+        }
+        for (uint32_t i = 0; i < kFrontSize; i++) {
+            uint32_t index;
+            if (!dequeBuffer(index)) {
+                ASSERT(0);
+            }
+            m_front.push_back(index);
+        }
+        return true;
+    }
+
+    bool queueOutputBuffers()
+    {
+        for (size_t i = 0; i < m_dmabuf.size(); i++) {
+            if (std::find(m_front.begin(), m_front.end(), i) == m_front.end()) {
+                if (!queueBuffer(i)) {
+                    ASSERT(0);
+                }
+            }
+        }
+        return true;
+    }
+    virtual ~ExternalDmaBufRenderer()
+    {
+        if (m_surfaces.size()) {
+            vaDestroySurfaces(m_display->getID(), &m_surfaces[0], m_surfaces.size());
+        }
+    }
+
+private:
+    bool acquireBufferHandle(uintptr_t& handle, VAImage& image, VASurfaceID surface)
+    {
+        if (!checkVaapiStatus(vaDeriveImage(m_display->getID(), surface, &image), "DeriveImage"))
+            return false;
+        VABufferInfo bufferInfo;
+        bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+        if (!checkVaapiStatus(vaAcquireBufferHandle(m_display->getID(), image.buf, &bufferInfo), "AcquireBufferHandle")) {
+            checkVaapiStatus(vaDestroyImage(m_display->getID(), image.image_id), "vaDestroyImage");
+            return false;
+        }
+        handle = bufferInfo.handle;
+        return true;
+    }
+    bool releaseBufferHandle(VAImage& image)
+    {
+        checkVaapiStatus(vaReleaseBufferHandle(m_display->getID(), image.buf), "ReleaseBufferHandle");
+        checkVaapiStatus(vaDestroyImage(m_display->getID(), image.image_id), "vaDestroyImage");
+        return true;
+    }
+    bool setSurfaceInfo(VASurfaceID surface)
+    {
+        VAImage image;
+        if (!checkVaapiStatus(vaDeriveImage(m_display->getID(), surface, &image), "DeriveImage"))
+            return false;
+        struct v4l2_create_buffers createBuffers;
+        memset(&createBuffers, 0, sizeof(createBuffers));
+        v4l2_pix_format_mplane& format = createBuffers.format.fmt.pix_mp;
+        format.pixelformat = image.format.fourcc;
+        format.width = image.width;
+        format.height = image.height;
+        format.num_planes = image.num_planes;
+        for (uint32_t i = 0; i < format.num_planes; i++) {
+            format.plane_fmt[i].bytesperline = image.pitches[i];
+            //not really right, but we use sizeimage to deliver offset
+            format.plane_fmt[i].sizeimage = image.offsets[i];
+        }
+        int32_t ioctlRet = m_device->ioctl(VIDIOC_CREATE_BUFS, &createBuffers);
+        checkVaapiStatus(vaDestroyImage(m_display->getID(), image.image_id), "vaDestroyImage");
+        return ioctlRet != -1;
+    }
+    bool setupOutputBuffers(uint32_t width, uint32_t height, uint32_t count)
+    {
+        m_surfaces.resize(count);
+
+        VASurfaceAttrib attrib;
+        uint32_t rtFormat = VA_RT_FORMAT_YUV420;
+        int pixelFormat = VA_FOURCC_NV12;
+        attrib.type = VASurfaceAttribPixelFormat;
+        attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
+        attrib.value.type = VAGenericValueTypeInteger;
+        attrib.value.value.i = pixelFormat;
+        VAStatus status;
+        status = vaCreateSurfaces(m_display->getID(), rtFormat,
+            width, height, &m_surfaces[0], count, &attrib, 1);
+        ASSERT(status == VA_STATUS_SUCCESS);
+        ASSERT(setSurfaceInfo(m_surfaces[0]));
+        m_dmabuf.resize(count);
+        m_images.resize(count);
+        for (uint32_t i = 0; i < count; i++) {
+            if (!acquireBufferHandle(m_dmabuf[i], m_images[i], m_surfaces[i]))
+                ASSERT(0);
+        }
+        return true;
+    }
+    void addAndPopFront(uint32_t& index)
+    {
+        m_front.push_back(index);
+        index = m_front.front();
+        m_front.pop_front();
+    }
+    bool render(uint32_t& index)
+    {
+        ASSERT(index < m_surfaces.size());
+        VASurfaceID s = m_surfaces[index];
+        VAStatus status = vaPutSurface(m_display->getID(), s,
+            m_x11Window, 0, 0, m_width, m_height,
+            0, 0, m_width, m_height,
+            NULL, 0, 0);
+        bool ret = checkVaapiStatus(status, "vaPutSurface");
+
+        addAndPopFront(index);
+        return ret;
+    }
+    DisplayPtr m_display;
+    std::vector<VASurfaceID> m_surfaces;
+    std::vector<uintptr_t> m_dmabuf;
+    std::vector<VAImage> m_images;
+    std::deque<uint32_t> m_front;
+    uint32_t m_width;
+    uint32_t m_height;
+};
+
+#ifdef __ENABLE_TESTS_GLES__ //our egl application need x11 for output
+
+#include "./egl/gles2_help.h"
+
+class EglRenderer : public X11Renderer {
+public:
+    EglRenderer(const SharedPtr<V4L2Device>& device, VideoDataMemoryType memoryType)
+        : X11Renderer(device, memoryType)
+        , m_eglContext(NULL)
+    {
+    }
+    bool setupOutputBuffers(uint32_t width, uint32_t height)
+    {
+        if (!createWindow(width, height)) {
+            ERROR("Create window failed");
+            return false;
+        }
+        uint32_t dpbSize;
+        if (!getDpbSize(dpbSize)) {
+            ERROR("get dpb size failed");
+            return false;
+        }
+        uint32_t count = dpbSize + kExtraOutputFrameCount;
+        if (!requestBuffers(count)) {
+            ERROR("requestBuffers failed");
+            return false;
+        }
+        return setupOutputBuffers(count) && queueOutputBuffersAtStart(count);
+    }
+    bool render(uint32_t& idx)
+    {
+        const uint32_t index = idx;
+        ASSERT(m_eglContext && m_textureIds.size());
+        ASSERT(index >= 0 && index < m_textureIds.size());
+        DEBUG("textureIds[%d] = 0x%x", index, m_textureIds[index]);
+        GLenum target = GL_TEXTURE_2D;
+        if (isDmaBuf())
+            target = GL_TEXTURE_EXTERNAL_OES;
+        int ret = drawTextures(m_eglContext, target, &m_textureIds[index], 1);
+
+        return ret == 0;
+    }
+    virtual ~EglRenderer()
+    {
+        if (m_textureIds.size())
+            glDeleteTextures(m_textureIds.size(), &m_textureIds[0]);
+        ASSERT(glGetError() == GL_NO_ERROR);
+        for (size_t i = 0; i < m_eglImages.size(); i++) {
+            destroyImage(m_eglContext->eglContext.display, m_eglImages[i]);
+        }
+        /*
+        there is still randomly fail in mesa; no good idea for it. seems mesa bug
+        0  0x00007ffff079c343 in _mesa_symbol_table_dtor () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
+        1  0x00007ffff073c55d in glsl_symbol_table::~glsl_symbol_table() () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
+        2  0x00007ffff072a4d5 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
+        3  0x00007ffff072a4bd in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
+        4  0x00007ffff064b48f in _mesa_reference_shader () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
+        5  0x00007ffff0649397 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
+        6  0x000000000040624d in releaseShader (program=0x77cd90) at ./egl/gles2_help.c:158
+        7  eglRelease (context=0x615920) at ./egl/gles2_help.c:310
+        8  0x0000000000402ca8 in main (argc=<optimized out>, argv=<optimized out>) at v4l2decode.cpp:531
+        */
+        if (m_eglContext)
+            eglRelease(m_eglContext);
+        if (m_x11Window)
+            XDestroyWindow(m_x11Display, m_x11Window);
+    }
+
+private:
+    bool setupOutputBuffers(uint32_t count)
+    {
+        m_textureIds.resize(count);
+        // setup all textures and eglImages
+
+        if (!m_eglContext) {
+            m_eglContext = eglInit(m_x11Display, m_x11Window, 0 /*VA_FOURCC_RGBA*/, isDmaBuf());
+            if (!m_eglContext)
+                return false;
+        }
+        m_eglImages.resize(count);
+        glGenTextures(count, &m_textureIds[0]);
+        for (uint32_t i = 0; i < count; i++) {
+            int ret = 0;
+            ret = m_device->useEglImage(m_eglContext->eglContext.display, m_eglContext->eglContext.context, i, &m_eglImages[i]);
+            ASSERT(ret == 0);
+
+            GLenum target = GL_TEXTURE_2D;
+            if (isDmaBuf())
+                target = GL_TEXTURE_EXTERNAL_OES;
+            glBindTexture(target, m_textureIds[i]);
+            imageTargetTexture2D(target, m_eglImages[i]);
+
+            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            DEBUG("textureIds[%d]: 0x%x, eglImages[%d]: 0x%p", i, m_textureIds[i], i, m_eglImages[i]);
+        }
+        return true;
+    }
+
+    bool isDmaBuf()
+    {
+        return m_memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF;
+    }
+
+    bool queueOutputBuffers()
+    {
+        return queueOutputBuffersAtStart((uint32_t)m_eglImages.size());
+    }
+
+    EGLContextType* m_eglContext;
+    std::vector<EGLImageKHR> m_eglImages;
+    std::vector<GLuint> m_textureIds;
+};
+
+#endif
+
+#endif
+
+SharedPtr<V4L2Renderer> V4L2Renderer::create(const SharedPtr<V4L2Device>& device, VideoDataMemoryType memoryType)
+{
+    SharedPtr<V4L2Renderer> renderer;
+#ifdef __ENABLE_X11__
+    if (memoryType == VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF)
+        renderer.reset(new ExternalDmaBufRenderer(device, memoryType));
+#ifdef __ENABLE_TESTS_GLES__
+    if (memoryType == VIDEO_DATA_MEMORY_TYPE_DRM_NAME || memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF)
+        renderer.reset(new EglRenderer(device, memoryType));
+#endif
+#endif
+
+    return renderer;
+}
diff --git a/tests/V4L2Renderer.h b/tests/V4L2Renderer.h
new file mode 100644
index 0000000..0117644
--- /dev/null
+++ b/tests/V4L2Renderer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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 <stdint.h>
+#include <Yami.h>
+
+class V4L2Device;
+class V4L2Renderer {
+public:
+    static SharedPtr<V4L2Renderer> create(const SharedPtr<V4L2Device>&, VideoDataMemoryType memoryType);
+    virtual bool setDisplay() = 0;
+    virtual bool setupOutputBuffers(uint32_t wdith, uint32_t height) = 0;
+    bool renderOneFrame();
+    virtual bool queueOutputBuffers() = 0;
+
+protected:
+    V4L2Renderer(const SharedPtr<V4L2Device>&, VideoDataMemoryType memoryType);
+    virtual ~V4L2Renderer(){};
+    bool getDpbSize(uint32_t& dpbSize);
+    bool requestBuffers(uint32_t& count);
+    bool queueBuffer(uint32_t index, unsigned long userptr = 0);
+    bool dequeBuffer(uint32_t& index);
+    virtual bool render(uint32_t& index) = 0;
+    virtual bool queueOutputBuffersAtStart(uint32_t count) = 0;
+
+    SharedPtr<V4L2Device> m_device;
+    VideoDataMemoryType m_memoryType;
+};
diff --git a/tests/decodehelp.cpp b/tests/decodehelp.cpp
index 5e1c4e5..a69eab6 100644
--- a/tests/decodehelp.cpp
+++ b/tests/decodehelp.cpp
@@ -43,12 +43,13 @@ static void printHelp(const char* app)
     printf("   -m <render mode>\n");
     printf("     -2: print MD5 by per frame and the whole decoded file MD5\n");
     printf("     -1: skip video rendering [*]\n");
-    printf("      0: dump video frame to file\n");
+    printf("      0: dump video frame to file [*]\n");
     printf("      1: render to X window [*]\n");
     printf("      2: texture: render to Pixmap + texture from Pixmap [*]\n");
     printf("      3: texture: export video frame as drm name (RGBX) + texture from drm name\n");
     printf("      4: texture: export video frame as dma_buf(RGBX) + texutre from dma_buf\n");
     printf("      5: texture: export video frame as dma_buf(NV12) + texture from dma_buf. not implement yet\n");
+    printf("      6: use external dma buf for decode and display, only v4l2decode support this\n");
     printf(" [*] v4l2decode doesn't support the option\n");
     printf("  --capi: use the codec capi to encode or decode, default(false)\n");
 }
diff --git a/tests/decodeinputavformat.cpp b/tests/decodeinputavformat.cpp
index 76a3b35..d890b2c 100644
--- a/tests/decodeinputavformat.cpp
+++ b/tests/decodeinputavformat.cpp
@@ -22,6 +22,10 @@
 #include "common/log.h"
 #include <Yami.h>
 
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 39, 100)
+#define av_packet_unref av_free_packet
+#endif
+
 DecodeInputAvFormat::DecodeInputAvFormat()
 :m_format(NULL),m_videoId(-1), m_codecId(AV_CODEC_ID_NONE), m_isEos(true)
 {
@@ -103,7 +107,9 @@ static const MimeEntry MimeEntrys[] = {
 #endif
 
     AV_CODEC_ID_H264, YAMI_MIME_H264,
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 100)
     AV_CODEC_ID_H265, YAMI_MIME_H265,
+#endif
     AV_CODEC_ID_WMV3, YAMI_MIME_VC1,
     AV_CODEC_ID_VC1, YAMI_MIME_VC1
 };
diff --git a/tests/decodeoutput.cpp b/tests/decodeoutput.cpp
index 1e02442..85fb37b 100644
--- a/tests/decodeoutput.cpp
+++ b/tests/decodeoutput.cpp
@@ -160,12 +160,17 @@ public:
         }
 
         uint32_t planes, width[3], height[3];
+        uint32_t xByte[3], yByte[3];
         if (!getPlaneResolution(src->fourcc, src->crop.width, src->crop.height, width, height, planes)) {
             ERROR("get plane reoslution failed");
             return false;
         }
+        if (!getPlaneResolution(src->fourcc, src->crop.x, src->crop.y, xByte, yByte, planes)) {
+            ERROR("get left-top coordinate failed");
+            return false;
+        }
         for (uint32_t i = 0; i < planes; i++) {
-            copyPlane(dest, p, image.offsets[i], width[i], height[i], image.pitches[i]);
+            copyPlane(dest, p, image.offsets[i] + yByte[i] * image.pitches[i], width[i], height[i], image.pitches[i], xByte[i]);
         }
         unmapImage(*m_display, image);
         return true;
@@ -173,14 +178,13 @@ public:
 
 private:
     static void copyPlane(std::vector<uint8_t>& v, uint8_t* data, uint32_t offset, uint32_t width,
-        uint32_t height, uint32_t pitch)
+        uint32_t height, uint32_t pitch, uint32_t widthOffset)
     {
         data += offset;
         for (uint32_t h = 0; h < height; h++) {
-            v.insert(v.end(), data, data + width);
+            v.insert(v.end(), data + widthOffset, data + width + widthOffset);
             data += pitch;
         }
-
     }
 
     bool init(uint32_t width, uint32_t height)
@@ -521,8 +525,8 @@ bool DecodeOutputXWindow::output(const SharedPtr<VideoFrame>& frame)
         return false;
 
     VAStatus status = vaPutSurface(*m_vaDisplay, (VASurfaceID)frame->surface,
-        m_window, 0, 0, frame->crop.width, frame->crop.height,
-        frame->crop.x, frame->crop.y, frame->crop.width, frame->crop.height,
+        m_window, frame->crop.x, frame->crop.y, frame->crop.width, frame->crop.height,
+        0, 0, frame->crop.width, frame->crop.height,
         NULL, 0, 0);
     return checkVaapiStatus(status, "vaPutSurface");
 }
diff --git a/tests/encode.cpp b/tests/encode.cpp
index 0592176..58760bf 100644
--- a/tests/encode.cpp
+++ b/tests/encode.cpp
@@ -45,6 +45,7 @@ int main(int argc, char** argv)
     VideoEncOutputBuffer outputBuffer;
     int encodeFrameCount = 0;
 
+    memset(&outputBuffer, 0, sizeof(VideoEncOutputBuffer));
     if (!process_cmdline(argc, argv))
         return -1;
 
@@ -82,6 +83,23 @@ int main(int argc, char** argv)
     setEncoderParameters(&encVideoParams);
     encVideoParams.size = sizeof(VideoParamsCommon);
     encoder->setParameters(VideoParamsTypeCommon, &encVideoParams);
+
+    VideoParamsHRD encVideoParamsHRD;
+    encVideoParamsHRD.size = sizeof(VideoParamsHRD);
+    encoder->getParameters(VideoParamsTypeHRD, &encVideoParamsHRD);
+    setEncoderParameterHRD(&encVideoParamsHRD);
+    encVideoParamsHRD.size = sizeof(VideoParamsHRD);
+    encoder->setParameters(VideoParamsTypeHRD, &encVideoParamsHRD);
+
+    if (qualityLevel != VIDEO_PARAMS_QUALITYLEVEL_NONE) {
+        VideoParamsQualityLevel encVideoParamsQualityLevel;
+        encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel);
+        encoder->getParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel);
+        encVideoParamsQualityLevel.level = qualityLevel;
+        encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel);
+        encoder->setParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel);
+    }
+
     // configure AVC encoding parameters
     VideoParamsAVC encVideoParamsAVC;
     if (!strcmp(output->getMimeType(), YAMI_MIME_H264)) {
@@ -159,6 +177,13 @@ int main(int argc, char** argv)
                 fwrite(MVBuffer.data, MVBuffer.bufferSize, 1, MVFp);
             }
 #endif
+            if (status == ENCODE_BUFFER_TOO_SMALL) {
+                maxOutSize = (maxOutSize * 3) / 2;
+                if (!createOutputBuffer(&outputBuffer, maxOutSize)) {
+                    fprintf(stderr, "fail to create output\n");
+                    goto error1;
+                }
+            }
         } while (status != ENCODE_BUFFER_NO_MORE);
 
         encodeFrameCount++;
@@ -184,8 +209,16 @@ int main(int argc, char** argv)
             fwrite(MVBuffer.data, MVBuffer.bufferSize, 1, MVFp);
         }
 #endif
+        if (status == ENCODE_BUFFER_TOO_SMALL) {
+            maxOutSize = (maxOutSize * 3) / 2;
+            if (!createOutputBuffer(&outputBuffer, maxOutSize)) {
+                fprintf(stderr, "fail to create output\n");
+                goto error1;
+            }
+        }
     } while (status != ENCODE_BUFFER_NO_MORE);
 
+error1:
     encoder->stop();
     releaseVideoEncoder(encoder);
     free(outputBuffer.data);
diff --git a/tests/encodehelp.h b/tests/encodehelp.h
index 8390aca..57ccd77 100644
--- a/tests/encodehelp.h
+++ b/tests/encodehelp.h
@@ -35,6 +35,11 @@ static VideoRateControl rcMode = RATE_CONTROL_CQP;
 static int frameCount = 0;
 static int numRefFrames = 1;
 static bool enableLowPower = false;
+static uint32_t bufferSize = 0;
+static uint32_t initBufferFullness = 0;
+static uint32_t windowSize = 1000;
+static uint32_t targetPercentage = 95;
+static uint32_t qualityLevel = VIDEO_PARAMS_QUALITYLEVEL_NONE;
 
 #ifdef __BUILD_GET_MV__
 static FILE *MVFp;
@@ -63,10 +68,10 @@ static void print_help(const char* app)
     printf("   -b <bitrate: kbps> optional\n");
     printf("   -f <frame rate> optional\n");
     printf("   -c <codec: HEVC|AVC|VP8|VP9|JPEG>\n");
-    printf("   -s <fourcc: NV12|IYUV|YV12|P010>\n");
+    printf("   -s <fourcc: NV12|I420|IYUV|YV12|P010>\n");
     printf("   -N <number of frames to encode(camera default 50), useful for camera>\n");
     printf("   --qp <initial qp> optional\n");
-    printf("   --rcmode <CBR|CQP> optional\n");
+    printf("   --rcmode <CBR|VBR|CQP> optional\n");
     printf("   --ipperiod <0 (I frame only) | 1 (I and P frames) | N (I,P and B frames, B frame number is N-1)> optional\n");
     printf("   --intraperiod <Intra frame period (default 30)> optional\n");
     printf("   --refnum <number of referece frames(default 1)> optional\n");
@@ -75,6 +80,12 @@ static void print_help(const char* app)
            "gold/alt (previous key frame) | 1 last (previous) gold (one before "
            "last) alt (one before gold)> optional\n");
     printf("   --lowpower <Enable AVC low power mode (default 0, Disabled)> optional\n");
+    printf("   --target-percnetage <target percentage of bitrate in VBR mode, default 95, range in(50-100)> optional\n");
+    printf("   --hrd-window-size <windows size in milliseconds, default 1000> optional\n");
+    printf("   --vbv-buffer-fullness <vbv initial buffer fullness in bit> optional\n");
+    printf("   --vbv-buffer-size <vbv buffer size in bit> optional\n");
+    printf("   --quality-level <encoded video qulity level(default 0), range[%d, %d]> optional\n",
+        VIDEO_PARAMS_QUALITYLEVEL_NONE, VIDEO_PARAMS_QUALITYLEVEL_MAX);
 }
 
 static VideoRateControl string_to_rc_mode(char *str)
@@ -83,6 +94,8 @@ static VideoRateControl string_to_rc_mode(char *str)
 
     if (!strcasecmp (str, "CBR"))
         rcMode = RATE_CONTROL_CBR;
+    else if (!strcasecmp(str, "VBR"))
+        rcMode = RATE_CONTROL_VBR;
     else if (!strcasecmp (str, "CQP"))
         rcMode = RATE_CONTROL_CQP;
     else {
@@ -96,16 +109,22 @@ static bool process_cmdline(int argc, char *argv[])
 {
     char opt;
     const struct option long_opts[] = {
-        {"help", no_argument, NULL, 'h' },
-        {"qp", required_argument, NULL, 0 },
-        {"rcmode", required_argument, NULL, 0 },
-        {"ipperiod", required_argument, NULL, 0 },
-        {"intraperiod", required_argument, NULL, 0 },
-        {"refnum", required_argument, NULL, 0 },
-        {"idrinterval", required_argument, NULL, 0 },
-        {"refmode", required_argument, NULL, 0 },
-        {"lowpower", no_argument, 0, 0},
-        {NULL, no_argument, NULL, 0 }};
+        { "help", no_argument, NULL, 'h' },
+        { "qp", required_argument, NULL, 0 },
+        { "rcmode", required_argument, NULL, 0 },
+        { "ipperiod", required_argument, NULL, 0 },
+        { "intraperiod", required_argument, NULL, 0 },
+        { "refnum", required_argument, NULL, 0 },
+        { "idrinterval", required_argument, NULL, 0 },
+        { "refmode", required_argument, NULL, 0 },
+        { "lowpower", no_argument, 0, 0 },
+        { "target-percnetage", required_argument, NULL, 0 },
+        { "hrd-window-size", required_argument, NULL, 0 },
+        { "vbv-buffer-fullness", required_argument, NULL, 0 },
+        { "vbv-buffer-size", required_argument, NULL, 0 },
+        { "quality-level", required_argument, NULL, 0 },
+        { NULL, no_argument, NULL, 0 }
+    };
     int option_index;
 
     if (argc < 2) {
@@ -174,6 +193,21 @@ static bool process_cmdline(int argc, char *argv[])
                 case 8:
                     enableLowPower = true;
                     break;
+                case 9:
+                    targetPercentage = atoi(optarg);
+                    break;
+                case 10:
+                    windowSize = atoi(optarg);
+                    break;
+                case 11:
+                    initBufferFullness = atoi(optarg);
+                    break;
+                case 12:
+                    bufferSize = atoi(optarg);
+                    break;
+                case 13:
+                    qualityLevel = atoi(optarg);
+                    break;
             }
         }
     }
@@ -185,8 +219,8 @@ static bool process_cmdline(int argc, char *argv[])
     }
 #endif
 
-    if ((rcMode == RATE_CONTROL_CBR) && (bitRate <= 0)) {
-        fprintf(stderr, "please make sure bitrate is positive when CBR mode\n");
+    if ((rcMode == RATE_CONTROL_CBR || rcMode == RATE_CONTROL_VBR) && (bitRate <= 0)) {
+        fprintf(stderr, "please make sure bitrate is positive when CBR/VBR mode\n");
         return false;
     }
 
@@ -234,4 +268,13 @@ void setEncoderParameters(VideoParamsCommon* encVideoParams)
     //encVideoParams->profile = VAProfileH264Main;
     //encVideoParams->profile = VAProfileVP8Version0_3;
 }
+
+void setEncoderParameterHRD(VideoParamsHRD* encVideoParamHRD)
+{
+    encVideoParamHRD->targetPercentage = targetPercentage;
+    encVideoParamHRD->windowSize = windowSize;
+    encVideoParamHRD->initBufferFullness = initBufferFullness;
+    encVideoParamHRD->bufferSize = bufferSize;
+}
+
 #endif
diff --git a/tests/encodeinput.cpp b/tests/encodeinput.cpp
index eb34e2b..1c81992 100644
--- a/tests/encodeinput.cpp
+++ b/tests/encodeinput.cpp
@@ -331,11 +331,15 @@ EncodeOutputVP9::EncodeOutputVP9()
 
 bool createOutputBuffer(VideoEncOutputBuffer* outputBuffer, int maxOutSize)
 {
-    outputBuffer->data = static_cast<uint8_t*>(malloc(maxOutSize));
-    if (!outputBuffer->data)
+    uint8_t* tmp;
+    tmp = static_cast<uint8_t*>(malloc(maxOutSize));
+    if (!tmp)
         return false;
     outputBuffer->bufferSize = maxOutSize;
     outputBuffer->format = OUTPUT_EVERYTHING;
+    if (outputBuffer->data)
+        free(outputBuffer->data);
+    outputBuffer->data = tmp;
     return true;
 }
 
diff --git a/tests/v4l2decode.cpp b/tests/v4l2decode.cpp
index 340daec..5a65c07 100644
--- a/tests/v4l2decode.cpp
+++ b/tests/v4l2decode.cpp
@@ -27,159 +27,25 @@
 #include  <sys/mman.h>
 #include <vector>
 #include <stdint.h>
-#include <inttypes.h>
 
 #include "common/log.h"
 #include "common/utils.h"
 #include "decodeinput.h"
 #include "decodehelp.h"
-#if ANDROID
-#include <gui/SurfaceComposerClient.h>
-#include <va/va_android.h>
-#elif __ENABLE_WAYLAND__
-#include <wayland-client.h>
-#else
-#include "./egl/gles2_help.h"
-#endif
+#include "V4L2Device.h"
+#include "V4L2Renderer.h"
+
 #include <Yami.h>
 
 #ifndef V4L2_EVENT_RESOLUTION_CHANGE
     #define V4L2_EVENT_RESOLUTION_CHANGE 5
 #endif
 
-#if __ENABLE_V4L2_OPS__
-#include "v4l2codec_device_ops.h"
-#include <dlfcn.h>
-#include <fcntl.h>
-#else
-#include "common/v4l2_wrapper.h"
-#endif
-
-int videoWidth = 0;
-int videoHeight = 0;
-static const char* typeStrDrmName = "drm-name";
-static const char* typeStrDmaBuf = "dma-buf";
-static const char* typeStrRawData = "raw-data";
-#define IS_DRM_NAME()   (!strcmp(memoryTypeStr, typeStrDrmName))
-#define IS_DMA_BUF()   (!strcmp(memoryTypeStr, typeStrDmaBuf))
-#define IS_RAW_DATA()   (!strcmp(memoryTypeStr, typeStrRawData))
-#define IS_ANDROID_BUFFER_HANDLE()   (!strcmp(memoryTypeStr, typeStrAndroidBufferHandle))
-
+uint32_t videoWidth = 0;
+uint32_t videoHeight = 0;
 static enum v4l2_memory inputMemoryType = V4L2_MEMORY_MMAP;
-#if ANDROID
-static const char* typeStrAndroidBufferHandle = "android-buffer-handle";
-static VideoDataMemoryType memoryType = VIDEO_DATA_MEMORY_TYPE_ANDROID_BUFFER_HANDLE;
-static enum v4l2_memory outputMemoryType = (enum v4l2_memory) V4L2_MEMORY_ANDROID_BUFFER_HANDLE;
-static const char* memoryTypeStr = typeStrAndroidBufferHandle;
-#else
 static VideoDataMemoryType memoryType = VIDEO_DATA_MEMORY_TYPE_DRM_NAME;
 static enum v4l2_memory outputMemoryType = V4L2_MEMORY_MMAP;
-static const char* memoryTypeStr = typeStrDrmName;
-#endif
-
-#ifdef ANDROID
-
-#ifndef CHECK_EQ
-#define CHECK_EQ(a, b) do {                     \
-            if ((a) != (b)) {                   \
-                assert(0 && "assert fails");    \
-            }                                   \
-    } while (0)
-#endif
-
-sp<SurfaceComposerClient> mClient;
-sp<SurfaceControl> mSurfaceCtl;
-sp<Surface> mSurface;
-sp<ANativeWindow> mNativeWindow;
-
-std::vector <ANativeWindowBuffer*> mWindBuff;
-
-bool createNativeWindow(__u32 pixelformat)
-{
-    mClient = new SurfaceComposerClient();
-    mSurfaceCtl = mClient->createSurface(String8("testsurface"),
-                                      800, 600, pixelformat, 0);
-
-    // configure surface
-    SurfaceComposerClient::openGlobalTransaction();
-    mSurfaceCtl->setLayer(100000);
-    mSurfaceCtl->setPosition(100, 100);
-    mSurfaceCtl->setSize(800, 600);
-    SurfaceComposerClient::closeGlobalTransaction();
-
-    mSurface = mSurfaceCtl->getSurface();
-    mNativeWindow = mSurface;
-
-    CHECK_EQ(0,
-             native_window_set_usage(
-             mNativeWindow.get(),
-             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
-             | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
-
-    CHECK_EQ(0,
-             native_window_set_scaling_mode(
-             mNativeWindow.get(),
-             NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
-
-    CHECK_EQ(0, native_window_set_buffers_dimensions(
-                mNativeWindow.get(),
-                videoWidth,
-                videoHeight));
-
-    return true;
-}
-#endif
-
-#if __ENABLE_V4L2_OPS__
-static struct V4l2CodecOps s_v4l2CodecOps;
-static int32_t s_v4l2Fd = 0;
-
-static bool loadV4l2CodecDevice(const char* libName )
-{
-    memset(&s_v4l2CodecOps, 0, sizeof(s_v4l2CodecOps));
-    s_v4l2Fd = 0;
-
-#ifndef ANDROID
-    if (!dlopen(libName, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) {
-#else
-    if (!dlopen(libName, RTLD_NOW | RTLD_GLOBAL)) {
-#endif
-      ERROR("Failed to load %s\n", libName);
-      return false;
-    }
-
-    V4l2codecOperationInitFunc initFunc = NULL;
-    initFunc = (V4l2codecOperationInitFunc)dlsym(RTLD_DEFAULT, "v4l2codecOperationInit");
-
-    if (!initFunc) {
-        ERROR("fail to dlsym v4l2codecOperationInit\n");
-        return false;
-    }
-
-    INIT_V4L2CODEC_OPS_SIZE_VERSION(&s_v4l2CodecOps);
-    if (!initFunc(&s_v4l2CodecOps)) {
-        ERROR("fail to init v4l2 device operation func pointers\n");
-        return false;
-    }
-
-    int isVersionMatch = 0;
-    IS_V4L2CODEC_OPS_VERSION_MATCH(s_v4l2CodecOps.mVersion, isVersionMatch);
-    if (!isVersionMatch) {
-        ERROR("V4l2CodecOps interface version doesn't match\n");
-        return false;
-    }
-    if(s_v4l2CodecOps.mSize != sizeof(V4l2CodecOps)) {
-        ERROR("V4l2CodecOps interface data structure size doesn't match\n");
-        return false;
-    }
-
-    return true;
-}
-#define SIMULATE_V4L2_OP(OP)  s_v4l2CodecOps.m##OP##Func
-#else
-#define SIMULATE_V4L2_OP(OP)  YamiV4L2_##OP
-#endif
-
 
 struct RawFrameData {
     uint32_t width;
@@ -201,24 +67,13 @@ uint32_t k_extraOutputFrameCount = 2;
 static std::vector<uint8_t*> inputFrames;
 static std::vector<struct RawFrameData> rawOutputFrames;
 
-static FILE* outfp = NULL;
-
-#if __ENABLE_X11__
-static Display * x11Display = NULL;
-static Window x11Window = 0;
-#endif
-#if __ENABLE_TESTS_GLES__
-static EGLContextType *eglContext = NULL;
-static std::vector<EGLImageKHR> eglImages;
-static std::vector<GLuint> textureIds;
-#endif
 static bool isReadEOS=false;
 static int32_t stagingBufferInDevice = 0;
 static uint32_t renderFrameCount = 0;
 
 static DecodeParameter params;
 
-bool feedOneInputFrame(DecodeInput * input, int fd, int index = -1 /* if index is not -1, simple enque it*/)
+bool feedOneInputFrame(const SharedPtr<DecodeInput>& input, const SharedPtr<V4L2Device>& device, int index = -1 /* if index is not -1, simple enque it*/)
 {
 
     VideoDecodeBuffer inputBuffer;
@@ -234,7 +89,7 @@ bool feedOneInputFrame(DecodeInput * input, int fd, int index = -1 /* if index i
     buf.length = k_inputPlaneCount;
 
     if (index == -1) {
-        ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQBUF, &buf);
+        ioctlRet = device->ioctl(VIDIOC_DQBUF, &buf);
         if (ioctlRet == -1)
             return true;
         stagingBufferInDevice --;
@@ -257,300 +112,22 @@ bool feedOneInputFrame(DecodeInput * input, int fd, int index = -1 /* if index i
         buf.flags = inputBuffer.flag;
     }
 
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buf);
+    ioctlRet = device->ioctl(VIDIOC_QBUF, &buf);
     ASSERT(ioctlRet != -1);
 
     stagingBufferInDevice ++;
     return true;
 }
 
-bool dumpOneVideoFrame(int32_t index)
-{
-    uint32_t row;
-
-    if (!outfp) {
-        char outFileName[256];
-        char* baseFileName = params.inputFile;
-        char* s = strrchr(params.inputFile, '/');
-        if (s)
-            baseFileName = s+1;
-        // V4L2 reports fourcc as NM12 (planar NV12), use hard code here
-        sprintf(outFileName, "%s/%s_%dx%d.NV12", params.outputFile.c_str(), baseFileName, rawOutputFrames[index].width, rawOutputFrames[index].height);
-        DEBUG("outFileName: %s", outFileName);
-        outfp = fopen(outFileName, "w+");
-    }
-
-    if (!outfp)
-        return false;
-
-    // Y plane
-    for (row=0; row<rawOutputFrames[index].height; row++) {
-        fwrite(rawOutputFrames[index].data + rawOutputFrames[index].offset[0] + rawOutputFrames[index].pitch[0] * row, rawOutputFrames[index].width, 1, outfp);
-    }
-    // UV plane
-    for (row=0; row<(rawOutputFrames[index].height+1)/2; row++) {
-        fwrite(rawOutputFrames[index].data + rawOutputFrames[index].offset[1] + rawOutputFrames[index].pitch[1] * row, (rawOutputFrames[index].width+1)/2*2, 1, outfp);
-    }
-
-    return true;
-}
-
-#ifdef ANDROID
-static bool displayOneVideoFrameAndroid(int32_t fd, int32_t index)
-{
-    int32_t ioctlRet = -1;
-    struct v4l2_buffer buffer;
-    memset(&buffer, 0, sizeof(buffer));
-
-    if (mNativeWindow->queueBuffer(mNativeWindow.get(), mWindBuff[index], -1) != 0) {
-        fprintf(stderr, "queue buffer to native window failed\n");
-        return false;
-    }
-
-    ANativeWindowBuffer* pbuf = NULL;
-    status_t err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &pbuf);
-    if (err != 0) {
-        fprintf(stderr, "dequeueBuffer failed: %s (%d)\n", strerror(-err), -err);
-        return false;
-    }
-
-    buffer.m.userptr = (unsigned long)pbuf;
-    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    uint32_t i;
-    for (i = 0; i < mWindBuff.size(); i++) {
-        if (pbuf == mWindBuff[i]) {
-            buffer.index = i;
-            break;
-        }
-    }
-    if (i == mWindBuff.size())
-        return false;
-
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer);
-    ASSERT(ioctlRet != -1);
-
-    return true;
-}
-
-#elif __ENABLE_WAYLAND__
-struct display {
-    SharedPtr<wl_display>        display;
-    SharedPtr<wl_compositor>     compositor;
-    SharedPtr<wl_shell>          shell;
-    SharedPtr<wl_shell_surface>  shell_surface;
-    SharedPtr<wl_surface>        surface;
-};
-
-struct bufstatus {
-    bool redrawPending;
-    struct wl_buffer *buffer;
-};
-
-static struct bufstatus redrawStatus;
-static struct display waylandDisplay;
-
-void registryHandle(
-    void                    *data,
-    struct wl_registry      *registry,
-    uint32_t                id,
-    const char              *interface,
-    uint32_t                version
-)
-{
-    struct display * d = (struct display * )data;
-
-    if (strcmp(interface, "wl_compositor") == 0)
-        d->compositor.reset((struct wl_compositor *)wl_registry_bind(registry, id,
-                                                   &wl_compositor_interface, 1), wl_compositor_destroy);
-    else if (strcmp(interface, "wl_shell") == 0)
-        d->shell.reset((struct wl_shell *)wl_registry_bind(registry, id,
-	                                               &wl_shell_interface, 1), wl_shell_destroy);
-}
-
-void frameRedrawCallback(void *data,
-	                                       struct wl_callback *callback, uint32_t time)
-{
-    struct bufstatus *redrawstatus = (struct bufstatus *)data;
-    redrawstatus->redrawPending = false;
-    if (redrawstatus->buffer)
-        wl_buffer_destroy (redrawstatus->buffer);
-    wl_callback_destroy(callback);
-}
-
-static struct wl_callback_listener frameCallbackListener = {frameRedrawCallback};
-
-bool ensureWindow(unsigned int width, unsigned int height)
-{
-    struct display * const d = &waylandDisplay;
-
-    if (!d->surface) {
-        d->surface.reset(wl_compositor_create_surface(d->compositor.get()), wl_surface_destroy);
-        if (!d->surface)
-            return false;
-    }
-
-    if (!d->shell_surface) {
-        d->shell_surface.reset(wl_shell_get_shell_surface(d->shell.get(), d->surface.get()),
-                                                                       wl_shell_surface_destroy);
-        if (!d->shell_surface)
-            return false;
-        wl_shell_surface_set_toplevel(d->shell_surface.get());
-    }
-    return true;
-}
-
-bool createWaylandDisplay()
-{
-    struct display *d = &waylandDisplay;
-    struct wl_registry_listener registry_listener = {
-        registryHandle,
-        NULL,
-    };
-
-    d->display.reset(wl_display_connect(NULL), wl_display_disconnect);
-    if (!d->display) {
-        return false;
-    }
-    wl_display_set_user_data(d->display.get(), d);
-    struct wl_registry *registry = wl_display_get_registry(d->display.get());
-    wl_registry_add_listener(registry, &registry_listener, d);
-    wl_display_dispatch(d->display.get());
-    redrawStatus.redrawPending = false;
-    return true;
-}
-
-bool vaPutSurfaceWayland(struct wl_buffer *buffer,
-                                              const VARectangle *srcRect,
-                                              const VARectangle *dstRect)
-{
-    struct wl_callback *callback;
-    struct display * const d = &waylandDisplay;
-
-    if (redrawStatus.redrawPending) {
-        wl_display_flush(d->display.get());
-        while (redrawStatus.redrawPending) {
-            wl_display_dispatch(d->display.get());
-        }
-    }
-
-    if (!ensureWindow(dstRect->width, dstRect->height))
-        return false;
-
-    wl_surface_attach(d->surface.get(), buffer, 0, 0);
-    wl_surface_damage(d->surface.get(), dstRect->x,
-		dstRect->y, dstRect->width, dstRect->height);
-    wl_display_flush(d->display.get());
-    redrawStatus.buffer = buffer;
-    redrawStatus.redrawPending = true;
-    callback = wl_surface_frame(d->surface.get());
-    wl_callback_add_listener(callback, &frameCallbackListener,&redrawStatus);
-    wl_surface_commit(d->surface.get());
-    return true;
-}
-
-bool output(struct wl_buffer *buffer)
-{
-    VARectangle srcRect, dstRect;
-    if (!ensureWindow(videoWidth, videoHeight))
-        return false;
-
-    srcRect.x = 0;
-    srcRect.y = 0;
-    srcRect.width  = videoWidth;
-    srcRect.height = videoHeight;
-
-    dstRect.x = 0;
-    dstRect.y = 0;
-    dstRect.width  = videoWidth;
-    dstRect.height = videoHeight;
-    return vaPutSurfaceWayland(buffer, &srcRect, &dstRect);
-}
-
-static bool displayOneVideoFrameWayland(int32_t fd, struct v4l2_buffer  *buf)
-{
-    int32_t ioctlRet = -1;
-    struct v4l2_buffer buffer;
-
-    output((struct wl_buffer *)(buf->m.userptr));
-    memset(&buffer, 0, sizeof(buffer));
-    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    buffer.index = (buf->index) ? (buf->index - 1): (outputQueueCapacity - 1);
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer);
-    ASSERT(ioctlRet != -1);
-    return true;
-}
-#elif __ENABLE_TESTS_GLES__
-bool displayOneVideoFrameEGL(int32_t fd, int32_t index)
-{
-    ASSERT(eglContext && textureIds.size());
-    ASSERT(index>=0 && (uint32_t)index<textureIds.size());
-    DEBUG("textureIds[%d] = 0x%x", index, textureIds[index]);
-
-    GLenum target = GL_TEXTURE_2D;
-    if (IS_DMA_BUF())
-        target = GL_TEXTURE_EXTERNAL_OES;
-    int ret = drawTextures(eglContext, target, &textureIds[index], 1);
-
-    return ret == 0;
-}
-#endif
 
-
-bool takeOneOutputFrame(int fd, int index = -1/* if index is not -1, simple enque it*/)
-{
-    struct v4l2_buffer buf;
-    struct v4l2_plane planes[k_maxOutputPlaneCount]; // YUV output, in fact, we use NV12 of 2 planes
-    int ioctlRet = -1;
-    bool ret = true;
-
-    memset(&buf, 0, sizeof(buf));
-    memset(&planes, 0, sizeof(planes));
-    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; //it indicates output buffer type
-    buf.memory = outputMemoryType;
-    buf.m.planes = planes;
-    buf.length = outputPlaneCount;
-
-    if (index == -1) {
-        ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQBUF, &buf);
-        if (ioctlRet == -1)
-            return false;
-
-        renderFrameCount++;
-#ifdef ANDROID
-        ret = displayOneVideoFrameAndroid(fd, buf.index);
-#elif __ENABLE_WAYLAND__
-        ret = displayOneVideoFrameWayland(fd, &buf);
-#else
-#ifdef __ENABLE_TESTS_GLES__
-        if (IS_DMA_BUF() || IS_DRM_NAME())
-            ret = displayOneVideoFrameEGL(fd, buf.index);
-#endif
-        if (IS_RAW_DATA())
-            ret = dumpOneVideoFrame(buf.index);
-#endif
-        // ASSERT(ret);
-        if (!ret) {
-            ERROR("display frame failed");
-        }
-    } else {
-        buf.index = index;
-    }
-#if (!defined(ANDROID) && !defined(__ENABLE_WAYLAND__))
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buf);
-    ASSERT(ioctlRet != -1);
-#endif
-    INFO("renderFrameCount: %d", renderFrameCount);
-    return true;
-}
-
-bool handleResolutionChange(int32_t fd)
+bool handleResolutionChange(const SharedPtr<V4L2Device>& device)
 {
     bool resolutionChanged = false;
     // check resolution change
     struct v4l2_event ev;
     memset(&ev, 0, sizeof(ev));
 
-    while (SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQEVENT, &ev) == 0) {
+    while (device->ioctl(VIDIOC_DQEVENT, &ev) == 0) {
         if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
             resolutionChanged = true;
             break;
@@ -563,7 +140,7 @@ bool handleResolutionChange(int32_t fd)
     struct v4l2_format format;
     memset(&format, 0, sizeof(format));
     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    if (SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_G_FMT, &format) == -1) {
+    if (device->ioctl(VIDIOC_G_FMT, &format) == -1) {
         return false;
     }
 
@@ -580,90 +157,68 @@ extern uint32_t v4l2PixelFormatFromMime(const char* mime);
 
 int main(int argc, char** argv)
 {
-    DecodeInput *input;
-    int32_t fd = -1;
+    SharedPtr<DecodeInput> input;
     uint32_t i = 0;
     int32_t ioctlRet = -1;
     YamiMediaCodec::CalcFps calcFps;
 
-#if (defined (__ENABLE_X11__) && !defined(__ENABLE_WAYLAND__))
-    XInitThreads();
-#endif
-
-#if __ENABLE_V4L2_OPS__
-    // FIXME, use libv4l2codec_hw.so instead
-    if (!loadV4l2CodecDevice("libyami_v4l2.so")) {
-        ERROR("fail to init v4l2codec device with __ENABLE_V4L2_OPS__\n");
-        return -1;
-    }
-#endif
-
     if (!processCmdLine(argc, argv, &params))
         return -1;
 
     switch (params.renderMode) {
     case 0:
         memoryType = VIDEO_DATA_MEMORY_TYPE_RAW_COPY;
-        memoryTypeStr = typeStrRawData;
     break;
     case 3:
         memoryType = VIDEO_DATA_MEMORY_TYPE_DRM_NAME;
-        memoryTypeStr = typeStrDrmName;
     break;
     case 4:
         memoryType = VIDEO_DATA_MEMORY_TYPE_DMA_BUF;
-        memoryTypeStr = typeStrDmaBuf;
+        break;
+    case 6:
+        memoryType = VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF;
     break;
     default:
-        ASSERT(0 && "unsupported render mode, -m [0,3,4] are supported");
+        ASSERT(0 && "unsupported render mode, -m [0,3,4, 6] are supported");
     break;
     }
-
-    input = DecodeInput::create(params.inputFile);
-    if (input==NULL) {
+    input.reset(DecodeInput::create(params.inputFile));
+    if (!input) {
         ERROR("fail to init input stream\n");
         return -1;
     }
 
+    SharedPtr<V4L2Device> device = V4L2Device::Create();
+    if (!device) {
+        ERROR("failed to create v4l2 device");
+        return -1;
+    }
+    SharedPtr<V4L2Renderer> renderer = V4L2Renderer::create(device, memoryType);
+    if (!renderer) {
+        ERROR("unsupported render mode %d, please check your build configuration", memoryType);
+        return -1;
+    }
+
     renderFrameCount = 0;
     calcFps.setAnchor();
     // open device
-    fd = SIMULATE_V4L2_OP(Open)("decoder", 0);
-    ASSERT(fd!=-1);
-#if __ENABLE_WAYLAND__
-    createWaylandDisplay();
-#if __ENABLE_V4L2_OPS__
-    char displayStr[32];
-    sprintf(displayStr, "%" PRIu64 "", (uint64_t)(waylandDisplay.display.get()));
-    ioctlRet = SIMULATE_V4L2_OP(SetParameter)(fd, "wayland-display", displayStr);
-#else
-    ioctlRet = SIMULATE_V4L2_OP(SetWaylandDisplay)(fd, m_waylandDisplay.display.get());
-#endif
-    ASSERT(ioctlRet != -1);
-#elif __ENABLE_X11__
-    x11Display = XOpenDisplay(NULL);
-    ASSERT(x11Display);
-    DEBUG("x11display: %p", x11Display);
-    #if __ENABLE_V4L2_OPS__
-    char displayStr[32];
-    sprintf(displayStr, "%" PRIu64 "", (uint64_t)x11Display);
-    ioctlRet = SIMULATE_V4L2_OP(SetParameter)(fd, "x11-display", displayStr);
-    #else
-    ioctlRet = SIMULATE_V4L2_OP(SetXDisplay)(fd, x11Display);
-    #endif
-#endif
-    // set output frame memory type
-#if __ENABLE_V4L2_OPS__
-    SIMULATE_V4L2_OP(SetParameter)(fd, "frame-memory-type", memoryTypeStr);
-#else
-    SIMULATE_V4L2_OP(FrameMemoryType)(fd, memoryType);
-#endif
+    if (!device->open("decoder", 0)) {
+        ERROR("open decode failed");
+        return -1;
+    }
+
+    ioctlRet = device->setFrameMemoryType(memoryType);
+
+    if (!renderer->setDisplay()) {
+        ERROR("set display failed");
+        return -1;
+    }
 
     // query hw capability
     struct v4l2_capability caps;
     memset(&caps, 0, sizeof(caps));
     caps.capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QUERYCAP, &caps);
+    ioctlRet = device->ioctl(VIDIOC_QUERYCAP, &caps);
     ASSERT(ioctlRet != -1);
 
     // set input/output data format
@@ -681,7 +236,7 @@ int main(int argc, char** argv)
     format.fmt.pix_mp.height = input->getHeight();
     format.fmt.pix_mp.num_planes = 1;
     format.fmt.pix_mp.plane_fmt[0].sizeimage = k_maxInputBufferSize;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_S_FMT, &format);
+    ioctlRet = device->ioctl(VIDIOC_S_FMT, &format);
     ASSERT(ioctlRet != -1);
 
     // set preferred output format
@@ -698,11 +253,11 @@ int main(int argc, char** argv)
         ERROR("No enough space to store codec data");
         return -1;
     }
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_S_FMT, &format);
+    ioctlRet = device->ioctl(VIDIOC_S_FMT, &format);
     ASSERT(ioctlRet != -1);
     // input port starts as early as possible to decide output frame format
     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMON, &type);
+    ioctlRet = device->ioctl(VIDIOC_STREAMON, &type);
     ASSERT(ioctlRet != -1);
 
     // setup input buffers
@@ -710,8 +265,8 @@ int main(int argc, char** argv)
     memset(&reqbufs, 0, sizeof(reqbufs));
     reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
     reqbufs.memory = inputMemoryType;
-    reqbufs.count = 2;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs);
+    reqbufs.count = 8;
+    ioctlRet = device->ioctl(VIDIOC_REQBUFS, &reqbufs);
     ASSERT(ioctlRet != -1);
     ASSERT(reqbufs.count>0);
     inputQueueCapacity = reqbufs.count;
@@ -727,15 +282,15 @@ int main(int argc, char** argv)
         buffer.memory = inputMemoryType;
         buffer.m.planes = planes;
         buffer.length = k_inputPlaneCount;
-        ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QUERYBUF, &buffer);
+        ioctlRet = device->ioctl(VIDIOC_QUERYBUF, &buffer);
         ASSERT(ioctlRet != -1);
 
         // length and mem_offset should be filled by VIDIOC_QUERYBUF above
-        void* address = SIMULATE_V4L2_OP(Mmap)(NULL,
-                                      buffer.m.planes[0].length,
-                                      PROT_READ | PROT_WRITE,
-                                      MAP_SHARED, fd,
-                                      buffer.m.planes[0].m.mem_offset);
+        void* address = device->mmap(NULL,
+            buffer.m.planes[0].length,
+            PROT_READ | PROT_WRITE,
+            MAP_SHARED,
+            buffer.m.planes[0].m.mem_offset);
         ASSERT(address);
         inputFrames[i] = static_cast<uint8_t*>(address);
         DEBUG("inputFrames[%d] = %p", i, inputFrames[i]);
@@ -743,7 +298,7 @@ int main(int argc, char** argv)
 
     // feed input frames first
     for (i=0; i<inputQueueCapacity; i++) {
-        if (!feedOneInputFrame(input, fd, i)) {
+        if (!feedOneInputFrame(input, device, i)) {
             break;
         }
     }
@@ -752,7 +307,7 @@ int main(int argc, char** argv)
     memset(&format, 0, sizeof(format));
     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
     while (1) {
-        if (SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_G_FMT, &format) != 0) {
+        if (device->ioctl(VIDIOC_G_FMT, &format) != 0) {
             if (errno != EINVAL) {
                 // EINVAL means we haven't seen sufficient stream to decode the format.
                 INFO("ioctl() failed: VIDIOC_G_FMT, haven't get video resolution during start yet, waiting");
@@ -767,205 +322,71 @@ int main(int argc, char** argv)
     videoWidth = format.fmt.pix_mp.width;
     videoHeight = format.fmt.pix_mp.height;
     ASSERT(videoWidth && videoHeight);
+    bool ret = renderer->setupOutputBuffers(videoWidth, videoHeight);
+    ASSERT(ret && "setupOutputBuffers failed");
 
-#ifdef ANDROID
-    __u32 pixelformat = format.fmt.pix_mp.pixelformat;
-    if (!createNativeWindow(pixelformat)) {
-        fprintf(stderr, "create native window error\n");
-        return -1;
-    }
-
-    int minUndequeuedBuffs = 0;
-    status_t err = mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffs);
-    if (err != 0) {
-        fprintf(stderr, "query native window min undequeued buffers error\n");
-        return err;
-    }
-#endif
-
-    // setup output buffers
-    // Number of output buffers we need.
-    struct v4l2_control ctrl;
-    memset(&ctrl, 0, sizeof(ctrl));
-    ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_G_CTRL, &ctrl);
-#ifndef ANDROID
-    uint32_t minOutputFrameCount = ctrl.value + k_extraOutputFrameCount;
-#else
-    uint32_t minOutputFrameCount = ctrl.value + k_extraOutputFrameCount + minUndequeuedBuffs;
-#endif
-
-    memset(&reqbufs, 0, sizeof(reqbufs));
-    reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    reqbufs.memory = outputMemoryType;
-    reqbufs.count = minOutputFrameCount;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs);
-    ASSERT(ioctlRet != -1);
-    ASSERT(reqbufs.count>0);
-    outputQueueCapacity = reqbufs.count;
-
-#if (defined (__ENABLE_X11__) && !defined(__ENABLE_WAYLAND__))
-    if (!IS_RAW_DATA()) {
-        x11Window = XCreateSimpleWindow(x11Display, DefaultRootWindow(x11Display)
-            , 0, 0, videoWidth, videoHeight, 0, 0
-            , WhitePixel(x11Display, 0));
-        XMapWindow(x11Display, x11Window);
-        textureIds.resize(outputQueueCapacity);
-    }
-#endif
-#if (!defined(ANDROID) && !defined(__ENABLE_WAYLAND__))
-    if (IS_RAW_DATA()) {
-        rawOutputFrames.resize(outputQueueCapacity);
-        for (i=0; i<outputQueueCapacity; i++) {
-            struct v4l2_plane planes[k_maxOutputPlaneCount];
-            struct v4l2_buffer buffer;
-            memset(&buffer, 0, sizeof(buffer));
-            memset(planes, 0, sizeof(planes));
-            buffer.index = i;
-            buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-            buffer.memory = outputMemoryType;
-            buffer.m.planes = planes;
-            buffer.length = outputPlaneCount;
-            ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QUERYBUF, &buffer);
-            ASSERT(ioctlRet != -1);
-
-            rawOutputFrames[i].width = format.fmt.pix_mp.width;
-            rawOutputFrames[i].height = format.fmt.pix_mp.height;
-            rawOutputFrames[i].fourcc = format.fmt.pix_mp.pixelformat;
-
-            for (int j=0; j<outputPlaneCount; j++) {
-                // length and mem_offset are filled by VIDIOC_QUERYBUF above
-                void* address = SIMULATE_V4L2_OP(Mmap)(NULL,
-                                              buffer.m.planes[j].length,
-                                              PROT_READ | PROT_WRITE,
-                                              MAP_SHARED, fd,
-                                              buffer.m.planes[j].m.mem_offset);
-                ASSERT(address);
-                if (j == 0) {
-                    rawOutputFrames[i].data = static_cast<uint8_t*>(address);
-                    rawOutputFrames[i].offset[0] = 0;
-                } else {
-                    rawOutputFrames[i].offset[j] = static_cast<uint8_t*>(address) - rawOutputFrames[i].data;
-                }
-
-                rawOutputFrames[i].pitch[j] = format.fmt.pix_mp.plane_fmt[j].bytesperline;
-            }
-        }
-    }
-#if __ENABLE_TESTS_GLES__
-    if (IS_DMA_BUF() || IS_DRM_NAME()) {
-        // setup all textures and eglImages
-        eglImages.resize(outputQueueCapacity);
-
-        if (!eglContext)
-            eglContext = eglInit(x11Display, x11Window, 0 /*VA_FOURCC_RGBA*/, IS_DMA_BUF());
-
-        glGenTextures(outputQueueCapacity, &textureIds[0] );
-        for (i=0; i<outputQueueCapacity; i++) {
-             int ret = 0;
-             ret = SIMULATE_V4L2_OP(UseEglImage)(fd, eglContext->eglContext.display, eglContext->eglContext.context, i, &eglImages[i]);
-             ASSERT(ret == 0);
-
-             GLenum target = GL_TEXTURE_2D;
-             if (IS_DMA_BUF())
-                 target = GL_TEXTURE_EXTERNAL_OES;
-             glBindTexture(target, textureIds[i]);
-             imageTargetTexture2D(target, eglImages[i]);
-
-             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-             DEBUG("textureIds[%d]: 0x%x, eglImages[%d]: 0x%p", i, textureIds[i], i, eglImages[i]);
-        }
-    }
-#endif
-#endif
-#if __ENABLE_WAYLAND__
-    struct v4l2_buffer buffer;
-    //queue buffs
-    for (uint32_t i = 0; i < outputQueueCapacity; i++) {
-        memset(&buffer, 0, sizeof(buffer));
-        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-        buffer.index = i;
-        ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer);
-        ASSERT(ioctlRet != -1);
-    }
-#else
-#ifndef ANDROID
-    // feed output frames first
-    for (i=0; i<outputQueueCapacity; i++) {
-        if (!takeOneOutputFrame(fd, i)) {
-            ASSERT(0);
-        }
-    }
-#else
-    struct v4l2_buffer buffer;
-
-    err = native_window_set_buffer_count(mNativeWindow.get(), outputQueueCapacity);
-    if (err != 0) {
-        fprintf(stderr, "native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err);
-        return -1;
-    }
-
-    //queue buffs
-    for (uint32_t i = 0; i < outputQueueCapacity; i++) {
-        ANativeWindowBuffer* pbuf = NULL;
-        memset(&buffer, 0, sizeof(buffer));
-
-        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &pbuf);
-        if (err != 0) {
-            fprintf(stderr, "dequeueBuffer failed: %s (%d)\n", strerror(-err), -err);
-            return -1;
-        }
-
-        buffer.m.userptr = (unsigned long)pbuf->handle;
-        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-        buffer.index = i;
-
-        ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer);
-        ASSERT(ioctlRet != -1);
-        mWindBuff.push_back(pbuf);
-    }
-
-    for (uint32_t i = 0; i < minUndequeuedBuffs; i++) {
-        memset(&buffer, 0, sizeof(buffer));
-        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-
-        ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQBUF, &buffer);
-        ASSERT(ioctlRet != -1);
-
-        err = mNativeWindow->cancelBuffer(mNativeWindow.get(), mWindBuff[buffer.index], -1);
-        if (err) {
-            fprintf(stderr, "queue empty window buffer error\n");
-            return -1;
-        }
-    }
-#endif
-#endif
     // output port starts as late as possible to adopt user provide output buffer
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMON, &type);
+    ioctlRet = device->ioctl(VIDIOC_STREAMON, &type);
     ASSERT(ioctlRet != -1);
+//#define SEEK_POS  500
+#ifdef SEEK_POS
+    uint32_t frames = 0;
+#endif
 
     bool event_pending=true; // try to get video resolution.
     uint32_t dqCountAfterEOS = 0;
     do {
         if (event_pending) {
-            handleResolutionChange(fd);
+            handleResolutionChange(device);
         }
 
-        takeOneOutputFrame(fd);
-        if (!feedOneInputFrame(input, fd)) {
+        renderer->renderOneFrame();
+        if (!feedOneInputFrame(input, device)) {
             if (stagingBufferInDevice == 0)
                 break;
             dqCountAfterEOS++;
         }
         if (dqCountAfterEOS == inputQueueCapacity)  // input drain
             break;
-    } while (SIMULATE_V4L2_OP(Poll)(fd, true, &event_pending) == 0);
+
+#ifdef SEEK_POS
+        frames++;
+        if (frames == SEEK_POS) {
+            input.reset(DecodeInput::create(params.inputFile));
+            if (!input) {
+                ERROR("fail to init input stream\n");
+                return -1;
+            }
+
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+            ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type);
+            ASSERT(ioctlRet != -1);
+
+            type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+            ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type);
+            ASSERT(ioctlRet != -1);
+            stagingBufferInDevice = 0;
+
+            type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+            ioctlRet = device->ioctl(VIDIOC_STREAMON, &type);
+            ASSERT(ioctlRet != -1);
+
+            for (i = 0; i < inputQueueCapacity; i++) {
+                if (!feedOneInputFrame(input, device, i)) {
+                    break;
+                }
+            }
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+            ioctlRet = device->ioctl(VIDIOC_STREAMON, &type);
+            renderer->queueOutputBuffers();
+        }
+#endif
+    } while (device->poll(true, &event_pending) == 0);
 
     // drain output buffer
     int retry = 3;
-    while (takeOneOutputFrame(fd) || (--retry)>0) { // output drain
+    while (renderer->renderOneFrame() || (--retry) > 0) { // output drain
         usleep(10000);
     }
 
@@ -978,65 +399,30 @@ int main(int argc, char** argv)
     reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
     reqbufs.memory = inputMemoryType;
     reqbufs.count = 0;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs);
+    ioctlRet = device->ioctl(VIDIOC_REQBUFS, &reqbufs);
     ASSERT(ioctlRet != -1);
 
     memset(&reqbufs, 0, sizeof(reqbufs));
     reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
     reqbufs.memory = outputMemoryType;
     reqbufs.count = 0;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs);
+    ioctlRet = device->ioctl(VIDIOC_REQBUFS, &reqbufs);
     ASSERT(ioctlRet != -1);
 
     // stop input port
     type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMOFF, &type);
+    ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type);
     ASSERT(ioctlRet != -1);
 
     // stop output port
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMOFF, &type);
+    ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type);
     ASSERT(ioctlRet != -1);
-#if __ENABLE_TESTS_GLES__
-    if(textureIds.size())
-        glDeleteTextures(textureIds.size(), &textureIds[0]);
-    ASSERT(glGetError() == GL_NO_ERROR);
-    for (i=0; i<eglImages.size(); i++) {
-        destroyImage(eglContext->eglContext.display, eglImages[i]);
-    }
-    /*
-    there is still randomly fail in mesa; no good idea for it. seems mesa bug
-    0  0x00007ffff079c343 in _mesa_symbol_table_dtor () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
-    1  0x00007ffff073c55d in glsl_symbol_table::~glsl_symbol_table() () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
-    2  0x00007ffff072a4d5 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
-    3  0x00007ffff072a4bd in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
-    4  0x00007ffff064b48f in _mesa_reference_shader () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
-    5  0x00007ffff0649397 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1
-    6  0x000000000040624d in releaseShader (program=0x77cd90) at ./egl/gles2_help.c:158
-    7  eglRelease (context=0x615920) at ./egl/gles2_help.c:310
-    8  0x0000000000402ca8 in main (argc=<optimized out>, argv=<optimized out>) at v4l2decode.cpp:531
-    */
-    if (eglContext)
-        eglRelease(eglContext);
-#endif
 
     // close device
-    ioctlRet = SIMULATE_V4L2_OP(Close)(fd);
+    ioctlRet = device->close();
     ASSERT(ioctlRet != -1);
 
-    if(input)
-        delete input;
-
-    if (outfp)
-        fclose(outfp);
-
-#if (defined (__ENABLE_X11__) && !defined(__ENABLE_WAYLAND__))
-    if (x11Display && x11Window)
-        XDestroyWindow(x11Display, x11Window);
-    if (x11Display)
-        XCloseDisplay(x11Display);
-#endif
-
     fprintf(stdout, "decode done\n");
     return 0;
 }
diff --git a/tests/vppinputoutput.h b/tests/vppinputoutput.h
index 1cc7fce..9a613fb 100644
--- a/tests/vppinputoutput.h
+++ b/tests/vppinputoutput.h
@@ -89,12 +89,17 @@ public:
             return false;
         }
         uint32_t byteWidth[3], byteHeight[3], planes;
+        uint32_t byteX[3], byteY[3];
         //image.width is not equal to frame->crop.width.
         //for supporting VPG Driver, use YV12 to replace I420
         if (!getPlaneResolution(frame->fourcc, frame->crop.width, frame->crop.height, byteWidth, byteHeight, planes)) {
             ERROR("get plane reoslution failed for %x, %dx%d", frame->fourcc, frame->crop.width, frame->crop.height);
             return false;
         }
+        if (!getPlaneResolution(frame->fourcc, frame->crop.x, frame->crop.y, byteX, byteY, planes)) {
+            ERROR("get left-top coordinate(%d,%d) failed", frame->crop.x, frame->crop.y);
+            return false;
+        }
         char* buf;
         status = vaMapBuffer(*m_display, image.buf, (void**)&buf);
         if (status != VA_STATUS_SUCCESS) {
@@ -105,9 +110,10 @@ public:
         bool ret = true;
         for (uint32_t i = 0; i < planes; i++) {
             char* ptr = buf + image.offsets[i];
+            ptr += image.pitches[i] * byteY[i];
             int w = byteWidth[i];
             for (uint32_t j = 0; j < byteHeight[i]; j++) {
-                ret = m_io(ptr, w, fp);
+                ret = m_io(ptr + byteX[i], w, fp);
                 if (!ret)
                     goto out;
                 ptr += image.pitches[i];
diff --git a/tests/vppoutputencode.cpp b/tests/vppoutputencode.cpp
index 2f3a5ed..2466b81 100755
--- a/tests/vppoutputencode.cpp
+++ b/tests/vppoutputencode.cpp
@@ -44,6 +44,11 @@ EncodeParams::EncodeParams()
     , temporalLayerNum(1)
     , priorityId(0)
     , enableLowPower(false)
+    , targetPercentage(95)
+    , windowSize(1000)
+    , initBufferFullness(0)
+    , bufferSize(0)
+    , qualityLevel(VIDEO_PARAMS_QUALITYLEVEL_NONE)
 {
     memset(layerBitRate, 0, sizeof(layerBitRate));
 }
@@ -107,6 +112,7 @@ static void setEncodeParam(const SharedPtr<IVideoEncoder>& encoder,
     encVideoParams.rcParams.diffQPIP = encParam->diffQPIP;
     encVideoParams.rcParams.diffQPIB = encParam->diffQPIB;
     encVideoParams.rcMode = encParam->rcMode;
+
     encVideoParams.numRefFrames = encParam->numRefFrames;
     encVideoParams.enableLowPower = encParam->enableLowPower;
     if (YAMI_FOURCC_P010 == fourcc)
@@ -119,6 +125,25 @@ static void setEncodeParam(const SharedPtr<IVideoEncoder>& encoder,
     encVideoParams.size = sizeof(VideoParamsCommon);
     encoder->setParameters(VideoParamsTypeCommon, &encVideoParams);
 
+    VideoParamsHRD encVideoParamsHRD;
+    encVideoParamsHRD.size = sizeof(VideoParamsHRD);
+    encoder->getParameters(VideoParamsTypeHRD, &encVideoParamsHRD);
+    encVideoParamsHRD.targetPercentage = encParam->targetPercentage;
+    encVideoParamsHRD.windowSize = encParam->windowSize;
+    encVideoParamsHRD.initBufferFullness = encParam->initBufferFullness;
+    encVideoParamsHRD.bufferSize = encParam->bufferSize;
+    encVideoParamsHRD.size = sizeof(VideoParamsHRD);
+    encoder->setParameters(VideoParamsTypeHRD, &encVideoParamsHRD);
+
+    if (encParam->qualityLevel != VIDEO_PARAMS_QUALITYLEVEL_NONE) {
+        VideoParamsQualityLevel encVideoParamsQualityLevel;
+        encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel);
+        encoder->getParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel);
+        encVideoParamsQualityLevel.level = encParam->qualityLevel;
+        encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel);
+        encoder->setParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel);
+    }
+
     // configure AVC encoding parameters
     VideoParamsAVC encVideoParamsAVC;
     if (!strcmp(mimeType, YAMI_MIME_H264)) {
diff --git a/tests/vppoutputencode.h b/tests/vppoutputencode.h
index aa43a05..68941e5 100644
--- a/tests/vppoutputencode.h
+++ b/tests/vppoutputencode.h
@@ -53,6 +53,11 @@ public:
     EncodeParamsVP9 m_encParamsVP9;
     uint32_t layerBitRate[4]; // specify each scalable layer bitrate
     bool enableLowPower;
+    uint32_t targetPercentage;
+    uint32_t windowSize; // use for HRD CPB length in ms
+    unsigned int initBufferFullness; /* in bits */
+    unsigned int bufferSize; /* in bits */
+    uint32_t qualityLevel;
 };
 
 class TranscodeParams
diff --git a/tests/yamitranscode.cpp b/tests/yamitranscode.cpp
index 6938f23..4cb72aa 100755
--- a/tests/yamitranscode.cpp
+++ b/tests/yamitranscode.cpp
@@ -43,7 +43,11 @@ static void print_help(const char* app)
     printf("   -N <number of frames to encode(camera default 50), useful for camera>\n");
     printf("   -t <AVC scalability temporal layer number  (default 1)> optional\n");
     printf("   --qp <initial qp> optional\n");
-    printf("   --rcmode <CBR|CQP> optional\n");
+    printf("   --rcmode <CBR|CQP|VBR> optional\n");
+    printf("   --target-percnetage <target percentage of bitrate in VBR mode, default 95, range in(50-100)> optional\n");
+    printf("   --hrd-window-size <windows size in milliseconds, default 1000> optional\n");
+    printf("   --vbv-buffer-fullness <vbv initial buffer fullness in bit> optional\n");
+    printf("   --vbv-buffer-size <vbv buffer size in bit> optional\n");
     printf("   --ipperiod <0 (I frame only) | 1 (I and P frames) | N (I,P and B frames, B frame number is N-1)> optional\n");
     printf("   --intraperiod <Intra frame period(default 30)> optional\n");
     printf("   --refnum <number of referece frames(default 1)> optional\n");
@@ -63,6 +67,8 @@ static void print_help(const char* app)
     printf("   --btl2 <svc-t layer 2 bitrate: kbps> optional\n");
     printf("   --btl3 <svc-t layer 3 bitrate: kbps> optional\n");
     printf("   --lowpower <Enable AVC low power mode (default 0, Disabled)> optional\n");
+    printf("   --quality-level <encoded video qulity level(default 0), range[%d, %d]> optional\n",
+        VIDEO_PARAMS_QUALITYLEVEL_NONE, VIDEO_PARAMS_QUALITYLEVEL_MAX);
     printf("   VP9 encoder specific options:\n");
     printf("   --refmode <VP9 Reference frames mode (default 0 last(previous), "
            "gold/alt (previous key frame) | 1 last (previous) gold (one before "
@@ -75,6 +81,9 @@ static VideoRateControl string_to_rc_mode(char *str)
 
     if (!strcasecmp (str, "CBR"))
         rcMode = RATE_CONTROL_CBR;
+    else if (!strcasecmp(str, "VBR")) {
+        rcMode = RATE_CONTROL_VBR;
+    }
     else if (!strcasecmp (str, "CQP"))
         rcMode = RATE_CONTROL_CQP;
     else {
@@ -88,30 +97,36 @@ static bool processCmdLine(int argc, char *argv[], TranscodeParams& para)
 {
     char opt;
     const struct option long_opts[] = {
-        {"help", no_argument, NULL, 'h' },
-        {"qp", required_argument, NULL, 0 },
-        {"rcmode", required_argument, NULL, 0 },
-        {"ipperiod", required_argument, NULL, 0 },
-        {"intraperiod", required_argument, NULL, 0 },
-        {"refnum", required_argument, NULL, 0 },
-        {"idrinterval", required_argument, NULL, 0 },
-        {"disable-cabac", no_argument, NULL, 0},
-        {"enable-dct8x8", no_argument, NULL, 0},
-        {"disable-deblock", no_argument, NULL, 0},
-        {"deblockalphadiv2", required_argument, NULL, 0},
-        {"deblockbetadiv2", required_argument, NULL, 0},
-        {"qpip", required_argument, NULL, 0 },
-        {"qpib", required_argument, NULL, 0 },
-        {"priorityid", required_argument, NULL, 0 },
-        {"refmode", required_argument, NULL, 0 },
-        {"ow", required_argument, NULL, 0 },
-        {"oh", required_argument, NULL, 0 },
-        {"btl0", required_argument, NULL, 0 },
-        {"btl1", required_argument, NULL, 0 },
-        {"btl2", required_argument, NULL, 0 },
-        {"btl3", required_argument, NULL, 0 },
-        {"lowpower", no_argument, NULL, 0 },
-        {NULL, no_argument, NULL, 0 }};
+        { "help", no_argument, NULL, 'h' },
+        { "qp", required_argument, NULL, 0 },
+        { "rcmode", required_argument, NULL, 0 },
+        { "ipperiod", required_argument, NULL, 0 },
+        { "intraperiod", required_argument, NULL, 0 },
+        { "refnum", required_argument, NULL, 0 },
+        { "idrinterval", required_argument, NULL, 0 },
+        { "disable-cabac", no_argument, NULL, 0 },
+        { "enable-dct8x8", no_argument, NULL, 0 },
+        { "disable-deblock", no_argument, NULL, 0 },
+        { "deblockalphadiv2", required_argument, NULL, 0 },
+        { "deblockbetadiv2", required_argument, NULL, 0 },
+        { "qpip", required_argument, NULL, 0 },
+        { "qpib", required_argument, NULL, 0 },
+        { "priorityid", required_argument, NULL, 0 },
+        { "refmode", required_argument, NULL, 0 },
+        { "ow", required_argument, NULL, 0 },
+        { "oh", required_argument, NULL, 0 },
+        { "btl0", required_argument, NULL, 0 },
+        { "btl1", required_argument, NULL, 0 },
+        { "btl2", required_argument, NULL, 0 },
+        { "btl3", required_argument, NULL, 0 },
+        { "lowpower", no_argument, NULL, 0 },
+        { "target-percnetage", required_argument, NULL, 0 },
+        { "hrd-window-size", required_argument, NULL, 0 },
+        { "vbv-buffer-fullness", required_argument, NULL, 0 },
+        { "vbv-buffer-size", required_argument, NULL, 0 },
+        { "quality-level", required_argument, NULL, 0 },
+        { NULL, no_argument, NULL, 0 }
+    };
     int option_index;
 
     if (argc < 2) {
@@ -225,6 +240,21 @@ static bool processCmdLine(int argc, char *argv[], TranscodeParams& para)
                 case 22:
                     para.m_encParams.enableLowPower = true;
                     break;
+                case 23:
+                    para.m_encParams.targetPercentage = atoi(optarg);
+                    break;
+                case 24:
+                    para.m_encParams.windowSize = atoi(optarg);
+                    break;
+                case 25:
+                    para.m_encParams.initBufferFullness = atoi(optarg);
+                    break;
+                case 26:
+                    para.m_encParams.bufferSize = atoi(optarg);
+                    break;
+                case 27:
+                    para.m_encParams.qualityLevel = atoi(optarg);
+                    break;
             }
         }
     }
@@ -250,6 +280,11 @@ static bool processCmdLine(int argc, char *argv[], TranscodeParams& para)
         return false;
     }
 
+    if ((para.m_encParams.rcMode == RATE_CONTROL_VBR) && (para.m_encParams.bitRate <= 0)) {
+        fprintf(stderr, "please make sure bitrate is positive when VBR mode\n");
+        return false;
+    }
+
     if (!strncmp(para.inputFileName.c_str(), "/dev/video", strlen("/dev/video")) && !para.frameCount)
         para.frameCount = 50;
 
diff --git a/vaapi/vaapidisplay.h b/vaapi/vaapidisplay.h
new file mode 100644
index 0000000..1df52f7
--- /dev/null
+++ b/vaapi/vaapidisplay.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * 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 vaapidisplay_h
+#define vaapidisplay_h
+
+#include <va/va.h>
+#include <va/va_tpi.h>
+#ifdef HAVE_VA_X11
+#include <va/va_x11.h>
+#endif
+#ifndef ANDROID
+#include <va/va_drm.h>
+#endif
+#include <vector>
+#include "common/lock.h"
+#include "common/NonCopyable.h"
+
+///abstract for all display, x11, wayland, ozone, android etc.
+namespace YamiMediaCodec {
+#ifndef VA_FOURCC_I420
+#define VA_FOURCC_I420 VA_FOURCC('I', '4', '2', '0')
+#endif
+class NativeDisplayBase;
+class VaapiDisplay;
+typedef SharedPtr<VaapiDisplay> DisplayPtr;
+class VaapiDisplay {
+    typedef SharedPtr<NativeDisplayBase> NativeDisplayPtr;
+    friend class DisplayCache;
+    friend class VaapiDisplayTest;
+
+public:
+    virtual ~VaapiDisplay();
+    //FIXME: add more create functions.
+    static DisplayPtr create(const NativeDisplay& display);
+    virtual bool setRotation(int degree);
+    VADisplay getID() const { return m_vaDisplay; }
+    const VAImageFormat* getVaFormat(uint32_t fourcc);
+
+protected:
+    /// for display cache management.
+    virtual bool isCompatible(const NativeDisplay& other);
+
+private:
+    VaapiDisplay(const NativeDisplayPtr& nativeDisplay, VADisplay vaDisplay)
+        : m_vaDisplay(vaDisplay)
+        , m_nativeDisplay(nativeDisplay){};
+
+    Lock m_lock;
+    VADisplay m_vaDisplay;
+    NativeDisplayPtr m_nativeDisplay;
+    std::vector<VAImageFormat> m_vaImageFormats;
+
+    DISALLOW_COPY_AND_ASSIGN(VaapiDisplay);
+};
+}
+#endif

-- 
libyami-utils packaging



More information about the pkg-multimedia-commits mailing list