summaryrefslogtreecommitdiff
authorKieth Liu <kieth.liu@amlogic.com>2015-09-22 02:21:09 (GMT)
committer Kieth Liu <kieth.liu@amlogic.com>2015-09-22 02:41:54 (GMT)
commit737fb2980a2e8953db2cca86c00b4abf96bfe4c8 (patch)
treec17c66d349f74718ea5ba42d4d4b2008f8e94905
parent2f2a5755ca37edbcaad527897662ac9120b53999 (diff)
downloadtv_input-737fb2980a2e8953db2cca86c00b4abf96bfe4c8.zip
tv_input-737fb2980a2e8953db2cca86c00b4abf96bfe4c8.tar.gz
tv_input-737fb2980a2e8953db2cca86c00b4abf96bfe4c8.tar.bz2
add frame capture API
Change-Id: Ib8c2abcdedb5572d9e1af33a7602acd2ef06ff4b
Diffstat
-rw-r--r--Android.mk43
-rw-r--r--screen_source/Android.mk31
-rw-r--r--screen_source/aml_screen.cpp296
-rw-r--r--screen_source/v4l2_vdin.cpp676
-rw-r--r--screen_source/v4l2_vdin.h144
-rw-r--r--tv_input.cpp54
6 files changed, 1226 insertions, 18 deletions
diff --git a/Android.mk b/Android.mk
index d5ddce6..b7040c8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -11,33 +11,48 @@ TVAPI_PATH := $(LOCAL_PATH)/tvapi
LIB_SQLITE_PATH := $(wildcard external/sqlite)
AM_LIBPLAYER_PATH := $(wildcard vendor/amlogic/frameworks/av/LibPlayer)
+
+ifneq (,$(wildcard hardware/amlogic/gralloc))
+ GRALLOC_DIR := hardware/amlogic/gralloc
+else
+ GRALLOC_DIR := hardware/libhardware/modules/gralloc
+endif
+
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := libcutils liblog
-LOCAL_SRC_FILES := tv_input.cpp
+LOCAL_SRC_FILES := tv_input.cpp \
+screen_source/v4l2_vdin.cpp
LOCAL_MODULE := tv_input.amlogic
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES += \
$(TVAPI_PATH)/libtv \
$(TVAPI_PATH)/android \
- $(DVB_PATH)/android/ndk/include \
- $(DVB_PATH)/include/am_adp \
- $(DVB_PATH)/include/am_mw \
- $(DVB_PATH)/include/am_ver \
- $(DVB_PATH)/android/ndk/include \
+ $(DVB_PATH)/android/ndk/include \
+ $(DVB_PATH)/include/am_adp \
+ $(DVB_PATH)/include/am_mw \
+ $(DVB_PATH)/include/am_ver \
+ $(DVB_PATH)/android/ndk/include \
$(LIB_SQLITE_PATH)/dist \
- $(TVAPI_PATH)/libtv/tvdb \
- $(TVAPI_PATH)/libtv/tv \
- $(TVAPI_PATH)/libtv/include \
- $(AM_LIBPLAYER_PATH)/amadec/include \
- $(AM_LIBPLAYER_PATH)/amcodec/include \
- $(AM_LIBPLAYER_PATH)/amffmpeg \
- $(AM_LIBPLAYER_PATH)/amplayer \
- system/media/audio_effects/include \
+ $(TVAPI_PATH)/libtv/tvdb \
+ $(TVAPI_PATH)/libtv/tv \
+ $(TVAPI_PATH)/libtv/include \
+ $(AM_LIBPLAYER_PATH)/amadec/include \
+ $(AM_LIBPLAYER_PATH)/amcodec/include \
+ $(AM_LIBPLAYER_PATH)/amffmpeg \
+ $(AM_LIBPLAYER_PATH)/amplayer \
+ system/media/audio_effects/include \
+ system/core/libion/include \
+ system/core/libion/kernel-headers \
+ $(GRALLOC_DIR) \
+ screen_source
LOCAL_SHARED_LIBRARIES += \
libtv \
libtvserver \
libtv_jni
+
+LOCAL_SHARED_LIBRARIES += libutils liblog libui
+
include $(BUILD_SHARED_LIBRARY)
include $(LOCAL_PATH)/tvapi/Android.mk
diff --git a/screen_source/Android.mk b/screen_source/Android.mk
new file mode 100644
index 0000000..a40269f
--- a/dev/null
+++ b/screen_source/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2013 Amlogic
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# /system/lib/hw/screen_source.amlogic.so
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := aml_screen.cpp v4l2_vdin.cpp
+
+ifneq (,$(wildcard hardware/amlogic/gralloc))
+ GRALLOC_DIR := hardware/amlogic/gralloc
+else
+ GRALLOC_DIR := hardware/libhardware/modules/gralloc
+endif
+
+LOCAL_C_INCLUDES += frameworks/native/include/utils \
+ frameworks/native/include/android \
+ system/core/include/utils \
+ system/core/libion/include \
+ system/core/libion/kernel-headers \
+ $(GRALLOC_DIR)
+
+LOCAL_SHARED_LIBRARIES:= libutils liblog libui
+
+LOCAL_MODULE := screen_source.amlogic
+LOCAL_CFLAGS:= -DLOG_TAG=\"screen_source\"
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
diff --git a/screen_source/aml_screen.cpp b/screen_source/aml_screen.cpp
new file mode 100644
index 0000000..62fb94b
--- a/dev/null
+++ b/screen_source/aml_screen.cpp
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "screen_source"
+#include <hardware/hardware.h>
+#include <hardware/aml_screen.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <linux/videodev2.h>
+#include <sys/time.h>
+
+
+#include <errno.h>
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include "v4l2_vdin.h"
+
+#ifndef LOGD
+#define LOGD ALOGD
+#endif
+#ifndef LOGV
+#define LOGV ALOGV
+#endif
+#ifndef LOGE
+#define LOGE ALOGE
+#endif
+#ifndef LOGI
+#define LOGI ALOGI
+#endif
+
+static unsigned int gAmlScreenOpen = 0;
+static android::Mutex gAmlScreenLock;
+
+/*****************************************************************************/
+
+static int aml_screen_device_open(const struct hw_module_t *module, const char *name,
+ struct hw_device_t **device);
+
+static struct hw_module_methods_t aml_screen_module_methods = {
+open:
+ aml_screen_device_open
+};
+
+aml_screen_module_t HAL_MODULE_INFO_SYM = {
+common:
+ {
+tag:
+ HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+id:
+ AML_SCREEN_HARDWARE_MODULE_ID,
+name: "aml screen source module"
+ ,
+author: "Amlogic"
+ ,
+methods:
+ &aml_screen_module_methods,
+dso :
+ NULL,
+reserved :
+ {0},
+ }
+};
+
+/*****************************************************************************/
+
+static int aml_screen_device_close(struct hw_device_t *dev)
+{
+ android::vdin_screen_source *source = NULL;
+ aml_screen_device_t *ctx = (aml_screen_device_t *)dev;
+
+ android::Mutex::Autolock lock(gAmlScreenLock);
+ if (ctx) {
+ if (ctx->priv) {
+ source = (android::vdin_screen_source *)ctx->priv;
+ delete source;
+ source = NULL;
+ }
+ free(ctx);
+ }
+ gAmlScreenOpen--;
+ return 0;
+}
+
+int screen_source_start(struct aml_screen_device *dev)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->start();
+}
+
+int screen_source_stop(struct aml_screen_device *dev)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->stop();
+}
+
+int screen_source_pause(struct aml_screen_device *dev)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->pause();
+}
+
+int screen_source_get_format(struct aml_screen_device *dev)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->get_format();
+}
+
+int screen_source_set_format(struct aml_screen_device *dev, int width, int height, int pix_format)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+
+ if ((width > 0) && (height > 0) && ((pix_format == V4L2_PIX_FMT_NV21) || (pix_format == V4L2_PIX_FMT_YUV420))) {
+ return source->set_format(width, height, pix_format);
+ } else {
+ return source->set_format();
+ }
+}
+
+int screen_source_set_rotation(struct aml_screen_device *dev, int degree)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->set_rotation(degree);
+}
+
+int screen_source_set_crop(struct aml_screen_device *dev, int x, int y, int width, int height)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+
+ if ((x >= 0) && (y >= 0) && (width > 0) && (height > 0))
+ return source->set_crop(x, y, width, height);
+
+ return android::BAD_VALUE;
+}
+
+int screen_source_set_amlvideo2_crop(struct aml_screen_device *dev, int x, int y, int width, int height)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+
+ if ((x >= 0) && (y >= 0) && (width > 0) && (height > 0))
+ return source->set_amlvideo2_crop(x, y, width, height);
+
+ return android::BAD_VALUE;
+}
+
+int screen_source_aquire_buffer(struct aml_screen_device *dev, aml_screen_buffer_info_t *buff_info)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+
+ return source->aquire_buffer(buff_info);
+}
+
+int screen_source_release_buffer(struct aml_screen_device *dev, long *ptr)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->release_buffer(ptr);
+}
+
+int screen_source_set_state_callback(struct aml_screen_device *dev, olStateCB callback)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->set_state_callback(callback);
+}
+
+int screen_source_set_preview_window(struct aml_screen_device *dev, ANativeWindow *window)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->set_preview_window(window);
+}
+
+int screen_source_set_data_callback(struct aml_screen_device *dev, app_data_callback callback, void *user)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->set_data_callback(callback, user);
+}
+
+int screen_source_set_frame_rate(struct aml_screen_device *dev, int frameRate)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->set_frame_rate(frameRate);
+}
+
+int screen_source_set_source_type(struct aml_screen_device *dev, SOURCETYPE sourceType)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->set_source_type(sourceType);
+}
+
+int screen_source_get_source_type(struct aml_screen_device *dev)
+{
+ android::vdin_screen_source *source = (android::vdin_screen_source *)dev->priv;
+ return source->get_source_type();
+}
+
+/* int screen_source_inc_buffer_refcount(struct aml_screen_device* dev, int* ptr)
+{
+ android::vdin_screen_source* source = (android::vdin_screen_source*)dev->priv;
+ return source->inc_buffer_refcount(ptr);
+} */
+
+/*****************************************************************************/
+
+static int aml_screen_device_open(const struct hw_module_t *module, const char *name,
+ struct hw_device_t **device)
+{
+ int status = -EINVAL;
+ android::vdin_screen_source *source = NULL;
+ android::Mutex::Autolock lock(gAmlScreenLock);
+
+ LOGV("aml_screen_device_open");
+
+ if (!strcmp(name, AML_SCREEN_SOURCE)) {
+ if (gAmlScreenOpen > 1) {
+ ALOGD("aml screen device already open");
+ *device = NULL;
+ return -EINVAL;
+ }
+
+ aml_screen_device_t *dev = (aml_screen_device_t *)malloc(sizeof(aml_screen_device_t));
+
+ if (!dev) {
+ LOGE("no memory for the screen source device");
+ return -ENOMEM;
+ }
+ /* initialize handle here */
+ memset(dev, 0, sizeof(*dev));
+
+ source = new android::vdin_screen_source;
+ if (!source) {
+ LOGE("no memory for class of vdin_screen_source");
+ free (dev);
+ return -ENOMEM;
+ }
+
+ if (source->init() != 0) {
+ LOGE("open vdin_screen_source failed!");
+ free (dev);
+ return -1;
+ }
+
+ dev->priv = (void *)source;
+
+ /* initialize the procs */
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = const_cast<hw_module_t *>(module);
+ dev->common.close = aml_screen_device_close;
+
+ dev->ops.start = screen_source_start;
+ dev->ops.stop = screen_source_stop;
+ dev->ops.pause = screen_source_pause;
+ dev->ops.get_format = screen_source_get_format;
+ dev->ops.set_format = screen_source_set_format;
+ dev->ops.set_rotation = screen_source_set_rotation;
+ dev->ops.set_crop = screen_source_set_crop;
+ dev->ops.set_amlvideo2_crop = screen_source_set_amlvideo2_crop;
+ dev->ops.aquire_buffer = screen_source_aquire_buffer;
+ dev->ops.release_buffer = screen_source_release_buffer;
+ dev->ops.setStateCallBack = screen_source_set_state_callback;
+ dev->ops.setPreviewWindow = screen_source_set_preview_window;
+ dev->ops.setDataCallBack = screen_source_set_data_callback;
+ dev->ops.set_frame_rate = screen_source_set_frame_rate;
+ dev->ops.set_source_type = screen_source_set_source_type;
+ dev->ops.get_source_type = screen_source_get_source_type;
+ // dev->ops.inc_buffer_refcount = screen_source_inc_buffer_refcount;
+ *device = &dev->common;
+ status = 0;
+ gAmlScreenOpen++;
+ }
+ return status;
+}
diff --git a/screen_source/v4l2_vdin.cpp b/screen_source/v4l2_vdin.cpp
new file mode 100644
index 0000000..bd63166
--- a/dev/null
+++ b/screen_source/v4l2_vdin.cpp
@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+
+
+//reinclude because of a bug with the log macros
+//#define LOG_NDEBUG 0
+#define LOG_TAG "V4L2VINSOURCE"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <linux/videodev2.h>
+#include <sys/time.h>
+
+#include <cutils/properties.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "v4l2_vdin.h"
+#include <ui/GraphicBufferMapper.h>
+#include <ui/GraphicBuffer.h>
+#include <linux/videodev2.h>
+
+namespace android {
+
+#define V4L2_ROTATE_ID 0x980922
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *) 0)->member) *__mptr = (ptr); \
+ (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
+#endif
+
+#define BOUNDRY 32
+
+#define ALIGN(x) (x + (BOUNDRY) - 1)& ~((BOUNDRY) - 1)
+
+ static size_t getBufSize(int format, int width, int height)
+ {
+ size_t buf_size = 0;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_NV21:
+ buf_size = width * height * 3 / 2;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_RGB565:
+ buf_size = width * height * 2;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ buf_size = width * height * 3;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ buf_size = width * height * 4;
+ break;
+ default:
+ ALOGE("Invalid format");
+ buf_size = 0;
+ }
+ return buf_size;
+ }
+
+ static int getNativeWindowFormat(int format)
+ {
+ int nativeFormat = HAL_PIXEL_FORMAT_YCbCr_422_I;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YVU420:
+ nativeFormat = HAL_PIXEL_FORMAT_YV12;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ nativeFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ nativeFormat = HAL_PIXEL_FORMAT_YCbCr_422_I;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ nativeFormat = HAL_PIXEL_FORMAT_RGB_565;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ nativeFormat = HAL_PIXEL_FORMAT_RGB_888;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ nativeFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ break;
+ default:
+ ALOGE("Invalid format,Use default format");
+ }
+ return nativeFormat;
+ }
+
+
+ static ANativeWindowBuffer *handle_to_buffer(buffer_handle_t *handle)
+ {
+ return container_of(handle, ANativeWindowBuffer, handle);
+ }
+
+ vdin_screen_source::vdin_screen_source()
+ : mCameraHandle(-1),
+ mVideoInfo(NULL)
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ }
+
+ int vdin_screen_source::init()
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ mCameraHandle = open("/dev/video11", O_RDWR | O_NONBLOCK);
+ if (mCameraHandle < 0) {
+ ALOGE("[%s %d] mCameraHandle:%x [%s]", __FUNCTION__, __LINE__, mCameraHandle, strerror(errno));
+ return -1;
+ }
+ mVideoInfo = (struct VideoInfo *) calloc (1, sizeof (struct VideoInfo));
+ if (mVideoInfo == NULL) {
+ ALOGE("[%s %d] no memory for mVideoInfo", __FUNCTION__, __LINE__);
+ close(mCameraHandle);
+ return NO_MEMORY;
+ }
+ mBufferCount = 4;
+ mPixelFormat = V4L2_PIX_FMT_NV21;
+ mNativeWindowPixelFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ mFrameWidth = 1280;
+ mFrameHeight = 720;
+ mBufferSize = mFrameWidth * mFrameHeight * 3 / 2;
+ mSetStateCB = NULL;
+ mState = STOP;
+ mANativeWindow = NULL;
+ mFrameType = 0;
+ mWorkThread = NULL;
+ mDataCB = NULL;
+ mOpen = false;
+ return NO_ERROR;
+ }
+
+ vdin_screen_source::~vdin_screen_source()
+ {
+ if (mVideoInfo) {
+ free (mVideoInfo);
+ }
+ if (mCameraHandle >= 0) {
+ close(mCameraHandle);
+ }
+ }
+
+ int vdin_screen_source::start_v4l2_device()
+ {
+ int ret = -1;
+
+ ALOGV("[%s %d] mCameraHandle:%x", __FUNCTION__, __LINE__, mCameraHandle);
+
+ ioctl(mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap);
+
+ mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
+ mVideoInfo->rb.count = mBufferCount;
+
+ ret = ioctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
+
+ if (ret < 0) {
+ ALOGE("[%s %d] VIDIOC_REQBUFS:%d mCameraHandle:%x", __FUNCTION__, __LINE__, ret, mCameraHandle);
+ return ret;
+ }
+
+ for (int i = 0; i < mBufferCount; i++) {
+ memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
+
+ mVideoInfo->buf.index = i;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ ALOGE("[%s %d]VIDIOC_QUERYBUF %d failed", __FUNCTION__, __LINE__, i);
+ return ret;
+ }
+ mVideoInfo->canvas[i] = mVideoInfo->buf.reserved;
+ mVideoInfo->mem[i] = (long *)mmap (0, mVideoInfo->buf.length, PROT_READ | PROT_WRITE,
+ MAP_SHARED, mCameraHandle, mVideoInfo->buf.m.offset);
+
+ if (mVideoInfo->mem[i] == MAP_FAILED) {
+ ALOGE("[%s %d] MAP_FAILED", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ mVideoInfo->refcount[i] = 0;
+ mBufs.add(mVideoInfo->mem[i], i);
+ }
+ ALOGV("[%s %d] VIDIOC_QUERYBUF successful", __FUNCTION__, __LINE__);
+
+ for (int i = 0; i < mBufferCount; i++) {
+ mVideoInfo->buf.index = i;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ ALOGE("VIDIOC_QBUF Failed");
+ return -1;
+ }
+ }
+ enum v4l2_buf_type bufType;
+ bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
+
+ ALOGV("[%s %d] VIDIOC_STREAMON:%x", __FUNCTION__, __LINE__, ret);
+ return ret;
+ }
+
+ int vdin_screen_source::stop_v4l2_device()
+ {
+ int ret;
+ enum v4l2_buf_type bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType);
+ if (ret < 0) {
+ ALOGE("StopStreaming: Unable to stop capture: %s", strerror(errno));
+ }
+ for (int i = 0; i < mBufferCount; i++) {
+ if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) {
+ ALOGE("Unmap failed");
+ }
+ }
+ return ret;
+ }
+
+ int vdin_screen_source::start()
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int ret;
+ if (mOpen == true) {
+ ALOGI("already open");
+ return NO_ERROR;
+ }
+
+ ret = start_v4l2_device();
+ if (ret != NO_ERROR) {
+ ALOGE("Start v4l2 device failed:%d", ret);
+ return ret;
+ }
+ if (mFrameType & NATIVE_WINDOW_DATA) {
+ ret = init_native_window();
+ if (ret != NO_ERROR) {
+ ALOGE("Init Native Window Failed:%d", ret);
+ return ret;
+ }
+ }
+ if (mFrameType & NATIVE_WINDOW_DATA || mFrameType & CALL_BACK_DATA) {
+ ALOGD("Create Work Thread");
+ mWorkThread = new WorkThread(this);
+ }
+ if (mSetStateCB != NULL) {
+ mSetStateCB(START);
+ }
+ mState = START;
+ mOpen = true;
+ ALOGV("%s %d ret:%d", __FUNCTION__, __LINE__, ret);
+ return NO_ERROR;
+ }
+
+ int vdin_screen_source::pause()
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ mState = PAUSE;
+ if (mSetStateCB != NULL) {
+ mSetStateCB(PAUSE);
+ }
+ return NO_ERROR;
+ }
+ int vdin_screen_source::stop()
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int ret;
+ mState = STOPING;
+
+ if (mWorkThread != NULL) {
+ mWorkThread->requestExitAndWait();
+ mWorkThread.clear();
+ }
+
+ mBufferCount = 0;
+ mState = STOP;
+ if (mSetStateCB != NULL) {
+ mSetStateCB(STOP);
+ }
+ mOpen = false;
+ return ret;
+ }
+
+ int vdin_screen_source::set_state_callback(olStateCB callback)
+ {
+ if (!callback) {
+ ALOGE("NULL state callback pointer");
+ return BAD_VALUE;
+ }
+ mSetStateCB = callback;
+ return NO_ERROR;
+ }
+
+ int vdin_screen_source::set_preview_window(ANativeWindow *window)
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ if (mOpen == true) {
+ return NO_ERROR;
+ }
+ //can work without a valid window object ?
+ if (window == NULL) {
+ ALOGD("NULL window object passed to ScreenSource");
+ if (mWorkThread != NULL) {
+ mWorkThread->requestExitAndWait();
+ mWorkThread.clear();
+ }
+ mFrameType &= ~NATIVE_WINDOW_DATA;
+ return NO_ERROR;
+ }
+ mFrameType |= NATIVE_WINDOW_DATA;
+ mANativeWindow = window;
+ return NO_ERROR;
+ }
+
+ int vdin_screen_source::set_data_callback(app_data_callback callback, void *user)
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ if (callback == NULL) {
+ ALOGE("NULL data callback pointer");
+ return BAD_VALUE;
+ }
+ mDataCB = callback;
+ mUser = user;
+ mFrameType |= CALL_BACK_DATA;
+ return NO_ERROR;
+ }
+
+ int vdin_screen_source::get_format()
+ {
+ return mPixelFormat;
+ }
+
+ int vdin_screen_source::set_format(int width, int height, int color_format)
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ if (mOpen == true) {
+ return NO_ERROR;
+ }
+ int ret;
+ mVideoInfo->width = ALIGN(width);
+ mVideoInfo->height = height;
+ mVideoInfo->framesizeIn = (mVideoInfo->width * mVideoInfo->height << 3); //note color format
+ mVideoInfo->formatIn = color_format;
+
+ mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->format.fmt.pix.width = ALIGN(width);
+ mVideoInfo->format.fmt.pix.height = height;
+ mVideoInfo->format.fmt.pix.pixelformat = color_format;
+ mPixelFormat = color_format;
+ mNativeWindowPixelFormat = getNativeWindowFormat(color_format);
+ mFrameWidth = ALIGN(width);
+ mFrameHeight = height;
+ mBufferSize = getBufSize(color_format, mFrameWidth, mFrameHeight);
+ ALOGD("mFrameWidth:%d,mFrameHeight:%d", mFrameWidth, mFrameHeight);
+ ALOGD("mPixelFormat:%x,mNativeWindowPixelFormat:%x,mBufferSize:%d", mPixelFormat, mNativeWindowPixelFormat, mBufferSize);
+ ret = ioctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format);
+ if (ret < 0) {
+ ALOGE("[%s %d]VIDIOC_S_FMT %d", __FUNCTION__, __LINE__, ret);
+ return ret;
+ }
+ return ret;
+ }
+
+ int vdin_screen_source::set_rotation(int degree)
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+
+ int ret = 0;
+ struct v4l2_control ctl;
+
+ if (mCameraHandle < 0) {
+ return -1;
+ }
+
+ if ((degree != 0) && (degree != 90) && (degree != 180) && (degree != 270)) {
+ ALOGE("Set rotate value invalid: %d.", degree);
+ return -1;
+ }
+
+ memset( &ctl, 0, sizeof(ctl));
+ ctl.value = degree;
+ ctl.id = V4L2_ROTATE_ID;
+ ret = ioctl(mCameraHandle, VIDIOC_S_CTRL, &ctl);
+
+ if (ret < 0) {
+ ALOGE("Set rotate value fail: %s. ret=%d", strerror(errno), ret);
+ }
+ return ret ;
+ }
+
+ int vdin_screen_source::set_crop(int x, int y, int width, int height)
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ if (NULL == mANativeWindow.get())
+ return BAD_VALUE;
+
+ int err = NO_ERROR;
+ android_native_rect_t crop = { x, y, x + width - 1, y + height - 1 };
+ err = native_window_set_crop(mANativeWindow.get(), &crop);
+ if (err != 0) {
+ ALOGW("Failed to set crop!");
+ return err;
+ }
+ return NO_ERROR;
+ }
+
+ int vdin_screen_source::set_frame_rate(int frameRate)
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ int ret = 0;
+ struct v4l2_control ctl;
+
+ if (mCameraHandle < 0) {
+ return -1;
+ }
+
+ struct v4l2_streamparm sparm;
+ memset(&sparm, 0, sizeof( sparm ));
+ sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//stream_flag;
+ sparm.parm.output.timeperframe.denominator = frameRate;
+ sparm.parm.output.timeperframe.numerator = 1;
+
+ ret = ioctl(mCameraHandle, VIDIOC_S_PARM, &sparm);
+ if (ret < 0) {
+ ALOGE("Set frame rate fail: %s. ret=%d", strerror(errno), ret);
+ }
+ return ret ;
+ }
+
+ int vdin_screen_source::set_amlvideo2_crop(int x, int y, int width, int height)
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ int ret = 0;
+
+ struct v4l2_crop crop;
+ memset(&crop, 0, sizeof(struct v4l2_crop));
+
+ crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ crop.c.left = x;
+ crop.c.top = y;
+ crop.c.width = width;
+ crop.c.height = height;
+ ret = ioctl(mCameraHandle, VIDIOC_S_CROP, &crop);
+ if (ret) {
+ ALOGE("Set frame rate fail: %s. ret=%d", strerror(errno), ret);
+ }
+
+ return ret ;
+ }
+
+ int vdin_screen_source::set_source_type(int sourceType)
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ int ret = 0;
+
+ ret = ioctl(mCameraHandle, VIDIOC_S_INPUT, &sourceType);
+ if (ret < 0) {
+ ALOGE("Set source type fail: %s. ret:%d", strerror(errno), ret);
+ }
+ return ret;
+ }
+
+ int vdin_screen_source::get_source_type()
+ {
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ int ret = -1;
+ int sourceType;
+
+ ret = ioctl(mCameraHandle, VIDIOC_G_INPUT, &sourceType);
+ if (ret < 0) {
+ ALOGE("Set source type fail: %s. ret:%d", strerror(errno), ret);
+ return ret;
+ }
+ return sourceType;
+ }
+
+ int vdin_screen_source::aquire_buffer(aml_screen_buffer_info_t *buff_info)
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int ret = -1;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ if (EAGAIN == errno) {
+ ret = -EAGAIN;
+ } else {
+ ALOGE("[%s %d]aquire_buffer %d", __FUNCTION__, __LINE__, ret);
+ }
+ buff_info->buffer_mem = 0;
+ buff_info->buffer_canvas = 0;
+ return ret;
+ }
+ buff_info->buffer_mem = mVideoInfo->mem[mVideoInfo->buf.index];
+ buff_info->buffer_canvas = mVideoInfo->canvas[mVideoInfo->buf.index];
+ buff_info->tv_sec = mVideoInfo->buf.timestamp.tv_sec;
+ buff_info->tv_usec = mVideoInfo->buf.timestamp.tv_usec;
+ return ret;
+ }
+
+ /* int vdin_screen_source::inc_buffer_refcount(int *ptr){
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int ret = -1;
+ int index;
+ index = mBufs.valueFor((unsigned int)ptr);
+ mVideoInfo->refcount[index] += 1;
+ return true;
+ } */
+
+ int vdin_screen_source::release_buffer(long *ptr)
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int ret = -1;
+ int currentIndex;
+ v4l2_buffer hbuf_query;
+
+ Mutex::Autolock autoLock(mLock);
+
+ currentIndex = mBufs.valueFor(ptr);
+ if (mVideoInfo->refcount[currentIndex] > 0) {
+ mVideoInfo->refcount[currentIndex] -= 1;
+ } else {
+ ALOGE("return buffer when refcount already zero");
+ return 0;
+ }
+ if (mVideoInfo->refcount[currentIndex] == 0) {
+ memset(&hbuf_query, 0, sizeof(v4l2_buffer));
+ hbuf_query.index = currentIndex;
+ hbuf_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ hbuf_query.memory = V4L2_MEMORY_MMAP;
+ ALOGV("return buffer :%d", currentIndex);
+ ret = ioctl(mCameraHandle, VIDIOC_QBUF, &hbuf_query);
+ if (ret != 0) {
+ ALOGE("Return Buffer :%d failed", currentIndex);
+ }
+ }
+ return 0;
+ }
+
+ int vdin_screen_source::init_native_window()
+ {
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int err = NO_ERROR;
+
+ if (NULL == mANativeWindow.get()) {
+ return BAD_VALUE;
+ }
+
+ // Set gralloc usage bits for window.
+ err = native_window_set_usage(mANativeWindow.get(), SCREENSOURCE_GRALLOC_USAGE);
+ if (err != 0) {
+ ALOGE("native_window_set_usage failed: %s\n", strerror(-err));
+ if (ENODEV == err ) {
+ ALOGE("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+ return err;
+ }
+
+ ALOGD("Number of buffers set to ANativeWindow %d", mBufferCount);
+ ///Set the number of buffers needed for camera preview
+ err = native_window_set_buffer_count(mANativeWindow.get(), mBufferCount);
+ if (err != 0) {
+ ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err);
+ if (ENODEV == err) {
+ ALOGE("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+ return err;
+ }
+
+ ALOGD("native_window_set_buffers_geometry format:0x%x", mNativeWindowPixelFormat);
+ // Set window geometry
+ err = native_window_set_buffers_geometry(
+ mANativeWindow.get(),
+ mFrameWidth,
+ mFrameHeight,
+ mNativeWindowPixelFormat);
+
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_geometry failed: %s", strerror(-err));
+ if ( ENODEV == err ) {
+ ALOGE("Surface abandoned!");
+ mANativeWindow = NULL;
+ }
+ return err;
+ }
+ err = native_window_set_scaling_mode(mANativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ if (err != 0) {
+ ALOGW("Failed to set scaling mode: %d", err);
+ return err;
+ }
+ return NO_ERROR;
+ }
+
+ int vdin_screen_source::workThread()
+ {
+ bool buff_keep = false;
+ int index;
+ aml_screen_buffer_info_t buff_info;
+ int ret;
+ long *src = NULL;
+ unsigned char *dest = NULL;
+ uint8_t *handle = NULL;
+ ANativeWindowBuffer *buf;
+ if (mState == START) {
+ usleep(5000);
+ ret = aquire_buffer(&buff_info);
+ if (ret != 0 || (buff_info.buffer_mem == 0)) {
+ ALOGV("Get V4l2 buffer failed");
+ return ret;
+ }
+ src = (long *)buff_info.buffer_mem;
+ index = mBufs.valueFor(src);
+ if (mFrameType & NATIVE_WINDOW_DATA) {
+ mVideoInfo->refcount[index] += 1;
+ if (mANativeWindow.get() == NULL) {
+ ALOGE("Null window");
+ return BAD_VALUE;
+ }
+ ret = mANativeWindow->dequeueBuffer_DEPRECATED(mANativeWindow.get(), &buf);
+ if (ret != 0) {
+ ALOGE("dequeue buffer failed :%s (%d)", strerror(-ret), -ret);
+ return BAD_VALUE;
+ }
+ mANativeWindow->lockBuffer_DEPRECATED(mANativeWindow.get(), buf);
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
+ graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest);
+ if (dest == NULL) {
+ ALOGE("Invalid Gralloc Handle");
+ return BAD_VALUE;
+ }
+ memcpy(dest, src, mBufferSize);
+ graphicBuffer->unlock();
+ mANativeWindow->queueBuffer_DEPRECATED(mANativeWindow.get(), buf);
+ graphicBuffer.clear();
+ ALOGV("queue one buffer to native window");
+ release_buffer(src);
+ }
+ if (mFrameType & CALL_BACK_DATA && mDataCB != NULL && mState == START) {
+ mVideoInfo->refcount[index] += 1;
+ mDataCB(mUser, &buff_info);
+ }
+ }
+ return NO_ERROR;
+ }
+
+}
diff --git a/screen_source/v4l2_vdin.h b/screen_source/v4l2_vdin.h
new file mode 100644
index 0000000..0277884
--- a/dev/null
+++ b/screen_source/v4l2_vdin.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <linux/videodev2.h>
+#include <sys/time.h>
+
+#include <utils/KeyedVector.h>
+#include <cutils/properties.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/threads.h>
+#include <android/native_window.h>
+#include <gralloc_priv.h>
+
+#include <hardware/aml_screen.h>
+
+namespace android {
+
+#define NB_BUFFER 6
+
+ struct VideoInfo {
+ struct v4l2_capability cap;
+ struct v4l2_format format;
+ struct v4l2_buffer buf;
+ struct v4l2_requestbuffers rb;
+ long *mem[NB_BUFFER];
+ unsigned canvas[NB_BUFFER];
+ unsigned refcount[NB_BUFFER];
+ bool isStreaming;
+ int width;
+ int height;
+ int formatIn;
+ int framesizeIn;
+ };
+ enum State {
+ START,
+ PAUSE,
+ STOPING,
+ STOP,
+ };
+
+ enum FrameType {
+ NATIVE_WINDOW_DATA = 0x1,
+ CALL_BACK_DATA = 0x2,
+ };
+
+ typedef void (*olStateCB)(int state);
+
+ typedef void (*app_data_callback)(void *user, aml_screen_buffer_info_t *buff_info);
+
+#define SCREENSOURCE_GRALLOC_USAGE GRALLOC_USAGE_HW_TEXTURE | \
+ GRALLOC_USAGE_HW_RENDER | \
+ GRALLOC_USAGE_SW_READ_RARELY | \
+ GRALLOC_USAGE_SW_WRITE_NEVER
+
+ class vdin_screen_source {
+ public:
+ vdin_screen_source();
+ ~vdin_screen_source();
+ int init();
+ int start();
+ int stop();
+ int pause();
+ int get_format();
+ int set_format(int width = 640, int height = 480, int color_format = V4L2_PIX_FMT_NV21);
+ int set_rotation(int degree);
+ int set_crop(int x, int y, int width, int height);
+ int set_amlvideo2_crop(int x, int y, int width, int height);
+ int aquire_buffer(aml_screen_buffer_info_t *buff_info);
+ // int inc_buffer_refcount(int* ptr);
+ int release_buffer(long *ptr);
+ int set_state_callback(olStateCB callback);
+ int set_data_callback(app_data_callback callback, void *user);
+ int set_preview_window(ANativeWindow *window);
+ int set_frame_rate(int frameRate);
+ int set_source_type(int sourceType);
+ int get_source_type();
+ int start_v4l2_device();
+ int stop_v4l2_device();
+ private:
+ int init_native_window();
+ int workThread();
+ private:
+ class WorkThread : public Thread {
+ vdin_screen_source *mSource;
+ public:
+ WorkThread(vdin_screen_source *source) :
+ Thread(false), mSource(source) { }
+ virtual void onFirstRef()
+ {
+ run("vdin screen source work thread", PRIORITY_URGENT_DISPLAY);
+ }
+ virtual bool threadLoop()
+ {
+ mSource->workThread();
+ // loop until we need to quit
+ return true;
+ }
+ };
+ private:
+ int mCurrentIndex;
+ KeyedVector<long *, long> mBufs;
+ int mBufferCount;
+ int mFrameWidth;
+ int mFrameHeight;
+ int mBufferSize;
+ volatile int mState;
+ olStateCB mSetStateCB;
+ int mPixelFormat;
+ int mNativeWindowPixelFormat;
+ sp<ANativeWindow> mANativeWindow;
+ sp<WorkThread> mWorkThread;
+ mutable Mutex mLock;
+ int mCameraHandle;
+ struct VideoInfo *mVideoInfo;
+ int mFrameType;
+ app_data_callback mDataCB;
+ bool mOpen;
+ void *mUser;
+ };
+
+}
diff --git a/tv_input.cpp b/tv_input.cpp
index 0cfc0b4..8c8a224 100644
--- a/tv_input.cpp
+++ b/tv_input.cpp
@@ -25,12 +25,20 @@
#include <tv/CTv.h>
#include <tvin/CTvin.h>
#include <tvserver/TvService.h>
+#include <screen_source/v4l2_vdin.h>
+#include <ui/GraphicBufferMapper.h>
+#include <ui/GraphicBuffer.h>
/*****************************************************************************/
#define LOGD(...) \
{ \
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__); }
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *) 0)->member) *__mptr = (ptr); \
+ (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
+#endif
typedef struct tv_input_private {
tv_input_device_t device;
@@ -40,6 +48,7 @@ typedef struct tv_input_private {
void *callback_data;
//TvService* pTvService;
CTv *pTv;
+ vdin_screen_source *pScreen;
} tv_input_private_t;
static int notify_ATV_device_available(tv_input_private_t *priv)
@@ -290,7 +299,7 @@ static int tv_input_initialize(struct tv_input_device *dev,
/* HDMI3_DEVICE_AVAILABLE */
notify_HDMI_device_available(priv, SOURCE_HDMI3, 1);
notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, 1);
-
+ //
return 0;
}
@@ -318,6 +327,8 @@ static int tv_input_open_stream(struct tv_input_device *dev, int device_id,
priv->pTv->SetSourceSwitchInput((tv_source_input_t) device_id);
return 0;
} else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) {
+ priv->pScreen->set_format(1920, 1080, V4L2_PIX_FMT_NV21);
+ priv->pScreen->start_v4l2_device();
return 0;
}
}
@@ -328,18 +339,49 @@ static int tv_input_close_stream(struct tv_input_device *dev, int device_id,
int stream_id)
{
tv_input_private_t *priv = (tv_input_private_t *)dev;
- if (priv) {
+ if (stream_id == NORMAL_STREAM_ID) {
LOGD ( "%s, SetSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
priv->pTv->StopTvLock();
return 0;
+ } else if (stream_id == FRAME_CAPTURE_STREAM_ID) {
+ priv->pScreen->stop_v4l2_device();
+ return 0;
}
return -EINVAL;
}
static int tv_input_request_capture(
- struct tv_input_device *, int, int, buffer_handle_t, uint32_t)
+ struct tv_input_device *dev, int device_id, int stream_id, buffer_handle_t buffer, uint32_t seq)
{
- return -EINVAL;
+ tv_input_private_t *priv = (tv_input_private_t *)dev;
+ int index;
+ aml_screen_buffer_info_t buff_info;
+ int mFrameWidth , mFrameHeight ;
+ int ret;
+ long *src = NULL;
+ unsigned char *dest = NULL;
+ ANativeWindowBuffer *buf;
+ ret = priv->pScreen->aquire_buffer(&buff_info);
+ if (ret != 0 || (buff_info.buffer_mem == 0)) {
+ LOGD("Get V4l2 buffer failed");
+ return -EWOULDBLOCK;
+ }
+ src = (long *)buff_info.buffer_mem;
+
+ buf = container_of(&buffer, ANativeWindowBuffer, handle);
+
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
+ graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest);
+ if (dest == NULL) {
+ LOGD("Invalid Gralloc Handle");
+ return -EWOULDBLOCK;
+ }
+ memcpy(dest, src, mFrameWidth * mFrameHeight * 3 / 2);
+ graphicBuffer->unlock();
+ graphicBuffer.clear();
+ LOGD("queue one buffer to native window");
+ priv->pScreen->release_buffer(src);
+ return 0;
}
static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t)
@@ -376,6 +418,10 @@ static int tv_input_device_open(const struct hw_module_t *module,
dev->pTv = new CTv();
TvService::instantiate(dev->pTv);
dev->pTv->OpenTv();
+ dev->pScreen = new vdin_screen_source();
+ if (dev->pScreen->init() != 0 ) {
+ LOGD("init screen source not ok!");
+ }
/* initialize the procs */
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1;