mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-28 05:58:29 +00:00
camera: Added SDL_GetCameraDevicePosition.
Otherwise, as a property, you have to open each camera device to figure out which ones are which.
This commit is contained in:
@@ -70,6 +70,19 @@ typedef struct SDL_CameraSpec
|
|||||||
int interval_denominator; /**< Frame rate demoninator ((dom / num) == fps, (num / dom) == duration) */
|
int interval_denominator; /**< Frame rate demoninator ((dom / num) == fps, (num / dom) == duration) */
|
||||||
} SDL_CameraSpec;
|
} SDL_CameraSpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position of camera in relation to system device.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameraDevicePosition
|
||||||
|
*/
|
||||||
|
typedef enum SDL_CameraPosition
|
||||||
|
{
|
||||||
|
SDL_CAMERA_POSITION_UNKNOWN,
|
||||||
|
SDL_CAMERA_POSITION_FRONT_FACING,
|
||||||
|
SDL_CAMERA_POSITION_BACK_FACING
|
||||||
|
} SDL_CameraPosition;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this function to get the number of built-in camera drivers.
|
* Use this function to get the number of built-in camera drivers.
|
||||||
*
|
*
|
||||||
@@ -210,6 +223,25 @@ extern DECLSPEC SDL_CameraSpec *SDLCALL SDL_GetCameraDeviceSupportedFormats(SDL_
|
|||||||
*/
|
*/
|
||||||
extern DECLSPEC char * SDLCALL SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id);
|
extern DECLSPEC char * SDLCALL SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the camera in relation to the system.
|
||||||
|
*
|
||||||
|
* Most platforms will report UNKNOWN, but mobile devices, like phones, can
|
||||||
|
* often make a distiction between cameras on the front of the device (that
|
||||||
|
* points towards the user, for taking "selfies") and cameras on the back
|
||||||
|
* (for filming in the direction the user is facing).
|
||||||
|
*
|
||||||
|
* \param instance_id the camera device instance ID
|
||||||
|
* \returns The position of the camera on the system hardware.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameraDevices
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_CameraPosition SDLCALL SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a video capture device (a "camera").
|
* Open a video capture device (a "camera").
|
||||||
*
|
*
|
||||||
@@ -305,16 +337,6 @@ extern DECLSPEC SDL_CameraDeviceID SDLCALL SDL_GetCameraInstanceID(SDL_Camera *c
|
|||||||
/**
|
/**
|
||||||
* Get the properties associated with an opened camera.
|
* Get the properties associated with an opened camera.
|
||||||
*
|
*
|
||||||
* The following read-only properties are provided by SDL:
|
|
||||||
*
|
|
||||||
* - `SDL_PROP_CAMERA_POSITION_STRING`: the position of the camera in
|
|
||||||
* relation to the hardware it is connected to. This is currently either
|
|
||||||
* the string "front" or "back", to signify which side of the user's
|
|
||||||
* device a camera is on. Future versions of SDL may add other position
|
|
||||||
* strings. This property is only set if this information can be
|
|
||||||
* determined by SDL. Most platforms do not set this attribute at all,
|
|
||||||
* but mobile devices tend to.
|
|
||||||
*
|
|
||||||
* \param camera the SDL_Camera obtained from SDL_OpenCameraDevice()
|
* \param camera the SDL_Camera obtained from SDL_OpenCameraDevice()
|
||||||
* \returns a valid property ID on success or 0 on failure; call
|
* \returns a valid property ID on success or 0 on failure; call
|
||||||
* SDL_GetError() for more information.
|
* SDL_GetError() for more information.
|
||||||
@@ -328,8 +350,6 @@ extern DECLSPEC SDL_CameraDeviceID SDLCALL SDL_GetCameraInstanceID(SDL_Camera *c
|
|||||||
*/
|
*/
|
||||||
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetCameraProperties(SDL_Camera *camera);
|
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetCameraProperties(SDL_Camera *camera);
|
||||||
|
|
||||||
#define SDL_PROP_CAMERA_POSITION_STRING "SDL.camera.position"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the spec that a camera is using when generating images.
|
* Get the spec that a camera is using when generating images.
|
||||||
*
|
*
|
||||||
|
@@ -398,9 +398,8 @@ static int SDLCALL CameraSpecCmp(const void *vpa, const void *vpb)
|
|||||||
return 0; // apparently, they're equal.
|
return 0; // apparently, they're equal.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The camera backends call this when a new device is plugged in.
|
// The camera backends call this when a new device is plugged in.
|
||||||
SDL_CameraDevice *SDL_AddCameraDevice(const char *name, int num_specs, const SDL_CameraSpec *specs, void *handle)
|
SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle)
|
||||||
{
|
{
|
||||||
SDL_assert(name != NULL);
|
SDL_assert(name != NULL);
|
||||||
SDL_assert(num_specs >= 0);
|
SDL_assert(num_specs >= 0);
|
||||||
@@ -425,6 +424,8 @@ SDL_CameraDevice *SDL_AddCameraDevice(const char *name, int num_specs, const SDL
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device->position = position;
|
||||||
|
|
||||||
device->lock = SDL_CreateMutex();
|
device->lock = SDL_CreateMutex();
|
||||||
if (!device->lock) {
|
if (!device->lock) {
|
||||||
SDL_free(device->name);
|
SDL_free(device->name);
|
||||||
@@ -457,7 +458,13 @@ SDL_CameraDevice *SDL_AddCameraDevice(const char *name, int num_specs, const SDL
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_CAMERA
|
#if DEBUG_CAMERA
|
||||||
SDL_Log("CAMERA: Adding device ('%s') with %d spec%s%s", name, num_specs, (num_specs == 1) ? "" : "s", (num_specs == 0) ? "" : ":");
|
const char *posstr = "unknown position";
|
||||||
|
if (position == SDL_CAMERA_POSITION_FRONT_FACING) {
|
||||||
|
posstr = "front-facing";
|
||||||
|
} else if (position == SDL_CAMERA_POSITION_BACK_FACING) {
|
||||||
|
posstr = "back-facing";
|
||||||
|
}
|
||||||
|
SDL_Log("CAMERA: Adding device '%s' (%s) with %d spec%s%s", name, posstr, num_specs, (num_specs == 1) ? "" : "s", (num_specs == 0) ? "" : ":");
|
||||||
for (int i = 0; i < num_specs; i++) {
|
for (int i = 0; i < num_specs; i++) {
|
||||||
const SDL_CameraSpec *spec = &device->all_specs[i];
|
const SDL_CameraSpec *spec = &device->all_specs[i];
|
||||||
SDL_Log("CAMERA: - fmt=%s, w=%d, h=%d, numerator=%d, denominator=%d", SDL_GetPixelFormatName(spec->format), spec->width, spec->height, spec->interval_numerator, spec->interval_denominator);
|
SDL_Log("CAMERA: - fmt=%s, w=%d, h=%d, numerator=%d, denominator=%d", SDL_GetPixelFormatName(spec->format), spec->width, spec->height, spec->interval_numerator, spec->interval_denominator);
|
||||||
@@ -658,6 +665,18 @@ char *SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_CameraPosition SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id)
|
||||||
|
{
|
||||||
|
SDL_CameraPosition retval = SDL_CAMERA_POSITION_UNKNOWN;
|
||||||
|
SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id);
|
||||||
|
if (device) {
|
||||||
|
retval = device->position;
|
||||||
|
ReleaseCameraDevice(device);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDL_CameraDeviceID *SDL_GetCameraDevices(int *count)
|
SDL_CameraDeviceID *SDL_GetCameraDevices(int *count)
|
||||||
{
|
{
|
||||||
int dummy_count;
|
int dummy_count;
|
||||||
|
@@ -25,14 +25,14 @@
|
|||||||
|
|
||||||
#include "../SDL_hashtable.h"
|
#include "../SDL_hashtable.h"
|
||||||
|
|
||||||
#define DEBUG_CAMERA 0
|
#define DEBUG_CAMERA 1
|
||||||
|
|
||||||
typedef struct SDL_CameraDevice SDL_CameraDevice;
|
typedef struct SDL_CameraDevice SDL_CameraDevice;
|
||||||
|
|
||||||
/* Backends should call this as devices are added to the system (such as
|
/* Backends should call this as devices are added to the system (such as
|
||||||
a USB camera being plugged in), and should also be called for
|
a USB camera being plugged in), and should also be called for
|
||||||
for every device found during DetectDevices(). */
|
for every device found during DetectDevices(). */
|
||||||
extern SDL_CameraDevice *SDL_AddCameraDevice(const char *name, int num_specs, const SDL_CameraSpec *specs, void *handle);
|
extern SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle);
|
||||||
|
|
||||||
/* Backends should call this if an opened camera device is lost.
|
/* Backends should call this if an opened camera device is lost.
|
||||||
This can happen due to i/o errors, or a device being unplugged, etc. */
|
This can happen due to i/o errors, or a device being unplugged, etc. */
|
||||||
@@ -82,6 +82,9 @@ struct SDL_CameraDevice
|
|||||||
// Human-readable device name.
|
// Human-readable device name.
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
// Position of camera (front-facing, back-facing, etc).
|
||||||
|
SDL_CameraPosition position;
|
||||||
|
|
||||||
// When refcount hits zero, we destroy the device object.
|
// When refcount hits zero, we destroy the device object.
|
||||||
SDL_AtomicInt refcount;
|
SDL_AtomicInt refcount;
|
||||||
|
|
||||||
|
@@ -575,7 +575,7 @@ static void ANDROIDCAMERA_FreeDeviceHandle(SDL_CameraDevice *device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data, char **fullname, const char **posstr)
|
static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data, char **fullname, SDL_CameraPosition *position)
|
||||||
{
|
{
|
||||||
SDL_zerop(add_data);
|
SDL_zerop(add_data);
|
||||||
|
|
||||||
@@ -608,16 +608,15 @@ static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*posstr = NULL;
|
|
||||||
ACameraMetadata_const_entry posentry;
|
ACameraMetadata_const_entry posentry;
|
||||||
if (pACameraMetadata_getConstEntry(metadata, ACAMERA_LENS_FACING, &posentry) == ACAMERA_OK) { // ignore this if it fails.
|
if (pACameraMetadata_getConstEntry(metadata, ACAMERA_LENS_FACING, &posentry) == ACAMERA_OK) { // ignore this if it fails.
|
||||||
if (*posentry.data.u8 == ACAMERA_LENS_FACING_FRONT) {
|
if (*posentry.data.u8 == ACAMERA_LENS_FACING_FRONT) {
|
||||||
*posstr = "front";
|
*position = SDL_CAMERA_POSITION_FRONT_FACING;
|
||||||
if (!*fullname) {
|
if (!*fullname) {
|
||||||
*fullname = SDL_strdup("Front-facing camera");
|
*fullname = SDL_strdup("Front-facing camera");
|
||||||
}
|
}
|
||||||
} else if (*posentry.data.u8 == ACAMERA_LENS_FACING_BACK) {
|
} else if (*posentry.data.u8 == ACAMERA_LENS_FACING_BACK) {
|
||||||
*posstr = "back";
|
*position = SDL_CAMERA_POSITION_BACK_FACING;
|
||||||
if (!*fullname) {
|
if (!*fullname) {
|
||||||
*fullname = SDL_strdup("Back-facing camera");
|
*fullname = SDL_strdup("Back-facing camera");
|
||||||
}
|
}
|
||||||
@@ -680,22 +679,16 @@ static void MaybeAddDevice(const char *devid)
|
|||||||
return; // already have this one.
|
return; // already have this one.
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *posstr = NULL;
|
SDL_CameraPosition position = SDL_CAMERA_POSITION_UNKNOWN;
|
||||||
char *fullname = NULL;
|
char *fullname = NULL;
|
||||||
CameraFormatAddData add_data;
|
CameraFormatAddData add_data;
|
||||||
GatherCameraSpecs(devid, &add_data, &fullname, &posstr);
|
GatherCameraSpecs(devid, &add_data, &fullname, &position);
|
||||||
if (add_data.num_specs > 0) {
|
if (add_data.num_specs > 0) {
|
||||||
char *namecpy = SDL_strdup(devid);
|
char *namecpy = SDL_strdup(devid);
|
||||||
if (namecpy) {
|
if (namecpy) {
|
||||||
SDL_CameraDevice *device = SDL_AddCameraDevice(fullname, add_data.num_specs, add_data.specs, namecpy);
|
SDL_CameraDevice *device = SDL_AddCameraDevice(fullname, position, add_data.num_specs, add_data.specs, namecpy);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
SDL_free(namecpy);
|
SDL_free(namecpy);
|
||||||
} else if (device && posstr) {
|
|
||||||
SDL_Camera *camera = (SDL_Camera *) device; // currently there's no separation between physical and logical device.
|
|
||||||
SDL_PropertiesID props = SDL_GetCameraProperties(camera);
|
|
||||||
if (props) {
|
|
||||||
SDL_SetStringProperty(props, SDL_PROP_CAMERA_POSITION_STRING, posstr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -399,24 +399,15 @@ static void MaybeAddDevice(AVCaptureDevice *avdevice)
|
|||||||
CameraFormatAddData add_data;
|
CameraFormatAddData add_data;
|
||||||
GatherCameraSpecs(avdevice, &add_data);
|
GatherCameraSpecs(avdevice, &add_data);
|
||||||
if (add_data.num_specs > 0) {
|
if (add_data.num_specs > 0) {
|
||||||
SDL_CameraDevice *device = SDL_AddCameraDevice(avdevice.localizedName.UTF8String, add_data.num_specs, add_data.specs, (void *) CFBridgingRetain(avdevice));
|
SDL_CameraPosition position = SDL_CAMERA_POSITION_UNKNOWN;
|
||||||
if (device) {
|
if (avdevice.position == AVCaptureDevicePositionFront) {
|
||||||
const char *posstr = NULL;
|
position = SDL_CAMERA_POSITION_FRONT_FACING;
|
||||||
if (avdevice.position == AVCaptureDevicePositionFront) {
|
} else if (avdevice.position == AVCaptureDevicePositionBack) {
|
||||||
posstr = "front";
|
position = SDL_CAMERA_POSITION_BACK_FACING;
|
||||||
} else if (avdevice.position == AVCaptureDevicePositionBack) {
|
|
||||||
posstr = "back";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (posstr) {
|
|
||||||
SDL_Camera *camera = (SDL_Camera *) device; // currently there's no separation between physical and logical device.
|
|
||||||
SDL_PropertiesID props = SDL_GetCameraProperties(camera);
|
|
||||||
if (props) {
|
|
||||||
SDL_SetStringProperty(props, SDL_PROP_CAMERA_POSITION_STRING, posstr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
SDL_AddCameraDevice(avdevice.localizedName.UTF8String, position, add_data.num_specs, add_data.specs, (void *) CFBridgingRetain(avdevice));
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(add_data.specs);
|
SDL_free(add_data.specs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -228,7 +228,7 @@ static void EMSCRIPTENCAMERA_DetectDevices(void)
|
|||||||
// will pop up a user permission dialog warning them we're trying to access the camera, and we generally
|
// will pop up a user permission dialog warning them we're trying to access the camera, and we generally
|
||||||
// don't want that during SDL_Init().
|
// don't want that during SDL_Init().
|
||||||
if (supported) {
|
if (supported) {
|
||||||
SDL_AddCameraDevice("Web browser's camera", 0, NULL, (void *) (size_t) 0x1);
|
SDL_AddCameraDevice("Web browser's camera", SDL_CAMERA_POSITION_UNKNOWN, 0, NULL, (void *) (size_t) 0x1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -777,7 +777,7 @@ static void MaybeAddDevice(IMFActivate *activation)
|
|||||||
CameraFormatAddData add_data;
|
CameraFormatAddData add_data;
|
||||||
GatherCameraSpecs(source, &add_data);
|
GatherCameraSpecs(source, &add_data);
|
||||||
if (add_data.num_specs > 0) {
|
if (add_data.num_specs > 0) {
|
||||||
SDL_AddCameraDevice(name, add_data.num_specs, add_data.specs, symlink);
|
SDL_AddCameraDevice(name, SDL_CAMERA_POSITION_UNKNOWN, add_data.num_specs, add_data.specs, symlink);
|
||||||
}
|
}
|
||||||
SDL_free(add_data.specs);
|
SDL_free(add_data.specs);
|
||||||
IMFActivate_ShutdownObject(activation);
|
IMFActivate_ShutdownObject(activation);
|
||||||
|
@@ -778,7 +778,7 @@ static void MaybeAddDevice(const char *path)
|
|||||||
if (handle->path) {
|
if (handle->path) {
|
||||||
handle->bus_info = SDL_strdup((char *)vcap.bus_info);
|
handle->bus_info = SDL_strdup((char *)vcap.bus_info);
|
||||||
if (handle->bus_info) {
|
if (handle->bus_info) {
|
||||||
if (SDL_AddCameraDevice((const char *) vcap.card, add_data.num_specs, add_data.specs, handle)) {
|
if (SDL_AddCameraDevice((const char *) vcap.card, SDL_CAMERA_POSITION_UNKNOWN, add_data.num_specs, add_data.specs, handle)) {
|
||||||
SDL_free(add_data.specs);
|
SDL_free(add_data.specs);
|
||||||
return; // good to go.
|
return; // good to go.
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user