static void *audio_thread(void *param) { struct audio_output *audio = param; uint64_t buffer_time = audio->info.buffer_ms * 1000000; uint64_t prev_time = os_gettime_ns() - buffer_time; uint64_t audio_time; os_set_thread_name("audio-io: audio thread"); const char *audio_thread_name = profile_store_name(obs_get_profiler_name_store(), "audio_thread(%s)", audio->info.name); while (os_event_try(audio->stop_event) == EAGAIN) { os_sleep_ms(AUDIO_WAIT_TIME); profile_start(audio_thread_name); pthread_mutex_lock(&audio->line_mutex); audio_time = os_gettime_ns() - buffer_time; audio_time = mix_and_output(audio, audio_time, prev_time); prev_time = audio_time; pthread_mutex_unlock(&audio->line_mutex); profile_end(audio_thread_name); profile_reenable_thread(); } return NULL; }
static void *connect_thread(void *data) { struct rtmp_stream *stream = data; int ret; os_set_thread_name("rtmp-stream: connect_thread"); if (!init_connect(stream)) { obs_output_signal_stop(stream->output, OBS_OUTPUT_BAD_PATH); return NULL; } ret = try_connect(stream); if (ret != OBS_OUTPUT_SUCCESS) { obs_output_signal_stop(stream->output, ret); info("Connection to %s failed: %d", stream->path.array, ret); } if (!stopping(stream)) pthread_detach(stream->connect_thread); os_atomic_set_bool(&stream->connecting, false); return NULL; }
static void *video_thread(void *param) { struct video_output *video = param; os_set_thread_name("video-io: video thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "video_thread(%s)", video->info.name); while (os_sem_wait(video->update_semaphore) == 0) { if (video->stop) break; profile_start(video_thread_name); while (!video->stop && !video_output_cur_frame(video)) { video->total_frames++; } video->total_frames++; profile_end(video_thread_name); profile_reenable_thread(); } return NULL; }
void mssapi_captions::main_thread() try { HRESULT hr; os_set_thread_name(__FUNCTION__); hr = grammar->SetDictationState(SPRS_ACTIVE); if (FAILED(hr)) throw HRError("SetDictationState failed", hr); hr = recognizer->SetRecoState(SPRST_ACTIVE); if (FAILED(hr)) throw HRError("SetRecoState(SPRST_ACTIVE) failed", hr); HANDLE events[] = {notify, stop}; started = true; for (;;) { DWORD ret = WaitForMultipleObjects(2, events, false, INFINITE); if (ret != WAIT_OBJECT_0) break; CSpEvent event; bool exit = false; while (event.GetFrom(context) == S_OK) { if (event.eEventId == SPEI_RECOGNITION) { ISpRecoResult *result = event.RecoResult(); CoTaskMemPtr<wchar_t> text; hr = result->GetText((ULONG)-1, (ULONG)-1, true, &text, nullptr); if (FAILED(hr)) continue; char text_utf8[512]; os_wcs_to_utf8(text, 0, text_utf8, 512); callback(text_utf8); blog(LOG_DEBUG, "\"%s\"", text_utf8); } else if (event.eEventId == SPEI_END_SR_STREAM) { exit = true; break; } } if (exit) break; } audio->Stop(); } catch (HRError err) { blog(LOG_WARNING, "%s failed: %s (%lX)", __FUNCTION__, err.str, err.hr); }
static void *send_thread(void *data) { struct rtmp_stream *stream = data; os_set_thread_name("rtmp-stream: send_thread"); while (os_sem_wait(stream->send_sem) == 0) { struct encoder_packet packet; if (stopping(stream) && stream->stop_ts == 0) { break; } if (!get_next_packet(stream, &packet)) continue; if (stopping(stream)) { if (can_shutdown_stream(stream, &packet)) { obs_free_encoder_packet(&packet); break; } } if (!stream->sent_headers) { if (!send_headers(stream)) { os_atomic_set_bool(&stream->disconnected, true); break; } } if (send_packet(stream, &packet, false, packet.track_idx) < 0) { os_atomic_set_bool(&stream->disconnected, true); break; } } if (disconnected(stream)) { info("Disconnected from %s", stream->path.array); } else { info("User stopped the stream"); } RTMP_Close(&stream->rtmp); if (!stopping(stream)) { pthread_detach(stream->send_thread); obs_output_signal_stop(stream->output, OBS_OUTPUT_DISCONNECTED); } else { obs_output_end_data_capture(stream->output); } free_packets(stream); os_event_reset(stream->stop_event); os_atomic_set_bool(&stream->active, false); stream->sent_headers = false; return NULL; }
void *obs_video_thread(void *param) { uint64_t last_time = 0; uint64_t cur_time = os_gettime_ns(); uint64_t interval = video_output_get_frame_time(obs->video.video); os_set_thread_name("libobs: graphics thread"); while (!video_output_stopped(obs->video.video)) { last_time = tick_sources(cur_time, last_time); render_displays(); output_frame(&cur_time, interval); } UNUSED_PARAMETER(param); return NULL; }
static void *audio_thread(void *param) { struct audio_output *audio = param; size_t rate = audio->info.samples_per_sec; uint64_t samples = 0; uint64_t start_time = os_gettime_ns(); uint64_t prev_time = start_time; uint64_t audio_time = prev_time; uint32_t audio_wait_time = (uint32_t)(audio_frames_to_ns(rate, AUDIO_OUTPUT_FRAMES) / 1000000); os_set_thread_name("audio-io: audio thread"); const char *audio_thread_name = profile_store_name(obs_get_profiler_name_store(), "audio_thread(%s)", audio->info.name); while (os_event_try(audio->stop_event) == EAGAIN) { uint64_t cur_time; os_sleep_ms(audio_wait_time); profile_start(audio_thread_name); cur_time = os_gettime_ns(); while (audio_time <= cur_time) { samples += AUDIO_OUTPUT_FRAMES; audio_time = start_time + audio_frames_to_ns(rate, samples); input_and_output(audio, audio_time, prev_time); prev_time = audio_time; } profile_end(audio_thread_name); profile_reenable_thread(); } return NULL; }
void *obs_video_thread(void *param) { uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); obs->video.video_time = os_gettime_ns(); os_set_thread_name("libobs: graphics thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "obs_video_thread(%g ms)", interval / 1000000.); profile_register_root(video_thread_name, interval); while (!video_output_stopped(obs->video.video)) { profile_start(video_thread_name); profile_start(tick_sources_name); last_time = tick_sources(obs->video.video_time, last_time); profile_end(tick_sources_name); profile_start(render_displays_name); render_displays(); profile_end(render_displays_name); profile_start(output_frame_name); output_frame(); profile_end(output_frame_name); profile_end(video_thread_name); profile_reenable_thread(); video_sleep(&obs->video, &obs->video.video_time, interval); } UNUSED_PARAMETER(param); return NULL; }
void *obs_graphics_thread(void *param) { uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); uint64_t frame_time_total_ns = 0; uint64_t fps_total_ns = 0; uint32_t fps_total_frames = 0; obs->video.video_time = os_gettime_ns(); os_set_thread_name("libobs: graphics thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "obs_graphics_thread(%g"NBSP"ms)", interval / 1000000.); profile_register_root(video_thread_name, interval); srand((unsigned int)time(NULL)); while (!video_output_stopped(obs->video.video)) { uint64_t frame_start = os_gettime_ns(); uint64_t frame_time_ns; profile_start(video_thread_name); profile_start(tick_sources_name); last_time = tick_sources(obs->video.video_time, last_time); profile_end(tick_sources_name); profile_start(render_displays_name); render_displays(); profile_end(render_displays_name); profile_start(output_frame_name); output_frame(); profile_end(output_frame_name); frame_time_ns = os_gettime_ns() - frame_start; profile_end(video_thread_name); profile_reenable_thread(); video_sleep(&obs->video, &obs->video.video_time, interval); frame_time_total_ns += frame_time_ns; fps_total_ns += (obs->video.video_time - last_time); fps_total_frames++; if (fps_total_ns >= 1000000000ULL) { obs->video.video_fps = (double)fps_total_frames / ((double)fps_total_ns / 1000000000.0); obs->video.video_avg_frame_time_ns = frame_time_total_ns / (uint64_t)fps_total_frames; frame_time_total_ns = 0; fps_total_ns = 0; fps_total_frames = 0; } } UNUSED_PARAMETER(param); return NULL; }
void *obs_graphics_thread(void *param) { uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); uint64_t frame_time_total_ns = 0; uint64_t fps_total_ns = 0; uint32_t fps_total_frames = 0; bool gpu_was_active = false; bool raw_was_active = false; bool was_active = false; obs->video.video_time = os_gettime_ns(); os_set_thread_name("libobs: graphics thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "obs_graphics_thread(%g"NBSP"ms)", interval / 1000000.); profile_register_root(video_thread_name, interval); srand((unsigned int)time(NULL)); while (!video_output_stopped(obs->video.video)) { uint64_t frame_start = os_gettime_ns(); uint64_t frame_time_ns; bool raw_active = obs->video.raw_active > 0; #ifdef _WIN32 bool gpu_active = obs->video.gpu_encoder_active > 0; #else const bool gpu_active = 0; #endif bool active = raw_active || gpu_active; if (!was_active && active) clear_base_frame_data(); if (!raw_was_active && raw_active) clear_raw_frame_data(); #ifdef _WIN32 if (!gpu_was_active && gpu_active) clear_gpu_frame_data(); #endif raw_was_active = raw_active; gpu_was_active = gpu_active; was_active = active; profile_start(video_thread_name); profile_start(tick_sources_name); last_time = tick_sources(obs->video.video_time, last_time); profile_end(tick_sources_name); profile_start(output_frame_name); output_frame(raw_active, gpu_active); profile_end(output_frame_name); profile_start(render_displays_name); render_displays(); profile_end(render_displays_name); frame_time_ns = os_gettime_ns() - frame_start; profile_end(video_thread_name); profile_reenable_thread(); video_sleep(&obs->video, raw_active, gpu_active, &obs->video.video_time, interval); frame_time_total_ns += frame_time_ns; fps_total_ns += (obs->video.video_time - last_time); fps_total_frames++; if (fps_total_ns >= 1000000000ULL) { obs->video.video_fps = (double)fps_total_frames / ((double)fps_total_ns / 1000000000.0); obs->video.video_avg_frame_time_ns = frame_time_total_ns / (uint64_t)fps_total_frames; frame_time_total_ns = 0; fps_total_ns = 0; fps_total_frames = 0; } } UNUSED_PARAMETER(param); return NULL; }
static inline bool mp_media_thread(mp_media_t *m) { os_set_thread_name("mp_media_thread"); if (!init_avformat(m)) { return false; } if (!mp_media_reset(m)) { return false; } for (;;) { bool reset, kill, is_active; bool timeout = false; pthread_mutex_lock(&m->mutex); is_active = m->active; pthread_mutex_unlock(&m->mutex); if (!is_active) { if (os_sem_wait(m->sem) < 0) return false; } else { timeout = mp_media_sleepto(m); } pthread_mutex_lock(&m->mutex); reset = m->reset; kill = m->kill; m->reset = false; m->kill = false; pthread_mutex_unlock(&m->mutex); if (kill) { break; } if (reset) { mp_media_reset(m); continue; } /* frames are ready */ if (is_active && !timeout) { if (m->has_video) mp_media_next_video(m, false); if (m->has_audio) mp_media_next_audio(m); if (!mp_media_prepare_frames(m)) return false; if (mp_media_eof(m)) continue; mp_media_calc_next_ns(m); } } return true; }