From 12eca135360c0dec53e5a80873240181ac2c45f6 Mon Sep 17 00:00:00 2001 From: Joaquin Bartaburu Date: Thu, 23 Jul 2026 16:23:38 -0300 Subject: [PATCH 1/2] feat: handle init_data when encoder sends it on first frame encoded --- src/moq-output.cpp | 59 ++++++++++++++++++++++++++++++++++++---------- src/moq-output.h | 3 ++- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/moq-output.cpp b/src/moq-output.cpp index 4040dda..ea1c091 100644 --- a/src/moq-output.cpp +++ b/src/moq-output.cpp @@ -165,6 +165,27 @@ moq_media_track_t *MOQOutput::CreateVideoTrack(moq_media_sender_t *new_sender) return new_track; } +moq_media_track_t *MOQOutput::CreateVideoTrackFromPacket(moq_media_sender_t *cur_sender, struct encoder_packet *packet) +{ + std::vector init = AnnexBToAvcC(packet->data, packet->size); + if (init.empty()) { + return nullptr; + } + + video_init_data = std::move(init); + video_codec = AvcCodecString(video_init_data); + + moq_media_track_t *new_track = CreateVideoTrack(cur_sender); + if (!new_track) { + blog(LOG_WARNING, "[obs-moq] failed to create video track from first frame"); + return nullptr; + } + + blog(LOG_INFO, "[obs-moq] video track created from first frame (codec %s, init_data %zu bytes)", + video_codec.c_str(), video_init_data.size()); + return new_track; +} + moq_media_track_t *MOQOutput::CreateAudioTrack(moq_media_sender_t *new_sender) { moq_media_track_cfg_t tcfg; @@ -257,12 +278,15 @@ bool MOQOutput::Connect() return false; } - moq_media_track_t *new_video_track = CreateVideoTrack(media_sender); - if (!new_video_track) { - blog(LOG_WARNING, "[obs-moq] failed to create video track"); - moq_media_sender_destroy(media_sender); - obs_output_signal_stop(output, OBS_OUTPUT_ERROR); - return false; + moq_media_track_t *new_video_track = nullptr; + if (!video_init_data.empty()) { + new_video_track = CreateVideoTrack(media_sender); + if (!new_video_track) { + blog(LOG_WARNING, "[obs-moq] failed to create video track"); + moq_media_sender_destroy(media_sender); + obs_output_signal_stop(output, OBS_OUTPUT_ERROR); + return false; + } } moq_media_track_t *new_audio_track = CreateAudioTrack(media_sender); @@ -348,8 +372,8 @@ void MOQOutput::Stop(bool signal) start_time_ns = os_gettime_ns(); } -void MOQOutput::SendPacket(struct encoder_packet *packet, moq_media_track_t *track, bool is_sync, bool starts_group, - bool ends_group) +void MOQOutput::SendPacket(struct encoder_packet *packet, moq_media_track_t **track, bool is_sync, + bool starts_group, bool ends_group) { moq_rcbuf_t *payload = nullptr; @@ -376,12 +400,21 @@ void MOQOutput::SendPacket(struct encoder_packet *packet, moq_media_track_t *tra moq_result_t res; { std::lock_guard lock(sender_mutex); - if (!sender || !track) { - // release the rcbuf since we won't be sending it + if (!sender) { moq_rcbuf_decref(payload); return; } - res = moq_media_sender_write(sender, track, &obj); + + if (!*track && packet->type == OBS_ENCODER_VIDEO && packet->keyframe) { + *track = CreateVideoTrackFromPacket(sender, packet); + } + + if (!*track) { + moq_rcbuf_decref(payload); + return; + } + + res = moq_media_sender_write(sender, *track, &obj); } if (res != MOQ_OK) { @@ -404,10 +437,10 @@ void MOQOutput::Data(struct encoder_packet *packet) return; } if (packet->type == OBS_ENCODER_VIDEO) { - SendPacket(packet, video_track, packet->keyframe, packet->keyframe, false); + SendPacket(packet, &video_track, packet->keyframe, packet->keyframe, false); } if (packet->type == OBS_ENCODER_AUDIO) { - SendPacket(packet, audio_track, true, true, true); + SendPacket(packet, &audio_track, true, true, true); } } diff --git a/src/moq-output.h b/src/moq-output.h index ff35928..e95329e 100644 --- a/src/moq-output.h +++ b/src/moq-output.h @@ -45,8 +45,9 @@ class MOQOutput { bool LoadVideoEncoderSettings(); bool LoadAudioEncoderSettings(); moq_media_track_t *CreateVideoTrack(moq_media_sender_t *new_sender); + moq_media_track_t *CreateVideoTrackFromPacket(moq_media_sender_t *cur_sender, struct encoder_packet *packet); moq_media_track_t *CreateAudioTrack(moq_media_sender_t *new_sender); - void SendPacket(struct encoder_packet *packet, moq_media_track_t *track, bool is_sync, bool starts_group, + void SendPacket(struct encoder_packet *packet, moq_media_track_t **track, bool is_sync, bool starts_group, bool ends_group); bool ResolveServiceConfig(); bool Connect(); From c76542939fa8f50ccebf9276b0464ab169ad7f59 Mon Sep 17 00:00:00 2001 From: Joaquin Bartaburu Date: Mon, 27 Jul 2026 14:16:35 -0300 Subject: [PATCH 2/2] format fix --- src/moq-output.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/moq-output.cpp b/src/moq-output.cpp index ea1c091..0ea7e94 100644 --- a/src/moq-output.cpp +++ b/src/moq-output.cpp @@ -372,8 +372,8 @@ void MOQOutput::Stop(bool signal) start_time_ns = os_gettime_ns(); } -void MOQOutput::SendPacket(struct encoder_packet *packet, moq_media_track_t **track, bool is_sync, - bool starts_group, bool ends_group) +void MOQOutput::SendPacket(struct encoder_packet *packet, moq_media_track_t **track, bool is_sync, bool starts_group, + bool ends_group) { moq_rcbuf_t *payload = nullptr;