From cd26be4585f0532bb94a4b944f905d20de902206 Mon Sep 17 00:00:00 2001 From: lianghu.su Date: Tue, 04 Mar 2014 03:06:49 +0000 Subject: pd[#87148]:HDMI IN V01 version:OSD display for HDMI IN by yuanxiaoyu. --- 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 #include "v4l2_vdin.h" +#include +#include +#include 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(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 #include #include +#include +#include +#include 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 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 mBufs; + int mBufferCount; + int mFrameWidth; + int mFrameHeight; + int mBufferSize; + volatile int mState; + olStateCB mSetStateCB; + int mPixelFormat; + int mNativeWindowPixelFormat; + sp mANativeWindow; + sp 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 -- cgit