Add split Muninn OBS source types
This commit is contained in:
parent
e2461ee4ac
commit
bdf940ba73
3 changed files with 249 additions and 64 deletions
|
|
@ -3,6 +3,8 @@ MimirAudioStem.MapName="Shared memory map"
|
|||
MimirAudioStem.StemId="Stem id"
|
||||
MimirProgramTexture="Mimir Program Texture"
|
||||
MuninnStream="Muninn Stream"
|
||||
MuninnVideoSource="Muninn Video"
|
||||
MuninnAudioSource="Muninn Audio"
|
||||
MuninnStream.Stream="Muninn stream"
|
||||
MuninnStream.Video="Muninn video"
|
||||
MuninnStream.Audio="Muninn audio"
|
||||
|
|
|
|||
|
|
@ -71,6 +71,14 @@ constexpr uint32_t MuninnMaxRudpLatencyBudgetMs = 2000;
|
|||
constexpr uint32_t MuninnMaxRudpAudioReorderMs = 2000;
|
||||
constexpr size_t MuninnAudioReorderMaxPackets = 128;
|
||||
constexpr size_t MuninnAudioQueueMaxPackets = 32;
|
||||
constexpr const char *MuninnDisabledVideoSourceId = "video:none";
|
||||
constexpr const char *MuninnDisabledAudioSourceId = "audio:none";
|
||||
|
||||
enum class MuninnSourceKind {
|
||||
Combined,
|
||||
VideoOnly,
|
||||
AudioOnly,
|
||||
};
|
||||
|
||||
struct MuninnStreamOption {
|
||||
std::string stream_id;
|
||||
|
|
@ -96,6 +104,7 @@ struct MuninnQueuedAudio {
|
|||
};
|
||||
|
||||
struct MuninnSource {
|
||||
MuninnSourceKind kind = MuninnSourceKind::Combined;
|
||||
obs_source_t *source = nullptr;
|
||||
obs_source_t *media = nullptr;
|
||||
obs_source_t *audio_media = nullptr;
|
||||
|
|
@ -136,6 +145,16 @@ static void muninn_child_audio(void *param, obs_source_t *source, const struct a
|
|||
static void stop_audio_worker(MuninnSource *ctx);
|
||||
static std::string canonical_muninn_stream_id(const std::string &stream_id);
|
||||
|
||||
static bool source_wants_video(const MuninnSource *ctx)
|
||||
{
|
||||
return !ctx || ctx->kind != MuninnSourceKind::AudioOnly;
|
||||
}
|
||||
|
||||
static bool source_wants_audio(const MuninnSource *ctx)
|
||||
{
|
||||
return !ctx || ctx->kind != MuninnSourceKind::VideoOnly;
|
||||
}
|
||||
|
||||
struct RudpBridgeOutputs {
|
||||
std::string video_url;
|
||||
std::string audio_url;
|
||||
|
|
@ -2293,8 +2312,8 @@ static std::vector<uint8_t> encode_capture_stream_command_wire(const MuninnSourc
|
|||
record.write_string(observed_at);
|
||||
record.write_u64(ctx->rudp_video_bitrate_kbps);
|
||||
record.write_u64(ctx->rudp_latency_budget_ms);
|
||||
record.write_string(ctx->video_source_id);
|
||||
record.write_string(ctx->audio_source_id);
|
||||
record.write_string(source_wants_video(ctx) ? ctx->video_source_id : MuninnDisabledVideoSourceId);
|
||||
record.write_string(source_wants_audio(ctx) ? ctx->audio_source_id : MuninnDisabledAudioSourceId);
|
||||
|
||||
muninn_media_wire::MsgpackWriter document;
|
||||
document.write_map_len(9);
|
||||
|
|
@ -3182,19 +3201,33 @@ static obs_source_t *create_ffmpeg_child_source(MuninnSource *ctx,
|
|||
|
||||
static void create_or_update_media(MuninnSource *ctx, const std::string &url, bool force_restart = false)
|
||||
{
|
||||
const bool wants_video = source_wants_video(ctx);
|
||||
const bool wants_audio = source_wants_audio(ctx);
|
||||
if (url.empty()) {
|
||||
release_media(ctx);
|
||||
ctx->stream_url.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!force_restart && ctx->media && equivalent_rudp_stream_url(ctx->stream_url, url)) {
|
||||
if (!wants_video && !wants_audio) {
|
||||
release_media(ctx);
|
||||
ctx->stream_url.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!force_restart &&
|
||||
((wants_video && ctx->media) || (wants_audio && ctx->audio_decoder)) &&
|
||||
equivalent_rudp_stream_url(ctx->stream_url, url)) {
|
||||
ctx->stream_url = url;
|
||||
return;
|
||||
}
|
||||
|
||||
if (starts_with(url, "rudp://")) {
|
||||
if (!force_restart && ctx->bridge && ctx->media && ctx->audio_decoder && !ctx->stream_url.empty()) {
|
||||
if (!force_restart &&
|
||||
ctx->bridge &&
|
||||
(!wants_video || ctx->media) &&
|
||||
(!wants_audio || ctx->audio_decoder) &&
|
||||
!ctx->stream_url.empty()) {
|
||||
const auto previous_parts = muninn_rudp_url::parse(ctx->stream_url);
|
||||
const auto next_parts = muninn_rudp_url::parse(url);
|
||||
if (previous_parts && next_parts &&
|
||||
|
|
@ -3214,12 +3247,19 @@ static void create_or_update_media(MuninnSource *ctx, const std::string &url, bo
|
|||
ctx->bridge = std::make_unique<RudpMediaBridge>();
|
||||
}
|
||||
const auto outputs = ctx->bridge->start(url);
|
||||
ctx->media = create_ffmpeg_child_source(ctx, "Muninn Stream Video", outputs.video_url, "h264", false);
|
||||
if (!ctx->audio_decoder) {
|
||||
ctx->audio_decoder = std::make_unique<FfmpegAudioDecoder>();
|
||||
bool activated = false;
|
||||
if (wants_video) {
|
||||
ctx->media = create_ffmpeg_child_source(ctx, "Muninn Stream Video", outputs.video_url, "h264", false);
|
||||
activated = ctx->media != nullptr;
|
||||
}
|
||||
ctx->audio_decoder->start(ctx, outputs.audio_url);
|
||||
if (ctx->media) {
|
||||
if (wants_audio) {
|
||||
if (!ctx->audio_decoder) {
|
||||
ctx->audio_decoder = std::make_unique<FfmpegAudioDecoder>();
|
||||
}
|
||||
ctx->audio_decoder->start(ctx, outputs.audio_url);
|
||||
activated = true;
|
||||
}
|
||||
if (activated) {
|
||||
ctx->stream_url = url;
|
||||
} else {
|
||||
ctx->stream_url.clear();
|
||||
|
|
@ -3230,8 +3270,12 @@ static void create_or_update_media(MuninnSource *ctx, const std::string &url, bo
|
|||
}
|
||||
|
||||
release_ffmpeg_children(ctx);
|
||||
ctx->media = create_ffmpeg_child_source(ctx, "Muninn Stream Media", url, "mpegts", true);
|
||||
if (ctx->media) {
|
||||
if (wants_video) {
|
||||
ctx->media = create_ffmpeg_child_source(ctx, "Muninn Stream Media", url, "mpegts", wants_audio);
|
||||
} else if (wants_audio) {
|
||||
ctx->audio_media = create_ffmpeg_child_source(ctx, "Muninn Stream Audio", url, "mpegts", true);
|
||||
}
|
||||
if (ctx->media || ctx->audio_media) {
|
||||
ctx->stream_url = url;
|
||||
} else {
|
||||
ctx->stream_url.clear();
|
||||
|
|
@ -3278,8 +3322,12 @@ static void reconcile_selected_stream(MuninnSource *ctx)
|
|||
ctx->stream_id = selected->stream_id;
|
||||
const auto previous_video_source_id = ctx->video_source_id;
|
||||
const auto previous_audio_source_id = ctx->audio_source_id;
|
||||
ctx->video_source_id = selected_source_id(selected->video_sources, ctx->video_source_id);
|
||||
ctx->audio_source_id = selected_source_id(selected->audio_sources, ctx->audio_source_id);
|
||||
ctx->video_source_id = source_wants_video(ctx)
|
||||
? selected_source_id(selected->video_sources, ctx->video_source_id)
|
||||
: MuninnDisabledVideoSourceId;
|
||||
ctx->audio_source_id = source_wants_audio(ctx)
|
||||
? selected_source_id(selected->audio_sources, ctx->audio_source_id)
|
||||
: MuninnDisabledAudioSourceId;
|
||||
const bool source_selection_changed =
|
||||
ctx->video_source_id != previous_video_source_id || ctx->audio_source_id != previous_audio_source_id;
|
||||
if (selection_changed || source_selection_changed) {
|
||||
|
|
@ -3427,21 +3475,31 @@ static bool muninn_refresh_streams(obs_properties_t *props, obs_property_t *, vo
|
|||
refresh_catalog(ctx);
|
||||
obs_property_t *video_list = obs_properties_get(props, "video_source_id");
|
||||
obs_property_t *audio_list = obs_properties_get(props, "audio_source_id");
|
||||
if (video_list) {
|
||||
if (video_list && source_wants_video(ctx)) {
|
||||
populate_source_list(video_list, catalog_video_sources(ctx));
|
||||
}
|
||||
if (audio_list) {
|
||||
if (audio_list && source_wants_audio(ctx)) {
|
||||
populate_source_list(audio_list, catalog_audio_sources(ctx));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *muninn_get_name(void *)
|
||||
static const char *muninn_get_name_combined(void *)
|
||||
{
|
||||
return obs_module_text("MuninnStream");
|
||||
}
|
||||
|
||||
static const char *muninn_get_name_video(void *)
|
||||
{
|
||||
return obs_module_text("MuninnVideoSource");
|
||||
}
|
||||
|
||||
static const char *muninn_get_name_audio(void *)
|
||||
{
|
||||
return obs_module_text("MuninnAudioSource");
|
||||
}
|
||||
|
||||
static void audio_worker_loop(MuninnSource *ctx)
|
||||
{
|
||||
while (true) {
|
||||
|
|
@ -3498,9 +3556,10 @@ static void stop_audio_worker(MuninnSource *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static void muninn_update(void *data, obs_data_t *settings)
|
||||
static void muninn_update_kind(void *data, obs_data_t *settings, MuninnSourceKind kind)
|
||||
{
|
||||
auto *ctx = static_cast<MuninnSource *>(data);
|
||||
ctx->kind = kind;
|
||||
const auto previous_command_rudp_target = ctx->command_rudp_target;
|
||||
const auto previous_media_target_host = ctx->media_target_host;
|
||||
const auto previous_media_port = ctx->media_port;
|
||||
|
|
@ -3539,8 +3598,16 @@ static void muninn_update(void *data, obs_data_t *settings)
|
|||
configured_audio_reorder >= 0 ? std::min<int64_t>(configured_audio_reorder, MuninnMaxRudpAudioReorderMs)
|
||||
: MuninnDefaultRudpAudioReorderMs);
|
||||
ctx->stream_id = obs_string(settings, "stream_id", "");
|
||||
ctx->video_source_id = obs_string(settings, "video_source_id", ctx->video_source_id.c_str());
|
||||
ctx->audio_source_id = obs_string(settings, "audio_source_id", ctx->audio_source_id.c_str());
|
||||
if (source_wants_video(ctx)) {
|
||||
ctx->video_source_id = obs_string(settings, "video_source_id", ctx->video_source_id.c_str());
|
||||
} else {
|
||||
ctx->video_source_id = MuninnDisabledVideoSourceId;
|
||||
}
|
||||
if (source_wants_audio(ctx)) {
|
||||
ctx->audio_source_id = obs_string(settings, "audio_source_id", ctx->audio_source_id.c_str());
|
||||
} else {
|
||||
ctx->audio_source_id = MuninnDisabledAudioSourceId;
|
||||
}
|
||||
if (ctx->command_rudp_target != previous_command_rudp_target ||
|
||||
ctx->media_target_host != previous_media_target_host ||
|
||||
ctx->media_port != previous_media_port ||
|
||||
|
|
@ -3558,18 +3625,51 @@ static void muninn_update(void *data, obs_data_t *settings)
|
|||
reconcile_selected_stream(ctx);
|
||||
}
|
||||
|
||||
static void *muninn_create(obs_data_t *settings, obs_source_t *source)
|
||||
static void muninn_update_combined(void *data, obs_data_t *settings)
|
||||
{
|
||||
muninn_update_kind(data, settings, MuninnSourceKind::Combined);
|
||||
}
|
||||
|
||||
static void muninn_update_video(void *data, obs_data_t *settings)
|
||||
{
|
||||
muninn_update_kind(data, settings, MuninnSourceKind::VideoOnly);
|
||||
}
|
||||
|
||||
static void muninn_update_audio(void *data, obs_data_t *settings)
|
||||
{
|
||||
muninn_update_kind(data, settings, MuninnSourceKind::AudioOnly);
|
||||
}
|
||||
|
||||
static void *muninn_create_kind(obs_data_t *settings, obs_source_t *source, MuninnSourceKind kind)
|
||||
{
|
||||
auto *ctx = new MuninnSource();
|
||||
ctx->kind = kind;
|
||||
ctx->source = source;
|
||||
ctx->bridge = std::make_unique<RudpMediaBridge>();
|
||||
ctx->catalog_discovery = std::make_unique<CatalogDiscoveryReceiver>();
|
||||
ctx->catalog_discovery->start();
|
||||
start_audio_worker(ctx);
|
||||
muninn_update(ctx, settings);
|
||||
if (source_wants_audio(ctx)) {
|
||||
start_audio_worker(ctx);
|
||||
}
|
||||
muninn_update_kind(ctx, settings, kind);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void *muninn_create_combined(obs_data_t *settings, obs_source_t *source)
|
||||
{
|
||||
return muninn_create_kind(settings, source, MuninnSourceKind::Combined);
|
||||
}
|
||||
|
||||
static void *muninn_create_video(obs_data_t *settings, obs_source_t *source)
|
||||
{
|
||||
return muninn_create_kind(settings, source, MuninnSourceKind::VideoOnly);
|
||||
}
|
||||
|
||||
static void *muninn_create_audio(obs_data_t *settings, obs_source_t *source)
|
||||
{
|
||||
return muninn_create_kind(settings, source, MuninnSourceKind::AudioOnly);
|
||||
}
|
||||
|
||||
static void muninn_destroy(void *data)
|
||||
{
|
||||
auto *ctx = static_cast<MuninnSource *>(data);
|
||||
|
|
@ -3593,7 +3693,7 @@ static uint32_t muninn_height(void *data)
|
|||
return ctx->media ? obs_source_get_height(ctx->media) : 0;
|
||||
}
|
||||
|
||||
static void muninn_defaults(obs_data_t *settings)
|
||||
static void muninn_defaults_kind(obs_data_t *settings, MuninnSourceKind kind)
|
||||
{
|
||||
obs_data_set_default_string(settings, "store_path", MuninnStorePath);
|
||||
obs_data_set_default_string(settings, "command_exe_path", MuninnCommandExePath);
|
||||
|
|
@ -3605,11 +3705,32 @@ static void muninn_defaults(obs_data_t *settings)
|
|||
obs_data_set_default_int(settings, "rudp_latency_budget_ms", MuninnDefaultRudpLatencyBudgetMs);
|
||||
obs_data_set_default_int(settings, "rudp_audio_reorder_ms", MuninnDefaultRudpAudioReorderMs);
|
||||
obs_data_set_default_string(settings, "stream_id", "");
|
||||
obs_data_set_default_string(settings, "video_source_id", "display:0");
|
||||
obs_data_set_default_string(settings, "audio_source_id", "wasapi-loopback:Realtek");
|
||||
obs_data_set_default_string(
|
||||
settings,
|
||||
"video_source_id",
|
||||
kind == MuninnSourceKind::AudioOnly ? MuninnDisabledVideoSourceId : "display:0");
|
||||
obs_data_set_default_string(
|
||||
settings,
|
||||
"audio_source_id",
|
||||
kind == MuninnSourceKind::VideoOnly ? MuninnDisabledAudioSourceId : "wasapi-loopback:Realtek");
|
||||
}
|
||||
|
||||
static obs_properties_t *muninn_properties(void *data)
|
||||
static void muninn_defaults_combined(obs_data_t *settings)
|
||||
{
|
||||
muninn_defaults_kind(settings, MuninnSourceKind::Combined);
|
||||
}
|
||||
|
||||
static void muninn_defaults_video(obs_data_t *settings)
|
||||
{
|
||||
muninn_defaults_kind(settings, MuninnSourceKind::VideoOnly);
|
||||
}
|
||||
|
||||
static void muninn_defaults_audio(obs_data_t *settings)
|
||||
{
|
||||
muninn_defaults_kind(settings, MuninnSourceKind::AudioOnly);
|
||||
}
|
||||
|
||||
static obs_properties_t *muninn_properties_kind(void *data, MuninnSourceKind kind)
|
||||
{
|
||||
auto *ctx = static_cast<MuninnSource *>(data);
|
||||
const auto store_path = ctx ? ctx->store_path : std::string(MuninnStorePath);
|
||||
|
|
@ -3623,42 +3744,68 @@ static obs_properties_t *muninn_properties(void *data)
|
|||
} else {
|
||||
populate_stream_list(streams, store_path);
|
||||
}
|
||||
obs_property_t *video_sources =
|
||||
obs_properties_add_list(props, "video_source_id", obs_module_text("MuninnStream.Video"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_t *audio_sources =
|
||||
obs_properties_add_list(props, "audio_source_id", obs_module_text("MuninnStream.Audio"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
if (ctx) {
|
||||
populate_source_list(video_sources, catalog_video_sources(ctx));
|
||||
populate_source_list(audio_sources, catalog_audio_sources(ctx));
|
||||
} else {
|
||||
populate_source_list(video_sources, {{"display:0", "Display 1"}});
|
||||
populate_source_list(audio_sources, {{"wasapi-loopback:Realtek", "Realtek loopback"}});
|
||||
if (kind != MuninnSourceKind::AudioOnly) {
|
||||
obs_property_t *video_sources =
|
||||
obs_properties_add_list(props, "video_source_id", obs_module_text("MuninnStream.Video"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
if (ctx) {
|
||||
populate_source_list(video_sources, catalog_video_sources(ctx));
|
||||
} else {
|
||||
populate_source_list(video_sources, {{"display:0", "Display 1"}});
|
||||
}
|
||||
}
|
||||
if (kind != MuninnSourceKind::VideoOnly) {
|
||||
obs_property_t *audio_sources =
|
||||
obs_properties_add_list(props, "audio_source_id", obs_module_text("MuninnStream.Audio"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
if (ctx) {
|
||||
populate_source_list(audio_sources, catalog_audio_sources(ctx));
|
||||
} else {
|
||||
populate_source_list(audio_sources, {{"wasapi-loopback:Realtek", "Realtek loopback"}});
|
||||
}
|
||||
}
|
||||
if (kind != MuninnSourceKind::AudioOnly) {
|
||||
obs_properties_add_int(
|
||||
props,
|
||||
"rudp_video_bitrate_kbps",
|
||||
obs_module_text("MuninnStream.VideoBitrateKbps"),
|
||||
1000,
|
||||
MuninnMaxRudpVideoBitrateKbps,
|
||||
500);
|
||||
obs_properties_add_int(
|
||||
props,
|
||||
"rudp_latency_budget_ms",
|
||||
obs_module_text("MuninnStream.VideoLatencyMs"),
|
||||
100,
|
||||
MuninnMaxRudpLatencyBudgetMs,
|
||||
50);
|
||||
}
|
||||
if (kind != MuninnSourceKind::VideoOnly) {
|
||||
obs_properties_add_int(
|
||||
props,
|
||||
"rudp_audio_reorder_ms",
|
||||
obs_module_text("MuninnStream.AudioReorderMs"),
|
||||
0,
|
||||
MuninnMaxRudpAudioReorderMs,
|
||||
25);
|
||||
}
|
||||
obs_properties_add_int(
|
||||
props,
|
||||
"rudp_video_bitrate_kbps",
|
||||
obs_module_text("MuninnStream.VideoBitrateKbps"),
|
||||
1000,
|
||||
MuninnMaxRudpVideoBitrateKbps,
|
||||
500);
|
||||
obs_properties_add_int(
|
||||
props,
|
||||
"rudp_latency_budget_ms",
|
||||
obs_module_text("MuninnStream.VideoLatencyMs"),
|
||||
100,
|
||||
MuninnMaxRudpLatencyBudgetMs,
|
||||
50);
|
||||
obs_properties_add_int(
|
||||
props,
|
||||
"rudp_audio_reorder_ms",
|
||||
obs_module_text("MuninnStream.AudioReorderMs"),
|
||||
0,
|
||||
MuninnMaxRudpAudioReorderMs,
|
||||
25);
|
||||
obs_properties_add_button(props, "refresh_streams", obs_module_text("MuninnStream.Refresh"), muninn_refresh_streams);
|
||||
return props;
|
||||
}
|
||||
|
||||
static obs_properties_t *muninn_properties_combined(void *data)
|
||||
{
|
||||
return muninn_properties_kind(data, MuninnSourceKind::Combined);
|
||||
}
|
||||
|
||||
static obs_properties_t *muninn_properties_video(void *data)
|
||||
{
|
||||
return muninn_properties_kind(data, MuninnSourceKind::VideoOnly);
|
||||
}
|
||||
|
||||
static obs_properties_t *muninn_properties_audio(void *data)
|
||||
{
|
||||
return muninn_properties_kind(data, MuninnSourceKind::AudioOnly);
|
||||
}
|
||||
|
||||
static void muninn_video_tick(void *data, float)
|
||||
{
|
||||
auto *ctx = static_cast<MuninnSource *>(data);
|
||||
|
|
@ -3716,14 +3863,48 @@ static obs_source_info muninn_source_info = {
|
|||
.id = "muninn_stream_source",
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_AUDIO,
|
||||
.get_name = muninn_get_name,
|
||||
.create = muninn_create,
|
||||
.get_name = muninn_get_name_combined,
|
||||
.create = muninn_create_combined,
|
||||
.destroy = muninn_destroy,
|
||||
.get_width = muninn_width,
|
||||
.get_height = muninn_height,
|
||||
.get_defaults = muninn_defaults,
|
||||
.get_properties = muninn_properties,
|
||||
.update = muninn_update,
|
||||
.get_defaults = muninn_defaults_combined,
|
||||
.get_properties = muninn_properties_combined,
|
||||
.update = muninn_update_combined,
|
||||
.video_tick = muninn_video_tick,
|
||||
.video_render = muninn_render,
|
||||
.enum_active_sources = muninn_enum_active_sources,
|
||||
};
|
||||
|
||||
static obs_source_info muninn_video_source_info = {
|
||||
.id = "muninn_video_source",
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_VIDEO,
|
||||
.get_name = muninn_get_name_video,
|
||||
.create = muninn_create_video,
|
||||
.destroy = muninn_destroy,
|
||||
.get_width = muninn_width,
|
||||
.get_height = muninn_height,
|
||||
.get_defaults = muninn_defaults_video,
|
||||
.get_properties = muninn_properties_video,
|
||||
.update = muninn_update_video,
|
||||
.video_tick = muninn_video_tick,
|
||||
.video_render = muninn_render,
|
||||
.enum_active_sources = muninn_enum_active_sources,
|
||||
};
|
||||
|
||||
static obs_source_info muninn_audio_source_info = {
|
||||
.id = "muninn_audio_source",
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_AUDIO,
|
||||
.get_name = muninn_get_name_audio,
|
||||
.create = muninn_create_audio,
|
||||
.destroy = muninn_destroy,
|
||||
.get_width = muninn_width,
|
||||
.get_height = muninn_height,
|
||||
.get_defaults = muninn_defaults_audio,
|
||||
.get_properties = muninn_properties_audio,
|
||||
.update = muninn_update_audio,
|
||||
.video_tick = muninn_video_tick,
|
||||
.video_render = muninn_render,
|
||||
.enum_active_sources = muninn_enum_active_sources,
|
||||
|
|
@ -3734,4 +3915,6 @@ static obs_source_info muninn_source_info = {
|
|||
void mimir_register_muninn_source()
|
||||
{
|
||||
obs_register_source(&muninn_source_info);
|
||||
obs_register_source(&muninn_video_source_info);
|
||||
obs_register_source(&muninn_audio_source_info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,4 +68,4 @@ if ($WhatIf) {
|
|||
Copy-Item -LiteralPath $pluginDll -Destination $targetDll -Force
|
||||
Copy-Item -Path (Join-Path $localeSourceDir "*") -Destination $targetLocaleDir -Force
|
||||
Write-Host "Installed Mimir OBS plugin: $targetDll"
|
||||
Write-Host "OBS source types: Mimir Program Texture, Mimir Audio Stem, Muninn Stream"
|
||||
Write-Host "OBS source types: Mimir Program Texture, Mimir Audio Stem, Muninn Stream, Muninn Video, Muninn Audio"
|
||||
|
|
|
|||
Loading…
Reference in a new issue