Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"ENABLE_FRONTEND_API": false,
"ENABLE_QT": false,
"CMAKE_EXPORT_COMPILE_COMMANDS": true,
"MOQ_VERSION": "0.1.2",
"MOQ_VERSION": "0.2.0",
"MOQ_ARCHIVE": "tar.gz"
}
},
Expand Down Expand Up @@ -173,4 +173,4 @@
"configuration": "RelWithDebInfo"
}
]
}
}
29 changes: 16 additions & 13 deletions src/moq-output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ MoQOutput::MoQOutput(obs_data_t *, obs_output_t *output)
path(),
total_bytes_sent(0),
connect_time_ms(0),
origin(moq_origin_create()),
broadcast(moq_publish_create()),
session(0),
video(0),
audio(0),
broadcast(moq_broadcast_create())
audio(0)
{
}

MoQOutput::~MoQOutput()
{
moq_broadcast_close(broadcast);
moq_publish_close(broadcast);
moq_origin_close(origin);

Stop();
}
Comment on lines 24 to 30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Resource cleanup order may be incorrect.

moq_publish_close(broadcast) is called before Stop(), but Stop() closes the video/audio tracks that were created under the broadcast. Closing the parent (broadcast) before its children (tracks) may cause issues.

Consider calling Stop() first:

🔎 Suggested fix
 MoQOutput::~MoQOutput()
 {
+	Stop();
+
 	moq_publish_close(broadcast);
 	moq_origin_close(origin);
-
-	Stop();
 }
🤖 Prompt for AI Agents
In src/moq-output.cpp around lines 24 to 30, the destructor currently calls
moq_publish_close(broadcast) and moq_origin_close(origin) before Stop(), which
can close the broadcast parent while its video/audio tracks are still open;
change the order so Stop() is called first to shut down and release tracks, then
call moq_publish_close(broadcast) and moq_origin_close(origin) afterward (retain
any existing null/validity checks and error handling when closing resources).

Expand Down Expand Up @@ -82,18 +84,17 @@ bool MoQOutput::Start()

// Start establishing a session with the MoQ server
// NOTE: You could publish the same broadcasts to multiple sessions if you want (redundant ingest).
session = moq_session_connect(server_url.c_str(), session_connect_callback, this);
session = moq_session_connect(server_url.data(), server_url.size(), origin, NULL, session_connect_callback, this);
if (session < 0) {
LOG_ERROR("Failed to initialize MoQ server: %d", session);
return false;
}

LOG_INFO("Publishing broadcast: %s", path.c_str());

// Publish the one broadcast to the session.
// NOTE: You could publish multiple broadcasts to the same session if you want (multi ingest).
// Publish the broadcast to the origin we created.
// TODO: There is currently no unpublish function.
auto result = moq_broadcast_publish(broadcast, session, path.c_str());
auto result = moq_origin_publish(origin, path.data(), path.size(), broadcast);
if (result < 0) {
LOG_ERROR("Failed to publish broadcast to session: %d", result);
return false;
Expand All @@ -112,11 +113,11 @@ void MoQOutput::Stop(bool signal)
}

if (video > 0) {
moq_track_close(video);
moq_publish_media_close(video);
}

if (audio > 0) {
moq_track_close(audio);
moq_publish_media_close(audio);
}

if (signal) {
Expand Down Expand Up @@ -154,7 +155,7 @@ void MoQOutput::AudioData(struct encoder_packet *packet)

auto pts = util_mul_div64(packet->pts, 1000000ULL * packet->timebase_num, packet->timebase_den);

auto result = moq_track_write(audio, packet->data, packet->size, pts);
auto result = moq_publish_media_frame(audio, packet->data, packet->size, pts);
if (result < 0) {
LOG_ERROR("Failed to write audio frame: %d", result);
return;
Expand All @@ -175,7 +176,7 @@ void MoQOutput::VideoData(struct encoder_packet *packet)

auto pts = util_mul_div64(packet->pts, 1000000ULL * packet->timebase_num, packet->timebase_den);

auto result = moq_track_write(video, packet->data, packet->size, pts);
auto result = moq_publish_media_frame(video, packet->data, packet->size, pts);
if (result < 0) {
LOG_ERROR("Failed to write video frame: %d", result);
return;
Expand Down Expand Up @@ -215,7 +216,8 @@ void MoQOutput::VideoInit()
}

const char *codec = obs_encoder_get_codec(encoder);
video = moq_track_create(broadcast, codec, extra_data, extra_size);

video = moq_publish_media_ordered(broadcast, codec, strlen(codec), extra_data, extra_size);
if (video < 0) {
LOG_ERROR("Failed to initialize video track: %d", video);
return;
Expand Down Expand Up @@ -253,7 +255,8 @@ void MoQOutput::AudioInit()
}

const char *codec = obs_encoder_get_codec(encoder);
audio = moq_track_create(broadcast, codec, extra_data, extra_size);

audio = moq_publish_media_ordered(broadcast, codec, strlen(codec), extra_data, extra_size);
if (audio < 0) {
LOG_ERROR("Failed to initialize audio track: %d", audio);
return;
Expand Down
1 change: 1 addition & 0 deletions src/moq-output.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class MoQOutput
int connect_time_ms;
std::chrono::steady_clock::time_point connect_start;

int origin;
int session;
int broadcast;
int video;
Expand Down
4 changes: 2 additions & 2 deletions src/moq-service.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "moq-service.h"

// TODO: Define supported codecs.
const char *audio_codecs[] = {"aac", "opus", nullptr};
const char *video_codecs[] = {"h264", "hevc", "av1", nullptr};
const char *audio_codecs[] = {"aac", nullptr};
const char *video_codecs[] = {"h264", nullptr};

MoQService::MoQService(obs_data_t *settings, obs_service_t *) : server(), path()
{
Expand Down
3 changes: 2 additions & 1 deletion src/obs-moq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ MODULE_EXPORT const char *obs_module_description(void)
bool obs_module_load(void)
{
// Use RUST_LOG env var for more verbose output
moq_log_level("info");
// The second argument is the string length of the first argument.
moq_log_level("info", 4);

register_moq_output();
register_moq_service();
Expand Down
Loading