diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-06-14 19:32:18 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2023-06-14 19:32:18 +0000 |
commit | e4492e9c8add9183157ea1ac4d926b5e70046750 (patch) | |
tree | 46014dc39b585585c35a21bd117ceca997d8a95b | |
parent | 5b574d68e87d79ebc14a59d5b7e8d8e3ed3325df (diff) | |
parent | e26532d7f6143f436f9ebabbc2bc4e8e32b348bb (diff) | |
download | qemu-e4492e9c8add9183157ea1ac4d926b5e70046750.tar.gz |
Merge "Fix webcam orientation on Mac" into snap-temp-L93000000961281579
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, |