Changed algorithm of Android camera synchronisation --- added "auto-grab" mode.
This commit is contained in:
parent
e7ef84b2c2
commit
e262f054ad
@ -353,6 +353,7 @@ enum
|
|||||||
CV_CAP_PROP_TRIGGER_DELAY =25,
|
CV_CAP_PROP_TRIGGER_DELAY =25,
|
||||||
CV_CAP_PROP_WHITE_BALANCE_RED_V =26,
|
CV_CAP_PROP_WHITE_BALANCE_RED_V =26,
|
||||||
CV_CAP_PROP_MAX_DC1394 =27,
|
CV_CAP_PROP_MAX_DC1394 =27,
|
||||||
|
CV_CAP_PROP_AUTOGRAB =1024, // property for highgui class CvCapture_Android only
|
||||||
// OpenNI map generators
|
// OpenNI map generators
|
||||||
CV_CAP_OPENNI_DEPTH_GENERATOR = 0,
|
CV_CAP_OPENNI_DEPTH_GENERATOR = 0,
|
||||||
CV_CAP_OPENNI_IMAGE_GENERATOR = 1 << 31,
|
CV_CAP_OPENNI_IMAGE_GENERATOR = 1 << 31,
|
||||||
|
@ -102,10 +102,18 @@ private:
|
|||||||
bool m_hasGray;
|
bool m_hasGray;
|
||||||
bool m_hasColor;
|
bool m_hasColor;
|
||||||
|
|
||||||
|
enum CvCapture_Android_DataState {
|
||||||
|
CVCAPTURE_ANDROID_STATE_NO_FRAME=0,
|
||||||
|
CVCAPTURE_ANDROID_STATE_HAS_NEW_FRAME_UNGRABBED,
|
||||||
|
CVCAPTURE_ANDROID_STATE_HAS_FRAME_GRABBED
|
||||||
|
};
|
||||||
|
volatile CvCapture_Android_DataState m_dataState;
|
||||||
|
|
||||||
//synchronization
|
//synchronization
|
||||||
pthread_mutex_t m_nextFrameMutex;
|
pthread_mutex_t m_nextFrameMutex;
|
||||||
pthread_cond_t m_nextFrameCond;
|
pthread_cond_t m_nextFrameCond;
|
||||||
volatile bool m_waitingNextFrame;
|
volatile bool m_waitingNextFrame;
|
||||||
|
volatile bool m_shouldAutoGrab;
|
||||||
|
|
||||||
void prepareCacheForYUV420i(int width, int height);
|
void prepareCacheForYUV420i(int width, int height);
|
||||||
static bool convertYUV420i2Grey(int width, int height, const unsigned char* yuv, cv::Mat& resmat);
|
static bool convertYUV420i2Grey(int width, int height, const unsigned char* yuv, cv::Mat& resmat);
|
||||||
@ -131,11 +139,15 @@ public:
|
|||||||
if(isConnected() && buffer != 0 && bufferSize > 0)
|
if(isConnected() && buffer != 0 && bufferSize > 0)
|
||||||
{
|
{
|
||||||
m_framesReceived++;
|
m_framesReceived++;
|
||||||
if (m_capture->m_waitingNextFrame)
|
if (m_capture->m_waitingNextFrame || m_capture->m_shouldAutoGrab)
|
||||||
{
|
{
|
||||||
m_capture->setFrame(buffer, bufferSize);
|
|
||||||
pthread_mutex_lock(&m_capture->m_nextFrameMutex);
|
pthread_mutex_lock(&m_capture->m_nextFrameMutex);
|
||||||
|
|
||||||
|
m_capture->setFrame(buffer, bufferSize);
|
||||||
|
|
||||||
|
m_capture->m_dataState = CvCapture_Android::CVCAPTURE_ANDROID_STATE_HAS_NEW_FRAME_UNGRABBED;
|
||||||
m_capture->m_waitingNextFrame = false;//set flag that no more frames required at this moment
|
m_capture->m_waitingNextFrame = false;//set flag that no more frames required at this moment
|
||||||
|
|
||||||
pthread_cond_broadcast(&m_capture->m_nextFrameCond);
|
pthread_cond_broadcast(&m_capture->m_nextFrameCond);
|
||||||
pthread_mutex_unlock(&m_capture->m_nextFrameMutex);
|
pthread_mutex_unlock(&m_capture->m_nextFrameMutex);
|
||||||
}
|
}
|
||||||
@ -174,7 +186,9 @@ CvCapture_Android::CvCapture_Android(int cameraId)
|
|||||||
m_frameYUV420inext = 0;
|
m_frameYUV420inext = 0;
|
||||||
m_hasGray = false;
|
m_hasGray = false;
|
||||||
m_hasColor = false;
|
m_hasColor = false;
|
||||||
|
m_dataState = CVCAPTURE_ANDROID_STATE_NO_FRAME;
|
||||||
m_waitingNextFrame = false;
|
m_waitingNextFrame = false;
|
||||||
|
m_shouldAutoGrab = false;
|
||||||
m_framesGrabbed = 0;
|
m_framesGrabbed = 0;
|
||||||
m_CameraParamsChanged = false;
|
m_CameraParamsChanged = false;
|
||||||
|
|
||||||
@ -209,16 +223,22 @@ CvCapture_Android::~CvCapture_Android()
|
|||||||
{
|
{
|
||||||
((HighguiAndroidCameraActivity*)m_activity)->LogFramesRate();
|
((HighguiAndroidCameraActivity*)m_activity)->LogFramesRate();
|
||||||
|
|
||||||
//m_activity->disconnect() will be automatically called inside destructor;
|
|
||||||
delete m_frameYUV420i;
|
|
||||||
delete m_frameYUV420inext;
|
|
||||||
m_frameYUV420i = 0;
|
|
||||||
m_frameYUV420inext = 0;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&m_nextFrameMutex);
|
pthread_mutex_lock(&m_nextFrameMutex);
|
||||||
|
|
||||||
|
unsigned char *tmp1=m_frameYUV420i;
|
||||||
|
unsigned char *tmp2=m_frameYUV420inext;
|
||||||
|
m_frameYUV420i = 0;
|
||||||
|
m_frameYUV420inext = 0;
|
||||||
|
delete tmp1;
|
||||||
|
delete tmp2;
|
||||||
|
|
||||||
|
m_dataState=CVCAPTURE_ANDROID_STATE_NO_FRAME;
|
||||||
pthread_cond_broadcast(&m_nextFrameCond);
|
pthread_cond_broadcast(&m_nextFrameCond);
|
||||||
|
|
||||||
pthread_mutex_unlock(&m_nextFrameMutex);
|
pthread_mutex_unlock(&m_nextFrameMutex);
|
||||||
|
|
||||||
|
//m_activity->disconnect() will be automatically called inside destructor;
|
||||||
delete m_activity;
|
delete m_activity;
|
||||||
m_activity = 0;
|
m_activity = 0;
|
||||||
|
|
||||||
@ -255,12 +275,21 @@ bool CvCapture_Android::setProperty( int propIdx, double propValue )
|
|||||||
case CV_CAP_PROP_FRAME_HEIGHT:
|
case CV_CAP_PROP_FRAME_HEIGHT:
|
||||||
m_activity->setProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT, propValue);
|
m_activity->setProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT, propValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CV_CAP_PROP_AUTOGRAB:
|
||||||
|
m_shouldAutoGrab=(propValue != 0);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CV_Error( CV_StsOutOfRange, "Failed attempt to SET unsupported camera property." );
|
CV_Error( CV_StsOutOfRange, "Failed attempt to SET unsupported camera property." );
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (propIdx != CV_CAP_PROP_AUTOGRAB) {// property for highgui class CvCapture_Android only
|
||||||
m_CameraParamsChanged = true;
|
m_CameraParamsChanged = true;
|
||||||
}
|
}
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -270,59 +299,84 @@ bool CvCapture_Android::grabFrame()
|
|||||||
if( !isOpened() )
|
if( !isOpened() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool res=false;
|
||||||
pthread_mutex_lock(&m_nextFrameMutex);
|
pthread_mutex_lock(&m_nextFrameMutex);
|
||||||
if (m_CameraParamsChanged)
|
if (m_CameraParamsChanged)
|
||||||
{
|
{
|
||||||
m_activity->applyProperties();
|
m_activity->applyProperties();
|
||||||
m_CameraParamsChanged = false;
|
m_CameraParamsChanged = false;
|
||||||
|
m_dataState= CVCAPTURE_ANDROID_STATE_NO_FRAME;//we will wait new frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_dataState!=CVCAPTURE_ANDROID_STATE_HAS_NEW_FRAME_UNGRABBED) {
|
||||||
m_waitingNextFrame = true;
|
m_waitingNextFrame = true;
|
||||||
pthread_cond_wait(&m_nextFrameCond, &m_nextFrameMutex);
|
pthread_cond_wait(&m_nextFrameCond, &m_nextFrameMutex);
|
||||||
int res=pthread_mutex_unlock(&m_nextFrameMutex);
|
}
|
||||||
if (res) {
|
|
||||||
LOGE("Error in CvCapture_Android::grabFrame: pthread_mutex_unlock returned %d --- probably, this object has been destroyed", res);
|
if (m_dataState == CVCAPTURE_ANDROID_STATE_HAS_NEW_FRAME_UNGRABBED) {
|
||||||
|
//swap current and new frames
|
||||||
|
unsigned char* tmp = m_frameYUV420i;
|
||||||
|
m_frameYUV420i = m_frameYUV420inext;
|
||||||
|
m_frameYUV420inext = tmp;
|
||||||
|
|
||||||
|
//discard cached frames
|
||||||
|
m_hasGray = false;
|
||||||
|
m_hasColor = false;
|
||||||
|
|
||||||
|
m_dataState=CVCAPTURE_ANDROID_STATE_HAS_FRAME_GRABBED;
|
||||||
|
m_framesGrabbed++;
|
||||||
|
|
||||||
|
res=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res_unlock=pthread_mutex_unlock(&m_nextFrameMutex);
|
||||||
|
if (res_unlock) {
|
||||||
|
LOGE("Error in CvCapture_Android::grabFrame: pthread_mutex_unlock returned %d --- probably, this object has been destroyed", res_unlock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_framesGrabbed++;
|
return res;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IplImage* CvCapture_Android::retrieveFrame( int outputType )
|
IplImage* CvCapture_Android::retrieveFrame( int outputType )
|
||||||
{
|
{
|
||||||
IplImage* image = 0;
|
IplImage* image = NULL;
|
||||||
if (0 != m_frameYUV420i)
|
|
||||||
|
unsigned char *current_frameYUV420i=m_frameYUV420i;
|
||||||
|
//Attention! all the operations in this function below should occupy less time than the period between two frames from camera
|
||||||
|
if (NULL != current_frameYUV420i)
|
||||||
{
|
{
|
||||||
switch(outputType)
|
switch(outputType)
|
||||||
{
|
{
|
||||||
case CV_CAP_ANDROID_COLOR_FRAME:
|
case CV_CAP_ANDROID_COLOR_FRAME:
|
||||||
if (!m_hasColor)
|
if (!m_hasColor)
|
||||||
if (!(m_hasColor = convertYUV420i2BGR888(m_width, m_height, m_frameYUV420i, m_frameColor.mat)))
|
if (!(m_hasColor = convertYUV420i2BGR888(m_width, m_height, current_frameYUV420i, m_frameColor.mat)))
|
||||||
return 0;
|
return NULL;
|
||||||
image = m_frameColor.getIplImagePtr();
|
image = m_frameColor.getIplImagePtr();
|
||||||
break;
|
break;
|
||||||
case CV_CAP_ANDROID_GREY_FRAME:
|
case CV_CAP_ANDROID_GREY_FRAME:
|
||||||
if (!m_hasGray)
|
if (!m_hasGray)
|
||||||
if (!(m_hasGray = convertYUV420i2Grey(m_width, m_height, m_frameYUV420i, m_frameGray.mat)))
|
if (!(m_hasGray = convertYUV420i2Grey(m_width, m_height, current_frameYUV420i, m_frameGray.mat)))
|
||||||
return 0;
|
return NULL;
|
||||||
image = m_frameGray.getIplImagePtr();
|
image = m_frameGray.getIplImagePtr();
|
||||||
break;
|
break;
|
||||||
case CV_CAP_ANDROID_COLOR_FRAME_RGB:
|
case CV_CAP_ANDROID_COLOR_FRAME_RGB:
|
||||||
if (!m_hasColor)
|
if (!m_hasColor)
|
||||||
if (!(m_hasColor = convertYUV420i2RGB888(m_width, m_height, m_frameYUV420i, m_frameColor.mat)))
|
if (!(m_hasColor = convertYUV420i2RGB888(m_width, m_height, current_frameYUV420i, m_frameColor.mat)))
|
||||||
return 0;
|
return NULL;
|
||||||
image = m_frameColor.getIplImagePtr();
|
image = m_frameColor.getIplImagePtr();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGE("Unsupported frame output format: %d", outputType);
|
LOGE("Unsupported frame output format: %d", outputType);
|
||||||
CV_Error( CV_StsOutOfRange, "Output frame format is not supported." );
|
CV_Error( CV_StsOutOfRange, "Output frame format is not supported." );
|
||||||
image = 0;
|
image = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Attention: this method should be called inside pthread_mutex_lock(m_nextFrameMutex) only
|
||||||
void CvCapture_Android::setFrame(const void* buffer, int bufferSize)
|
void CvCapture_Android::setFrame(const void* buffer, int bufferSize)
|
||||||
{
|
{
|
||||||
int width = m_activity->getFrameWidth();
|
int width = m_activity->getFrameWidth();
|
||||||
@ -335,12 +389,13 @@ void CvCapture_Android::setFrame(const void* buffer, int bufferSize)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//allocate memery if needed
|
//allocate memory if needed
|
||||||
prepareCacheForYUV420i(width, height);
|
prepareCacheForYUV420i(width, height);
|
||||||
|
|
||||||
//copy data
|
//copy data
|
||||||
memcpy(m_frameYUV420inext, buffer, bufferSize);
|
memcpy(m_frameYUV420inext, buffer, bufferSize);
|
||||||
|
|
||||||
|
#if 0 //moved this part of code into grabFrame
|
||||||
//swap current and new frames
|
//swap current and new frames
|
||||||
unsigned char* tmp = m_frameYUV420i;
|
unsigned char* tmp = m_frameYUV420i;
|
||||||
m_frameYUV420i = m_frameYUV420inext;
|
m_frameYUV420i = m_frameYUV420inext;
|
||||||
@ -349,6 +404,7 @@ void CvCapture_Android::setFrame(const void* buffer, int bufferSize)
|
|||||||
//discard cached frames
|
//discard cached frames
|
||||||
m_hasGray = false;
|
m_hasGray = false;
|
||||||
m_hasColor = false;
|
m_hasColor = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CvCapture_Android::prepareCacheForYUV420i(int width, int height)
|
void CvCapture_Android::prepareCacheForYUV420i(int width, int height)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user