Android: camera moved to a dedicated thread

Actual camera work moved to JCameraWorker which lives in dedicated
thread. JCamera now acts as proxy calling JCameraWorker methods with
invokeMethod (when it is needed).

[ChangeLog][QtMultimedia][Android] camera operations moved to a
dedicated thread

Task-number: QTBUG-35564
Change-Id: Ie4edcbf0869d56b0fef4ad0c820450cc77657fdd
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
Denis Kormalev
2013-12-16 12:54:17 +04:00
committed by The Qt Project
parent ecce937a05
commit a0df6c3836
5 changed files with 688 additions and 164 deletions

View File

@@ -182,7 +182,10 @@ bool QAndroidCameraSession::open()
if (m_camera) { if (m_camera) {
connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed())); connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed()));
connect(m_camera, SIGNAL(previewFetched(QByteArray)), this, SLOT(onCameraPreviewFetched(QByteArray)));
connect(m_camera, SIGNAL(pictureCaptured(QByteArray)), this, SLOT(onCameraPictureCaptured(QByteArray))); connect(m_camera, SIGNAL(pictureCaptured(QByteArray)), this, SLOT(onCameraPictureCaptured(QByteArray)));
connect(m_camera, SIGNAL(previewStarted()), this, SLOT(onCameraPreviewStarted()));
connect(m_camera, SIGNAL(previewStopped()), this, SLOT(onCameraPreviewStopped()));
m_nativeOrientation = m_camera->getNativeOrientation(); m_nativeOrientation = m_camera->getNativeOrientation();
@@ -309,11 +312,6 @@ void QAndroidCameraSession::startPreview()
m_camera->startPreview(); m_camera->startPreview();
m_previewStarted = true; m_previewStarted = true;
m_status = QCamera::ActiveStatus;
emit statusChanged(m_status);
setReadyForCapture(true);
} }
void QAndroidCameraSession::stopPreview() void QAndroidCameraSession::stopPreview()
@@ -331,11 +329,6 @@ void QAndroidCameraSession::stopPreview()
if (m_videoOutput) if (m_videoOutput)
m_videoOutput->stop(); m_videoOutput->stop();
m_previewStarted = false; m_previewStarted = false;
m_status = QCamera::LoadedStatus;
emit statusChanged(m_status);
setReadyForCapture(false);
} }
void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settings) void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settings)
@@ -507,11 +500,15 @@ void QAndroidCameraSession::onCameraPictureExposed()
return; return;
emit imageExposed(m_currentImageCaptureId); emit imageExposed(m_currentImageCaptureId);
QByteArray lastFrame = m_camera->fetchLastPreviewFrame(); m_camera->fetchLastPreviewFrame();
if (lastFrame.size()) { }
void QAndroidCameraSession::onCameraPreviewFetched(const QByteArray &preview)
{
if (preview.size()) {
QtConcurrent::run(this, &QAndroidCameraSession::processPreviewImage, QtConcurrent::run(this, &QAndroidCameraSession::processPreviewImage,
m_currentImageCaptureId, m_currentImageCaptureId,
lastFrame, preview,
m_camera->getRotation()); m_camera->getRotation());
} }
} }
@@ -532,10 +529,28 @@ void QAndroidCameraSession::onCameraPictureCaptured(const QByteArray &data)
// Preview needs to be restarted after taking a picture // Preview needs to be restarted after taking a picture
m_camera->startPreview(); m_camera->startPreview();
}
void QAndroidCameraSession::onCameraPreviewStarted()
{
if (m_status == QCamera::StartingStatus) {
m_status = QCamera::ActiveStatus;
emit statusChanged(m_status);
}
setReadyForCapture(true); setReadyForCapture(true);
} }
void QAndroidCameraSession::onCameraPreviewStopped()
{
if (m_status == QCamera::StoppingStatus) {
m_status = QCamera::LoadedStatus;
emit statusChanged(m_status);
}
setReadyForCapture(false);
}
void QAndroidCameraSession::processCapturedImage(int id, void QAndroidCameraSession::processCapturedImage(int id,
const QByteArray &data, const QByteArray &data,
const QSize &resolution, const QSize &resolution,

View File

@@ -113,7 +113,10 @@ private Q_SLOTS:
void onApplicationStateChanged(Qt::ApplicationState state); void onApplicationStateChanged(Qt::ApplicationState state);
void onCameraPictureExposed(); void onCameraPictureExposed();
void onCameraPreviewFetched(const QByteArray &preview);
void onCameraPictureCaptured(const QByteArray &data); void onCameraPictureCaptured(const QByteArray &data);
void onCameraPreviewStarted();
void onCameraPreviewStopped();
private: private:
bool open(); bool open();

File diff suppressed because it is too large Load Diff

View File

@@ -49,9 +49,15 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class JCamera : public QObject, public QJNIObjectPrivate class QThread;
class JCameraWorker;
class JCamera : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS(CameraFacing)
Q_ENUMS(ImageFormat)
public: public:
enum CameraFacing { enum CameraFacing {
CameraFacingBack = 0, CameraFacingBack = 0,
@@ -72,7 +78,7 @@ public:
static JCamera *open(int cameraId); static JCamera *open(int cameraId);
int cameraId() const { return m_cameraId; } int cameraId() const;
void lock(); void lock();
void unlock(); void unlock();
@@ -90,7 +96,7 @@ public:
ImageFormat getPreviewFormat(); ImageFormat getPreviewFormat();
void setPreviewFormat(ImageFormat fmt); void setPreviewFormat(ImageFormat fmt);
QSize previewSize() const { return m_previewSize; } QSize previewSize() const;
void setPreviewSize(const QSize &size); void setPreviewSize(const QSize &size);
void setPreviewTexture(jobject surfaceTexture); void setPreviewTexture(jobject surfaceTexture);
@@ -149,12 +155,15 @@ public:
void takePicture(); void takePicture();
QByteArray fetchLastPreviewFrame(); void fetchLastPreviewFrame();
QJNIObjectPrivate getCameraObject();
static bool initJNI(JNIEnv *env); static bool initJNI(JNIEnv *env);
Q_SIGNALS: Q_SIGNALS:
void previewSizeChanged(); void previewSizeChanged();
void previewStarted();
void previewStopped();
void autoFocusStarted(); void autoFocusStarted();
void autoFocusComplete(bool success); void autoFocusComplete(bool success);
@@ -163,21 +172,12 @@ Q_SIGNALS:
void pictureExposed(); void pictureExposed();
void pictureCaptured(const QByteArray &data); void pictureCaptured(const QByteArray &data);
void previewFetched(const QByteArray &preview);
private: private:
JCamera(int cameraId, jobject cam); JCamera(int cameraId, jobject cam, QThread *workerThread);
void applyParameters();
QStringList callStringListMethod(const char *methodName); JCameraWorker *d;
int m_cameraId;
QJNIObjectPrivate m_info;
QJNIObjectPrivate m_parameters;
QSize m_previewSize;
int m_rotation;
bool m_hasAPI14;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -151,7 +151,7 @@ void JMediaRecorder::setAudioSource(AudioSource source)
void JMediaRecorder::setCamera(JCamera *camera) void JMediaRecorder::setCamera(JCamera *camera)
{ {
QJNIObjectPrivate cam = camera->getObjectField("m_camera", "Landroid/hardware/Camera;"); QJNIObjectPrivate cam = camera->getCameraObject();
callMethod<void>("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); callMethod<void>("setCamera", "(Landroid/hardware/Camera;)V", cam.object());
} }