mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-26 10:06:42 +08:00
camera: Make refcounts more robust, and actually destroy disconnected cameras.
Fixes #14049.
This commit is contained in:
+27
-3
@@ -229,10 +229,15 @@ static void ZombieReleaseFrame(SDL_Camera *device, SDL_Surface *frame) // Reclai
|
||||
// we just leave zombie_pixels alone, as we'll reuse it for every new frame until the camera is closed.
|
||||
}
|
||||
|
||||
|
||||
static void ObtainPhysicalCameraObj(SDL_Camera *device);
|
||||
static void ReleaseCamera(SDL_Camera *device);
|
||||
|
||||
|
||||
static void ClosePhysicalCamera(SDL_Camera *device)
|
||||
{
|
||||
if (!device) {
|
||||
return;
|
||||
if (!device || (device->hidden == NULL)) {
|
||||
return; // device is not open.
|
||||
}
|
||||
|
||||
SDL_SetAtomicInt(&device->shutdown, 1);
|
||||
@@ -244,6 +249,8 @@ static void ClosePhysicalCamera(SDL_Camera *device)
|
||||
device->thread = NULL;
|
||||
}
|
||||
|
||||
ObtainPhysicalCameraObj(device);
|
||||
|
||||
// release frames that are queued up somewhere...
|
||||
if (!device->needs_conversion && !device->needs_scaling) {
|
||||
for (SurfaceList *i = device->filled_output_surfaces.next; i != NULL; i = i->next) {
|
||||
@@ -255,6 +262,7 @@ static void ClosePhysicalCamera(SDL_Camera *device)
|
||||
}
|
||||
|
||||
camera_driver.impl.CloseDevice(device);
|
||||
device->hidden = NULL; // just in case backend didn't reset this.
|
||||
|
||||
SDL_DestroyProperties(device->props);
|
||||
|
||||
@@ -280,13 +288,16 @@ static void ClosePhysicalCamera(SDL_Camera *device)
|
||||
device->adjust_timestamp = 0;
|
||||
|
||||
SDL_zero(device->spec);
|
||||
UnrefPhysicalCamera(device); // we're closed, release a reference.
|
||||
|
||||
ReleaseCamera(device);
|
||||
}
|
||||
|
||||
// Don't hold the device lock when calling this, as we may destroy the device!
|
||||
void UnrefPhysicalCamera(SDL_Camera *device)
|
||||
{
|
||||
if (SDL_AtomicDecRef(&device->refcount)) {
|
||||
// take it out of the device list.
|
||||
// take it out of the device list. This will call DestroyCameraHashItem to clean up the object.
|
||||
SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
||||
if (SDL_RemoveFromHashTable(camera_driver.device_hash, (const void *) (uintptr_t) device->instance_id)) {
|
||||
SDL_AddAtomicInt(&camera_driver.device_count, -1);
|
||||
@@ -555,6 +566,8 @@ void SDL_CameraDisconnected(SDL_Camera *device)
|
||||
pending_tail->next = p;
|
||||
pending_tail = p;
|
||||
}
|
||||
|
||||
UnrefPhysicalCamera(device); // camera is disconnected, drop its reference
|
||||
}
|
||||
|
||||
ReleaseCamera(device);
|
||||
@@ -941,6 +954,8 @@ static int SDLCALL CameraThread(void *devicep)
|
||||
SDL_Log("CAMERA: dev[%p] Start thread 'CameraThread'", devicep);
|
||||
#endif
|
||||
|
||||
RefPhysicalCamera(device); // this thread holds a reference.
|
||||
|
||||
SDL_assert(device != NULL);
|
||||
SDL_CameraThreadSetup(device);
|
||||
|
||||
@@ -952,6 +967,8 @@ static int SDLCALL CameraThread(void *devicep)
|
||||
|
||||
SDL_CameraThreadShutdown(device);
|
||||
|
||||
UnrefPhysicalCamera(device); // this thread no longer holds a reference.
|
||||
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("CAMERA: dev[%p] End thread 'CameraThread'", devicep);
|
||||
#endif
|
||||
@@ -1245,6 +1262,8 @@ SDL_Camera *SDL_OpenCamera(SDL_CameraID instance_id, const SDL_CameraSpec *spec)
|
||||
}
|
||||
}
|
||||
|
||||
RefPhysicalCamera(device); // we're open, hold a reference.
|
||||
|
||||
ReleaseCamera(device); // unlock, we're good to go!
|
||||
|
||||
return device; // currently there's no separation between physical and logical device.
|
||||
@@ -1443,6 +1462,11 @@ void SDL_QuitCamera(void)
|
||||
static void SDLCALL DestroyCameraHashItem(void *userdata, const void *key, const void *value)
|
||||
{
|
||||
SDL_Camera *device = (SDL_Camera *) value;
|
||||
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("DESTROYING CAMERA '%s'", device->name);
|
||||
#endif
|
||||
|
||||
ClosePhysicalCamera(device);
|
||||
camera_driver.impl.FreeDeviceHandle(device);
|
||||
SDL_DestroyMutex(device->lock);
|
||||
|
||||
Reference in New Issue
Block a user