mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-19 09:39:15 +00:00
libobs: Refactor obs-output encoded use of mixes
There was quite a bit of conflated usage of mixes (which refers to raw audio) and encoder counts. This fully separates the two and makes a distinct separation when iterating over mixes vs encoders.
This commit is contained in:
parent
d70171daa6
commit
61284cf9ba
|
@ -1024,7 +1024,7 @@ struct obs_output {
|
||||||
volatile bool data_active;
|
volatile bool data_active;
|
||||||
volatile bool end_data_capture_thread_active;
|
volatile bool end_data_capture_thread_active;
|
||||||
int64_t video_offset;
|
int64_t video_offset;
|
||||||
int64_t audio_offsets[MAX_AUDIO_MIXES];
|
int64_t audio_offsets[MAX_OUTPUT_AUDIO_ENCODERS];
|
||||||
int64_t highest_audio_ts;
|
int64_t highest_audio_ts;
|
||||||
int64_t highest_video_ts;
|
int64_t highest_video_ts;
|
||||||
pthread_t end_data_capture_thread;
|
pthread_t end_data_capture_thread;
|
||||||
|
@ -1054,7 +1054,7 @@ struct obs_output {
|
||||||
video_t *video;
|
video_t *video;
|
||||||
audio_t *audio;
|
audio_t *audio;
|
||||||
obs_encoder_t *video_encoder;
|
obs_encoder_t *video_encoder;
|
||||||
obs_encoder_t *audio_encoders[MAX_AUDIO_MIXES];
|
obs_encoder_t *audio_encoders[MAX_OUTPUT_AUDIO_ENCODERS];
|
||||||
obs_service_t *service;
|
obs_service_t *service;
|
||||||
size_t mixer_mask;
|
size_t mixer_mask;
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ static inline void free_packets(struct obs_output *output)
|
||||||
da_free(output->interleaved_packets);
|
da_free(output->interleaved_packets);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void clear_audio_buffers(obs_output_t *output)
|
static inline void clear_raw_audio_buffers(obs_output_t *output)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||||
for (size_t j = 0; j < MAX_AV_PLANES; j++) {
|
for (size_t j = 0; j < MAX_AV_PLANES; j++) {
|
||||||
|
@ -215,14 +215,14 @@ void obs_output_destroy(obs_output_t *output)
|
||||||
output);
|
output);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (output->audio_encoders[i]) {
|
if (output->audio_encoders[i]) {
|
||||||
obs_encoder_remove_output(
|
obs_encoder_remove_output(
|
||||||
output->audio_encoders[i], output);
|
output->audio_encoders[i], output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_audio_buffers(output);
|
clear_raw_audio_buffers(output);
|
||||||
|
|
||||||
os_event_destroy(output->stopping_event);
|
os_event_destroy(output->stopping_event);
|
||||||
pthread_mutex_destroy(&output->pause.mutex);
|
pthread_mutex_destroy(&output->pause.mutex);
|
||||||
|
@ -572,16 +572,16 @@ static inline bool pause_can_stop(struct pause_data *pause)
|
||||||
static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
||||||
{
|
{
|
||||||
obs_encoder_t *venc;
|
obs_encoder_t *venc;
|
||||||
obs_encoder_t *aenc[MAX_AUDIO_MIXES];
|
obs_encoder_t *aenc[MAX_OUTPUT_AUDIO_ENCODERS];
|
||||||
uint64_t closest_v_ts;
|
uint64_t closest_v_ts;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
venc = output->video_encoder;
|
venc = output->video_encoder;
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++)
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++)
|
||||||
aenc[i] = output->audio_encoders[i];
|
aenc[i] = output->audio_encoders[i];
|
||||||
|
|
||||||
pthread_mutex_lock(&venc->pause.mutex);
|
pthread_mutex_lock(&venc->pause.mutex);
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (aenc[i]) {
|
if (aenc[i]) {
|
||||||
pthread_mutex_lock(&aenc[i]->pause.mutex);
|
pthread_mutex_lock(&aenc[i]->pause.mutex);
|
||||||
}
|
}
|
||||||
|
@ -595,7 +595,7 @@ static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
||||||
if (!pause_can_start(&venc->pause)) {
|
if (!pause_can_start(&venc->pause)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (aenc[i] && !pause_can_start(&aenc[i]->pause)) {
|
if (aenc[i] && !pause_can_start(&aenc[i]->pause)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -604,7 +604,7 @@ static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
||||||
os_atomic_set_bool(&venc->paused, true);
|
os_atomic_set_bool(&venc->paused, true);
|
||||||
venc->pause.ts_start = closest_v_ts;
|
venc->pause.ts_start = closest_v_ts;
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (aenc[i]) {
|
if (aenc[i]) {
|
||||||
os_atomic_set_bool(&aenc[i]->paused, true);
|
os_atomic_set_bool(&aenc[i]->paused, true);
|
||||||
aenc[i]->pause.ts_start = closest_v_ts;
|
aenc[i]->pause.ts_start = closest_v_ts;
|
||||||
|
@ -614,7 +614,7 @@ static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
||||||
if (!pause_can_stop(&venc->pause)) {
|
if (!pause_can_stop(&venc->pause)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (aenc[i] && !pause_can_stop(&aenc[i]->pause)) {
|
if (aenc[i] && !pause_can_stop(&aenc[i]->pause)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +623,7 @@ static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
||||||
os_atomic_set_bool(&venc->paused, false);
|
os_atomic_set_bool(&venc->paused, false);
|
||||||
end_pause(&venc->pause, closest_v_ts);
|
end_pause(&venc->pause, closest_v_ts);
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (aenc[i]) {
|
if (aenc[i]) {
|
||||||
os_atomic_set_bool(&aenc[i]->paused, false);
|
os_atomic_set_bool(&aenc[i]->paused, false);
|
||||||
end_pause(&aenc[i]->pause, closest_v_ts);
|
end_pause(&aenc[i]->pause, closest_v_ts);
|
||||||
|
@ -636,7 +636,7 @@ static bool obs_encoded_output_pause(obs_output_t *output, bool pause)
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
for (size_t i = MAX_AUDIO_MIXES; i > 0; i--) {
|
for (size_t i = MAX_OUTPUT_AUDIO_ENCODERS; i > 0; i--) {
|
||||||
if (aenc[i - 1]) {
|
if (aenc[i - 1]) {
|
||||||
pthread_mutex_unlock(&aenc[i - 1]->pause.mutex);
|
pthread_mutex_unlock(&aenc[i - 1]->pause.mutex);
|
||||||
}
|
}
|
||||||
|
@ -801,8 +801,9 @@ void obs_output_remove_encoder_internal(struct obs_output *output,
|
||||||
if (output->video_encoder == encoder) {
|
if (output->video_encoder == encoder) {
|
||||||
output->video_encoder = NULL;
|
output->video_encoder = NULL;
|
||||||
} else {
|
} else {
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (output->audio_encoders[i] == encoder)
|
obs_encoder_t *audio = output->audio_encoders[i];
|
||||||
|
if (audio == encoder)
|
||||||
output->audio_encoders[i] = NULL;
|
output->audio_encoders[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -870,7 +871,7 @@ void obs_output_set_audio_encoder(obs_output_t *output, obs_encoder_t *encoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
|
if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
|
||||||
if (idx >= MAX_AUDIO_MIXES) {
|
if (idx >= MAX_OUTPUT_AUDIO_ENCODERS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -900,15 +901,8 @@ obs_encoder_t *obs_output_get_audio_encoder(const obs_output_t *output,
|
||||||
if (!obs_output_valid(output, "obs_output_get_audio_encoder"))
|
if (!obs_output_valid(output, "obs_output_get_audio_encoder"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
|
if (idx >= MAX_OUTPUT_AUDIO_ENCODERS)
|
||||||
if (idx >= MAX_AUDIO_MIXES) {
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (idx > 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output->audio_encoders[idx];
|
return output->audio_encoders[idx];
|
||||||
}
|
}
|
||||||
|
@ -1054,42 +1048,18 @@ void obs_output_set_audio_conversion(
|
||||||
output->audio_conversion_set = true;
|
output->audio_conversion_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t num_audio_mixes(const struct obs_output *output)
|
|
||||||
{
|
|
||||||
size_t mix_count = 1;
|
|
||||||
|
|
||||||
if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
|
|
||||||
mix_count = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
|
||||||
if (!output->audio_encoders[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
mix_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mix_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool audio_valid(const struct obs_output *output, bool encoded)
|
static inline bool audio_valid(const struct obs_output *output, bool encoded)
|
||||||
{
|
{
|
||||||
if (encoded) {
|
if (encoded) {
|
||||||
size_t mix_count = num_audio_mixes(output);
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (!mix_count)
|
if (output->audio_encoders[i]) {
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
for (size_t i = 0; i < mix_count; i++) {
|
|
||||||
if (!output->audio_encoders[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
return false;
|
||||||
if (!output->audio)
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return output->audio != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool can_begin_data_capture(const struct obs_output *output,
|
static bool can_begin_data_capture(const struct obs_output *output,
|
||||||
|
@ -1166,10 +1136,10 @@ get_audio_conversion(struct obs_output *output)
|
||||||
static size_t get_track_index(const struct obs_output *output,
|
static size_t get_track_index(const struct obs_output *output,
|
||||||
struct encoder_packet *pkt)
|
struct encoder_packet *pkt)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
struct obs_encoder *encoder = output->audio_encoders[i];
|
struct obs_encoder *encoder = output->audio_encoders[i];
|
||||||
|
|
||||||
if (pkt->encoder == encoder)
|
if (encoder && pkt->encoder == encoder)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,7 +1390,6 @@ static size_t get_interleaved_start_idx(struct obs_output *output)
|
||||||
|
|
||||||
static int prune_premature_packets(struct obs_output *output)
|
static int prune_premature_packets(struct obs_output *output)
|
||||||
{
|
{
|
||||||
size_t audio_mixes = num_audio_mixes(output);
|
|
||||||
struct encoder_packet *video;
|
struct encoder_packet *video;
|
||||||
int video_idx;
|
int video_idx;
|
||||||
int max_idx;
|
int max_idx;
|
||||||
|
@ -1438,10 +1407,13 @@ static int prune_premature_packets(struct obs_output *output)
|
||||||
video = &output->interleaved_packets.array[video_idx];
|
video = &output->interleaved_packets.array[video_idx];
|
||||||
duration_usec = video->timebase_num * 1000000LL / video->timebase_den;
|
duration_usec = video->timebase_num * 1000000LL / video->timebase_den;
|
||||||
|
|
||||||
for (size_t i = 0; i < audio_mixes; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
struct encoder_packet *audio;
|
struct encoder_packet *audio;
|
||||||
int audio_idx;
|
int audio_idx;
|
||||||
|
|
||||||
|
if (!output->audio_encoders[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
audio_idx = find_first_packet_type_idx(output,
|
audio_idx = find_first_packet_type_idx(output,
|
||||||
OBS_ENCODER_AUDIO, i);
|
OBS_ENCODER_AUDIO, i);
|
||||||
if (audio_idx == -1) {
|
if (audio_idx == -1) {
|
||||||
|
@ -1565,18 +1537,20 @@ find_last_packet_type(struct obs_output *output, enum obs_encoder_type type,
|
||||||
|
|
||||||
static bool get_audio_and_video_packets(struct obs_output *output,
|
static bool get_audio_and_video_packets(struct obs_output *output,
|
||||||
struct encoder_packet **video,
|
struct encoder_packet **video,
|
||||||
struct encoder_packet **audio,
|
struct encoder_packet **audio)
|
||||||
size_t audio_mixes)
|
|
||||||
{
|
{
|
||||||
*video = find_first_packet_type(output, OBS_ENCODER_VIDEO, 0);
|
*video = find_first_packet_type(output, OBS_ENCODER_VIDEO, 0);
|
||||||
if (!*video)
|
if (!*video)
|
||||||
output->received_video = false;
|
output->received_video = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < audio_mixes; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
audio[i] = find_first_packet_type(output, OBS_ENCODER_AUDIO, i);
|
if (output->audio_encoders[i]) {
|
||||||
if (!audio[i]) {
|
audio[i] = find_first_packet_type(output,
|
||||||
output->received_audio = false;
|
OBS_ENCODER_AUDIO, i);
|
||||||
return false;
|
if (!audio[i]) {
|
||||||
|
output->received_audio = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,26 +1561,50 @@ static bool get_audio_and_video_packets(struct obs_output *output,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_first_audio_encoder_index(const struct obs_output *output,
|
||||||
|
size_t *index)
|
||||||
|
{
|
||||||
|
if (!index)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
|
if (output->audio_encoders[i]) {
|
||||||
|
*index = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool initialize_interleaved_packets(struct obs_output *output)
|
static bool initialize_interleaved_packets(struct obs_output *output)
|
||||||
{
|
{
|
||||||
struct encoder_packet *video;
|
struct encoder_packet *video;
|
||||||
struct encoder_packet *audio[MAX_AUDIO_MIXES];
|
struct encoder_packet *audio[MAX_OUTPUT_AUDIO_ENCODERS];
|
||||||
struct encoder_packet *last_audio[MAX_AUDIO_MIXES];
|
struct encoder_packet *last_audio[MAX_OUTPUT_AUDIO_ENCODERS];
|
||||||
size_t audio_mixes = num_audio_mixes(output);
|
|
||||||
size_t start_idx;
|
size_t start_idx;
|
||||||
|
size_t first_audio_idx;
|
||||||
|
|
||||||
if (!get_audio_and_video_packets(output, &video, audio, audio_mixes))
|
if (!get_first_audio_encoder_index(output, &first_audio_idx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < audio_mixes; i++)
|
if (!get_audio_and_video_packets(output, &video, audio))
|
||||||
last_audio[i] =
|
return false;
|
||||||
find_last_packet_type(output, OBS_ENCODER_AUDIO, i);
|
|
||||||
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
|
if (output->audio_encoders[i]) {
|
||||||
|
last_audio[i] = find_last_packet_type(
|
||||||
|
output, OBS_ENCODER_AUDIO, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ensure that there is audio past the first video packet */
|
/* ensure that there is audio past the first video packet */
|
||||||
for (size_t i = 0; i < audio_mixes; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (last_audio[i]->dts_usec < video->dts_usec) {
|
if (output->audio_encoders[i]) {
|
||||||
output->received_audio = false;
|
if (last_audio[i]->dts_usec < video->dts_usec) {
|
||||||
return false;
|
output->received_audio = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1614,19 +1612,20 @@ static bool initialize_interleaved_packets(struct obs_output *output)
|
||||||
start_idx = get_interleaved_start_idx(output);
|
start_idx = get_interleaved_start_idx(output);
|
||||||
if (start_idx) {
|
if (start_idx) {
|
||||||
discard_to_idx(output, start_idx);
|
discard_to_idx(output, start_idx);
|
||||||
if (!get_audio_and_video_packets(output, &video, audio,
|
if (!get_audio_and_video_packets(output, &video, audio))
|
||||||
audio_mixes))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get new offsets */
|
/* get new offsets */
|
||||||
output->video_offset = video->pts;
|
output->video_offset = video->pts;
|
||||||
for (size_t i = 0; i < audio_mixes; i++)
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
output->audio_offsets[i] = audio[i]->dts;
|
if (output->audio_encoders[i]) {
|
||||||
|
output->audio_offsets[i] = audio[i]->dts;
|
||||||
|
}
|
||||||
|
}
|
||||||
#if DEBUG_STARTING_PACKETS == 1
|
#if DEBUG_STARTING_PACKETS == 1
|
||||||
int64_t v = video->dts_usec;
|
int64_t v = video->dts_usec;
|
||||||
int64_t a = audio[0]->dts_usec;
|
int64_t a = audio[first_audio_idx]->dts_usec;
|
||||||
int64_t diff = v - a;
|
int64_t diff = v - a;
|
||||||
|
|
||||||
blog(LOG_DEBUG,
|
blog(LOG_DEBUG,
|
||||||
|
@ -1636,7 +1635,7 @@ static bool initialize_interleaved_packets(struct obs_output *output)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* subtract offsets from highest TS offset variables */
|
/* subtract offsets from highest TS offset variables */
|
||||||
output->highest_audio_ts -= audio[0]->dts_usec;
|
output->highest_audio_ts -= audio[first_audio_idx]->dts_usec;
|
||||||
output->highest_video_ts -= video->dts_usec;
|
output->highest_video_ts -= video->dts_usec;
|
||||||
|
|
||||||
/* apply new offsets to all existing packet DTS/PTS values */
|
/* apply new offsets to all existing packet DTS/PTS values */
|
||||||
|
@ -1885,11 +1884,11 @@ static void default_raw_audio_callback(void *param, size_t mix_idx,
|
||||||
static inline void start_audio_encoders(struct obs_output *output,
|
static inline void start_audio_encoders(struct obs_output *output,
|
||||||
encoded_callback_t encoded_callback)
|
encoded_callback_t encoded_callback)
|
||||||
{
|
{
|
||||||
size_t num_mixes = num_audio_mixes(output);
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
|
if (output->audio_encoders[i]) {
|
||||||
for (size_t i = 0; i < num_mixes; i++) {
|
obs_encoder_start(output->audio_encoders[i],
|
||||||
obs_encoder_start(output->audio_encoders[i], encoded_callback,
|
encoded_callback, output);
|
||||||
output);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1919,7 +1918,7 @@ static void reset_packet_data(obs_output_t *output)
|
||||||
output->highest_video_ts = 0;
|
output->highest_video_ts = 0;
|
||||||
output->video_offset = 0;
|
output->video_offset = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++)
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++)
|
||||||
output->audio_offsets[i] = 0;
|
output->audio_offsets[i] = 0;
|
||||||
|
|
||||||
free_packets(output);
|
free_packets(output);
|
||||||
|
@ -2049,14 +2048,14 @@ bool obs_output_can_begin_data_capture(const obs_output_t *output,
|
||||||
has_service);
|
has_service);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool initialize_audio_encoders(obs_output_t *output,
|
static inline bool initialize_audio_encoders(obs_output_t *output)
|
||||||
size_t num_mixes)
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < num_mixes; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
if (!obs_encoder_initialize(output->audio_encoders[i])) {
|
obs_encoder_t *audio = output->audio_encoders[i];
|
||||||
|
|
||||||
|
if (audio && !obs_encoder_initialize(audio)) {
|
||||||
obs_output_set_last_error(
|
obs_output_set_last_error(
|
||||||
output, obs_encoder_get_last_error(
|
output, obs_encoder_get_last_error(audio));
|
||||||
output->audio_encoders[i]));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2064,10 +2063,9 @@ static inline bool initialize_audio_encoders(obs_output_t *output,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline obs_encoder_t *find_inactive_audio_encoder(obs_output_t *output,
|
static inline obs_encoder_t *find_inactive_audio_encoder(obs_output_t *output)
|
||||||
size_t num_mixes)
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < num_mixes; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
struct obs_encoder *audio = output->audio_encoders[i];
|
struct obs_encoder *audio = output->audio_encoders[i];
|
||||||
|
|
||||||
if (audio && !audio->active && !audio->paired_encoder)
|
if (audio && !audio->active && !audio->paired_encoder)
|
||||||
|
@ -2077,11 +2075,10 @@ static inline obs_encoder_t *find_inactive_audio_encoder(obs_output_t *output,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pair_encoders(obs_output_t *output, size_t num_mixes)
|
static inline void pair_encoders(obs_output_t *output)
|
||||||
{
|
{
|
||||||
struct obs_encoder *video = output->video_encoder;
|
struct obs_encoder *video = output->video_encoder;
|
||||||
struct obs_encoder *audio =
|
struct obs_encoder *audio = find_inactive_audio_encoder(output);
|
||||||
find_inactive_audio_encoder(output, num_mixes);
|
|
||||||
|
|
||||||
if (video && audio) {
|
if (video && audio) {
|
||||||
pthread_mutex_lock(&audio->init_mutex);
|
pthread_mutex_lock(&audio->init_mutex);
|
||||||
|
@ -2103,7 +2100,6 @@ static inline void pair_encoders(obs_output_t *output, size_t num_mixes)
|
||||||
bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags)
|
bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags)
|
||||||
{
|
{
|
||||||
bool encoded, has_video, has_audio, has_service;
|
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"))
|
if (!obs_output_valid(output, "obs_output_initialize_encoders"))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2122,7 +2118,7 @@ bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags)
|
||||||
obs_encoder_get_last_error(output->video_encoder));
|
obs_encoder_get_last_error(output->video_encoder));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (has_audio && !initialize_audio_encoders(output, num_mixes))
|
if (has_audio && !initialize_audio_encoders(output))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2150,7 +2146,7 @@ static bool begin_delayed_capture(obs_output_t *output)
|
||||||
|
|
||||||
static void reset_raw_output(obs_output_t *output)
|
static void reset_raw_output(obs_output_t *output)
|
||||||
{
|
{
|
||||||
clear_audio_buffers(output);
|
clear_raw_audio_buffers(output);
|
||||||
|
|
||||||
if (output->audio) {
|
if (output->audio) {
|
||||||
const struct audio_output_info *aoi =
|
const struct audio_output_info *aoi =
|
||||||
|
@ -2187,7 +2183,6 @@ static void reset_raw_output(obs_output_t *output)
|
||||||
bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags)
|
bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags)
|
||||||
{
|
{
|
||||||
bool encoded, has_video, has_audio, has_service;
|
bool encoded, has_video, has_audio, has_service;
|
||||||
size_t num_mixes;
|
|
||||||
|
|
||||||
if (!obs_output_valid(output, "obs_output_begin_data_capture"))
|
if (!obs_output_valid(output, "obs_output_begin_data_capture"))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2210,9 +2205,8 @@ bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags)
|
||||||
has_service))
|
has_service))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
num_mixes = num_audio_mixes(output);
|
|
||||||
if (has_video && has_audio)
|
if (has_video && has_audio)
|
||||||
pair_encoders(output, num_mixes);
|
pair_encoders(output);
|
||||||
|
|
||||||
os_atomic_set_bool(&output->data_active, true);
|
os_atomic_set_bool(&output->data_active, true);
|
||||||
hook_data_capture(output, encoded, has_video, has_audio);
|
hook_data_capture(output, encoded, has_video, has_audio);
|
||||||
|
@ -2240,11 +2234,10 @@ bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags)
|
||||||
static inline void stop_audio_encoders(obs_output_t *output,
|
static inline void stop_audio_encoders(obs_output_t *output,
|
||||||
encoded_callback_t encoded_callback)
|
encoded_callback_t encoded_callback)
|
||||||
{
|
{
|
||||||
size_t num_mixes = num_audio_mixes(output);
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
|
obs_encoder_t *audio = output->audio_encoders[i];
|
||||||
for (size_t i = 0; i < num_mixes; i++) {
|
if (audio)
|
||||||
obs_encoder_stop(output->audio_encoders[i], encoded_callback,
|
obs_encoder_stop(audio, encoded_callback, output);
|
||||||
output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2650,7 +2643,7 @@ const char *obs_output_get_last_error(obs_output_t *output)
|
||||||
return vencoder->last_error_message;
|
return vencoder->last_error_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
|
||||||
obs_encoder_t *aencoder = output->audio_encoders[i];
|
obs_encoder_t *aencoder = output->audio_encoders[i];
|
||||||
if (aencoder && aencoder->last_error_message) {
|
if (aencoder && aencoder->last_error_message) {
|
||||||
return aencoder->last_error_message;
|
return aencoder->last_error_message;
|
||||||
|
|
|
@ -29,6 +29,8 @@ extern "C" {
|
||||||
#define OBS_OUTPUT_MULTI_TRACK (1 << 4)
|
#define OBS_OUTPUT_MULTI_TRACK (1 << 4)
|
||||||
#define OBS_OUTPUT_CAN_PAUSE (1 << 5)
|
#define OBS_OUTPUT_CAN_PAUSE (1 << 5)
|
||||||
|
|
||||||
|
#define MAX_OUTPUT_AUDIO_ENCODERS 6
|
||||||
|
|
||||||
struct encoder_packet;
|
struct encoder_packet;
|
||||||
|
|
||||||
struct obs_output_info {
|
struct obs_output_info {
|
||||||
|
|
Loading…
Reference in a new issue