@@ -156,9 +156,17 @@ void MoQOutput::AudioData(struct encoder_packet *packet)
156156 return ;
157157 }
158158
159- auto pts = util_mul_div64 (packet->pts , 1000000ULL * packet->timebase_num , packet->timebase_den );
159+ // Add ~1 second offset to handle negative PTS from audio priming frames.
160+ // TODO: This is slightly wrong when den is not evenly divisible by num, but close enough.
161+ int64_t pts = packet->pts + packet->timebase_den / packet->timebase_num ;
162+ if (pts < 0 ) {
163+ LOG_WARNING (" Dropping audio frame with negative PTS: %lld" , (long long )packet->pts );
164+ return ;
165+ }
166+
167+ auto pts_us = util_mul_div64 (pts, 1000000ULL * packet->timebase_num , packet->timebase_den );
160168
161- auto result = moq_publish_media_frame (audio, packet->data , packet->size , pts );
169+ auto result = moq_publish_media_frame (audio, packet->data , packet->size , pts_us );
162170 if (result < 0 ) {
163171 LOG_ERROR (" Failed to write audio frame: %d" , result);
164172 return ;
@@ -177,9 +185,17 @@ void MoQOutput::VideoData(struct encoder_packet *packet)
177185 return ;
178186 }
179187
180- auto pts = util_mul_div64 (packet->pts , 1000000ULL * packet->timebase_num , packet->timebase_den );
188+ // Add ~1 second offset to match audio for A/V sync.
189+ // TODO: This is slightly wrong when den is not evenly divisible by num, but close enough.
190+ int64_t pts = packet->pts + packet->timebase_den / packet->timebase_num ;
191+ if (pts < 0 ) {
192+ LOG_WARNING (" Dropping video frame with negative PTS: %lld" , (long long )packet->pts );
193+ return ;
194+ }
195+
196+ auto pts_us = util_mul_div64 (pts, 1000000ULL * packet->timebase_num , packet->timebase_den );
181197
182- auto result = moq_publish_media_frame (video, packet->data , packet->size , pts );
198+ auto result = moq_publish_media_frame (video, packet->data , packet->size , pts_us );
183199 if (result < 0 ) {
184200 LOG_ERROR (" Failed to write video frame: %d" , result);
185201 return ;
0 commit comments