@@ -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+
232237static 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!
286297void 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)
14431462static 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