13#include <QtConcurrent/qtconcurrentrun.h>
19#include <private/qplatformimagecapture_p.h>
20#include <private/qplatformvideosink_p.h>
21#include <private/qmemoryvideobuffer_p.h>
22#include <private/qcameradevice_p.h>
23#include <private/qmediastoragelocation_p.h>
24#include <QImageWriter>
36 , m_previewStarted(
false)
37 , m_readyForCapture(
false)
38 , m_currentImageCaptureId(-1)
39 , m_previewCallback(0)
44 this, &QAndroidCameraSession::onApplicationStateChanged);
49 &QAndroidCameraSession::updateOrientation);
76 if (m_active == active)
82 m_isStateSaved =
true;
83 m_savedState = active;
87 m_isStateSaved =
false;
89 setActiveHelper(m_active);
93void QAndroidCameraSession::setActiveHelper(
bool active)
99 if (!m_camera && !open()) {
107void QAndroidCameraSession::updateAvailableCameras()
109 g_availableCameras->clear();
112 for (
int i = 0;
i < numCameras; ++
i) {
116 if (!
info->id.isEmpty()) {
126 g_availableCameras->append(
info->create());
133 if (g_availableCameras->isEmpty())
134 updateAvailableCameras();
136 return *g_availableCameras;
139bool QAndroidCameraSession::open()
147 this, &QAndroidCameraSession::onCameraPictureExposed);
149 this, &QAndroidCameraSession::onLastPreviewFrameFetched,
152 this, &QAndroidCameraSession::onNewPreviewFrame,
155 this, &QAndroidCameraSession::onCameraPictureCaptured);
157 this, &QAndroidCameraSession::onCameraPreviewStarted);
159 this, &QAndroidCameraSession::onCameraPreviewStopped);
161 this, &QAndroidCameraSession::onCameraPreviewFailedToStart);
163 this, &QAndroidCameraSession::onCameraTakePictureFailed);
174 return m_camera != 0;
177void QAndroidCameraSession::close()
184 m_readyForCapture =
false;
185 m_currentImageCaptureId = -1;
186 m_currentImageCaptureFileName.
clear();
187 m_actualImageSettings = m_requestedImageSettings;
199 m_videoOutput->
stop();
200 m_videoOutput->
reset();
205 if (m_videoOutput->
isReady()) {
206 onVideoOutputReady(
true);
209 this, &QAndroidCameraSession::onVideoOutputReady);
218 m_requestedFpsRange.
min =
format.minFrameRate();
219 m_requestedFpsRange.
max =
format.maxFrameRate();
224 if (m_readyForCapture)
238 QSize adjustedViewfinderResolution;
241 const bool validCaptureSize = captureSize.
width() > 0 && captureSize.
height() > 0;
246 adjustedViewfinderResolution = captureSize;
248 qreal captureAspectRatio = 0;
249 if (validCaptureSize)
252 if (validCaptureSize) {
254 qreal minAspectDiff = 1;
255 QSize closestResolution;
256 for (
int i = previewSizes.
count() - 1;
i >= 0; --
i) {
260 adjustedViewfinderResolution =
size;
262 }
else if (minAspectDiff >
qAbs(sizeAspect - captureAspectRatio)) {
263 closestResolution =
size;
264 minAspectDiff =
qAbs(sizeAspect - captureAspectRatio);
267 if (!adjustedViewfinderResolution.
isValid()) {
268 qWarning(
"Cannot find a viewfinder resolution matching the capture aspect ratio.");
269 if (closestResolution.
isValid()) {
270 adjustedViewfinderResolution = closestResolution;
271 qWarning(
"Using closest viewfinder resolution.");
277 adjustedViewfinderResolution = previewSizes.
last();
290 if (adjustedFps.
min == 0 || adjustedFps.
max == 0)
291 adjustedFps = currentFpsRange;
296 QSize cameraOutputResolution = adjustedViewfinderResolution;
297 QSize videoOutputResolution = adjustedViewfinderResolution;
301 if (rotation == 90 || rotation == 270) {
307 if (currentViewfinderResolution != cameraOutputResolution
308 || (m_videoOutput && currentVideoOutputResolution != videoOutputResolution)
309 || currentPreviewFormat != adjustedPreviewFormat || currentFpsRange.
min != adjustedFps.
min
310 || currentFpsRange.
max != adjustedFps.
max) {
316 if (m_previewStarted && restartPreview)
324 if (m_previewStarted && restartPreview)
360bool QAndroidCameraSession::startPreview()
362 if (!m_camera || !m_videoOutput)
365 if (m_previewStarted)
383 m_previewStarted =
true;
384 m_videoOutput->
start();
389QSize QAndroidCameraSession::getDefaultResolution()
const
395 if (hasHighQualityProfile) {
406void QAndroidCameraSession::stopPreview()
408 if (!m_camera || !m_previewStarted)
419 m_videoOutput->
stop();
420 m_videoOutput->
reset();
422 m_previewStarted =
false;
427 if (m_requestedImageSettings ==
settings)
430 m_requestedImageSettings = m_actualImageSettings =
settings;
432 applyImageSettings();
434 if (m_readyForCapture)
440 m_rotationEnabled =
true;
445 m_rotationEnabled =
false;
448void QAndroidCameraSession::updateOrientation()
450 if (!m_camera || !m_rotationEnabled)
468 int deviceOrientation = 0;
469 switch (screenOrientation) {
474 deviceOrientation = 90;
477 deviceOrientation = 180;
480 deviceOrientation = 270;
489 rotation = (nativeCameraOrientation + deviceOrientation) % 360;
490 rotation = (360 - rotation) % 360;
492 rotation = (nativeCameraOrientation - deviceOrientation + 360) % 360;
507 m_videoFrameCallbackMutex.
lock();
508 m_previewCallback = callback;
511 m_videoFrameCallbackMutex.
unlock();
514void QAndroidCameraSession::applyImageSettings()
522 const QSize requestedResolution = m_requestedImageSettings.
resolution();
524 if (!requestedResolution.
isValid()) {
526 }
else if (!supportedResolutions.
contains(requestedResolution)) {
528 int reqPixelCount = requestedResolution.
width() * requestedResolution.
height();
530 for (
int i = 0;
i < supportedResolutions.
size(); ++
i) {
531 const QSize &
s = supportedResolutions.
at(
i);
532 supportedPixelCounts.
append(
s.width() *
s.height());
535 m_actualImageSettings.
setResolution(supportedResolutions.
at(closestIndex));
539 int jpegQuality = 100;
540 switch (m_requestedImageSettings.
quality()) {
562 return isActive() && m_readyForCapture;
567 if (m_readyForCapture == ready)
570 m_readyForCapture = ready;
574int QAndroidCameraSession::captureImage()
576 const int newImageCaptureId = m_currentImageCaptureId + 1;
581 return newImageCaptureId;
586 m_currentImageCaptureId = newImageCaptureId;
591 return m_currentImageCaptureId;
596 m_currentImageCaptureFileName =
fileName;
597 m_imageCaptureToBuffer =
false;
598 return captureImage();
603 m_currentImageCaptureFileName.
clear();
604 m_imageCaptureToBuffer =
true;
605 return captureImage();
608void QAndroidCameraSession::onCameraTakePictureFailed()
611 tr(
"Failed to capture image"));
617void QAndroidCameraSession::onCameraPictureExposed()
626void QAndroidCameraSession::onLastPreviewFrameFetched(
const QVideoFrame &
frame)
637void QAndroidCameraSession::processPreviewImage(
int id,
const QVideoFrame &
frame,
int rotation)
656 m_videoFrameCallbackMutex.
lock();
658 if (m_previewCallback)
661 m_videoFrameCallbackMutex.
unlock();
664void QAndroidCameraSession::onCameraPictureCaptured(
const QVideoFrame &
frame)
684 m_currentImageCaptureId,
frame, m_imageCaptureToBuffer,
685 m_currentImageCaptureFileName);
692void QAndroidCameraSession::onCameraPreviewStarted()
697void QAndroidCameraSession::onCameraPreviewFailedToStart()
706 m_videoOutput->
stop();
707 m_videoOutput->
reset();
709 m_previewStarted =
false;
716void QAndroidCameraSession::onCameraPreviewStopped()
718 if (!m_previewStarted)
723void QAndroidCameraSession::processCapturedImage(
int id,
const QVideoFrame &
frame,
735 if (!writer.canWrite()) {
741 const bool written = writer.write(
frame.toImage());
754void QAndroidCameraSession::onVideoOutputReady(
bool ready)
756 if (ready && m_active)
760void QAndroidCameraSession::onApplicationStateChanged()
765 if (!m_keepActive && m_active) {
766 m_savedState = m_active;
768 m_isStateSaved =
true;
772 if (m_isStateSaved) {
774 m_isStateSaved =
false;
784 m_keepActive = keepAlive;
798 m_retryPreviewConnection =
807 delete m_textureOutput;
808 m_textureOutput =
nullptr;
813 setVideoOutput(m_textureOutput);
818#include "moc_qandroidcamerasession_p.cpp"
int getValue(Field field) const
static bool hasProfile(jint cameraId, Quality quality)
static AndroidCamcorderProfile get(jint cameraId, Quality quality)
ImageFormat getPreviewFormat()
QSize getPreferredPreviewSizeForVideo()
void setPictureSize(const QSize &size)
static AndroidCamera::ImageFormat AndroidImageFormatFromQtPixelFormat(QVideoFrameFormat::PixelFormat)
QList< QCameraFormat > getSupportedFormats()
bool setPreviewDisplay(AndroidSurfaceHolder *surfaceHolder)
QList< FpsRange > getSupportedPreviewFpsRange()
void newPreviewFrame(const QVideoFrame &frame)
static int getNumberOfCameras()
void previewFailedToStart()
static QVideoFrameFormat::PixelFormat QtPixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat)
void lastPreviewFrameFetched(const QVideoFrame &frame)
bool setPreviewTexture(AndroidSurfaceTexture *surfaceTexture)
FpsRange getPreviewFpsRange()
void fetchLastPreviewFrame()
void setPreviewFpsRange(FpsRange)
void setJpegQuality(int quality)
QList< QSize > getSupportedPictureSizes()
static void getCameraInfo(int id, QCameraDevicePrivate *info)
QList< QSize > getSupportedPreviewSizes()
static AndroidCamera * open(int cameraId)
QList< ImageFormat > getSupportedPreviewFormats()
void setDisplayOrientation(int degrees)
QSize previewSize() const
int getNativeOrientation()
void notifyNewFrames(bool notify)
void setPreviewSize(const QSize &size)
void setPreviewFormat(ImageFormat fmt)
void pictureCaptured(const QVideoFrame &frame)
void setVideoSink(QVideoSink *surface)
int currentCameraRotation() const
void setImageSettings(const QImageEncoderSettings &settings)
void setActive(bool active)
void imageCaptured(int id, const QImage &preview)
void error(int error, const QString &errorString)
QList< AndroidCamera::FpsRange > getSupportedPreviewFpsRange() const
void setCameraFormat(const QCameraFormat &format)
int capture(const QString &fileName)
void readyForCaptureChanged(bool)
void imageCaptureError(int id, int error, const QString &errorString)
void setVideoOutput(QAndroidVideoOutput *output)
bool isReadyForCapture() const
void imageAvailable(int id, const QVideoFrame &buffer)
void applyResolution(const QSize &captureSize=QSize(), bool restartPreview=true)
AndroidCamera * camera() const
QList< QVideoFrameFormat::PixelFormat > getSupportedPixelFormats() const
QList< QSize > getSupportedPreviewSizes() const
void setKeepAlive(bool keepAlive)
void imageSaved(int id, const QString &fileName)
static const QList< QCameraDevice > & availableCameras()
void setPreviewFormat(AndroidCamera::ImageFormat format)
void imageExposed(int id)
void setReadyForCapture(bool ready)
void setPreviewCallback(PreviewCallback *callback)
virtual AndroidSurfaceHolder * surfaceHolder()
virtual void setVideoSize(const QSize &)
virtual QSize getVideoSize() const
virtual AndroidSurfaceTexture * surfaceTexture()
\inmodule QtCore \reentrant
static Qt::ApplicationState applicationState()
QScreen * primaryScreen
the primary (or default) screen of the application.
void applicationStateChanged(Qt::ApplicationState state)
QImageCapture::Quality quality() const
void setFormat(QImageCapture::FileFormat f)
void setResolution(const QSize &s)
The QImageWriter class provides a format independent interface for writing images to files or other d...
qsizetype size() const noexcept
const_reference at(qsizetype i) const noexcept
qsizetype count() const noexcept
void append(parameter_type t)
void unlock() noexcept
Unlocks the mutex.
void lock() noexcept
Locks the mutex.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Qt::ScreenOrientation primaryOrientation
the primary screen orientation
Qt::ScreenOrientation orientation
the screen orientation
void orientationChanged(Qt::ScreenOrientation orientation)
This signal is emitted when the orientation of the screen changes with orientation as an argument.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr QSize transposed() const noexcept
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
void transpose() noexcept
Swaps the width and height values.
\macro QT_RESTRICTED_CAST_FROM_ASCII
void clear()
Clears the contents of the string and makes it null.
The QVideoFrame class represents a frame of video data.
The QVideoSink class represents a generic sink for video data.
QPlatformVideoSink * platformVideoSink() const
Combined button and popup list for selecting options.
auto run(QThreadPool *pool, Function &&f, Args &&...args)
@ InvertedLandscapeOrientation
@ InvertedPortraitOrientation
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
constexpr T qAbs(const T &t)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum format
GLuint GLenum GLenum transform
GLsizei GLenum GLboolean sink
static QT_BEGIN_NAMESPACE bool isRelative(const QString &path)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
QT_BEGIN_NAMESPACE typedef uchar * output
QFileInfo info(fileName)
[8]
QSettings settings("MySoft", "Star Runner")
[0]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
myObject disconnect()
[26]
virtual void onFrameAvailable(const QVideoFrame &frame)=0
bool contains(const AT &t) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent