libobs: Add multi-track support to non-encoded outputs
parent
8b98568bbc
commit
b8a3ae1b10
|
@ -117,6 +117,18 @@ Output Definition Structure (obs_output_info)
|
|||
This is called when the output recieves raw audio data. Only applies
|
||||
to outputs that are not encoded.
|
||||
|
||||
**This callback must be used with single-track raw outputs.**
|
||||
|
||||
:param frames: The raw audio frames
|
||||
|
||||
.. member:: void (*obs_output_info.raw_audio2)(void *data, size_t idx, struct audio_data *frames)
|
||||
|
||||
This is called when the output recieves raw audio data. Only applies
|
||||
to outputs that are not encoded.
|
||||
|
||||
**This callback must be used with multi-track raw outputs.**
|
||||
|
||||
:param idx: The audio track index
|
||||
:param frames: The raw audio frames
|
||||
|
||||
.. member:: void (*obs_output_info.encoded_packet)(void *data, struct encoder_packet *packet)
|
||||
|
@ -472,7 +484,19 @@ General Output Functions
|
|||
.. function:: void obs_output_set_mixer(obs_output_t *output, size_t mixer_idx)
|
||||
size_t obs_output_get_mixer(const obs_output_t *output)
|
||||
|
||||
Sets/gets the current audio mixer for non-encoded outputs.
|
||||
Sets/gets the current audio mixer for non-encoded outputs. For
|
||||
multi-track outputs, this would be the equivalent of setting the mask
|
||||
only for the specified mixer index.
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: void obs_output_set_mixers(obs_output_t *output, size_t mixers)
|
||||
size_t obs_output_get_mixers(const obs_output_t *output)
|
||||
|
||||
Sets/gets the current audio mixers (via mask) for non-encoded
|
||||
multi-track outputs. If used with single-track outputs, the
|
||||
single-track output will use either the first set mixer track in the
|
||||
bitmask, or the first track if none is set in the bitmask.
|
||||
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -863,7 +863,7 @@ struct obs_output {
|
|||
obs_encoder_t *video_encoder;
|
||||
obs_encoder_t *audio_encoders[MAX_AUDIO_MIXES];
|
||||
obs_service_t *service;
|
||||
size_t mixer_idx;
|
||||
size_t mixer_mask;
|
||||
|
||||
uint32_t scaled_width;
|
||||
uint32_t scaled_height;
|
||||
|
|
|
@ -675,9 +675,15 @@ void obs_register_output_s(const struct obs_output_info *info, size_t size)
|
|||
CHECK_REQUIRED_VAL_(info, raw_video,
|
||||
obs_register_output);
|
||||
|
||||
if (info->flags & OBS_OUTPUT_AUDIO)
|
||||
CHECK_REQUIRED_VAL_(info, raw_audio,
|
||||
obs_register_output);
|
||||
if (info->flags & OBS_OUTPUT_AUDIO) {
|
||||
if (info->flags & OBS_OUTPUT_MULTI_TRACK) {
|
||||
CHECK_REQUIRED_VAL_(info, raw_audio2,
|
||||
obs_register_output);
|
||||
} else {
|
||||
CHECK_REQUIRED_VAL_(info, raw_audio,
|
||||
obs_register_output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef CHECK_REQUIRED_VAL_
|
||||
|
||||
|
|
|
@ -544,19 +544,46 @@ audio_t *obs_output_audio(const obs_output_t *output)
|
|||
output->audio : NULL;
|
||||
}
|
||||
|
||||
static inline size_t get_first_mixer(const obs_output_t *output)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||
if ((((size_t)1 << i) & output->mixer_mask) != 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
output->mixer_mask = (size_t)1 << mixer_idx;
|
||||
}
|
||||
|
||||
size_t obs_output_get_mixer(const obs_output_t *output)
|
||||
{
|
||||
return obs_output_valid(output, "obs_output_get_mixer") ?
|
||||
output->mixer_idx : 0;
|
||||
if (!obs_output_valid(output, "obs_output_get_mixer"))
|
||||
return 0;
|
||||
|
||||
return get_first_mixer(output);
|
||||
}
|
||||
|
||||
void obs_output_set_mixers(obs_output_t *output, size_t mixers)
|
||||
{
|
||||
if (!obs_output_valid(output, "obs_output_set_mixers"))
|
||||
return;
|
||||
|
||||
output->mixer_mask = mixers;
|
||||
}
|
||||
|
||||
size_t obs_output_get_mixers(const obs_output_t *output)
|
||||
{
|
||||
return obs_output_valid(output, "obs_output_get_mixers") ?
|
||||
output->mixer_mask : 0;
|
||||
}
|
||||
|
||||
void obs_output_remove_encoder(struct obs_output *output,
|
||||
|
@ -1476,6 +1503,7 @@ static void default_raw_video_callback(void *param, struct video_data *frame)
|
|||
output->total_frames++;
|
||||
}
|
||||
|
||||
|
||||
static void default_raw_audio_callback(void *param, size_t mix_idx,
|
||||
struct audio_data *frames)
|
||||
{
|
||||
|
@ -1483,9 +1511,10 @@ static void default_raw_audio_callback(void *param, size_t mix_idx,
|
|||
if (!data_active(output))
|
||||
return;
|
||||
|
||||
output->info.raw_audio(output->context.data, frames);
|
||||
|
||||
UNUSED_PARAMETER(mix_idx);
|
||||
if (output->info.raw_audio2)
|
||||
output->info.raw_audio2(output->context.data, mix_idx, frames);
|
||||
else
|
||||
output->info.raw_audio(output->context.data, frames);
|
||||
}
|
||||
|
||||
static inline void start_audio_encoders(struct obs_output *output,
|
||||
|
@ -1499,6 +1528,25 @@ static inline void start_audio_encoders(struct obs_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void start_raw_audio(obs_output_t *output)
|
||||
{
|
||||
if (output->info.raw_audio2) {
|
||||
for (int idx = 0; idx < MAX_AUDIO_MIXES; idx++) {
|
||||
if ((output->mixer_mask & ((size_t)1 << idx)) != 0) {
|
||||
audio_output_connect(output->audio, idx,
|
||||
get_audio_conversion(output),
|
||||
default_raw_audio_callback,
|
||||
output);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
audio_output_connect(output->audio, get_first_mixer(output),
|
||||
get_audio_conversion(output),
|
||||
default_raw_audio_callback,
|
||||
output);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_packet_data(obs_output_t *output)
|
||||
{
|
||||
output->received_audio = false;
|
||||
|
@ -1557,9 +1605,7 @@ static void hook_data_capture(struct obs_output *output, bool encoded,
|
|||
get_video_conversion(output),
|
||||
default_raw_video_callback, output);
|
||||
if (has_audio)
|
||||
audio_output_connect(output->audio, output->mixer_idx,
|
||||
get_audio_conversion(output),
|
||||
default_raw_audio_callback, output);
|
||||
start_raw_audio(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1786,6 +1832,25 @@ static inline void stop_audio_encoders(obs_output_t *output,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void stop_raw_audio(obs_output_t *output)
|
||||
{
|
||||
if (output->info.raw_audio2) {
|
||||
for (int idx = 0; idx < MAX_AUDIO_MIXES; idx++) {
|
||||
if ((output->mixer_mask & ((size_t)1 << idx)) != 0) {
|
||||
audio_output_disconnect(output->audio,
|
||||
idx,
|
||||
default_raw_audio_callback,
|
||||
output);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
audio_output_disconnect(output->audio,
|
||||
get_first_mixer(output),
|
||||
default_raw_audio_callback,
|
||||
output);
|
||||
}
|
||||
}
|
||||
|
||||
static void *end_data_capture_thread(void *data)
|
||||
{
|
||||
bool encoded, has_video, has_audio, has_service;
|
||||
|
@ -1812,9 +1877,7 @@ static void *end_data_capture_thread(void *data)
|
|||
stop_raw_video(output->video,
|
||||
default_raw_video_callback, output);
|
||||
if (has_audio)
|
||||
audio_output_disconnect(output->audio,
|
||||
output->mixer_idx,
|
||||
default_raw_audio_callback, output);
|
||||
stop_raw_audio(output);
|
||||
}
|
||||
|
||||
if (has_service)
|
||||
|
|
|
@ -71,6 +71,9 @@ struct obs_output_info {
|
|||
/* only used with encoded outputs, separated with semicolon */
|
||||
const char *encoded_video_codecs;
|
||||
const char *encoded_audio_codecs;
|
||||
|
||||
/* raw audio callback for multi track outputs */
|
||||
void (*raw_audio2)(void *data, size_t idx, struct audio_data *frames);
|
||||
};
|
||||
|
||||
EXPORT void obs_register_output_s(const struct obs_output_info *info,
|
||||
|
|
|
@ -1632,6 +1632,12 @@ EXPORT void obs_output_set_mixer(obs_output_t *output, size_t mixer_idx);
|
|||
/** Gets the current audio mixer for non-encoded outputs */
|
||||
EXPORT size_t obs_output_get_mixer(const obs_output_t *output);
|
||||
|
||||
/** Sets the current audio mixes (mask) for a non-encoded multi-track output */
|
||||
EXPORT void obs_output_set_mixers(obs_output_t *output, size_t mixers);
|
||||
|
||||
/** Gets the current audio mixes (mask) for a non-encoded multi-track output */
|
||||
EXPORT size_t obs_output_get_mixers(const obs_output_t *output);
|
||||
|
||||
/**
|
||||
* Sets the current video encoder associated with this output,
|
||||
* required for encoded outputs
|
||||
|
|
Loading…
Reference in New Issue