@@ -14,10 +14,8 @@ MoQOutput::MoQOutput(obs_data_t *, obs_output_t *output)
1414 total_bytes_sent(0 ),
1515 connect_time_ms(0 ),
1616 origin(moq_origin_create()),
17- broadcast(moq_publish_create()),
1817 session(0 ),
19- video(0 ),
20- audio(0 )
18+ broadcast(moq_publish_create())
2119{
2220}
2321
@@ -57,9 +55,15 @@ bool MoQOutput::Start()
5755
5856 path = obs_service_get_connect_info (service, OBS_SERVICE_CONNECT_INFO_STREAM_KEY);
5957
60- const obs_encoder_t *encoder = obs_output_get_video_encoder2 (output, 0 );
58+ bool found_encoder = false ;
59+ for (uint32_t idx = 0 ; idx < MAX_OUTPUT_VIDEO_ENCODERS; idx++) {
60+ if (obs_output_get_video_encoder2 (output, idx)) {
61+ found_encoder = true ;
62+ break ;
63+ }
64+ }
6165
62- if (!encoder ) {
66+ if (!found_encoder ) {
6367 LOG_ERROR (" Failed to get video encoder" );
6468 return false ;
6569 }
@@ -113,15 +117,17 @@ void MoQOutput::Stop(bool signal)
113117 session = 0 ;
114118 }
115119
116- if (video > 0 ) {
117- moq_publish_media_close (video);
118- video = 0 ;
120+ for ( auto &[encoder, handle] : video_tracks ) {
121+ if (handle > 0 )
122+ moq_publish_media_close (handle) ;
119123 }
124+ video_tracks.clear ();
120125
121- if (audio > 0 ) {
122- moq_publish_media_close (audio);
123- audio = 0 ;
126+ for ( auto &[encoder, handle] : audio_tracks ) {
127+ if (handle > 0 )
128+ moq_publish_media_close (handle) ;
124129 }
130+ audio_tracks.clear ();
125131
126132 if (signal) {
127133 obs_output_signal_stop (output, OBS_OUTPUT_SUCCESS);
@@ -147,14 +153,18 @@ void MoQOutput::Data(struct encoder_packet *packet)
147153
148154void MoQOutput::AudioData (struct encoder_packet *packet)
149155{
150- if (audio == 0 ) {
151- AudioInit ();
152- }
156+ obs_encoder_t *encoder = packet->encoder ;
153157
154- if (audio < 0 ) {
158+ auto it = audio_tracks.find (encoder);
159+ if (it == audio_tracks.end ()) {
160+ AudioInit (encoder);
161+ it = audio_tracks.find (encoder);
162+ }
163+ if (it == audio_tracks.end () || it->second < 0 ) {
155164 // We failed to initialize the audio track, so we can't write any data.
156165 return ;
157166 }
167+ int handle = it->second ;
158168
159169 // Add ~1 second offset to handle negative PTS from audio priming frames.
160170 // TODO: This is slightly wrong when den is not evenly divisible by num, but close enough.
@@ -166,7 +176,7 @@ void MoQOutput::AudioData(struct encoder_packet *packet)
166176
167177 auto pts_us = util_mul_div64 (pts, 1000000ULL * packet->timebase_num , packet->timebase_den );
168178
169- auto result = moq_publish_media_frame (audio , packet->data , packet->size , pts_us);
179+ auto result = moq_publish_media_frame (handle , packet->data , packet->size , pts_us);
170180 if (result < 0 ) {
171181 LOG_ERROR (" Failed to write audio frame: %d" , result);
172182 return ;
@@ -177,13 +187,16 @@ void MoQOutput::AudioData(struct encoder_packet *packet)
177187
178188void MoQOutput::VideoData (struct encoder_packet *packet)
179189{
180- if (video == 0 ) {
181- VideoInit ();
182- }
190+ obs_encoder_t *encoder = packet->encoder ;
183191
184- if (video < 0 ) {
185- return ;
192+ auto it = video_tracks.find (encoder);
193+ if (it == video_tracks.end ()) {
194+ VideoInit (encoder);
195+ it = video_tracks.find (encoder);
186196 }
197+ if (it == video_tracks.end () || it->second < 0 )
198+ return ;
199+ int handle = it->second ;
187200
188201 // Add ~1 second offset to match audio for A/V sync.
189202 // TODO: This is slightly wrong when den is not evenly divisible by num, but close enough.
@@ -195,7 +208,7 @@ void MoQOutput::VideoData(struct encoder_packet *packet)
195208
196209 auto pts_us = util_mul_div64 (pts, 1000000ULL * packet->timebase_num , packet->timebase_den );
197210
198- auto result = moq_publish_media_frame (video , packet->data , packet->size , pts_us);
211+ auto result = moq_publish_media_frame (handle , packet->data , packet->size , pts_us);
199212 if (result < 0 ) {
200213 LOG_ERROR (" Failed to write video frame: %d" , result);
201214 return ;
@@ -204,9 +217,8 @@ void MoQOutput::VideoData(struct encoder_packet *packet)
204217 total_bytes_sent += packet->size ;
205218}
206219
207- void MoQOutput::VideoInit ()
220+ void MoQOutput::VideoInit (obs_encoder_t *encoder )
208221{
209- obs_encoder_t *encoder = obs_output_get_video_encoder (output);
210222 if (!encoder) {
211223 LOG_ERROR (" Failed to get video encoder" );
212224 return ;
@@ -247,18 +259,18 @@ void MoQOutput::VideoInit()
247259 }
248260
249261 // Intialize the media import module with the codec and initialization data.
250- video = moq_publish_media_ordered (broadcast, moq_codec, strlen (moq_codec), extra_data, extra_size);
251- if (video < 0 ) {
252- LOG_ERROR (" Failed to initialize video track: %d" , video);
262+ int handle = moq_publish_media_ordered (broadcast, moq_codec, strlen (moq_codec), extra_data, extra_size);
263+ video_tracks[encoder] = handle;
264+ if (handle < 0 ) {
265+ LOG_ERROR (" Failed to initialize video track: %d" , handle);
253266 return ;
254267 }
255268
256269 LOG_INFO (" Video track initialized successfully" );
257270}
258271
259- void MoQOutput::AudioInit ()
272+ void MoQOutput::AudioInit (obs_encoder_t *encoder )
260273{
261- obs_encoder_t *encoder = obs_output_get_audio_encoder (output, 0 );
262274 if (!encoder) {
263275 LOG_ERROR (" Failed to get audio encoder" );
264276 return ;
@@ -286,9 +298,10 @@ void MoQOutput::AudioInit()
286298
287299 const char *codec = obs_encoder_get_codec (encoder);
288300
289- audio = moq_publish_media_ordered (broadcast, codec, strlen (codec), extra_data, extra_size);
290- if (audio < 0 ) {
291- LOG_ERROR (" Failed to initialize audio track: %d" , audio);
301+ int handle = moq_publish_media_ordered (broadcast, codec, strlen (codec), extra_data, extra_size);
302+ audio_tracks[encoder] = handle;
303+ if (handle < 0 ) {
304+ LOG_ERROR (" Failed to initialize audio track: %d" , handle);
292305 return ;
293306 }
294307
@@ -297,7 +310,8 @@ void MoQOutput::AudioInit()
297310
298311void register_moq_output ()
299312{
300- const uint32_t base_flags = OBS_OUTPUT_ENCODED | OBS_OUTPUT_SERVICE;
313+ const uint32_t base_flags = OBS_OUTPUT_ENCODED | OBS_OUTPUT_SERVICE | OBS_OUTPUT_MULTI_TRACK_VIDEO |
314+ OBS_OUTPUT_MULTI_TRACK_AUDIO;
301315
302316 const char *audio_codecs = " aac;opus" ;
303317 const char *video_codecs = " h264;hevc;av1" ;
0 commit comments