[go: nahoru, domu]

mm-video-v4l2: vidc: Add support for hypervisor

On hypervisor targets, video decode and encode core drivers
are in backend. The v4l2 calls are routed to backend via
video frontend driver. Video hypervisor intercept will intercept
calls that need to be propagated to video frontend driver.

Change-Id: Id4d95739814bd2b13e1cdee456eb3ee928c86f0c
diff --git a/Android.mk b/Android.mk
index 9eaaa6c..eae0e2b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -11,4 +11,7 @@
 include $(QCOM_MEDIA_ROOT)/mm-video-v4l2/Android.mk
 include $(QCOM_MEDIA_ROOT)/libc2dcolorconvert/Android.mk
 include $(QCOM_MEDIA_ROOT)/libarbitrarybytes/Android.mk
+ifeq ($(ENABLE_HYP),true)
+include $(QCOM_MEDIA_ROOT)/hypv-intercept/Android.mk
+endif
 endif
diff --git a/Makefile.am b/Makefile.am
index 937748f..f6478e7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,4 +8,8 @@
 BUILD_COMPONENTS += mm-video-v4l2
 endif
 
+if TARGET_HYPERVISOR
+BUILD_COMPONENTS += hypv-intercept
+endif
+
 SUBDIRS := $(BUILD_COMPONENTS)
diff --git a/configure.ac b/configure.ac
index 9a67851..3c1e6ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,6 +101,14 @@
                 [Enable conditional compile for build mm video [default=no]]),
         [build_mm_video="${enableval}"])
 
+AC_ARG_ENABLE([target-hypervisor],
+	AC_HELP_STRING([--enable-target-hypervisor],
+		[Enable conditional compile for target hypervisor [default=no]]),
+	[target_hypervisor="${enableval}"],
+	target_hypervisor=no)
+
+AM_CONDITIONAL(TARGET_HYPERVISOR, test "x$target_hypervisor" = "xyes")
+
 AC_ARG_WITH([sanitized-headers],
         [AS_HELP_STRING([--with-sanitized-headers=DIR],[location of the sanitized Linux kernel headers])],
         [CPPFLAGS="$CPPFLAGS -I $withval"])
@@ -203,3 +211,9 @@
         mm-video-v4l2/vidc/vdec/Makefile \
         ])
 AC_OUTPUT
+
+AM_COND_IF( [TARGET_HYPERVISOR], [
+AC_CONFIG_FILES([ \
+        hypv-intercept/Makefile \
+        ])])
+AC_OUTPUT
diff --git a/hypv-intercept/Android.mk b/hypv-intercept/Android.mk
new file mode 100644
index 0000000..00f066d
--- /dev/null
+++ b/hypv-intercept/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        hypv_intercept.cpp
+LOCAL_C_INCLUDES = $(TOP)/hardware/qcom/media/mm-video-v4l2/vidc/common/inc
+
+LOCAL_SHARED_LIBRARIES := liblog libdl
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := libhypv_intercept
+
+LOCAL_MODULE_PATH_32      := $(TARGET_OUT_VENDOR)/lib
+LOCAL_MODULE_PATH_64      := $(TARGET_OUT_VENDOR)/lib64
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/hypv-intercept/Makefile.am b/hypv-intercept/Makefile.am
new file mode 100644
index 0000000..75817cd
--- /dev/null
+++ b/hypv-intercept/Makefile.am
@@ -0,0 +1,23 @@
+# -----------------------------------------------------------------------------
+#               Common definitons
+# -----------------------------------------------------------------------------
+
+AM_CFLAGS = -g -O3
+AM_CFLAGS += -Werror
+
+AM_CPPFLAGS = -D_ANDROID_
+AM_CPPFLAGS += -DHAVE_ANDROID_OS
+AM_CPPFLAGS += -I$(top_srcdir)/mm-video-v4l2/vidc/common/inc
+
+# -----------------------------------------------------------------------------
+#           Make the Shared library (libhypv_intercept)
+# -----------------------------------------------------------------------------
+h_sources = hypv_intercept.h
+c_sources = hypv_intercept.cpp
+
+include_HEADERS = $(h_source)
+lib_LTLIBRARIES = libhypv_intercept.la
+libhypv_intercept_la_SOURCES = $(c_sources)
+libhypv_intercept_la_CFLAGS = $(AM_CFLAGS) -fPIC
+libhypv_intercept_la_CPPFLAGS = $(AM_CPPFLAGS)
+libhypv_intercept_la_LDFLAGS = -shared -llog -ldl
diff --git a/hypv-intercept/hypv_intercept.cpp b/hypv-intercept/hypv_intercept.cpp
new file mode 100644
index 0000000..e285d79
--- /dev/null
+++ b/hypv-intercept/hypv_intercept.cpp
@@ -0,0 +1,225 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include "hypv_intercept.h"
+#include "vidc_debug.h"
+
+typedef HVFE_HANDLE (*video_fe_open_func)(const char*, int, hvfe_callback_t*);
+typedef int (*video_fe_ioctl_func)(HVFE_HANDLE, int, void*);
+typedef int (*video_fe_close_func)(HVFE_HANDLE);
+
+#define MAX_HVFE_HANDLE_STORAGE     16
+#define HYPV_HANDLE_SIGNATURE       0x2bcd0000
+#define HYPV_HANDLE_SIGNATURE_MASK  0xffff0000
+#define HYPV_HANDLE_MASK            0x0000ffff
+
+static void *hvfe_lib_handle = NULL;
+static video_fe_open_func video_fe_open = NULL;
+static video_fe_ioctl_func video_fe_ioctl = NULL;
+static video_fe_close_func video_fe_close = NULL;
+static pthread_mutex_t g_hvfe_handle_lock = PTHREAD_MUTEX_INITIALIZER;
+static HVFE_HANDLE g_hvfe_handle_storage[MAX_HVFE_HANDLE_STORAGE];
+static int g_hvfe_handle_count  = 0;
+
+#define IS_HYPERVISOR_VIDEO_HANDLE(fd) ((fd & HYPV_HANDLE_SIGNATURE_MASK)==HYPV_HANDLE_SIGNATURE)
+#define HYP_INITIALIZED  (g_hvfe_handle_count > 0)
+
+static int add_to_hvfe_handle_storage(HVFE_HANDLE handle_to_store)
+{
+    int rc = 0;
+
+    if (g_hvfe_handle_count >= MAX_HVFE_HANDLE_STORAGE) {
+        DEBUG_PRINT_ERROR("reached max handle count");
+        rc = -1;
+    } else {
+        int i;
+
+        for (i = 0; i < MAX_HVFE_HANDLE_STORAGE; i++) {
+            if (g_hvfe_handle_storage[i] == 0) {
+                g_hvfe_handle_storage[i] = handle_to_store;
+                rc = i;
+                g_hvfe_handle_count++;
+                break;
+            }
+        }
+        if (i >= MAX_HVFE_HANDLE_STORAGE) {
+            DEBUG_PRINT_ERROR("failed to find empty slot");
+            rc = -1;
+        }
+    }
+
+    return rc;
+}
+
+static int hypv_init(void)
+{
+    int rc = 0;
+
+    hvfe_lib_handle = dlopen("libhyp_video_fe.so", RTLD_NOW);
+    if (hvfe_lib_handle == NULL) {
+        DEBUG_PRINT_ERROR("failed to open libhyp_video_fe");
+        rc = -1;
+    } else {
+        video_fe_open = (video_fe_open_func)dlsym(hvfe_lib_handle, "video_fe_open");
+        if (video_fe_open == NULL) {
+            DEBUG_PRINT_ERROR("failed to get video_fe_open handle");
+            rc = -1;
+        } else {
+            video_fe_ioctl = (video_fe_ioctl_func)dlsym(hvfe_lib_handle, "video_fe_ioctl");
+            if (video_fe_ioctl == NULL) {
+                DEBUG_PRINT_ERROR("failed to get video_fe_ioctl handle");
+                rc = -1;
+            } else {
+                video_fe_close = (video_fe_close_func)dlsym(hvfe_lib_handle, "video_fe_close");
+                if (video_fe_close == 0) {
+                    DEBUG_PRINT_ERROR("failed to get video_fe_close handle");
+                    rc = -1;
+                }//video_fe_close
+            } //video_fe_ioctl
+        } //video_fe_open
+    } //hvfe_lib_handle
+
+    if (rc < 0 && hvfe_lib_handle) {
+        dlclose(hvfe_lib_handle);
+        hvfe_lib_handle = NULL;
+    }
+
+    return rc;
+}
+
+static void hypv_deinit(void)
+{
+    dlclose(hvfe_lib_handle);
+    hvfe_lib_handle = NULL;
+
+    return;
+}
+
+int hypv_open(const char *str, int flag, hvfe_callback_t* cb)
+{
+    int rc = 0;
+
+    pthread_mutex_lock(&g_hvfe_handle_lock);
+    if (!HYP_INITIALIZED) {
+        if ((rc = hypv_init()) < 0) {
+            DEBUG_PRINT_ERROR("hypervisor init failed");
+            pthread_mutex_unlock(&g_hvfe_handle_lock);
+            return rc;
+        }
+    }
+
+    HVFE_HANDLE hvfe_handle = video_fe_open(str, flag, cb);
+    DEBUG_PRINT_INFO("video_fe_open handle=%p", hvfe_handle);
+    if (hvfe_handle == NULL) {
+        DEBUG_PRINT_ERROR("video_fe_open failed");
+        rc = -1;
+    } else {
+        int fd = add_to_hvfe_handle_storage(hvfe_handle);
+        if (fd < 0) {
+            DEBUG_PRINT_ERROR("failed to store hvfe handle");
+            video_fe_close(hvfe_handle);
+            rc = -1;
+        } else {
+            rc = (HYPV_HANDLE_SIGNATURE | fd);
+        }
+    }
+    pthread_mutex_unlock(&g_hvfe_handle_lock);
+
+    if (rc < 0)
+        hypv_deinit();
+
+    return rc;
+}
+
+int hypv_ioctl(int fd, int cmd, void *data)
+{
+    int rc = 0;
+
+    if (!HYP_INITIALIZED) {
+        DEBUG_PRINT_ERROR("hypervisor not initialized");
+        return -1;
+    }
+
+    if (IS_HYPERVISOR_VIDEO_HANDLE(fd)) {
+        int fd_index = fd & HYPV_HANDLE_MASK;
+        if (fd_index >= MAX_HVFE_HANDLE_STORAGE) {
+            DEBUG_PRINT_ERROR("invalid fd_index=%d", fd_index);
+            rc = -1;
+        } else {
+            rc = video_fe_ioctl(g_hvfe_handle_storage[fd_index], cmd, data);
+            DEBUG_PRINT_INFO("hyp ioctl: fd=%d, fd_index=%d, cmd=0x%x, data=0x%p, rc =%d",
+                              fd, fd_index, cmd, data, rc);
+        }
+    } else {
+        DEBUG_PRINT_ERROR("native ioctl: fd=%d, cmd=0x%x, data=0x%p", fd, cmd, data);
+        rc = ioctl(fd, cmd, data);
+    }
+
+    return rc;
+}
+
+int hypv_close(int fd)
+{
+    int rc = 0;
+
+    if (!HYP_INITIALIZED) {
+        DEBUG_PRINT_ERROR("hypervisor not initialized");
+        return -1;
+    }
+
+    if (IS_HYPERVISOR_VIDEO_HANDLE(fd)) {
+        int fd_index = fd & HYPV_HANDLE_MASK;
+
+        if ((fd_index >= MAX_HVFE_HANDLE_STORAGE) || (fd_index < 0)) {
+            DEBUG_PRINT_ERROR("invalid fd=%d", fd_index);
+            rc = -1;
+        } else {
+            pthread_mutex_lock(&g_hvfe_handle_lock);
+            rc = video_fe_close(g_hvfe_handle_storage[fd_index]);
+            g_hvfe_handle_storage[fd_index] = 0;
+            if (--g_hvfe_handle_count == 0)
+                hypv_deinit();
+            pthread_mutex_unlock(&g_hvfe_handle_lock);
+        }
+    } else {
+        rc = close(fd);
+    }
+
+    return rc;
+}
diff --git a/hypv-intercept/hypv_intercept.h b/hypv-intercept/hypv_intercept.h
new file mode 100644
index 0000000..422eaa9
--- /dev/null
+++ b/hypv-intercept/hypv_intercept.h
@@ -0,0 +1,45 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef __HYPV_INTERCEPT_H__
+#define __HYPV_INTERCEPT_H__
+
+typedef void* HVFE_HANDLE;
+typedef int (*hvfe_callback_handler_t)(void *context, void *message);
+
+struct hvfe_callback_t
+{
+    hvfe_callback_handler_t handler;
+    void* context;
+};
+
+int hypv_open(const char *str, int flag, hvfe_callback_t* cb);
+int hypv_ioctl(int fd, int cmd, void *data);
+int hypv_close(int fd);
+
+#endif
diff --git a/mm-video-v4l2/vidc/vdec/Android.mk b/mm-video-v4l2/vidc/vdec/Android.mk
index 6b390b2..d959ab1 100644
--- a/mm-video-v4l2/vidc/vdec/Android.mk
+++ b/mm-video-v4l2/vidc/vdec/Android.mk
@@ -88,6 +88,10 @@
 
 libmm-vdec-def += -DALLOCATE_OUTPUT_NATIVEHANDLE
 
+ifeq ($(ENABLE_HYP),true)
+libmm-vdec-def += -DHYPERVISOR
+libmm-vdec-inc += $(TOP)/hardware/qcom/media/hypv-intercept
+endif
 # ---------------------------------------------------------------------------------
 # 			Make the Shared library (libOmxVdec)
 # ---------------------------------------------------------------------------------
@@ -115,6 +119,9 @@
 LOCAL_SHARED_LIBRARIES  += libqdMetaData
 LOCAL_SHARED_LIBRARIES  += libplatformconfig
 LOCAL_SHARED_LIBRARIES  += libarbitrarybytes
+ifeq ($(ENABLE_HYP),true)
+LOCAL_SHARED_LIBRARIES  += libhypv_intercept
+endif
 
 LOCAL_SRC_FILES         := src/ts_parser.cpp
 LOCAL_STATIC_LIBRARIES  := libOmxVidcCommon
diff --git a/mm-video-v4l2/vidc/vdec/Makefile.am b/mm-video-v4l2/vidc/vdec/Makefile.am
index 691bb2d..4aebb42 100644
--- a/mm-video-v4l2/vidc/vdec/Makefile.am
+++ b/mm-video-v4l2/vidc/vdec/Makefile.am
@@ -22,6 +22,11 @@
 AM_CPPFLAGS += -D_ANDROID_ICS_
 AM_CPPFLAGS += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT
 AM_CPPFLAGS += -DNATIVE_BASE_DISABLE
+
+if TARGET_HYPERVISOR
+AM_CPPFLAGS += -DHYPERVISOR
+AM_CPPFLAGS += -I$(top_srcdir)/hypv-intercept/
+endif
 #AM_CPPFLAGS += "-include stdint.h"
 AM_CPPFLAGS += "-Dstrlcpy=g_strlcpy"
 AM_CPPFLAGS += "-Dstrlcat=g_strlcat"
@@ -77,3 +82,8 @@
 libOmxVdec_la_LDFLAGS += -llog  -lcutils -lglib-2.0 -lion -lqdMetaData
 libOmxVdec_la_LDFLAGS += -L$(top_builddir)/libc2dcolorconvert  -L$(top_builddir)/libplatformconfig -L$(top_builddir)/libarbitrarybytes
 libOmxVdec_la_LDFLAGS += -lc2dcolorconvert -lplatformconfig -larbitrarybytes
+
+if TARGET_HYPERVISOR
+libOmxVdec_la_LDFLAGS += -L$(top_builddir)/hypv-intercept
+libOmxVdec_la_LDFLAGS += -lhypv_intercept
+endif
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
index 98e6310..c8e6491 100644
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
@@ -52,6 +52,9 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <stdlib.h>
+#ifdef HYPERVISOR
+#include "hypv_intercept.h"
+#endif
 #include <media/hardware/HardwareAPI.h>
 #include <sys/eventfd.h>
 #include "PlatformConfig.h"
@@ -151,6 +154,10 @@
 
 using namespace android;
 
+#ifdef HYPERVISOR
+#define ioctl(x, y, z) hypv_ioctl(x, y, z)
+#endif
+
 static OMX_U32 maxSmoothStreamingWidth = 1920;
 static OMX_U32 maxSmoothStreamingHeight = 1088;
 
@@ -1042,7 +1049,11 @@
 
     unsubscribe_to_events(drv_ctx.video_driver_fd);
     close(m_poll_efd);
+#ifdef HYPERVISOR
+    hypv_close(drv_ctx.video_driver_fd);
+#else
     close(drv_ctx.video_driver_fd);
+#endif
     pthread_mutex_destroy(&m_lock);
     pthread_mutex_destroy(&c_lock);
     pthread_mutex_destroy(&buf_lock);
@@ -2333,7 +2344,14 @@
         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
     }
 
+#ifdef HYPERVISOR
+    hvfe_callback_t hvfe_cb;
+    hvfe_cb.handler = async_message_process;
+    hvfe_cb.context = (void *)this;
+    drv_ctx.video_driver_fd = hypv_open(device_name, O_RDWR, &hvfe_cb);
+#else
     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
+#endif
 
     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
 
@@ -2350,6 +2368,7 @@
         return OMX_ErrorInsufficientResources;
     }
     ret = subscribe_to_events(drv_ctx.video_driver_fd);
+#ifndef HYPERVISOR
     if (!ret) {
         async_thread_created = true;
         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
@@ -2359,6 +2378,7 @@
         async_thread_created = false;
         return OMX_ErrorInsufficientResources;
     }
+#endif
 
 #ifdef OUTPUT_EXTRADATA_LOG
     outputExtradataFile = fopen (output_extradata_filename, "ab");
@@ -9827,6 +9847,9 @@
         return false;
     }
 
+#ifdef HYPERVISOR
+    flag = 0;
+#endif
     ion_info->alloc_data.flags = flag;
     ion_info->alloc_data.len = buffer_size;
 
diff --git a/mm-video-v4l2/vidc/venc/Android.mk b/mm-video-v4l2/vidc/venc/Android.mk
index df6d876..5ea5cd5 100644
--- a/mm-video-v4l2/vidc/venc/Android.mk
+++ b/mm-video-v4l2/vidc/venc/Android.mk
@@ -53,6 +53,10 @@
 
 libmm-venc-def += -DUSE_CAMERA_METABUFFER_UTILS
 
+ifeq ($(ENABLE_HYP),true)
+libmm-venc-def += -DHYPERVISOR
+endif
+
 # Common Includes
 libmm-venc-inc      := $(LOCAL_PATH)/inc
 libmm-venc-inc      += $(TOP)/system/core/libion/include
@@ -69,6 +73,10 @@
 libmm-venc-inc      += $(TOP)/frameworks/native/libs/nativebase/include
 libmm-venc-inc      += $(TOP)/frameworks/native/libs/arect/include
 
+ifeq ($(ENABLE_HYP),true)
+libmm-venc-inc      += hardware/qcom/media/hypv-intercept
+endif
+
 ifneq ($(call is-board-platform-in-list, $(TARGETS_THAT_DONT_SUPPORT_SW_VENC_ROTATION)),true)
 libmm-venc-inc      += hardware/libhardware/include/hardware
 endif
@@ -105,6 +113,9 @@
 LOCAL_SHARED_LIBRARIES    += libc2dcolorconvert
 # endif # ($(BOARD_USES_ADRENO), true)
 LOCAL_SHARED_LIBRARIES += libqdMetaData
+ifeq ($(ENABLE_HYP),true)
+LOCAL_SHARED_LIBRARIES += libhypv_intercept
+endif
 LOCAL_STATIC_LIBRARIES    := libOmxVidcCommon
 
 LOCAL_SRC_FILES   := src/omx_video_base.cpp
diff --git a/mm-video-v4l2/vidc/venc/Makefile.am b/mm-video-v4l2/vidc/venc/Makefile.am
index 16186c3..906fde7 100644
--- a/mm-video-v4l2/vidc/venc/Makefile.am
+++ b/mm-video-v4l2/vidc/venc/Makefile.am
@@ -19,6 +19,12 @@
 AM_CPPFLAGS += -UOUTPUT_BUFFER_LOG
 AM_CPPFLAGS += -Werror
 AM_CPPFLAGS += -D_ANDROID_ICS_
+
+if TARGET_HYPERVISOR
+AM_CPPFLAGS += -DHYPERVISOR
+AM_CPPFLAGS += -I$(top_srcdir)/hypv-intercept/
+endif
+
 AM_CPPFLAGS += -DUSE_ION
 AM_CPPFLAGS += -Wno-enum-compare
 #AM_CPPFLAGS += "-include stdint.h"
@@ -79,5 +85,10 @@
 libOmxVenc_la_LDFLAGS = -module -shared -avoid-version
 libOmxVenc_la_LDFLAGS += -lstdc++ -lpthread -llog -lutils -lcutils -lglib-2.0 -lbase -ldl -lpthread -lion
 
-libOmxVenc_la_LDFLAGS += -L$(top_builddir)/libc2dcolorconvert  -L$(top_builddir)/libplatformconfig -L$(top_builddir)/libarbitrarybytes
-libOmxVenc_la_LDFLAGS += -lc2dcolorconvert -lplatformconfig -larbitrarybytes
+libOmxVenc_la_LDFLAGS += -L$(top_builddir)/libplatformconfig
+libOmxVenc_la_LDFLAGS += -lplatformconfig
+
+if TARGET_HYPERVISOR
+libOmxVenc_la_LDFLAGS += -L$(top_builddir)/hypv-intercept
+libOmxVenc_la_LDFLAGS += -lhypv_intercept
+endif
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
index 3f8330f..7abcd5a 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2018, Linux Foundation. All rights reserved.
+Copyright (c) 2010-2019, Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -5116,6 +5116,9 @@
                 (unsigned int)ion_info->alloc_data.len,
                 ion_info->alloc_data.flags);
     }
+#ifdef HYPERVISOR
+    ion_info->alloc_data.flags &= (~ION_FLAG_CACHED);
+#endif
 
     rc = ion_alloc_fd(ion_info->dev_fd, ion_info->alloc_data.len, 0,
                       ion_info->alloc_data.heap_id_mask,
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
index cec4bc5..6a9c5bf 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -620,6 +620,7 @@
             msg_thread_created = false;
             goto init_error;
         } else {
+#ifndef HYPERVISOR
             async_thread_created = true;
             r = pthread_create(&async_thread_id,0, venc_dev::async_venc_message_thread, this);
             if (r < 0) {
@@ -632,6 +633,7 @@
                 goto init_error;
             } else
                 dev_set_message_thread_id(async_thread_id);
+#endif
         }
     }
 
diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index 323e619..368a152 100644
--- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -35,6 +35,9 @@
 #include "video_encoder_device_v4l2.h"
 #include "omx_video_encoder.h"
 #include "media/msm_vidc_utils.h"
+#ifdef HYPERVISOR
+#include "hypv_intercept.h"
+#endif
 #ifdef USE_ION
 #include <linux/msm_ion.h>
 #endif
@@ -64,6 +67,10 @@
 
 #define YUV_STATS_LIBRARY_NAME "libgpustats.so" // UBWC case: use GPU library
 
+#ifdef HYPERVISOR
+#define ioctl(x, y, z) hypv_ioctl(x, y, z)
+#endif
+
 #undef ALIGN
 #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))
 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
@@ -1630,6 +1637,65 @@
     return status;
 }
 
+#ifdef HYPERVISOR
+static int async_message_process_v4l2 (void *context, void* message)
+{
+    int rc = 0;
+    struct v4l2_buffer *v4l2_buf=NULL;
+    OMX_BUFFERHEADERTYPE* omxhdr = NULL;
+    struct venc_msg *vencmsg = (venc_msg *)message;
+    venc_dev *vencdev = reinterpret_cast<venc_dev*>(context);
+    omx_venc *omx = vencdev->venc_handle;
+    omx_video *omx_venc_base = (omx_video *)vencdev->venc_handle;
+
+    if (VEN_MSG_OUTPUT_BUFFER_DONE == vencmsg->msgcode) {
+        v4l2_buf = (struct v4l2_buffer *)vencmsg->buf.clientdata;
+        omxhdr=omx_venc_base->m_out_mem_ptr+v4l2_buf->index;
+        vencmsg->buf.len= v4l2_buf->m.planes->bytesused;
+        vencmsg->buf.offset = v4l2_buf->m.planes->data_offset;
+        vencmsg->buf.flags = 0;
+        vencmsg->buf.ptrbuffer = (OMX_U8 *)omx_venc_base->m_pOutput_pmem[v4l2_buf->index].buffer;
+        vencmsg->buf.clientdata=(void*)omxhdr;
+        vencmsg->buf.timestamp = (uint64_t) v4l2_buf->timestamp.tv_sec *
+                                 (uint64_t) 1000000 + (uint64_t) v4l2_buf->timestamp.tv_usec;
+
+        if (v4l2_buf->flags & V4L2_BUF_FLAG_KEYFRAME)
+            vencmsg->buf.flags |= OMX_BUFFERFLAG_SYNCFRAME;
+
+        if (v4l2_buf->flags & V4L2_BUF_FLAG_PFRAME) {
+            vencmsg->buf.flags |= OMX_VIDEO_PictureTypeP;
+        } else if (v4l2_buf->flags & V4L2_BUF_FLAG_BFRAME) {
+            vencmsg->buf.flags |= OMX_VIDEO_PictureTypeB;
+        }
+
+        if (v4l2_buf->flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
+            vencmsg->buf.flags |= OMX_BUFFERFLAG_CODECCONFIG;
+
+        if (v4l2_buf->flags & V4L2_QCOM_BUF_FLAG_EOS)
+            vencmsg->buf.flags |= OMX_BUFFERFLAG_EOS;
+
+        if (vencdev->num_output_planes > 1 && v4l2_buf->m.planes->bytesused)
+            vencmsg->buf.flags |= OMX_BUFFERFLAG_EXTRADATA;
+
+        if (omxhdr->nFilledLen)
+            vencmsg->buf.flags |= OMX_BUFFERFLAG_ENDOFFRAME;
+        vencdev->fbd++;
+    } else if (VEN_MSG_INPUT_BUFFER_DONE == vencmsg->msgcode) {
+        v4l2_buf = (struct v4l2_buffer *)vencmsg->buf.clientdata;
+        vencdev->ebd++;
+        if (omx_venc_base->mUseProxyColorFormat && !omx_venc_base->mUsesColorConversion)
+            omxhdr = &omx_venc_base->meta_buffer_hdr[v4l2_buf->index];
+        else
+            omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf->index];
+        vencmsg->buf.clientdata=(void*)omxhdr;
+        DEBUG_PRINT_LOW("sending EBD %p [id=%d]", omxhdr, v4l2_buf->index);
+    }
+    rc = omx->async_message_process((void *)omx, message);
+
+    return rc;
+}
+#endif
+
 bool venc_dev::venc_open(OMX_U32 codec)
 {
     int r, minqp = 0, maxqp = 127;
@@ -1647,7 +1713,16 @@
         device_name = (OMX_STRING)"/dev/video/q6_enc";
         supported_rc_modes = (RC_ALL & ~RC_CBR_CFR);
     }
-    m_nDriver_fd = open (device_name, O_RDWR);
+
+#ifdef HYPERVISOR
+    hvfe_callback_t hvfe_cb;
+    hvfe_cb.handler = async_message_process_v4l2;
+    hvfe_cb.context = (void *) this;
+    m_nDriver_fd = hypv_open(device_name, O_RDWR, &hvfe_cb);
+#else
+    m_nDriver_fd = open(device_name, O_RDWR);
+#endif
+
     if ((int)m_nDriver_fd < 0) {
         DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure");
         return false;
@@ -1910,7 +1985,11 @@
         DEBUG_PRINT_HIGH("venc_close X");
         unsubscribe_to_events(m_nDriver_fd);
         close(m_poll_efd);
+#ifdef HYPERVISOR
+        hypv_close(m_nDriver_fd);
+#else
         close(m_nDriver_fd);
+#endif
         m_nDriver_fd = -1;
     }