@@ -575,6 +575,8 @@ int start_mp4_recording(const char *stream_name) {
575575
576576 // Check if already running — also verify the recording is actually healthy.
577577 // Extract a dead context (if any) under the mutex, then join it outside.
578+ // FIX: treat writer==NULL + ctx->running==1 as "initializing" to prevent
579+ // duplicate instances during the RTSP-connect window (see start_mp4_recording_with_trigger).
578580 mp4_recording_ctx_t * dead_ctx = NULL ;
579581 pthread_mutex_lock (& recording_contexts_mutex );
580582 for (int i = 0 ; i < g_config .max_streams ; i ++ ) {
@@ -585,7 +587,12 @@ int start_mp4_recording(const char *stream_name) {
585587 log_info ("MP4 recording for stream %s already running and healthy" , stream_name );
586588 return 0 ; // Already running and healthy
587589 }
588-
590+ if (!writer && recording_contexts [i ]-> running ) {
591+ // Still initializing — mp4_writer not yet assigned by the thread. // <-- bug fix
592+ pthread_mutex_unlock (& recording_contexts_mutex );
593+ log_info ("MP4 recording for stream %s is initializing, skipping duplicate start" , stream_name );
594+ return 0 ;
595+ }
589596 // Dead — extract from slot under the lock, join outside
590597 log_warn ("MP4 recording for stream %s exists but is dead, cleaning up before restart" , stream_name );
591598 dead_ctx = recording_contexts [i ];
@@ -748,7 +755,12 @@ int start_mp4_recording_with_url(const char *stream_name, const char *url) {
748755 log_info ("MP4 recording for stream %s already running and healthy" , stream_name );
749756 return 0 ; // Already running and healthy
750757 }
751-
758+ if (!writer && recording_contexts [i ]-> running ) {
759+ // Still initializing — mp4_writer not yet assigned by the thread. // <-- bug fix
760+ pthread_mutex_unlock (& recording_contexts_mutex );
761+ log_info ("MP4 recording for stream %s is initializing, skipping duplicate start" , stream_name );
762+ return 0 ;
763+ }
752764 // Dead — extract from slot under the lock, join outside
753765 log_warn ("MP4 recording for stream %s exists but is dead, cleaning up before restart" , stream_name );
754766 dead_ctx = recording_contexts [i ];
@@ -979,6 +991,13 @@ int start_mp4_recording_with_trigger(const char *stream_name, const char *trigge
979991 log_info ("MP4 recording for stream %s already running and healthy" , stream_name );
980992 return 0 ; // Already running and healthy
981993 }
994+ if (!writer && recording_contexts [i ]-> running ) {
995+ // Still initializing — mp4_writer not yet assigned by the thread.
996+ // RTSP connect / avformat_find_stream_info still in progress.
997+ pthread_mutex_unlock (& recording_contexts_mutex );
998+ log_info ("MP4 recording for stream %s is initializing, skipping duplicate start" , stream_name );
999+ return 0 ;
1000+ }
9821001
9831002 // Dead — extract from slot under the lock, join outside
9841003 log_warn ("MP4 recording for stream %s exists but is dead, cleaning up before restart" , stream_name );
@@ -1118,6 +1137,8 @@ int start_mp4_recording_with_url_and_trigger(const char *stream_name, const char
11181137 config .url [sizeof (config .url ) - 1 ] = '\0' ;
11191138
11201139 // Check if already running — also verify the recording is actually healthy.
1140+ // FIX: treat writer==NULL + ctx->running==1 as "initializing" to prevent
1141+ // duplicate instances during the RTSP-connect window (see start_mp4_recording_with_trigger).
11211142 mp4_recording_ctx_t * dead_ctx = NULL ;
11221143 pthread_mutex_lock (& recording_contexts_mutex );
11231144 for (int i = 0 ; i < g_config .max_streams ; i ++ ) {
@@ -1128,7 +1149,12 @@ int start_mp4_recording_with_url_and_trigger(const char *stream_name, const char
11281149 log_info ("MP4 recording for stream %s already running and healthy" , stream_name );
11291150 return 0 ; // Already running and healthy
11301151 }
1131-
1152+ if (!writer && recording_contexts [i ]-> running ) {
1153+ // Still initializing — mp4_writer not yet assigned by the thread. // <-- bug fix
1154+ pthread_mutex_unlock (& recording_contexts_mutex );
1155+ log_info ("MP4 recording for stream %s is initializing, skipping duplicate start" , stream_name );
1156+ return 0 ;
1157+ }
11321158 // Dead — extract from slot under the lock, join outside
11331159 log_warn ("MP4 recording for stream %s exists but is dead, cleaning up before restart" , stream_name );
11341160 dead_ctx = recording_contexts [i ];
0 commit comments