From 43f281744280670214c7064e2a935241cc679145 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 3 Mar 2023 17:41:38 +0100 Subject: [PATCH] rtsp: fix SIGSEGV --- cmd/camera-streamer/status.cc | 7 +++++ output/rtsp/rtsp.cc | 53 +++++++++++++++++++++++++++++++---- output/rtsp/rtsp.h | 4 +++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/cmd/camera-streamer/status.cc b/cmd/camera-streamer/status.cc index 23076d5..a38244e 100644 --- a/cmd/camera-streamer/status.cc +++ b/cmd/camera-streamer/status.cc @@ -135,5 +135,12 @@ extern "C" void camera_status_json(http_worker_t *worker, FILE *stream) message["endpoints"]["stream"] = get_url(stream_lock.buf_list != NULL, "stream", "http", worker->host, http_options.port, "/stream"); message["endpoints"]["snapshot"] = get_url(snapshot_lock.buf_list != NULL, "snapshot", "http", worker->host, http_options.port, "/stream"); + if (rtsp_options.running) { + message["endpoints"]["rtsp"]["clients"] = rtsp_options.clients; + message["endpoints"]["rtsp"]["truncated"] = rtsp_options.truncated; + message["endpoints"]["rtsp"]["frames"] = rtsp_options.frames; + message["endpoints"]["rtsp"]["dropped"] = rtsp_options.dropped; + } + http_write_response(stream, "200 OK", "application/json", message.dump().c_str(), 0); } diff --git a/output/rtsp/rtsp.cc b/output/rtsp/rtsp.cc index 63cfdf9..f8fd3b8 100644 --- a/output/rtsp/rtsp.cc +++ b/output/rtsp/rtsp.cc @@ -24,6 +24,7 @@ extern "C" { static pthread_t rtsp_thread; static pthread_mutex_t rtsp_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; static class DynamicH264Stream *rtsp_streams; +static rtsp_options_t *rtsp_options; static const char *stream_name = "stream.h264"; @@ -31,7 +32,7 @@ class DynamicH264Stream : public FramedSource { public: DynamicH264Stream(UsageEnvironment& env) - : FramedSource(env), fHaveStartedReading(False) + : FramedSource(env), fHaveStartedReading(False), fFrameWaiting(False) { } @@ -61,12 +62,16 @@ public: } fHaveStartedReading = False; } + fFrameWaiting = False; pthread_mutex_unlock(&rtsp_lock); } void receiveData(buffer_t *buf) { - if (!isCurrentlyAwaitingData()) { + if (!isCurrentlyAwaitingData() || fFrameWaiting) { + if (rtsp_options) { + rtsp_options->dropped++; + } return; // we're not ready for the data yet } @@ -79,27 +84,42 @@ public: device_video_force_key(buf->buf_list->dev); fRequestedKeyFrame = true; } + if (rtsp_options) { + rtsp_options->dropped++; + } return; } + rtsp_options->frames++; + if (buf->used > fMaxSize) { fNumTruncatedBytes = buf->used - fMaxSize; fFrameSize = fMaxSize; + if (rtsp_options) { + rtsp_options->truncated++; + } } else { fNumTruncatedBytes = 0; fFrameSize = buf->used; } memcpy(fTo, buf->start, fFrameSize); + fFrameWaiting = true; + } - // Tell our client that we have new data - nextTask() = envir().taskScheduler().scheduleDelayedTask( - 0, (TaskFunc*)FramedSource::afterGetting, this); + void doFinishFrameGet() + { + if (fFrameWaiting) { + // Tell our client that we have new data + fFrameWaiting = false; + afterGetting(this); + } } Boolean fHaveStartedReading; Boolean fHadKeyFrame; Boolean fRequestedKeyFrame; + Boolean fFrameWaiting; DynamicH264Stream *pNextStream; }; @@ -178,10 +198,29 @@ protected: // redefined virtual functions } }; +static void rtsp_frame_finish() +{ + pthread_mutex_lock(&rtsp_lock); + int clients = 0; + for (DynamicH264Stream *stream = rtsp_streams; stream; stream = stream->pNextStream) { + stream->doFinishFrameGet(); + clients++; + } + if (rtsp_options) { + rtsp_options->clients = clients; + } + pthread_mutex_unlock(&rtsp_lock); +} + static void *rtsp_server_thread(void *opaque) { UsageEnvironment* env = (UsageEnvironment*)opaque; - env->taskScheduler().doEventLoop(); // does not return + BasicTaskScheduler0* taskScheduler = (BasicTaskScheduler*)&env->taskScheduler(); + + while(true) { + rtsp_frame_finish(); + taskScheduler->SingleStep(0); + } return NULL; } @@ -208,6 +247,8 @@ static void rtsp_h264_capture(buffer_lock_t *buf_lock, buffer_t *buf) extern "C" int rtsp_server(rtsp_options_t *options) { + rtsp_options = options; + // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); diff --git a/output/rtsp/rtsp.h b/output/rtsp/rtsp.h index 478af80..88b1d7a 100644 --- a/output/rtsp/rtsp.h +++ b/output/rtsp/rtsp.h @@ -3,6 +3,10 @@ typedef struct rtsp_options_s { bool running; uint port; + int clients; + int frames; + int truncated; + int dropped; } rtsp_options_t; int rtsp_server(rtsp_options_t *options);