static void *video_thread(void *param) { struct video_output *video = param; uint64_t cur_time = os_gettime_ns(); while (os_event_try(video->stop_event) == EAGAIN) { /* wait half a frame, update frame */ cur_time += (video->frame_time/2); os_sleepto_ns(cur_time); video->cur_video_time = cur_time; os_event_signal(video->update_event); /* wait another half a frame, swap and output frames */ cur_time += (video->frame_time/2); os_sleepto_ns(cur_time); pthread_mutex_lock(&video->data_mutex); video_swapframes(video); video_output_cur_frame(video); pthread_mutex_unlock(&video->data_mutex); } return NULL; }
static void droptest_cap_data_rate(struct rtmp_stream *stream, size_t size) { uint64_t ts = os_gettime_ns(); struct droptest_info info; info.ts = ts; info.size = size; circlebuf_push_back(&stream->droptest_info, &info, sizeof(info)); stream->droptest_size += size; if (stream->droptest_info.size) { circlebuf_peek_front(&stream->droptest_info, &info, sizeof(info)); if (stream->droptest_size > DROPTEST_MAX_BYTES) { uint64_t elapsed = ts - info.ts; if (elapsed < 1000000000ULL) { elapsed = 1000000000ULL - elapsed; os_sleepto_ns(ts + elapsed); } while (stream->droptest_size > DROPTEST_MAX_BYTES) { circlebuf_pop_front(&stream->droptest_info, &info, sizeof(info)); stream->droptest_size -= info.size; } } } }
static void *sinewave_thread(void *pdata) { struct sinewave_data *swd = pdata; uint64_t last_time = os_gettime_ns(); uint64_t ts = 0; double cos_val = 0.0; uint8_t bytes[480]; while (event_try(swd->event) == EAGAIN) { if (!os_sleepto_ns(last_time += 10000000)) last_time = os_gettime_ns(); for (size_t i = 0; i < 480; i++) { cos_val += rate * M_PI_X2; if (cos_val > M_PI_X2) cos_val -= M_PI_X2; double wave = cos(cos_val) * 0.5; bytes[i] = (uint8_t)((wave+1.0)*0.5 * 255.0); } struct source_audio data; data.data[0] = bytes; data.frames = 480; data.speakers = SPEAKERS_MONO; data.samples_per_sec = 48000; data.timestamp = ts; data.format = AUDIO_FORMAT_U8BIT; obs_source_output_audio(swd->source, &data); ts += 10000000; } return NULL; }
static inline void video_sleep(struct obs_core_video *video, bool raw_active, const bool gpu_active, uint64_t *p_time, uint64_t interval_ns) { struct obs_vframe_info vframe_info; uint64_t cur_time = *p_time; uint64_t t = cur_time + interval_ns; int count; if (os_sleepto_ns(t)) { *p_time = t; count = 1; } else { count = (int)((os_gettime_ns() - cur_time) / interval_ns); *p_time = cur_time + interval_ns * count; } video->total_frames += count; video->lagged_frames += count - 1; vframe_info.timestamp = cur_time; vframe_info.count = count; if (raw_active) circlebuf_push_back(&video->vframe_info_buffer, &vframe_info, sizeof(vframe_info)); if (gpu_active) circlebuf_push_back(&video->vframe_info_buffer_gpu, &vframe_info, sizeof(vframe_info)); }
static void *video_thread(void *param) { struct video_output *video = param; uint64_t cur_time = os_gettime_ns(); while (event_try(&video->stop_event) == EAGAIN) { /* wait half a frame, update frame */ os_sleepto_ns(cur_time += (video->frame_time/2)); video->cur_video_time = cur_time; event_signal(&video->update_event); /* wait another half a frame, swap and output frames */ os_sleepto_ns(cur_time += (video->frame_time/2)); video_swapframes(video); if (video->cur_frame) media_output_data(video->output, video->cur_frame); } return NULL; }
static inline bool mp_media_sleepto(mp_media_t *m) { bool timeout = false; if (!m->next_ns) { m->next_ns = os_gettime_ns(); } else { uint64_t t = os_gettime_ns(); const uint64_t timeout_ns = 200000000; if (m->next_ns > t && (m->next_ns - t) > timeout_ns) { os_sleepto_ns(t + timeout_ns); timeout = true; } else { os_sleepto_ns(m->next_ns); } } return timeout; }
static inline void video_sleep(struct obs_core_video *video, uint64_t *p_time, uint64_t interval_ns) { struct obs_vframe_info vframe_info; uint64_t cur_time = *p_time; uint64_t t = cur_time + interval_ns; int count; if (os_sleepto_ns(t)) { *p_time = t; count = 1; } else { count = (int)((os_gettime_ns() - cur_time) / interval_ns); *p_time = cur_time + interval_ns * count; } vframe_info.timestamp = cur_time; vframe_info.count = count; circlebuf_push_back(&video->vframe_info_buffer, &vframe_info, sizeof(vframe_info)); }