static bool flv_output_start(void *data) { struct flv_output *stream = data; obs_data_t *settings; const char *path; if (!obs_output_can_begin_data_capture(stream->output, 0)) return false; if (!obs_output_initialize_encoders(stream->output, 0)) return false; /* get path */ settings = obs_output_get_settings(stream->output); path = obs_data_get_string(settings, "path"); dstr_copy(&stream->path, path); obs_data_release(settings); stream->file = os_fopen(stream->path.array, "wb"); if (!stream->file) { warn("Unable to open FLV file '%s'", stream->path.array); return false; } /* write headers and start capture */ stream->active = true; obs_output_begin_data_capture(stream->output, 0); info("Writing FLV file '%s'...", stream->path.array); return true; }
static bool ffmpeg_mux_start(void *data) { struct ffmpeg_muxer *stream = data; obs_data_t *settings; struct dstr cmd; const char *path; if (!obs_output_can_begin_data_capture(stream->output, 0)) return false; if (!obs_output_initialize_encoders(stream->output, 0)) return false; settings = obs_output_get_settings(stream->output); path = obs_data_get_string(settings, "path"); dstr_copy(&stream->path, path); dstr_replace(&stream->path, "\"", "\"\""); obs_data_release(settings); build_command_line(stream, &cmd); stream->pipe = os_process_pipe_create(cmd.array, "w"); dstr_free(&cmd); if (!stream->pipe) { warn("Failed to create process pipe"); return false; } /* write headers and start capture */ stream->active = true; stream->capturing = true; obs_output_begin_data_capture(stream->output, 0); info("Writing file '%s'...", stream->path.array); return true; }
static int init_send(struct rtmp_stream *stream) { int ret; size_t idx = 0; bool next = true; #if defined(_WIN32) adjust_sndbuf_size(stream, MIN_SENDBUF_SIZE); #endif reset_semaphore(stream); ret = pthread_create(&stream->send_thread, NULL, send_thread, stream); if (ret != 0) { RTMP_Close(&stream->rtmp); warn("Failed to create send thread"); return OBS_OUTPUT_ERROR; } os_atomic_set_bool(&stream->active, true); while (next) { if (!send_meta_data(stream, idx++, &next)) { warn("Disconnected while attempting to connect to " "server."); return OBS_OUTPUT_DISCONNECTED; } } obs_output_begin_data_capture(stream->output, 0); return OBS_OUTPUT_SUCCESS; }
static void adjust_sndbuf_size(struct rtmp_stream *stream, int new_size) { int cur_sendbuf_size = new_size; socklen_t int_size = sizeof(int); #ifndef TEST_FRAMEDROPS getsockopt(stream->rtmp.m_sb.sb_socket, SOL_SOCKET, SO_SNDBUF, (char*)&cur_sendbuf_size, &int_size); if (cur_sendbuf_size < new_size) { cur_sendbuf_size = new_size; #else {cur_sendbuf_size = 1024*8; #endif setsockopt(stream->rtmp.m_sb.sb_socket, SOL_SOCKET, SO_SNDBUF, (const char*)&cur_sendbuf_size, int_size); } } static int init_send(struct rtmp_stream *stream) { int ret; #if defined(_WIN32) && !defined(FILE_TEST) adjust_sndbuf_size(stream, MIN_SENDBUF_SIZE); #endif reset_semaphore(stream); ret = pthread_create(&stream->send_thread, NULL, send_thread, stream); if (ret != 0) { RTMP_Close(&stream->rtmp); return OBS_OUTPUT_FAIL; } stream->active = true; send_headers(stream); obs_output_begin_data_capture(stream->output, 0); return OBS_OUTPUT_SUCCESS; }
static int init_send(struct rtmp_stream *stream) { int ret; size_t idx = 0; #if defined(_WIN32) adjust_sndbuf_size(stream, MIN_SENDBUF_SIZE); #endif reset_semaphore(stream); ret = pthread_create(&stream->send_thread, NULL, send_thread, stream); if (ret != 0) { RTMP_Close(&stream->rtmp); warn("Failed to create send thread"); return OBS_OUTPUT_ERROR; } os_atomic_set_bool(&stream->active, true); while (send_meta_data(stream, idx++)); obs_output_begin_data_capture(stream->output, 0); return OBS_OUTPUT_SUCCESS; }
static int init_send(struct rtmp_stream *stream) { int ret; size_t idx = 0; bool next = true; #if defined(_WIN32) adjust_sndbuf_size(stream, MIN_SENDBUF_SIZE); #endif reset_semaphore(stream); ret = pthread_create(&stream->send_thread, NULL, send_thread, stream); if (ret != 0) { RTMP_Close(&stream->rtmp); warn("Failed to create send thread"); return OBS_OUTPUT_ERROR; } if (stream->new_socket_loop) { int one = 1; #ifdef _WIN32 if (ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) { stream->rtmp.last_error_code = WSAGetLastError(); #else if (ioctl(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) { stream->rtmp.last_error_code = errno; #endif warn("Failed to set non-blocking socket"); return OBS_OUTPUT_ERROR; } os_event_reset(stream->send_thread_signaled_exit); info("New socket loop enabled by user"); if (stream->low_latency_mode) info("Low latency mode enabled by user"); if (stream->write_buf) bfree(stream->write_buf); int total_bitrate = 0; obs_output_t *context = stream->output; obs_encoder_t *vencoder = obs_output_get_video_encoder(context); if (vencoder) { obs_data_t *params = obs_encoder_get_settings(vencoder); if (params) { int bitrate = obs_data_get_int(params, "bitrate"); total_bitrate += bitrate; obs_data_release(params); } } obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, 0); if (aencoder) { obs_data_t *params = obs_encoder_get_settings(aencoder); if (params) { int bitrate = obs_data_get_int(params, "bitrate"); total_bitrate += bitrate; obs_data_release(params); } } // to bytes/sec int ideal_buffer_size = total_bitrate * 128; if (ideal_buffer_size < 131072) ideal_buffer_size = 131072; stream->write_buf_size = ideal_buffer_size; stream->write_buf = bmalloc(ideal_buffer_size); #ifdef _WIN32 ret = pthread_create(&stream->socket_thread, NULL, socket_thread_windows, stream); #else warn("New socket loop not supported on this platform"); return OBS_OUTPUT_ERROR; #endif if (ret != 0) { RTMP_Close(&stream->rtmp); warn("Failed to create socket thread"); return OBS_OUTPUT_ERROR; } stream->socket_thread_active = true; stream->rtmp.m_bCustomSend = true; stream->rtmp.m_customSendFunc = socket_queue_data; stream->rtmp.m_customSendParam = stream; } os_atomic_set_bool(&stream->active, true); while (next) { if (!send_meta_data(stream, idx++, &next)) { warn("Disconnected while attempting to connect to " "server."); set_output_error(stream); return OBS_OUTPUT_DISCONNECTED; } } obs_output_begin_data_capture(stream->output, 0); return OBS_OUTPUT_SUCCESS; } #ifdef _WIN32 static void win32_log_interface_type(struct rtmp_stream *stream) { RTMP *rtmp = &stream->rtmp; MIB_IPFORWARDROW route; uint32_t dest_addr, source_addr; char hostname[256]; HOSTENT *h; if (rtmp->Link.hostname.av_len >= sizeof(hostname) - 1) return; strncpy(hostname, rtmp->Link.hostname.av_val, sizeof(hostname)); hostname[rtmp->Link.hostname.av_len] = 0; h = gethostbyname(hostname); if (!h) return; dest_addr = *(uint32_t*)h->h_addr_list[0]; if (rtmp->m_bindIP.addrLen == 0) source_addr = 0; else if (rtmp->m_bindIP.addr.ss_family == AF_INET) source_addr = (*(struct sockaddr_in*)&rtmp->m_bindIP) .sin_addr.S_un.S_addr; else return; if (!GetBestRoute(dest_addr, source_addr, &route)) { MIB_IFROW row; memset(&row, 0, sizeof(row)); row.dwIndex = route.dwForwardIfIndex; if (!GetIfEntry(&row)) { uint32_t speed =row.dwSpeed / 1000000; char *type; struct dstr other = {0}; if (row.dwType == IF_TYPE_ETHERNET_CSMACD) { type = "ethernet"; } else if (row.dwType == IF_TYPE_IEEE80211) { type = "802.11"; } else { dstr_printf(&other, "type %lu", row.dwType); type = other.array; } info("Interface: %s (%s, %lu mbps)", row.bDescr, type, speed); dstr_free(&other); } } }