summaryrefslogtreecommitdiff
authorlianghu.su <lianghu.su@amlogic.com>2014-03-04 03:06:49 (GMT)
committer tao.dong <tao.dong@amlogic.com>2014-03-14 13:02:02 (GMT)
commitcd26be4585f0532bb94a4b944f905d20de902206 (patch)
tree9c1060cec9f29f82cc8a271cb6a76ac6adea8011
parentd9689c9321d0ecaf7a0732991f3d8b8239b6a7df (diff)
downloadscreen_source-cd26be4585f0532bb94a4b944f905d20de902206.zip
screen_source-cd26be4585f0532bb94a4b944f905d20de902206.tar.gz
screen_source-cd26be4585f0532bb94a4b944f905d20de902206.tar.bz2
pd[#87148]:HDMI IN V01 version:OSD display for HDMI IN by yuanxiaoyu.
Diffstat
-rwxr-xr-xAndroid.mk12
-rwxr-xr-xaml_screen.cpp90
-rwxr-xr-xv4l2_vdin.cpp463
-rwxr-xr-xv4l2_vdin.h83
4 files changed, 603 insertions, 45 deletions
diff --git a/Android.mk b/Android.mk
index 578e967..d59d896 100755
--- a/Android.mk
+++ b/Android.mk
@@ -10,7 +10,17 @@ include $(CLEAR_VARS)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES := aml_screen.cpp v4l2_vdin.cpp
-LOCAL_SHARED_LIBRARIES:= libutils liblog
+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 \
+ $(GRALLOC_DIR)
+
+LOCAL_SHARED_LIBRARIES:= libutils liblog libui
LOCAL_MODULE := screen_source.amlogic
LOCAL_CFLAGS:= -DLOG_TAG=\"screen_source\"
diff --git a/aml_screen.cpp b/aml_screen.cpp
index 52f0364..33923c9 100755
--- a/aml_screen.cpp
+++ b/aml_screen.cpp
@@ -51,6 +51,11 @@
#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,
@@ -80,6 +85,8 @@ 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;
@@ -88,6 +95,7 @@ static int aml_screen_device_close(struct hw_device_t *dev)
}
free(ctx);
}
+ gAmlScreenOpen--;
return 0;
}
@@ -102,6 +110,12 @@ 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;
@@ -127,17 +141,69 @@ int screen_source_set_rotation(struct aml_screen_device* dev, int degree)
return source->set_rotation(degree);
}
-int screen_source_aquire_buffer(struct aml_screen_device* dev, unsigned* buff_info)
+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_aquire_buffer(struct aml_screen_device* dev, int* 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, char* ptr)
+
+int screen_source_release_buffer(struct aml_screen_device* dev, int* 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,
@@ -145,10 +211,19 @@ static int aml_screen_device_open(const struct hw_module_t* module, const char*
{
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)
@@ -176,15 +251,24 @@ static int aml_screen_device_open(const struct hw_module_t* module, const char*
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.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/v4l2_vdin.cpp b/v4l2_vdin.cpp
index f15da75..f8a1d6a 100755
--- a/v4l2_vdin.cpp
+++ b/v4l2_vdin.cpp
@@ -39,11 +39,86 @@
#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)
@@ -58,21 +133,35 @@ vdin_screen_source::vdin_screen_source()
{
ALOGE("[%s %d] no memory for mVideoInfo", __FUNCTION__, __LINE__);
}
+ 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;
+
}
vdin_screen_source::~vdin_screen_source()
{
- if (mCameraHandle >= 0)
- {
- close(mCameraHandle);
- }
if (mVideoInfo)
{
free (mVideoInfo);
}
+ if (mCameraHandle >= 0)
+ {
+ close(mCameraHandle);
+ }
}
-int vdin_screen_source::start()
+int vdin_screen_source::start_v4l2_device()
{
int ret = -1;
@@ -82,7 +171,7 @@ int vdin_screen_source::start()
mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
- mVideoInfo->rb.count = NB_BUFFER;
+ mVideoInfo->rb.count = mBufferCount;
ret = ioctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
@@ -91,7 +180,7 @@ int vdin_screen_source::start()
return ret;
}
- for (int i = 0; i < NB_BUFFER; i++) {
+ for (int i = 0; i < mBufferCount; i++) {
memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
mVideoInfo->buf.index = i;
@@ -111,12 +200,12 @@ int vdin_screen_source::start()
ALOGE("[%s %d] MAP_FAILED", __FUNCTION__, __LINE__);
return -1;
}
-
- mBufs.add((int)mVideoInfo->mem[i], i);
+ mVideoInfo->refcount[i] = 0;
+ mBufs.add((int)mVideoInfo->mem[i],i);
}
ALOGV("[%s %d] VIDIOC_QUERYBUF successful", __FUNCTION__, __LINE__);
- for (int i = 0; i < NB_BUFFER; i++) {
+ 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;
@@ -132,47 +221,148 @@ int vdin_screen_source::start()
ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
ALOGV("[%s %d] VIDIOC_STREAMON:%x", __FUNCTION__, __LINE__, ret);
-
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;
+
+ if(mWorkThread != NULL){
+ mWorkThread->requestExitAndWait();
+ mWorkThread.clear();
+ }
+
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 < NB_BUFFER; i++)
+ for (int i = 0; i < mBufferCount; i++)
{
if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0)
ALOGE("Unmap failed");
}
+
+ 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 0;
+ 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 = width;
+ mVideoInfo->width = ALIGN(width);
mVideoInfo->height = height;
- mVideoInfo->framesizeIn = (width * height << 1); //note color format
+ 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 = width;
+ 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);
@@ -185,7 +375,8 @@ int vdin_screen_source::set_format(int width, int height, int color_format)
int vdin_screen_source::set_rotation(int degree)
{
ALOGV("[%s %d]", __FUNCTION__, __LINE__);
-
+ if(mOpen == true)
+ return NO_ERROR;
int ret = 0;
struct v4l2_control ctl;
@@ -210,11 +401,82 @@ int vdin_screen_source::set_rotation(int degree)
}
+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(mOpen == true)
+ return NO_ERROR;
+
+ 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_source_type(int sourceType)
+{
+ ALOGV("[%s %d]", __FUNCTION__, __LINE__);
+ int ret = 0;
-int vdin_screen_source::aquire_buffer(unsigned *buff_info)
-{
+ 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(int *buff_info)
+{
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
+ int ret = -1;
mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
@@ -234,20 +496,155 @@ int vdin_screen_source::aquire_buffer(unsigned *buff_info)
return ret;
}
-int vdin_screen_source::release_buffer(char* ptr)
+/* 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(int* ptr)
{
+ ALOGV("%s %d", __FUNCTION__, __LINE__);
int ret = -1;
- int CurrentIndex;
- v4l2_buffer hbuf_query;
- memset(&hbuf_query,0,sizeof(v4l2_buffer));
-
- CurrentIndex = mBufs.valueFor(( unsigned int )ptr);
- hbuf_query.index = CurrentIndex;
- hbuf_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- hbuf_query.memory = V4L2_MEMORY_MMAP;
- ret = ioctl(mCameraHandle, VIDIOC_QBUF, &hbuf_query);
-
+ int currentIndex;
+ v4l2_buffer hbuf_query;
+
+ currentIndex = mBufs.valueFor((unsigned int)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(){
+ int index;
+ int buff_info[2];
+ int ret;
+ unsigned char *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[0] == 0)){
+ ALOGV("Get V4l2 buffer failed");
+ return ret;
+ }
+ src = (unsigned char *)buff_info[0];
+ index = mBufs.valueFor((unsigned int)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((int*)src);
+ }
+ if(mFrameType & CALL_BACK_DATA && mDataCB != NULL){
+ mVideoInfo->refcount[index] += 1;
+ mDataCB(mUser, buff_info);
+ }
+ }
+ return NO_ERROR;
+}
+
}
diff --git a/v4l2_vdin.h b/v4l2_vdin.h
index 5af1a9d..0183464 100755
--- a/v4l2_vdin.h
+++ b/v4l2_vdin.h
@@ -30,10 +30,13 @@
#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>
namespace android {
-#define NB_BUFFER 4
+#define NB_BUFFER 6
struct VideoInfo {
struct v4l2_capability cap;
@@ -42,12 +45,33 @@ struct VideoInfo {
struct v4l2_requestbuffers rb;
void *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,
+ STOP,
+};
+
+enum FrameType{
+ NATIVE_WINDOW_DATA = 0x1,
+ CALL_BACK_DATA = 0x2,
+};
+
+typedef void (*olStateCB)(int state);
+
+typedef void (*app_data_callback)(void *user,
+ int *buffer);
+
+#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:
@@ -56,16 +80,59 @@ class vdin_screen_source {
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 aquire_buffer(unsigned* buff_info);
- int release_buffer(char* ptr);
- private:
- int mCurrentIndex;
- KeyedVector<int, int> mBufs;
- int mCameraHandle;
- struct VideoInfo *mVideoInfo;
+ int set_crop(int x, int y, int width, int height);
+ int aquire_buffer(int* buff_info);
+ // int inc_buffer_refcount(int* ptr);
+ int release_buffer(int* 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();
+ private:
+ int init_native_window();
+ int start_v4l2_device();
+ 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<int, int> 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;
};
} \ No newline at end of file