7#include <QtCore/QLoggingCategory>
25 auto planes =
frame.callMethod<QtJniTypes::AndroidImagePlaneArray>(
"getPlanes");
26 if (!planes.isValid())
29 int numberPlanes = jniEnv->GetArrayLength(planes.object<jarray>());
31 int pixelStrides[numberPlanes];
32 int rowStrides[numberPlanes];
33 int bufferSize[numberPlanes];
34 uint8_t *
buffer[numberPlanes];
36 auto resetPlane = [&](
int index) {
37 if (index < 0 || index > numberPlanes)
40 rowStrides[
index] = 0;
41 pixelStrides[
index] = 0;
42 bufferSize[
index] = 0;
47 QJniObject plane = jniEnv->GetObjectArrayElement(planes.object<jobjectArray>(),
index);
48 if (jniEnv.checkAndClearExceptions() || !plane.isValid()) {
53 rowStrides[
index] = plane.callMethod<jint>(
"getRowStride");
54 pixelStrides[
index] = plane.callMethod<jint>(
"getPixelStride");
56 auto byteBuffer = plane.callMethod<QtJniTypes::JavaByteBuffer>(
"getBuffer");
57 if (!byteBuffer.isValid()) {
64 buffer[
index] =
static_cast<uint8_t *
>(jniEnv->GetDirectBufferAddress(byteBuffer.object()));
65 bufferSize[
index] = byteBuffer.callMethod<jint>(
"remaining");
74 AndroidImageFormat imageFormat = AndroidImageFormat(
format);
76 switch (imageFormat) {
77 case AndroidImageFormat::JPEG:
80 case AndroidImageFormat::YUV_420_888:
81 if (numberPlanes < 3) {
86 if (pixelStrides[1] == 1)
88 else if (pixelStrides[1] == 2 && abs(
buffer[1] -
buffer[2]) == 1)
92 case AndroidImageFormat::HEIC:
96 case AndroidImageFormat::RAW_PRIVATE:
97 case AndroidImageFormat::RAW_SENSOR:
101 case AndroidImageFormat::FLEX_RGBA_8888:
102 case AndroidImageFormat::FLEX_RGB_888:
107 case AndroidImageFormat::YUV_422_888:
108 case AndroidImageFormat::YUV_444_888:
109 case AndroidImageFormat::YCBCR_P010:
119 qCWarning(qLCAndroidCameraFrame) <<
"Cannot determine image format!";
123 auto copyPlane = [&](
int mapIndex,
int arrayIndex) {
124 if (arrayIndex >= numberPlanes)
127 m_planes[mapIndex].rowStride = rowStrides[arrayIndex];
128 m_planes[mapIndex].size = bufferSize[arrayIndex];
129 m_planes[mapIndex].data =
buffer[arrayIndex];
132 switch (calculedPixelFormat) {
148 <<
"FFMpeg HW Mediacodec does not encode other than YCbCr formats";
151 m_planes[0].rowStride = m_image.bytesPerLine();
152 m_planes[0].size = m_image.sizeInBytes();
153 m_planes[0].data = m_image.bits();
160 long timestamp =
frame.callMethod<jlong>(
"getTimestamp");
161 m_timestamp = timestamp / 1000;
163 int width =
frame.callMethod<jint>(
"getWidth");
176 m_frame = jniEnv->NewGlobalRef(
frame.object());
177 jniEnv.checkAndClearExceptions();
178 }
else if (
frame.isValid()) {
179 frame.callMethod<
void>(
"close");
189 if (qFrame.isValid())
190 qFrame.callMethod<
void>(
"close");
194 jniEnv->DeleteGlobalRef(m_frame);
QAndroidCameraFrame(QJniObject frame)
static QImage fromData(QByteArrayView data, const char *format=nullptr)
Combined button and popup list for selecting options.
Q_DECLARE_JNI_CLASS(AndroidImageFormat, "android/graphics/ImageFormat")
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum format
Q_DECLARE_JNI_TYPE(File, "Ljava/io/File;")