rtsp: fix SIGSEGV

This commit is contained in:
Kamil Trzcinski 2023-03-03 17:41:38 +01:00
parent 9db8ba5fa5
commit 43f2817442
3 changed files with 58 additions and 6 deletions

View File

@ -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"]["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"); 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); http_write_response(stream, "200 OK", "application/json", message.dump().c_str(), 0);
} }

View File

@ -24,6 +24,7 @@ extern "C" {
static pthread_t rtsp_thread; static pthread_t rtsp_thread;
static pthread_mutex_t rtsp_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; static pthread_mutex_t rtsp_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static class DynamicH264Stream *rtsp_streams; static class DynamicH264Stream *rtsp_streams;
static rtsp_options_t *rtsp_options;
static const char *stream_name = "stream.h264"; static const char *stream_name = "stream.h264";
@ -31,7 +32,7 @@ class DynamicH264Stream : public FramedSource
{ {
public: public:
DynamicH264Stream(UsageEnvironment& env) DynamicH264Stream(UsageEnvironment& env)
: FramedSource(env), fHaveStartedReading(False) : FramedSource(env), fHaveStartedReading(False), fFrameWaiting(False)
{ {
} }
@ -61,12 +62,16 @@ public:
} }
fHaveStartedReading = False; fHaveStartedReading = False;
} }
fFrameWaiting = False;
pthread_mutex_unlock(&rtsp_lock); pthread_mutex_unlock(&rtsp_lock);
} }
void receiveData(buffer_t *buf) 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 return; // we're not ready for the data yet
} }
@ -79,27 +84,42 @@ public:
device_video_force_key(buf->buf_list->dev); device_video_force_key(buf->buf_list->dev);
fRequestedKeyFrame = true; fRequestedKeyFrame = true;
} }
if (rtsp_options) {
rtsp_options->dropped++;
}
return; return;
} }
rtsp_options->frames++;
if (buf->used > fMaxSize) { if (buf->used > fMaxSize) {
fNumTruncatedBytes = buf->used - fMaxSize; fNumTruncatedBytes = buf->used - fMaxSize;
fFrameSize = fMaxSize; fFrameSize = fMaxSize;
if (rtsp_options) {
rtsp_options->truncated++;
}
} else { } else {
fNumTruncatedBytes = 0; fNumTruncatedBytes = 0;
fFrameSize = buf->used; fFrameSize = buf->used;
} }
memcpy(fTo, buf->start, fFrameSize); memcpy(fTo, buf->start, fFrameSize);
fFrameWaiting = true;
}
// Tell our client that we have new data void doFinishFrameGet()
nextTask() = envir().taskScheduler().scheduleDelayedTask( {
0, (TaskFunc*)FramedSource::afterGetting, this); if (fFrameWaiting) {
// Tell our client that we have new data
fFrameWaiting = false;
afterGetting(this);
}
} }
Boolean fHaveStartedReading; Boolean fHaveStartedReading;
Boolean fHadKeyFrame; Boolean fHadKeyFrame;
Boolean fRequestedKeyFrame; Boolean fRequestedKeyFrame;
Boolean fFrameWaiting;
DynamicH264Stream *pNextStream; 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) static void *rtsp_server_thread(void *opaque)
{ {
UsageEnvironment* env = (UsageEnvironment*)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; 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) extern "C" int rtsp_server(rtsp_options_t *options)
{ {
rtsp_options = options;
// Begin by setting up our usage environment: // Begin by setting up our usage environment:
TaskScheduler* scheduler = BasicTaskScheduler::createNew(); TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);

View File

@ -3,6 +3,10 @@
typedef struct rtsp_options_s { typedef struct rtsp_options_s {
bool running; bool running;
uint port; uint port;
int clients;
int frames;
int truncated;
int dropped;
} rtsp_options_t; } rtsp_options_t;
int rtsp_server(rtsp_options_t *options); int rtsp_server(rtsp_options_t *options);