973d31b8c2
(This commit also modifies the UI, obs-ffmpeg, and obs-output modules) Fixes a long-time regression where the program would lock up if an encode call fails. Shuts down all outputs associated with the failing encoder and displays an error message to the user. Ideally, it would be best if a more detailed error could be displayed to the user about the nature of the error, though the primary problem is the encoder errors are typically not something the user would be able to understand. The current message is a bit of a generic error message; improvement is welcome. Another suggestion is to try to have the encoder restart seamlessly, though it would take a significant amount of work to be able to make it do something like that properly, and it sort of assumes that encoder failures are sporadic, which may not necessarily be the case with some hardware encoders on some systems. It may be better just to use another encoder in that case. For now, seamless restart is ruled out.
113 lines
2.8 KiB
C
113 lines
2.8 KiB
C
#include <obs-module.h>
|
|
#include <obs-avc.h>
|
|
#include <util/platform.h>
|
|
#include <util/circlebuf.h>
|
|
#include <util/dstr.h>
|
|
#include <util/threading.h>
|
|
#include <inttypes.h>
|
|
#include "librtmp/rtmp.h"
|
|
#include "librtmp/log.h"
|
|
#include "flv-mux.h"
|
|
#include "net-if.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <Iphlpapi.h>
|
|
#else
|
|
#include <sys/ioctl.h>
|
|
#endif
|
|
|
|
#define do_log(level, format, ...) \
|
|
blog(level, "[rtmp stream: '%s'] " format, \
|
|
obs_output_get_name(stream->output), ##__VA_ARGS__)
|
|
|
|
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
|
|
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
|
|
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
|
|
|
|
#define OPT_DROP_THRESHOLD "drop_threshold_ms"
|
|
#define OPT_PFRAME_DROP_THRESHOLD "pframe_drop_threshold_ms"
|
|
#define OPT_MAX_SHUTDOWN_TIME_SEC "max_shutdown_time_sec"
|
|
#define OPT_BIND_IP "bind_ip"
|
|
#define OPT_NEWSOCKETLOOP_ENABLED "new_socket_loop_enabled"
|
|
#define OPT_LOWLATENCY_ENABLED "low_latency_mode_enabled"
|
|
|
|
//#define TEST_FRAMEDROPS
|
|
|
|
#ifdef TEST_FRAMEDROPS
|
|
|
|
#define DROPTEST_MAX_KBPS 3000
|
|
#define DROPTEST_MAX_BYTES (DROPTEST_MAX_KBPS * 1000 / 8)
|
|
|
|
struct droptest_info {
|
|
uint64_t ts;
|
|
size_t size;
|
|
};
|
|
#endif
|
|
|
|
struct rtmp_stream {
|
|
obs_output_t *output;
|
|
|
|
pthread_mutex_t packets_mutex;
|
|
struct circlebuf packets;
|
|
bool sent_headers;
|
|
|
|
bool got_first_video;
|
|
int64_t start_dts_offset;
|
|
|
|
volatile bool connecting;
|
|
pthread_t connect_thread;
|
|
|
|
volatile bool active;
|
|
volatile bool disconnected;
|
|
volatile bool encode_error;
|
|
pthread_t send_thread;
|
|
|
|
int max_shutdown_time_sec;
|
|
|
|
os_sem_t *send_sem;
|
|
os_event_t *stop_event;
|
|
uint64_t stop_ts;
|
|
uint64_t shutdown_timeout_ts;
|
|
|
|
struct dstr path, key;
|
|
struct dstr username, password;
|
|
struct dstr encoder_name;
|
|
struct dstr bind_ip;
|
|
|
|
/* frame drop variables */
|
|
int64_t drop_threshold_usec;
|
|
int64_t pframe_drop_threshold_usec;
|
|
int min_priority;
|
|
float congestion;
|
|
|
|
int64_t last_dts_usec;
|
|
|
|
uint64_t total_bytes_sent;
|
|
int dropped_frames;
|
|
|
|
#ifdef TEST_FRAMEDROPS
|
|
struct circlebuf droptest_info;
|
|
size_t droptest_size;
|
|
#endif
|
|
|
|
RTMP rtmp;
|
|
|
|
bool new_socket_loop;
|
|
bool low_latency_mode;
|
|
bool disable_send_window_optimization;
|
|
bool socket_thread_active;
|
|
pthread_t socket_thread;
|
|
uint8_t *write_buf;
|
|
size_t write_buf_len;
|
|
size_t write_buf_size;
|
|
pthread_mutex_t write_buf_mutex;
|
|
os_event_t *buffer_space_available_event;
|
|
os_event_t *buffer_has_data_event;
|
|
os_event_t *socket_available_event;
|
|
os_event_t *send_thread_signaled_exit;
|
|
};
|
|
|
|
#ifdef _WIN32
|
|
void *socket_thread_windows(void *data);
|
|
#endif
|