Skip to content

Commit 1191f81

Browse files
committed
camera: Make refcounts more robust, and actually destroy disconnected cameras.
Fixes #14049.
1 parent 4f267fc commit 1191f81

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

src/camera/SDL_camera.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,15 @@ static void ZombieReleaseFrame(SDL_Camera *device, SDL_Surface *frame) // Reclai
229229
// we just leave zombie_pixels alone, as we'll reuse it for every new frame until the camera is closed.
230230
}
231231

232+
233+
static void ObtainPhysicalCameraObj(SDL_Camera *device);
234+
static void ReleaseCamera(SDL_Camera *device);
235+
236+
232237
static void ClosePhysicalCamera(SDL_Camera *device)
233238
{
234-
if (!device) {
235-
return;
239+
if (!device || (device->hidden == NULL)) {
240+
return; // device is not open.
236241
}
237242

238243
SDL_SetAtomicInt(&device->shutdown, 1);
@@ -244,6 +249,8 @@ static void ClosePhysicalCamera(SDL_Camera *device)
244249
device->thread = NULL;
245250
}
246251

252+
ObtainPhysicalCameraObj(device);
253+
247254
// release frames that are queued up somewhere...
248255
if (!device->needs_conversion && !device->needs_scaling) {
249256
for (SurfaceList *i = device->filled_output_surfaces.next; i != NULL; i = i->next) {
@@ -255,6 +262,7 @@ static void ClosePhysicalCamera(SDL_Camera *device)
255262
}
256263

257264
camera_driver.impl.CloseDevice(device);
265+
device->hidden = NULL; // just in case backend didn't reset this.
258266

259267
SDL_DestroyProperties(device->props);
260268

@@ -280,13 +288,16 @@ static void ClosePhysicalCamera(SDL_Camera *device)
280288
device->adjust_timestamp = 0;
281289

282290
SDL_zero(device->spec);
291+
UnrefPhysicalCamera(device); // we're closed, release a reference.
292+
293+
ReleaseCamera(device);
283294
}
284295

285296
// Don't hold the device lock when calling this, as we may destroy the device!
286297
void UnrefPhysicalCamera(SDL_Camera *device)
287298
{
288299
if (SDL_AtomicDecRef(&device->refcount)) {
289-
// take it out of the device list.
300+
// take it out of the device list. This will call DestroyCameraHashItem to clean up the object.
290301
SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
291302
if (SDL_RemoveFromHashTable(camera_driver.device_hash, (const void *) (uintptr_t) device->instance_id)) {
292303
SDL_AddAtomicInt(&camera_driver.device_count, -1);
@@ -555,6 +566,8 @@ void SDL_CameraDisconnected(SDL_Camera *device)
555566
pending_tail->next = p;
556567
pending_tail = p;
557568
}
569+
570+
UnrefPhysicalCamera(device); // camera is disconnected, drop its reference
558571
}
559572

560573
ReleaseCamera(device);
@@ -941,6 +954,8 @@ static int SDLCALL CameraThread(void *devicep)
941954
SDL_Log("CAMERA: dev[%p] Start thread 'CameraThread'", devicep);
942955
#endif
943956

957+
RefPhysicalCamera(device); // this thread holds a reference.
958+
944959
SDL_assert(device != NULL);
945960
SDL_CameraThreadSetup(device);
946961

@@ -952,6 +967,8 @@ static int SDLCALL CameraThread(void *devicep)
952967

953968
SDL_CameraThreadShutdown(device);
954969

970+
UnrefPhysicalCamera(device); // this thread no longer holds a reference.
971+
955972
#if DEBUG_CAMERA
956973
SDL_Log("CAMERA: dev[%p] End thread 'CameraThread'", devicep);
957974
#endif
@@ -1245,6 +1262,8 @@ SDL_Camera *SDL_OpenCamera(SDL_CameraID instance_id, const SDL_CameraSpec *spec)
12451262
}
12461263
}
12471264

1265+
RefPhysicalCamera(device); // we're open, hold a reference.
1266+
12481267
ReleaseCamera(device); // unlock, we're good to go!
12491268

12501269
return device; // currently there's no separation between physical and logical device.
@@ -1443,6 +1462,11 @@ void SDL_QuitCamera(void)
14431462
static void SDLCALL DestroyCameraHashItem(void *userdata, const void *key, const void *value)
14441463
{
14451464
SDL_Camera *device = (SDL_Camera *) value;
1465+
1466+
#if DEBUG_CAMERA
1467+
SDL_Log("DESTROYING CAMERA '%s'", device->name);
1468+
#endif
1469+
14461470
ClosePhysicalCamera(device);
14471471
camera_driver.impl.FreeDeviceHandle(device);
14481472
SDL_DestroyMutex(device->lock);

0 commit comments

Comments
 (0)