提交 b8a3ae1b 编写于 作者: J jp9000

libobs: Add multi-track support to non-encoded outputs

上级 8b98568b
...@@ -117,6 +117,18 @@ Output Definition Structure (obs_output_info) ...@@ -117,6 +117,18 @@ Output Definition Structure (obs_output_info)
This is called when the output recieves raw audio data. Only applies This is called when the output recieves raw audio data. Only applies
to outputs that are not encoded. 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 :param frames: The raw audio frames
.. member:: void (*obs_output_info.encoded_packet)(void *data, struct encoder_packet *packet) .. member:: void (*obs_output_info.encoded_packet)(void *data, struct encoder_packet *packet)
...@@ -472,7 +484,19 @@ General Output Functions ...@@ -472,7 +484,19 @@ General Output Functions
.. function:: void obs_output_set_mixer(obs_output_t *output, size_t mixer_idx) .. 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) 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 { ...@@ -863,7 +863,7 @@ struct obs_output {
obs_encoder_t *video_encoder; obs_encoder_t *video_encoder;
obs_encoder_t *audio_encoders[MAX_AUDIO_MIXES]; obs_encoder_t *audio_encoders[MAX_AUDIO_MIXES];
obs_service_t *service; obs_service_t *service;
size_t mixer_idx; size_t mixer_mask;
uint32_t scaled_width; uint32_t scaled_width;
uint32_t scaled_height; uint32_t scaled_height;
......
...@@ -675,10 +675,16 @@ void obs_register_output_s(const struct obs_output_info *info, size_t size) ...@@ -675,10 +675,16 @@ void obs_register_output_s(const struct obs_output_info *info, size_t size)
CHECK_REQUIRED_VAL_(info, raw_video, CHECK_REQUIRED_VAL_(info, raw_video,
obs_register_output); obs_register_output);
if (info->flags & OBS_OUTPUT_AUDIO) 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, CHECK_REQUIRED_VAL_(info, raw_audio,
obs_register_output); obs_register_output);
} }
}
}
#undef CHECK_REQUIRED_VAL_ #undef CHECK_REQUIRED_VAL_
REGISTER_OBS_DEF(size, obs_output_info, obs->output_types, info); REGISTER_OBS_DEF(size, obs_output_info, obs->output_types, info);
......
...@@ -544,19 +544,46 @@ audio_t *obs_output_audio(const obs_output_t *output) ...@@ -544,19 +544,46 @@ audio_t *obs_output_audio(const obs_output_t *output)
output->audio : NULL; 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) void obs_output_set_mixer(obs_output_t *output, size_t mixer_idx)
{ {
if (!obs_output_valid(output, "obs_output_set_mixer")) if (!obs_output_valid(output, "obs_output_set_mixer"))
return; return;
if (!active(output)) 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) size_t obs_output_get_mixer(const obs_output_t *output)
{ {
return obs_output_valid(output, "obs_output_get_mixer") ? if (!obs_output_valid(output, "obs_output_get_mixer"))
output->mixer_idx : 0; 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, 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) ...@@ -1476,6 +1503,7 @@ static void default_raw_video_callback(void *param, struct video_data *frame)
output->total_frames++; output->total_frames++;
} }
static void default_raw_audio_callback(void *param, size_t mix_idx, static void default_raw_audio_callback(void *param, size_t mix_idx,
struct audio_data *frames) struct audio_data *frames)
{ {
...@@ -1483,9 +1511,10 @@ static void default_raw_audio_callback(void *param, size_t mix_idx, ...@@ -1483,9 +1511,10 @@ static void default_raw_audio_callback(void *param, size_t mix_idx,
if (!data_active(output)) if (!data_active(output))
return; return;
if (output->info.raw_audio2)
output->info.raw_audio2(output->context.data, mix_idx, frames);
else
output->info.raw_audio(output->context.data, frames); output->info.raw_audio(output->context.data, frames);
UNUSED_PARAMETER(mix_idx);
} }
static inline void start_audio_encoders(struct obs_output *output, static inline void start_audio_encoders(struct obs_output *output,
...@@ -1499,6 +1528,25 @@ 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) static void reset_packet_data(obs_output_t *output)
{ {
output->received_audio = false; output->received_audio = false;
...@@ -1557,9 +1605,7 @@ static void hook_data_capture(struct obs_output *output, bool encoded, ...@@ -1557,9 +1605,7 @@ static void hook_data_capture(struct obs_output *output, bool encoded,
get_video_conversion(output), get_video_conversion(output),
default_raw_video_callback, output); default_raw_video_callback, output);
if (has_audio) if (has_audio)
audio_output_connect(output->audio, output->mixer_idx, start_raw_audio(output);
get_audio_conversion(output),
default_raw_audio_callback, output);
} }
} }
...@@ -1786,6 +1832,25 @@ static inline void stop_audio_encoders(obs_output_t *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) static void *end_data_capture_thread(void *data)
{ {
bool encoded, has_video, has_audio, has_service; bool encoded, has_video, has_audio, has_service;
...@@ -1812,9 +1877,7 @@ static void *end_data_capture_thread(void *data) ...@@ -1812,9 +1877,7 @@ static void *end_data_capture_thread(void *data)
stop_raw_video(output->video, stop_raw_video(output->video,
default_raw_video_callback, output); default_raw_video_callback, output);
if (has_audio) if (has_audio)
audio_output_disconnect(output->audio, stop_raw_audio(output);
output->mixer_idx,
default_raw_audio_callback, output);
} }
if (has_service) if (has_service)
......
...@@ -71,6 +71,9 @@ struct obs_output_info { ...@@ -71,6 +71,9 @@ struct obs_output_info {
/* only used with encoded outputs, separated with semicolon */ /* only used with encoded outputs, separated with semicolon */
const char *encoded_video_codecs; const char *encoded_video_codecs;
const char *encoded_audio_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, 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); ...@@ -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 */ /** Gets the current audio mixer for non-encoded outputs */
EXPORT size_t obs_output_get_mixer(const obs_output_t *output); 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, * Sets the current video encoder associated with this output,
* required for encoded outputs * required for encoded outputs
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册