Skip to content

Commit 1451554

Browse files
pkviettt2468
authored andcommitted
obs-ffmpeg: Fix SRT listener bug
Fixes #10504. There was a bug in FFmpeg implementation which was hidden by a bug in libsrt; it was fixed in a recent commit [1]. When we ported FFmpeg libsrt.c to obs, we brought the said bug along. When starting an SRT stream in listener mode, if no connection is made by a client, there were two issues: - 1) obs was stuck into a connecting loop, - 2) the socket was not closed when exiting OBS. This fixes the issue so that SRT is displaying that a stream started when in listener mode even if NO client is connected. This is the correct behaviour for a listener. The stream now closes properly. [1] https://git.videolan.org/?p=ffmpeg.git;a=commit;h=87677c2195e86b126c3438439a05d0a46ae5bb50 Signed-off-by: pkv <[email protected]>
1 parent e8f87e4 commit 1451554

File tree

3 files changed

+37
-32
lines changed

3 files changed

+37
-32
lines changed

plugins/obs-ffmpeg/obs-ffmpeg-mpegts.c

+21-23
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,14 @@ void ffmpeg_mpegts_log_error(int log_level, struct ffmpeg_data *data,
6363
blog(log_level, "%s", out);
6464
}
6565

66-
static bool is_rist(struct ffmpeg_output *stream)
66+
static bool is_rist(const char *url)
6767
{
68-
return !strncmp(stream->ff_data.config.url, RIST_PROTO,
69-
sizeof(RIST_PROTO) - 1);
68+
return !strncmp(url, RIST_PROTO, sizeof(RIST_PROTO) - 1);
7069
}
7170

72-
static bool is_srt(struct ffmpeg_output *stream)
71+
static bool is_srt(const char *url)
7372
{
74-
return !strncmp(stream->ff_data.config.url, SRT_PROTO,
75-
sizeof(SRT_PROTO) - 1);
73+
return !strncmp(url, SRT_PROTO, sizeof(SRT_PROTO) - 1);
7674
}
7775

7876
static bool proto_is_allowed(struct ffmpeg_output *stream)
@@ -467,8 +465,8 @@ static inline int open_output_file(struct ffmpeg_output *stream,
467465
struct ffmpeg_data *data)
468466
{
469467
int ret;
470-
bool rist = is_rist(stream);
471-
bool srt = is_srt(stream);
468+
bool rist = data->config.is_rist;
469+
bool srt = data->config.is_srt;
472470
bool allowed_proto = proto_is_allowed(stream);
473471
AVDictionary *dict = NULL;
474472

@@ -591,10 +589,7 @@ static void close_audio(struct ffmpeg_data *data)
591589
static void close_mpegts_url(struct ffmpeg_output *stream, bool is_rist)
592590
{
593591
int err = 0;
594-
AVIOContext *s = stream->s;
595-
if (!s)
596-
return;
597-
URLContext *h = s->opaque;
592+
URLContext *h = stream->h;
598593
if (!h)
599594
return; /* can happen when opening the url fails */
600595

@@ -608,10 +603,14 @@ static void close_mpegts_url(struct ffmpeg_output *stream, bool is_rist)
608603
av_freep(h);
609604

610605
/* close custom avio_context for srt or rist */
611-
avio_flush(stream->s);
612-
stream->s->opaque = NULL;
613-
av_freep(&stream->s->buffer);
614-
avio_context_free(&stream->s);
606+
AVIOContext *s = stream->s;
607+
if (!s)
608+
return;
609+
610+
avio_flush(s);
611+
s->opaque = NULL;
612+
av_freep(&s->buffer);
613+
avio_context_free(&s);
615614

616615
if (err)
617616
info("[ffmpeg mpegts muxer]: Error closing URL %s",
@@ -632,8 +631,8 @@ void ffmpeg_mpegts_data_free(struct ffmpeg_output *stream,
632631
}
633632

634633
if (data->output) {
635-
if (is_rist(stream) || is_srt(stream)) {
636-
close_mpegts_url(stream, is_rist(stream));
634+
if (data->config.is_rist || data->config.is_srt) {
635+
close_mpegts_url(stream, data->config.is_rist);
637636
} else {
638637
avio_close(data->output->pb);
639638
}
@@ -757,11 +756,10 @@ static void ffmpeg_mpegts_destroy(void *data)
757756
struct ffmpeg_output *output = data;
758757

759758
if (output) {
759+
ffmpeg_mpegts_full_stop(output);
760760
if (output->connecting)
761761
pthread_join(output->start_thread, NULL);
762762

763-
ffmpeg_mpegts_full_stop(output);
764-
765763
pthread_mutex_destroy(&output->write_mutex);
766764
os_sem_destroy(output->write_sem);
767765
os_event_destroy(output->stop_event);
@@ -910,7 +908,8 @@ static bool set_config(struct ffmpeg_output *stream)
910908
service, OBS_SERVICE_CONNECT_INFO_ENCRYPT_PASSPHRASE);
911909
config.format_name = "mpegts";
912910
config.format_mime_type = "video/M2PT";
913-
911+
config.is_rist = is_rist(config.url);
912+
config.is_srt = is_srt(config.url);
914913
/* 2. video settings */
915914

916915
// 2.a) set width & height
@@ -1110,6 +1109,7 @@ static void ffmpeg_mpegts_full_stop(void *data)
11101109
obs_output_end_data_capture(output->output);
11111110
ffmpeg_mpegts_deactivate(output);
11121111
}
1112+
ffmpeg_mpegts_data_free(output, &output->ff_data);
11131113
}
11141114

11151115
static void ffmpeg_mpegts_stop(void *data, uint64_t ts)
@@ -1144,8 +1144,6 @@ static void ffmpeg_mpegts_deactivate(struct ffmpeg_output *output)
11441144
da_free(output->packets);
11451145

11461146
pthread_mutex_unlock(&output->write_mutex);
1147-
1148-
ffmpeg_mpegts_data_free(output, &output->ff_data);
11491147
}
11501148

11511149
static uint64_t ffmpeg_mpegts_total_bytes(void *data)

plugins/obs-ffmpeg/obs-ffmpeg-output.h

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct ffmpeg_cfg {
4343
const char *password;
4444
const char *stream_id;
4545
const char *encrypt_passphrase;
46+
bool is_srt;
47+
bool is_rist;
4648
};
4749

4850
struct ffmpeg_audio_info {

plugins/obs-ffmpeg/obs-ffmpeg-srt.h

+14-9
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,15 @@ static int libsrt_network_wait_fd(URLContext *h, int eid, int write)
150150
int ret, len = 1, errlen = 1;
151151
SRTSOCKET ready[1];
152152
SRTSOCKET error[1];
153-
153+
SRTContext *s = (SRTContext *)h->priv_data;
154154
if (write) {
155155
ret = srt_epoll_wait(eid, error, &errlen, ready, &len,
156156
POLLING_TIME, 0, 0, 0, 0);
157157
} else {
158158
ret = srt_epoll_wait(eid, ready, &len, error, &errlen,
159159
POLLING_TIME, 0, 0, 0, 0);
160160
}
161-
if (len == 1 && errlen == 1) {
161+
if (len == 1 && errlen == 1 && s->mode == SRT_MODE_CALLER) {
162162
/* Socket reported in wsock AND rsock signifies an error. */
163163
int reason = srt_getrejectreason(*ready);
164164

@@ -232,7 +232,7 @@ static int libsrt_listen(int eid, SRTSOCKET fd, const struct sockaddr *addr,
232232
if (srt_listen(fd, 1))
233233
return libsrt_neterrno(h);
234234

235-
ret = libsrt_network_wait_fd_timeout(h, eid, 1, timeout,
235+
ret = libsrt_network_wait_fd_timeout(h, eid, 0, timeout,
236236
&h->interrupt_callback);
237237
if (ret < 0)
238238
return ret;
@@ -462,7 +462,7 @@ static int libsrt_setup(URLContext *h, const char *uri)
462462
char hostname[1024], proto[1024], path[1024];
463463
char portstr[10];
464464
int64_t open_timeout = 0;
465-
int eid, write_eid;
465+
int eid;
466466
struct sockaddr_in la;
467467

468468
av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
@@ -552,20 +552,23 @@ static int libsrt_setup(URLContext *h, const char *uri)
552552
blog(LOG_DEBUG,
553553
"[obs-ffmpeg mpegts muxer / libsrt]: libsrt_socket_nonblock failed");
554554

555-
ret = write_eid = libsrt_epoll_create(h, fd, 1);
556-
if (ret < 0)
557-
goto fail1;
558555
if (s->mode == SRT_MODE_LISTENER) {
556+
int read_eid = ret = libsrt_epoll_create(h, fd, 0);
557+
if (ret < 0)
558+
goto fail1;
559559
// multi-client
560-
ret = libsrt_listen(write_eid, fd, cur_ai->ai_addr,
560+
ret = libsrt_listen(read_eid, fd, cur_ai->ai_addr,
561561
(socklen_t)cur_ai->ai_addrlen, h,
562562
s->listen_timeout);
563-
srt_epoll_release(write_eid);
563+
srt_epoll_release(read_eid);
564564
if (ret < 0)
565565
goto fail1;
566566
srt_close(fd);
567567
fd = ret;
568568
} else {
569+
int write_eid = ret = libsrt_epoll_create(h, fd, 1);
570+
if (ret < 0)
571+
goto fail1;
569572
if (s->mode == SRT_MODE_RENDEZVOUS) {
570573
if (srt_bind(fd, (struct sockaddr *)&la,
571574
sizeof(struct sockaddr_in))) {
@@ -878,6 +881,8 @@ static int libsrt_write(URLContext *h, const uint8_t *buf, int size)
878881
static int libsrt_close(URLContext *h)
879882
{
880883
SRTContext *s = (SRTContext *)h->priv_data;
884+
if (!s)
885+
return 0;
881886
if (s->streamid)
882887
av_freep(&s->streamid);
883888
if (s->passphrase)

0 commit comments

Comments
 (0)