aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-06-14 19:32:18 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-06-14 19:32:18 +0000
commite4492e9c8add9183157ea1ac4d926b5e70046750 (patch)
tree46014dc39b585585c35a21bd117ceca997d8a95b
parent5b574d68e87d79ebc14a59d5b7e8d8e3ed3325df (diff)
parente26532d7f6143f436f9ebabbc2bc4e8e32b348bb (diff)
downloadqemu-e4492e9c8add9183157ea1ac4d926b5e70046750.tar.gz
Merge "Fix webcam orientation on Mac" into snap-temp-L93000000961281579
-rw-r--r--android/android-emu/android/camera/camera-capture-linux.c3
-rw-r--r--android/android-emu/android/camera/camera-capture-mac.m89
-rw-r--r--android/android-emu/android/camera/camera-capture-windows.cpp3
-rw-r--r--android/android-emu/android/camera/camera-capture.h3
-rw-r--r--android/android-emu/android/camera/camera-common.cpp14
-rw-r--r--android/android-emu/android/camera/camera-common.h15
-rw-r--r--android/android-emu/android/camera/camera-service.cpp13
-rw-r--r--android/android-emu/android/camera/camera-videoplayback.cpp3
-rw-r--r--android/android-emu/android/camera/camera-videoplayback.h3
-rw-r--r--android/android-emu/android/camera/camera-virtualscene.cpp3
-rw-r--r--android/android-emu/android/camera/camera-virtualscene.h4
-rw-r--r--android/android-emu/android/hw-sensors.cpp25
-rw-r--r--android/android-emu/android/hw-sensors.h3
13 files changed, 154 insertions, 27 deletions
diff --git a/android/android-emu/android/camera/camera-capture-linux.c b/android/android-emu/android/camera/camera-capture-linux.c
index 8fdd1037c2..8be5c53dbd 100644
--- a/android/android-emu/android/camera/camera-capture-linux.c
+++ b/android/android-emu/android/camera/camera-capture-linux.c
@@ -992,7 +992,8 @@ int camera_device_read_frame(CameraDevice* ccd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp) {
+ float exp_comp,
+ const char* direction) {
LinuxCameraDevice* cd;
/* Sanity checks. */
diff --git a/android/android-emu/android/camera/camera-capture-mac.m b/android/android-emu/android/camera/camera-capture-mac.m
index 624124d7a5..472295c5bb 100644
--- a/android/android-emu/android/camera/camera-capture-mac.m
+++ b/android/android-emu/android/camera/camera-capture-mac.m
@@ -21,6 +21,7 @@
#include "android/camera/camera-capture.h"
#include "android/camera/camera-format-converters.h"
+#include "android/hw-sensors.h"
#include "android/utils/debug.h"
#include "android/utils/system.h"
@@ -106,6 +107,8 @@ FourCCToInternal(uint32_t cm_pix_format)
int desired_width;
/* Desired frame height */
int desired_height;
+ /* Scratch buffer to hold imgs of desired rotation. */
+ void* desired_rotated_frame;
/* Scratch buffer to hold imgs of desired width and height. */
void* desired_scaled_frame;
}
@@ -137,12 +140,14 @@ FourCCToInternal(uint32_t cm_pix_format)
* in the device. The client should respond to this value by repeating the
* read, rather than reporting an error.
*/
-- (int)read_frame:(ClientFrame*)
- result_frame:(int)
- fbs_num:(float)
- r_scale:(float)
- g_scale:(float)
- b_scale:(float)exp_comp;
+- (int)read_frame:
+ (ClientFrame*)result_frame:
+ (int)fbs_num:
+ (float)r_scale:
+ (float)g_scale:
+ (float)b_scale:
+ (float)exp_comp:
+ (const char*)direction;
@end
@@ -175,6 +180,7 @@ FourCCToInternal(uint32_t cm_pix_format)
return nil;
}
success = false;
+ desired_rotated_frame = nil;
desired_scaled_frame = nil;
/* Create capture session. */
@@ -269,6 +275,11 @@ FourCCToInternal(uint32_t cm_pix_format)
free(desired_scaled_frame);
desired_scaled_frame = nil;
}
+
+ if (desired_rotated_frame != nil) {
+ free(desired_rotated_frame);
+ desired_rotated_frame = nil;
+ }
}
}
@@ -309,11 +320,13 @@ FourCCToInternal(uint32_t cm_pix_format)
}
}
-- (int)read_frame:(ClientFrame*)
- result_frame:(float)
- r_scale:(float)
- g_scale:(float)
- b_scale:(float)exp_comp {
+- (int)read_frame:
+ (ClientFrame*)result_frame:
+ (float)r_scale:
+ (float)g_scale:
+ (float)b_scale:
+ (float)exp_comp:
+ (const char*)direction {
int res = -1;
@@ -347,7 +360,50 @@ FourCCToInternal(uint32_t cm_pix_format)
if (pixels != nil) {
D("%s: convert frame\n", __func__);
+ vImage_Buffer rotate_input;
+ rotate_input.width = frame_width;
+ rotate_input.height = frame_height;
+ rotate_input.rowBytes = srcBpr;
+ rotate_input.data = pixels;
+
+ vImage_Buffer rotate_output;
+ AndroidCoarseOrientation orientation
+ = get_coarse_orientation();
+ switch (orientation) {
+ case ANDROID_COARSE_PORTRAIT:
+ case ANDROID_COARSE_REVERSE_PORTRAIT:
+ // Swap width and height
+ frame_height ^= frame_width;
+ frame_width ^= frame_height;
+ frame_height ^= frame_width;
+
+ srcBpr = srcBpp * frame_width;
+ break;
+ case ANDROID_COARSE_LANDSCAPE:
+ case ANDROID_COARSE_REVERSE_LANDSCAPE:
+ break;
+ }
+ rotate_output.width = frame_width;
+ rotate_output.height = frame_height;
+ rotate_output.rowBytes = srcBpr;
+ if (desired_rotated_frame == nil) {
+ desired_rotated_frame = realloc(desired_rotated_frame,
+ 4 * frame_width * frame_height);
+ }
+ rotate_output.data = desired_rotated_frame;
+ vImage_Error err = 0;
+ UInt8 backColor[] = {0, 0, 0, 0};
+ // Front and back camera has different rotations
+ int rotation = 0 == strcmp("back", direction) ?
+ (1 + orientation) % 4:
+ (5 - orientation) % 4;
+ err = vImageRotate90_ARGB8888(&rotate_input, &rotate_output,
+ rotation, backColor, 0);
+
+ if (err != kvImageNoError) {
+ E("%s: error in scale: 0x%x\n", __func__, err);
+ }
// AVFoundation doesn't provide pre-scaled output.
// Scale it here, using the Accelerate framework.
// Also needs to be the correct aspect ratio,
@@ -382,7 +438,7 @@ FourCCToInternal(uint32_t cm_pix_format)
scale_input.width = cropW;
scale_input.height = cropH;
scale_input.rowBytes = srcBpr;
- scale_input.data = ((char*)pixels) + start;
+ scale_input.data = ((char*)desired_rotated_frame) + start;
const int dstBpp = 4; // ARGB8888
scale_output.width = desired_width;
@@ -393,7 +449,7 @@ FourCCToInternal(uint32_t cm_pix_format)
D("%s: image scale %d %d -> %d %d\n",
__func__, frame_width, frame_height, desired_width, desired_height);
- vImage_Error err = vImageScale_ARGB8888(&scale_input, &scale_output, NULL, 0);
+ err = vImageScale_ARGB8888(&scale_input, &scale_output, NULL, 0);
if (err != kvImageNoError) {
E("%s: error in scale: 0x%x\n", __func__, err);
}
@@ -575,7 +631,8 @@ int camera_device_read_frame(CameraDevice* cd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp) {
+ float exp_comp,
+ const char* direction) {
MacCameraDevice* mcd;
/* Sanity checks. */
@@ -598,7 +655,9 @@ int camera_device_read_frame(CameraDevice* cd,
result_frame:
r_scale:
g_scale:
- b_scale:exp_comp];
+ b_scale:
+ exp_comp:
+ direction];
}
void
diff --git a/android/android-emu/android/camera/camera-capture-windows.cpp b/android/android-emu/android/camera/camera-capture-windows.cpp
index a0cf684a4f..67d4983a2a 100644
--- a/android/android-emu/android/camera/camera-capture-windows.cpp
+++ b/android/android-emu/android/camera/camera-capture-windows.cpp
@@ -1260,7 +1260,8 @@ int camera_device_read_frame(CameraDevice* ccd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp) {
+ float exp_comp,
+ const char* direction) {
MediaFoundationCameraDevice* cd = toMediaFoundationCameraDevice(ccd);
if (!cd) {
LOG(ERROR) << "Invalid camera descriptor.";
diff --git a/android/android-emu/android/camera/camera-capture.h b/android/android-emu/android/camera/camera-capture.h
index 4647b60028..8af8fdd3d9 100644
--- a/android/android-emu/android/camera/camera-capture.h
+++ b/android/android-emu/android/camera/camera-capture.h
@@ -113,7 +113,8 @@ extern int camera_device_read_frame(CameraDevice* cd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp);
+ float exp_comp,
+ const char* direction);
/* Closes camera device, opened in camera_device_open routine.
* Param:
diff --git a/android/android-emu/android/camera/camera-common.cpp b/android/android-emu/android/camera/camera-common.cpp
index 22b3f0a1f2..9e84d746d2 100644
--- a/android/android-emu/android/camera/camera-common.cpp
+++ b/android/android-emu/android/camera/camera-common.cpp
@@ -65,3 +65,17 @@ void camera_info_copy(CameraInfo* ci, const CameraInfo* from) {
ci->in_use = from->in_use;
}
}
+
+static GetCoarseOrientation sGetCoarseOrientation = nullptr;
+
+void set_coarse_orientation_getter(GetCoarseOrientation getCoarseOrientation) {
+ sGetCoarseOrientation = getCoarseOrientation;
+}
+
+int get_coarse_orientation() {
+ if (!sGetCoarseOrientation) {
+ VERBOSE_PRINT(camera, "WARNING: getCoarseOrientation not set");
+ return 0;
+ }
+ return sGetCoarseOrientation();
+}
diff --git a/android/android-emu/android/camera/camera-common.h b/android/android-emu/android/camera/camera-common.h
index 2b1fbb101b..47b003e890 100644
--- a/android/android-emu/android/camera/camera-common.h
+++ b/android/android-emu/android/camera/camera-common.h
@@ -216,4 +216,19 @@ enum ClientStartResult {
typedef enum ClientStartResult ClientStartResult;
+// Return the coarse orientation of the device.
+// 0: ANDROID_COARSE_PORTRAIT, 0 degrees
+// 1: ANDROID_COARSE_REVERSE_LANDSCAPE, 90 degrees
+// 2: ANDROID_COARSE_REVERSE_PORTRAIT, 180 degrees
+// 3: ANDROID_COARSE_LANDSCAPE, 270 degrees
+typedef int (*GetCoarseOrientation)();
+
+// Pass the function pointer to get coarse orientation.
+// Because of build dependency issue we need to set the function pointer here.
+void set_coarse_orientation_getter(GetCoarseOrientation getCoarseOrientation);
+
+// Return the coarse orientation of the device, using the
+// coarse orientation getter that was previously set.
+int get_coarse_orientation();
+
ANDROID_END_HEADER
diff --git a/android/android-emu/android/camera/camera-service.cpp b/android/android-emu/android/camera/camera-service.cpp
index fc95da856e..c478483134 100644
--- a/android/android-emu/android/camera/camera-service.cpp
+++ b/android/android-emu/android/camera/camera-service.cpp
@@ -461,6 +461,8 @@ _camera_service_init(CameraServiceDesc* csd)
/* Enumerate camera devices connected to the host. */
memset(csd->camera_info, 0, sizeof(CameraInfo) * MAX_CAMERA);
csd->camera_count = 0;
+ set_coarse_orientation_getter(
+ (GetCoarseOrientation)android_sensors_get_coarse_orientation);
if (androidHwConfig_hasVirtualSceneCamera(getConsoleAgents()->settings->hw())) {
/* Set up virtual scene camera emulation. */
@@ -779,7 +781,8 @@ struct CameraClient
float r_scale,
float g_scale,
float b_scale,
- float exp_comp);
+ float exp_comp,
+ const char* direction);
void (*close)(CameraDevice* cd);
/* Buffer allocated for video frames.
@@ -1555,7 +1558,7 @@ _camera_client_query_frame(CameraClient* cc, QemudClient* qc, const char* param)
looper_nowNsWithClock(looper_getForThread(), LOOPER_CLOCK_VIRTUAL);
repeat = cc->read_frame(cc->camera, &frame, r_scale, g_scale, b_scale,
- exp_comp);
+ exp_comp, cc->camera_info->direction);
/* Note that there is no (known) way how to wait on next frame being
* available, so we could dequeue frame buffer from the device only when we
@@ -1573,7 +1576,7 @@ _camera_client_query_frame(CameraClient* cc, QemudClient* qc, const char* param)
/* Sleep for 10 millisec before repeating the attempt. */
_camera_sleep(10);
repeat = cc->read_frame(cc->camera, &frame, r_scale, g_scale, b_scale,
- exp_comp);
+ exp_comp, cc->camera_info->direction);
D("wait 10ms and read again\n");
}
if (repeat == 1 && !cc->frames_cached) {
@@ -1768,7 +1771,7 @@ _camera_client_query_frame_v1(CameraClient* cc, QemudClient* qc, const char* par
looper_nowNsWithClock(looper_getForThread(), LOOPER_CLOCK_VIRTUAL);
repeat = cc->read_frame(cc->camera, &frame, r_scale, g_scale, b_scale,
- exp_comp);
+ exp_comp, cc->camera_info->direction);
/* Note that there is no (known) way how to wait on next frame being
* available, so we could dequeue frame buffer from the device only when we
@@ -1793,7 +1796,7 @@ _camera_client_query_frame_v1(CameraClient* cc, QemudClient* qc, const char* par
cc->frame_cache.resize(cc->frame_cache_size);
}
repeat = cc->read_frame(cc->camera, &frame, r_scale, g_scale, b_scale,
- exp_comp);
+ exp_comp, cc->camera_info->direction);
}
if (repeat == 1 && !cc->frames_cached) {
/* Waited too long for the first frame. */
diff --git a/android/android-emu/android/camera/camera-videoplayback.cpp b/android/android-emu/android/camera/camera-videoplayback.cpp
index ebd2aeff4a..b9585d1dd5 100644
--- a/android/android-emu/android/camera/camera-videoplayback.cpp
+++ b/android/android-emu/android/camera/camera-videoplayback.cpp
@@ -129,7 +129,8 @@ int camera_videoplayback_read_frame(CameraDevice* ccd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp) {
+ float exp_comp,
+ const char* direction) {
VideoPlaybackCameraDevice* cd = toVideoPlaybackCameraDevice(ccd);
if (!cd) {
E("%s: Invalid camera device descriptor", __FUNCTION__);
diff --git a/android/android-emu/android/camera/camera-videoplayback.h b/android/android-emu/android/camera/camera-videoplayback.h
index 92186fb54c..727d8d9f78 100644
--- a/android/android-emu/android/camera/camera-videoplayback.h
+++ b/android/android-emu/android/camera/camera-videoplayback.h
@@ -85,7 +85,8 @@ int camera_videoplayback_read_frame(CameraDevice* cd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp);
+ float exp_comp,
+ const char* direction);
// Closes the camera device, which was opened from the camera_videoplayback_open
// API.
diff --git a/android/android-emu/android/camera/camera-virtualscene.cpp b/android/android-emu/android/camera/camera-virtualscene.cpp
index 03c10dd228..6a90e6347d 100644
--- a/android/android-emu/android/camera/camera-virtualscene.cpp
+++ b/android/android-emu/android/camera/camera-virtualscene.cpp
@@ -111,7 +111,8 @@ int camera_virtualscene_read_frame(CameraDevice* ccd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp) {
+ float exp_comp,
+ const char* direction) {
RenderedCameraDevice* cd = toRenderedCameraDevice(ccd);
if (!cd) {
E("%s: Invalid camera device descriptor", __FUNCTION__);
diff --git a/android/android-emu/android/camera/camera-virtualscene.h b/android/android-emu/android/camera/camera-virtualscene.h
index 285f09c1d6..f7dcdea031 100644
--- a/android/android-emu/android/camera/camera-virtualscene.h
+++ b/android/android-emu/android/camera/camera-virtualscene.h
@@ -93,6 +93,7 @@ int camera_virtualscene_stop_capturing(CameraDevice* cd);
// where to convert the frame.
// |r_scale|, |g_scale|, |b_scale| - White balance scale.
// |exp_comp| - Exposure compensation.
+// |direction| - "front" or "back" camera
//
// Returns 0 on success, or non-zero on failure.
int camera_virtualscene_read_frame(CameraDevice* cd,
@@ -100,7 +101,8 @@ int camera_virtualscene_read_frame(CameraDevice* cd,
float r_scale,
float g_scale,
float b_scale,
- float exp_comp);
+ float exp_comp,
+ const char* direction);
// Closes the camera device, which was opened from the camera_virtualscene_open
// API.
diff --git a/android/android-emu/android/hw-sensors.cpp b/android/android-emu/android/hw-sensors.cpp
index 38d5953762..95b51d6251 100644
--- a/android/android-emu/android/hw-sensors.cpp
+++ b/android/android-emu/android/hw-sensors.cpp
@@ -1061,6 +1061,31 @@ extern int android_sensors_set_coarse_orientation(
return 0;
}
+/* Get the coarse orientation value */
+extern AndroidCoarseOrientation android_sensors_get_coarse_orientation() {
+ android_hw_sensors_init(NULL);
+ float x = 0;
+ float y = 0;
+ float z = 0;
+ float* rotation[] = {&x, &y, &z};
+ android_sensors_get(ANDROID_SENSOR_ACCELERATION, rotation, 3);
+
+ bool needRotateImage = false;
+ if (fabs(x) < fabs(y)) {
+ if (y < 0) {
+ return ANDROID_COARSE_REVERSE_PORTRAIT;
+ } else {
+ return ANDROID_COARSE_PORTRAIT;
+ }
+ } else {
+ if (x < 0) {
+ return ANDROID_COARSE_REVERSE_LANDSCAPE;
+ } else {
+ return ANDROID_COARSE_LANDSCAPE;
+ }
+ }
+}
+
/* Get sensor name from sensor id */
extern const char* android_sensors_get_name_from_id(int sensor_id) {
if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
diff --git a/android/android-emu/android/hw-sensors.h b/android/android-emu/android/hw-sensors.h
index 5b0ebf7ddb..31d207cea0 100644
--- a/android/android-emu/android/hw-sensors.h
+++ b/android/android-emu/android/hw-sensors.h
@@ -192,6 +192,9 @@ typedef enum {
extern int android_sensors_set_coarse_orientation(
AndroidCoarseOrientation orient, float tilt_degrees);
+/* get the coarse orientation value */
+extern AndroidCoarseOrientation android_sensors_get_coarse_orientation();
+
/* get sensor values */
extern int android_sensors_get(int sensor_id,
float* const* out,