提交 98375e1d 编写于 作者: A Andrey Kamaev

Refactoring of native camera implementation

上级 ffe7a658
#define USE_RECORDING_INSTEAD_PREVIEW 0
#if !defined(ANDROID_r2_2_2) && !defined(ANDROID_r2_3_3) && !defined(ANDROID_r3_0_1) #if !defined(ANDROID_r2_2_2) && !defined(ANDROID_r2_3_3) && !defined(ANDROID_r3_0_1)
#error unsupported version of Android #error unsupported version of Android
#endif #endif
...@@ -9,99 +7,163 @@ ...@@ -9,99 +7,163 @@
#include "../include/camera_properties.h" #include "../include/camera_properties.h"
#include <string> #include <string>
//undef logging macro from /system/core/libcutils/loghack.h
#ifdef LOGD
#undef LOGD
#endif
#ifdef LOGI
#undef LOGI
#endif
#ifdef LOGW
#undef LOGW
#endif
#ifdef LOGE
#undef LOGE
#endif
// LOGGING
#include <android/log.h>
#define CAMERA_LOG_TAG "OpenCV_NativeCamera"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, CAMERA_LOG_TAG, __VA_ARGS__))
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, CAMERA_LOG_TAG, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, CAMERA_LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, CAMERA_LOG_TAG, __VA_ARGS__))
using namespace android; using namespace android;
void debugShowFPS() void debugShowFPS()
{ {
static int mFrameCount = 0; static int mFrameCount = 0;
static int mLastFrameCount = 0; static int mLastFrameCount = 0;
static nsecs_t mLastFpsTime = systemTime();; static nsecs_t mLastFpsTime = systemTime();
static float mFps = 0; static float mFps = 0;
mFrameCount++; mFrameCount++;
if ( ( mFrameCount % 30 ) == 0 ) { if (( mFrameCount % 30 ) != 0)
return;
nsecs_t now = systemTime(); nsecs_t now = systemTime();
nsecs_t diff = now - mLastFpsTime; nsecs_t diff = now - mLastFpsTime;
if (diff==0) if (diff==0)
return; return;
mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
mLastFpsTime = now; mLastFpsTime = now;
mLastFrameCount = mFrameCount; mLastFrameCount = mFrameCount;
LOGI("####### [%d] Frames, %f FPS", mFrameCount, mFps); LOGI("### Camera FPS ### [%d] Frames, %.2f FPS", mFrameCount, mFps);
}
} }
class CameraHandler: public CameraListener class CameraHandler: public CameraListener
{ {
protected: protected:
int cameraId;
sp<Camera> camera; sp<Camera> camera;
CameraCallback cameraCallback;
CameraParameters params; CameraParameters params;
CameraCallback cameraCallback;
void* userData; void* userData;
int cameraId;
bool isEmptyCameraCallbackReported; int emptyCameraCallbackReported;
virtual void doCall(void* buffer, size_t bufferSize)
void doCall(void* buffer, size_t bufferSize)
{ {
if (cameraCallback == 0) if (cameraCallback == 0)
{ {
if (!isEmptyCameraCallbackReported) if (!emptyCameraCallbackReported)
LOGE("Camera callback is empty!"); LOGE("CameraHandler::doCall(void*, size_t): Camera callback is empty!");
isEmptyCameraCallbackReported = true; emptyCameraCallbackReported++;
return;
} }
else
{
bool res = (*cameraCallback)(buffer, bufferSize, userData); bool res = (*cameraCallback)(buffer, bufferSize, userData);
if(!res) closeCameraConnect(); if(!res)
{
LOGE("CameraHandler::doCall(void*, size_t): cameraCallback returns false (camera connection will be closed)");
closeCameraConnect();
}
}
} }
virtual void doCall(const sp<IMemory>& dataPtr) void doCall(const sp<IMemory>& dataPtr)
{ {
LOGI("doCall started");
if (dataPtr == NULL) if (dataPtr == NULL)
{ {
LOGE("CameraBuffer: dataPtr==NULL"); LOGE("CameraHandler::doCall(const sp<IMemory>&): dataPtr==NULL (no frame to handle)");
return; return;
} }
size_t size = dataPtr->size(); size_t size = dataPtr->size();
if (size <= 0) if (size <= 0)
{ {
LOGE("CameraBuffer: IMemory object is of zero size"); LOGE("CameraHandler::doCall(const sp<IMemory>&): IMemory object is of zero size");
return; return;
} }
unsigned char* buffer = (unsigned char *)dataPtr->pointer(); void* buffer = (void *)dataPtr->pointer();
if (!buffer) if (!buffer)
{ {
LOGE("CameraBuffer: Buffer pointer is invalid"); LOGE("CameraHandler::doCall(const sp<IMemory>&): Buffer pointer is NULL");
return; return;
} }
doCall(buffer, size); doCall(buffer, size);
} }
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
{
static uint32_t count = 0;
count++;
LOGE("Recording cb: %d %lld %%p Offset:%%d Stride:%%d\n", msgType, timestamp);
if (dataPtr == NULL)
{
LOGE("postDataTimestamp: dataPtr IS ZERO -- returning");
camera->releaseRecordingFrame(dataPtr);
LOGE("postDataTimestamp: camera->releaseRecordingFrame(dataPtr) is done");
return;
}
uint8_t *ptr = (uint8_t*) dataPtr->pointer();
if (ptr)
LOGE("VID_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9]);
else
LOGE("postDataTimestamp: Ptr is zero");
camera->releaseRecordingFrame(dataPtr);
}
public: public:
CameraHandler(CameraCallback callback = 0, void* _userData = 0):cameraCallback(callback), userData(_userData), cameraId(0), isEmptyCameraCallbackReported(false) {} CameraHandler(CameraCallback callback = 0, void* _userData = 0):
cameraId(0),
cameraCallback(callback),
userData(_userData),
emptyCameraCallbackReported(0)
{
LOGD("Instantiated new CameraHandler (%p, %p)", callback, _userData);
}
virtual ~CameraHandler() virtual ~CameraHandler()
{ {
LOGW("CameraHandler destructor is called!"); LOGD("CameraHandler destructor is called");
} }
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2)
{ {
LOGE("Notify cb: %d %d %d\n", msgType, ext1, ext2); LOGE("CameraHandler::Notify: msgType=%d ext1=%d ext2=%d\n", msgType, ext1, ext2);
#if 0 #if 0
if ( msgType & CAMERA_MSG_FOCUS ) if ( msgType & CAMERA_MSG_FOCUS )
LOGE("AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timevalDelay(&autofocus_start)); LOGE("CameraHandler::Notify AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timevalDelay(&autofocus_start));
if ( msgType & CAMERA_MSG_SHUTTER ) if ( msgType & CAMERA_MSG_SHUTTER )
LOGE("Shutter done in %llu us\n", timeval_delay(&picture_start)); LOGE("CameraHandler::Notify Shutter done in %llu us\n", timeval_delay(&picture_start));
#endif #endif
} }
...@@ -116,40 +178,16 @@ public: ...@@ -116,40 +178,16 @@ public:
} }
if (msgType != CAMERA_MSG_PREVIEW_FRAME) if (msgType != CAMERA_MSG_PREVIEW_FRAME)
LOGE("Recieved not CAMERA_MSG_PREVIEW_FRAME message %d", (int) msgType); LOGE("CameraHandler::postData Recieved message %d is not equal to CAMERA_MSG_PREVIEW_FRAME (%d)", (int) msgType, CAMERA_MSG_PREVIEW_FRAME);
if ( msgType & CAMERA_MSG_RAW_IMAGE ) if ( msgType & CAMERA_MSG_RAW_IMAGE )
LOGE("Unexpected data format: RAW\n"); LOGE("CameraHandler::postData Unexpected data format: RAW\n");
if (msgType & CAMERA_MSG_POSTVIEW_FRAME) if (msgType & CAMERA_MSG_POSTVIEW_FRAME)
LOGE("Unexpected data format: Postview frame\n"); LOGE("CameraHandler::postData Unexpected data format: Postview frame\n");
if (msgType & CAMERA_MSG_COMPRESSED_IMAGE ) if (msgType & CAMERA_MSG_COMPRESSED_IMAGE )
LOGE("Unexpected data format: JPEG"); LOGE("CameraHandler::postData Unexpected data format: JPEG");
}
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
{
static uint32_t count = 0;
count++;
LOGE("Recording cb: %d %lld %%p Offset:%%d Stride:%%d\n", msgType, timestamp);
if (dataPtr == NULL)
{
LOGE("postDataTimestamp: dataPtr IS ZERO -- returning");
camera->releaseRecordingFrame(dataPtr);
LOGE("postDataTimestamp: camera->releaseRecordingFrame(dataPtr) is done");
return;
}
uint8_t *ptr = (uint8_t*) dataPtr->pointer();
if (ptr)
LOGE("VID_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9]);
else
LOGE("postDataTimestamp: Ptr is zero");
camera->releaseRecordingFrame(dataPtr);
} }
static CameraHandler* initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters); static CameraHandler* initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters);
...@@ -164,11 +202,7 @@ public: ...@@ -164,11 +202,7 @@ public:
CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters) CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters)
{ {
// if (camera != NULL) LOGD("CameraHandler::initCameraConnect(%p, %d, %p, %p)", callback, cameraId, userData, prevCameraParameters);
// {
// LOGE("initCameraConnect: camera have been connected already");
// return false;
// }
sp<Camera> camera = 0; sp<Camera> camera = 0;
...@@ -179,7 +213,7 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, ...@@ -179,7 +213,7 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback,
camera = Camera::connect(cameraId); camera = Camera::connect(cameraId);
#endif #endif
if ( NULL == camera.get() ) if ( 0 == camera.get() )
{ {
LOGE("initCameraConnect: Unable to connect to CameraService\n"); LOGE("initCameraConnect: Unable to connect to CameraService\n");
return 0; return 0;
...@@ -189,15 +223,18 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, ...@@ -189,15 +223,18 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback,
camera->setListener(handler); camera->setListener(handler);
handler->camera = camera; handler->camera = camera;
handler->cameraId=cameraId; handler->cameraId = cameraId;
#if 1
//setting paramers from previous camera handler if (prevCameraParameters != 0)
if (prevCameraParameters != NULL) { {
LOGI("initCameraConnect: Setting paramers from previous camera handler");
camera->setParameters(prevCameraParameters->flatten()); camera->setParameters(prevCameraParameters->flatten());
} }
#endif
handler->params.unflatten(camera->getParameters());
android::String8 params_str = camera->getParameters();
LOGI("initCameraConnect: [%s]", params_str.string());
handler->params.unflatten(params_str);
LOGD("Supported Cameras: %s", handler->params.get("camera-indexes")); LOGD("Supported Cameras: %s", handler->params.get("camera-indexes"));
LOGD("Supported Picture Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES)); LOGD("Supported Picture Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES));
...@@ -216,9 +253,11 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, ...@@ -216,9 +253,11 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback,
//TODO: check if yuv420i format available. Set this format as preview format. //TODO: check if yuv420i format available. Set this format as preview format.
#if USE_RECORDING_INSTEAD_PREVIEW status_t pdstatus = camera->setPreviewDisplay(sp<ISurface>(0 /*new DummySurface*/));
status_t err = camera->setPreviewDisplay(sp<ISurface>(NULL /*new DummySurface1*/)); if (pdstatus != 0)
#endif {
LOGE("initCameraConnect: failed setPreviewDisplay(0) call; camera migth not work correcttly on some devices");
}
////ATTENTION: switching between two versions: with and without copying memory inside Android OS ////ATTENTION: switching between two versions: with and without copying memory inside Android OS
//// see the method CameraService::Client::copyFrameAndPostCopiedFrame and where it is used //// see the method CameraService::Client::copyFrameAndPostCopiedFrame and where it is used
...@@ -228,17 +267,15 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, ...@@ -228,17 +267,15 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback,
camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK );//without copy camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK );//without copy
#endif #endif
#if USE_RECORDING_INSTEAD_PREVIEW
status_t resStart = camera->startRecording();
#else
status_t resStart = camera->startPreview(); status_t resStart = camera->startPreview();
#endif
if (resStart != 0) if (resStart != 0)
{ {
LOGE("initCameraConnect: startPreview() fails. Closing camera connection...");
handler->closeCameraConnect(); handler->closeCameraConnect();
handler = 0; handler = 0;
} }
return handler; return handler;
} }
...@@ -246,17 +283,11 @@ void CameraHandler::closeCameraConnect() ...@@ -246,17 +283,11 @@ void CameraHandler::closeCameraConnect()
{ {
if (camera == NULL) if (camera == NULL)
{ {
LOGI("... camera is NULL"); LOGI("... camera is already NULL");
return; return;
} }
//TODO: ATTENTION! should we do it ALWAYS???
#if USE_RECORDING_INSTEAD_PREVIEW
camera->stopRecording();
#else
camera->stopPreview(); camera->stopPreview();
#endif
camera->disconnect(); camera->disconnect();
camera.clear(); camera.clear();
...@@ -290,18 +321,18 @@ double CameraHandler::getProperty(int propIdx) ...@@ -290,18 +321,18 @@ double CameraHandler::getProperty(int propIdx)
case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH: case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
{ {
int w,h; int w,h;
params.getPreviewSize(&w,&h); params.getPreviewSize(&w, &h);
return w; return w;
} }
case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT: case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
{ {
int w,h; int w,h;
params.getPreviewSize(&w,&h); params.getPreviewSize(&w, &h);
return h; return h;
} }
case ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING: case ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING:
{ {
cameraPropertySupportedPreviewSizesString=params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES); cameraPropertySupportedPreviewSizesString = params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
double res; double res;
memset(&res, 0, sizeof(res)); memset(&res, 0, sizeof(res));
(*( (void**)&res ))= (void*)( cameraPropertySupportedPreviewSizesString.c_str() ); (*( (void**)&res ))= (void*)( cameraPropertySupportedPreviewSizesString.c_str() );
...@@ -320,17 +351,17 @@ void CameraHandler::setProperty(int propIdx, double value) ...@@ -320,17 +351,17 @@ void CameraHandler::setProperty(int propIdx, double value)
case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH: case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
{ {
int w,h; int w,h;
params.getPreviewSize(&w,&h); params.getPreviewSize(&w, &h);
w = (int)value; w = (int)value;
params.setPreviewSize(w,h); params.setPreviewSize(w, h);
} }
break; break;
case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT: case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
{ {
int w,h; int w,h;
params.getPreviewSize(&w,&h); params.getPreviewSize(&w, &h);
h = (int)value; h = (int)value;
params.setPreviewSize(w,h); params.setPreviewSize(w, h);
} }
break; break;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册