|
@@ -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);
|