bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags) { bool encoded, has_video, has_audio, has_service; size_t num_mixes = num_audio_mixes(output); if (!obs_output_valid(output, "obs_output_initialize_encoders")) return false; if (active(output)) return delay_active(output); convert_flags(output, flags, &encoded, &has_video, &has_audio, &has_service); if (!encoded) return false; if (has_service && !obs_service_initialize(output->service, output)) return false; if (has_video && !obs_encoder_initialize(output->video_encoder)) return false; if (has_audio && !initialize_audio_encoders(output, num_mixes)) return false; if (has_video && has_audio) pair_encoders(output, num_mixes); return true; }
void obs_output_set_audio_encoder(obs_output_t *output, obs_encoder_t *encoder, size_t idx) { if (!obs_output_valid(output, "obs_output_set_audio_encoder")) return; if (encoder && encoder->info.type != OBS_ENCODER_AUDIO) { blog(LOG_WARNING, "obs_output_set_audio_encoder: " "encoder passed is not an audio encoder"); return; } if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) { if (idx >= MAX_AUDIO_MIXES) { return; } } else { if (idx > 0) { return; } } if (output->audio_encoders[idx] == encoder) return; obs_encoder_remove_output(output->audio_encoders[idx], output); obs_encoder_add_output(encoder, output); output->audio_encoders[idx] = encoder; }
void obs_output_set_media(obs_output_t *output, video_t *video, audio_t *audio) { if (!obs_output_valid(output, "obs_output_set_media")) return; output->video = video; output->audio = audio; }
void obs_output_set_mixer(obs_output_t *output, size_t mixer_idx) { if (!obs_output_valid(output, "obs_output_set_mixer")) return; if (!active(output)) output->mixer_idx = mixer_idx; }
obs_data_t *obs_output_get_settings(const obs_output_t *output) { if (!obs_output_valid(output, "obs_output_get_settings")) return NULL; obs_data_addref(output->context.settings); return output->context.settings; }
void obs_output_pause(obs_output_t *output) { if (!obs_output_valid(output, "obs_output_pause")) return; if (output->info.pause) output->info.pause(output->context.data); }
void obs_output_set_reconnect_settings(obs_output_t *output, int retry_count, int retry_sec) { if (!obs_output_valid(output, "obs_output_set_reconnect_settings")) return; output->reconnect_retry_max = retry_count; output->reconnect_retry_sec = retry_sec; }
int obs_output_get_frames_dropped(const obs_output_t *output) { if (!obs_output_valid(output, "obs_output_get_frames_dropped")) return 0; if (!output->info.get_dropped_frames) return 0; return output->info.get_dropped_frames(output->context.data); }
void obs_output_set_audio_conversion(obs_output_t *output, const struct audio_convert_info *conversion) { if (!obs_output_valid(output, "obs_output_set_audio_conversion")) return; if (!obs_ptr_valid(conversion, "obs_output_set_audio_conversion")) return; output->audio_conversion = *conversion; output->audio_conversion_set = true; }
void obs_output_update(obs_output_t *output, obs_data_t *settings) { if (!obs_output_valid(output, "obs_output_update")) return; obs_data_apply(output->context.settings, settings); if (output->info.update) output->info.update(output->context.data, output->context.settings); }
void obs_output_set_video_conversion(obs_output_t *output, const struct video_scale_info *conversion) { if (!obs_output_valid(output, "obs_output_set_video_conversion")) return; if (!obs_ptr_valid(conversion, "obs_output_set_video_conversion")) return; output->video_conversion = *conversion; output->video_conversion_set = true; }
void obs_output_force_stop(obs_output_t *output) { if (!obs_output_valid(output, "obs_output_force_stop")) return; if (!stopping(output)) { output->stop_code = 0; do_output_signal(output, "stopping"); obs_output_actual_stop(output, true, 0); } }
uint64_t obs_output_get_total_bytes(const obs_output_t *output) { if (!obs_output_valid(output, "obs_output_get_total_bytes")) return 0; if (!output->info.get_total_bytes) return 0; if (delay_active(output) && !delay_capturing(output)) return 0; return output->info.get_total_bytes(output->context.data); }
void obs_output_set_service(obs_output_t *output, obs_service_t *service) { if (!obs_output_valid(output, "obs_output_set_service")) return; if (active(output) || !service || service->active) return; if (service->output) service->output->service = NULL; output->service = service; service->output = output; }
uint32_t obs_output_get_height(const obs_output_t *output) { if (!obs_output_valid(output, "obs_output_get_height")) return 0; if ((output->info.flags & OBS_OUTPUT_VIDEO) == 0) return 0; if (output->info.flags & OBS_OUTPUT_ENCODED) return obs_encoder_get_height(output->video_encoder); else return output->scaled_height != 0 ? output->scaled_height : video_output_get_height(output->video); }
obs_properties_t *obs_output_properties(const obs_output_t *output) { if (!obs_output_valid(output, "obs_output_properties")) return NULL; if (output && output->info.get_properties) { obs_properties_t *props; props = output->info.get_properties(output->context.data); obs_properties_apply_settings(props, output->context.settings); return props; } return NULL; }
static void obs_output_end_data_capture_internal(obs_output_t *output, bool signal) { int ret; if (!obs_output_valid(output, "obs_output_end_data_capture")) return; if (!active(output) || !data_active(output)) { if (signal) { signal_stop(output); output->stop_code = OBS_OUTPUT_SUCCESS; } return; } if (delay_active(output)) { os_atomic_set_bool(&output->delay_capturing, false); if (!os_atomic_load_long(&output->delay_restart_refs)) { os_atomic_set_bool(&output->delay_active, false); } else { os_event_signal(output->stopping_event); return; } } os_atomic_set_bool(&output->data_active, false); if (output->video) log_frame_info(output); if (data_capture_ending(output)) pthread_join(output->end_data_capture_thread, NULL); os_atomic_set_bool(&output->end_data_capture_thread_active, true); ret = pthread_create(&output->end_data_capture_thread, NULL, end_data_capture_thread, output); if (ret != 0) { blog(LOG_WARNING, "Failed to create end_data_capture_thread " "for output '%s'!", output->context.name); end_data_capture_thread(output); } if (signal) { signal_stop(output); output->stop_code = OBS_OUTPUT_SUCCESS; } }
void obs_output_end_data_capture(obs_output_t *output) { bool encoded, has_video, has_audio, has_service; encoded_callback_t encoded_callback; if (!obs_output_valid(output, "obs_output_end_data_capture")) return; if (output->delay_active) { output->delay_capturing = false; return; } if (!output->active) return; convert_flags(output, 0, &encoded, &has_video, &has_audio, &has_service); if (encoded) { if (output->active_delay_ns) encoded_callback = process_delay; else encoded_callback = (has_video && has_audio) ? interleave_packets : default_encoded_callback; if (has_video) obs_encoder_stop(output->video_encoder, encoded_callback, output); if (has_audio) stop_audio_encoders(output, encoded_callback); } else { if (has_video) video_output_disconnect(output->video, default_raw_video_callback, output); if (has_audio) audio_output_disconnect(output->audio, output->mixer_idx, default_raw_audio_callback, output); } if (has_service) obs_service_deactivate(output->service, false); if (output->active_delay_ns) obs_output_cleanup_delay(output); do_output_signal(output, "deactivate"); output->active = false; }
void obs_output_remove_encoder(struct obs_output *output, struct obs_encoder *encoder) { if (!obs_output_valid(output, "obs_output_remove_encoder")) return; if (output->video_encoder == encoder) { output->video_encoder = NULL; } else { for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) { if (output->audio_encoders[i] == encoder) output->audio_encoders[i] = NULL; } } }
void obs_output_stop(obs_output_t *output) { bool encoded; if (!obs_output_valid(output, "obs_output_stop")) return; if (!output->context.data) return; encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0; if (encoded && output->active_delay_ns) { obs_output_delay_stop(output); } else { obs_output_actual_stop(output, false); do_output_signal(output, "stopping"); } }
bool obs_output_can_begin_data_capture(const obs_output_t *output, uint32_t flags) { bool encoded, has_video, has_audio, has_service; if (!obs_output_valid(output, "obs_output_can_begin_data_capture")) return false; if (output->delay_active) return true; if (output->active) return false; convert_flags(output, flags, &encoded, &has_video, &has_audio, &has_service); return can_begin_data_capture(output, encoded, has_video, has_audio, has_service); }
obs_encoder_t *obs_output_get_audio_encoder(const obs_output_t *output, size_t idx) { if (!obs_output_valid(output, "obs_output_get_audio_encoder")) return NULL; if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) { if (idx >= MAX_AUDIO_MIXES) { return NULL; } } else { if (idx > 0) { return NULL; } } return output->audio_encoders[idx]; }
void obs_output_signal_stop(obs_output_t *output, int code) { if (!obs_output_valid(output, "obs_output_signal_stop")) return; output->stop_code = code; if (can_reconnect(output, code)) { if (delay_active(output)) os_atomic_inc_long(&output->delay_restart_refs); obs_output_end_data_capture_internal(output, false); output_reconnect(output); } else { if (delay_active(output)) os_atomic_set_bool(&output->delay_active, false); obs_output_end_data_capture(output); } }
void obs_output_signal_stop(obs_output_t *output, int code) { if (!obs_output_valid(output, "obs_output_signal_stop")) return; obs_output_end_data_capture(output); if ((output->reconnecting && code != OBS_OUTPUT_SUCCESS) || code == OBS_OUTPUT_DISCONNECTED) { output_reconnect(output); } else { if (output->delay_active) { output->delay_active = false; obs_output_end_data_capture(output); } signal_stop(output, code); } }
bool obs_output_can_begin_data_capture(const obs_output_t *output, uint32_t flags) { bool encoded, has_video, has_audio, has_service; if (!obs_output_valid(output, "obs_output_can_begin_data_capture")) return false; if (delay_active(output)) return true; if (active(output)) return false; if (data_capture_ending(output)) pthread_join(output->end_data_capture_thread, NULL); convert_flags(output, flags, &encoded, &has_video, &has_audio, &has_service); return can_begin_data_capture(output, encoded, has_video, has_audio, has_service); }
bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags) { bool encoded, has_video, has_audio, has_service; if (!obs_output_valid(output, "obs_output_begin_data_capture")) return false; if (delay_active(output)) return begin_delayed_capture(output); if (active(output)) return false; output->total_frames = 0; convert_flags(output, flags, &encoded, &has_video, &has_audio, &has_service); if (!can_begin_data_capture(output, encoded, has_video, has_audio, has_service)) return false; os_atomic_set_bool(&output->data_active, true); hook_data_capture(output, encoded, has_video, has_audio); if (has_service) obs_service_activate(output->service); do_output_signal(output, "activate"); os_atomic_set_bool(&output->active, true); if (reconnecting(output)) { signal_reconnect_success(output); os_atomic_set_bool(&output->reconnecting, false); } else if (delay_active(output)) { do_output_signal(output, "starting"); } else { signal_start(output); } return true; }
void obs_output_set_video_encoder(obs_output_t *output, obs_encoder_t *encoder) { if (!obs_output_valid(output, "obs_output_set_video_encoder")) return; if (encoder && encoder->info.type != OBS_ENCODER_VIDEO) { blog(LOG_WARNING, "obs_output_set_video_encoder: " "encoder passed is not a video encoder"); return; } if (output->video_encoder == encoder) return; obs_encoder_remove_output(output->video_encoder, output); obs_encoder_add_output(encoder, output); output->video_encoder = encoder; /* set the preferred resolution on the encoder */ if (output->scaled_width && output->scaled_height) obs_encoder_set_scaled_size(output->video_encoder, output->scaled_width, output->scaled_height); }
bool obs_output_start(obs_output_t *output) { bool encoded; if (!obs_output_valid(output, "obs_output_start")) return false; if (!output->context.data) return false; encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0; if (encoded && output->delay_sec) { return obs_output_delay_start(output); } else { if (obs_output_actual_start(output)) { do_output_signal(output, "starting"); return true; } return false; } }
void obs_output_stop(obs_output_t *output) { bool encoded; if (!obs_output_valid(output, "obs_output_stop")) return; if (!output->context.data) return; if (!active(output) && !reconnecting(output)) return; if (reconnecting(output)) { obs_output_force_stop(output); return; } encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0; if (encoded && output->active_delay_ns) { obs_output_delay_stop(output); } else if (!stopping(output)) { do_output_signal(output, "stopping"); obs_output_actual_stop(output, false, os_gettime_ns()); } }
void obs_output_set_preferred_size(obs_output_t *output, uint32_t width, uint32_t height) { if (!obs_output_valid(output, "obs_output_set_preferred_size")) return; if ((output->info.flags & OBS_OUTPUT_VIDEO) == 0) return; if (active(output)) { blog(LOG_WARNING, "output '%s': Cannot set the preferred " "resolution while the output is active", obs_output_get_name(output)); return; } output->scaled_width = width; output->scaled_height = height; if (output->info.flags & OBS_OUTPUT_ENCODED) { if (output->video_encoder) obs_encoder_set_scaled_size(output->video_encoder, width, height); } }