@@ -25,8 +25,8 @@ namespace jni
2525 channels_ (channels ? channels : 1 ),
2626 playoutFramesIn10MS_ (0 ),
2727 recordingFramesIn10MS_ (0 ),
28- lastCallPlayoutMillis_ (0 ),
29- lastCallRecordMillis_ (0 ),
28+ nextPlayoutMillis_ (0 ),
29+ nextRecordMillis_ (0 ),
3030 audio_callback_ (nullptr )
3131 {
3232 audio_device_buffer_ = std::make_unique<webrtc::AudioDeviceBuffer>(&env.task_queue_factory ());
@@ -553,22 +553,35 @@ namespace jni
553553 int64_t currentTime = webrtc::TimeMillis ();
554554 mutex_.Lock ();
555555
556- if (lastCallPlayoutMillis_ == 0 || currentTime - lastCallPlayoutMillis_ >= 10 ) {
556+ // Seed the grid on the first tick.
557+ if (nextPlayoutMillis_ == 0 ) {
558+ nextPlayoutMillis_ = currentTime;
559+ }
560+
561+ if (currentTime >= nextPlayoutMillis_) {
557562 mutex_.Unlock ();
558563 audio_device_buffer_->RequestPlayoutData (playoutFramesIn10MS_);
559564 mutex_.Lock ();
560565
561566 audio_device_buffer_->GetPlayoutData (play_buffer_.data ());
562567
563- lastCallPlayoutMillis_ = currentTime;
568+ // Advance the grid by a fixed 10 ms rather than re-anchoring to currentTime,
569+ // so wake-up latency is corrected on the next tick instead of accumulating
570+ // into the frame period (which otherwise pulls the effective rate below 100 Hz).
571+ nextPlayoutMillis_ += 10 ;
572+
573+ // If we fell far behind (e.g. the thread was descheduled), resync to now
574+ // instead of bursting frames to catch up.
575+ if (nextPlayoutMillis_ < currentTime - 100 ) {
576+ nextPlayoutMillis_ = currentTime;
577+ }
564578 }
565579
580+ int64_t sleepMillis = nextPlayoutMillis_ - webrtc::TimeMillis ();
566581 mutex_.Unlock ();
567582
568- int64_t deltaTimeMillis = webrtc::TimeMillis () - currentTime;
569-
570- if (deltaTimeMillis < 10 ) {
571- webrtc::Thread::SleepMs (10 - deltaTimeMillis);
583+ if (sleepMillis > 0 ) {
584+ webrtc::Thread::SleepMs (sleepMillis);
572585 }
573586
574587 return true ;
@@ -588,7 +601,12 @@ namespace jni
588601 int64_t currentTime = webrtc::TimeMillis ();
589602 mutex_.Lock ();
590603
591- if (lastCallRecordMillis_ == 0 || currentTime - lastCallRecordMillis_ >= 10 ) {
604+ // Seed the grid on the first tick.
605+ if (nextRecordMillis_ == 0 ) {
606+ nextRecordMillis_ = currentTime;
607+ }
608+
609+ if (currentTime >= nextRecordMillis_) {
592610 size_t nSamplesOut = 0 ;
593611 const size_t nBytesPerSample = sizeof (int16_t );
594612 const size_t nChannels = channels_;
@@ -617,19 +635,28 @@ namespace jni
617635 audio_device_buffer_->SetRecordedBuffer (record_buffer_.data (), recordingFramesIn10MS_);
618636 audio_device_buffer_->SetVQEData (/* play_delay_ms*/ 0 , /* rec_delay_ms*/ 0 );
619637
620- lastCallRecordMillis_ = currentTime;
638+ // Advance the grid by a fixed 10 ms rather than re-anchoring to currentTime,
639+ // so wake-up latency is corrected on the next tick instead of accumulating
640+ // into the frame period (which otherwise pulls the effective rate below 100 Hz).
641+ nextRecordMillis_ += 10 ;
642+
643+ // If we fell far behind (e.g. the thread was descheduled), resync to now
644+ // instead of bursting frames to catch up.
645+ if (nextRecordMillis_ < currentTime - 100 ) {
646+ nextRecordMillis_ = currentTime;
647+ }
621648
622649 mutex_.Unlock ();
623650 audio_device_buffer_->DeliverRecordedData ();
624651 mutex_.Lock ();
625652 }
626653 }
627654
655+ int64_t sleepMillis = nextRecordMillis_ - webrtc::TimeMillis ();
628656 mutex_.Unlock ();
629657
630- int64_t deltaTimeMillis = webrtc::TimeMillis () - currentTime;
631- if (deltaTimeMillis < 10 ) {
632- webrtc::Thread::SleepMs (10 - deltaTimeMillis);
658+ if (sleepMillis > 0 ) {
659+ webrtc::Thread::SleepMs (sleepMillis);
633660 }
634661
635662 return true ;
0 commit comments