2020import android .os .Process ;
2121import androidx .annotation .Nullable ;
2222import java .nio .ByteBuffer ;
23+ import java .util .Arrays ;
2324import org .webrtc .CalledByNative ;
2425import org .webrtc .Logging ;
2526import org .webrtc .ThreadUtils ;
2627import org .webrtc .audio .JavaAudioDeviceModule .AudioTrackErrorCallback ;
2728import org .webrtc .audio .JavaAudioDeviceModule .AudioTrackStartErrorCode ;
2829import org .webrtc .audio .JavaAudioDeviceModule .AudioTrackStateCallback ;
30+ import org .webrtc .audio .JavaAudioDeviceModule .PlaybackSamplesReadyCallback ;
2931import org .webrtc .audio .LowLatencyAudioBufferManager ;
3032
3133class WebRtcAudioTrack {
@@ -76,6 +78,7 @@ class WebRtcAudioTrack {
7678
7779 private final @ Nullable AudioTrackErrorCallback errorCallback ;
7880 private final @ Nullable AudioTrackStateCallback stateCallback ;
81+ private final @ Nullable PlaybackSamplesReadyCallback audioSamplesReadyCallback ;
7982
8083 /**
8184 * Audio thread which keeps calling AudioTrack.write() to stream audio.
@@ -129,6 +132,17 @@ public void run() {
129132 reportWebRtcAudioTrackError ("AudioTrack.write failed: " + bytesWritten );
130133 }
131134 }
135+
136+ if (audioSamplesReadyCallback != null && keepAlive ) {
137+ // Copy the entire byte buffer array. The start of the byteBuffer is not necessarily
138+ // at index 0.
139+ byte [] data = Arrays .copyOfRange (byteBuffer .array (), byteBuffer .arrayOffset (),
140+ sizeInBytes + byteBuffer .arrayOffset ());
141+ audioSamplesReadyCallback .onWebRtcAudioTrackSamplesReady (
142+ new JavaAudioDeviceModule .AudioSamples (audioTrack .getAudioFormat (),
143+ audioTrack .getChannelCount (), audioTrack .getSampleRate (), data ));
144+ }
145+
132146 if (useLowLatency ) {
133147 bufferManager .maybeAdjustBufferSize (audioTrack );
134148 }
@@ -154,20 +168,21 @@ public void stopThread() {
154168 @ CalledByNative
155169 WebRtcAudioTrack (Context context , AudioManager audioManager ) {
156170 this (context , audioManager , null /* audioAttributes */ , null /* errorCallback */ ,
157- null /* stateCallback */ , false /* useLowLatency */ , true /* enableVolumeLogger */ );
171+ null /* stateCallback */ , null /* audioSamplesReadyCallback */ , false /* useLowLatency */ , true /* enableVolumeLogger */ );
158172 }
159173
160174 WebRtcAudioTrack (Context context , AudioManager audioManager ,
161175 @ Nullable AudioAttributes audioAttributes , @ Nullable AudioTrackErrorCallback errorCallback ,
162- @ Nullable AudioTrackStateCallback stateCallback , boolean useLowLatency ,
163- boolean enableVolumeLogger ) {
176+ @ Nullable AudioTrackStateCallback stateCallback , @ Nullable PlaybackSamplesReadyCallback audioSamplesReadyCallback ,
177+ boolean useLowLatency , boolean enableVolumeLogger ) {
164178 threadChecker .detachThread ();
165179 this .context = context ;
166180 this .audioManager = audioManager ;
167181 this .audioAttributes = audioAttributes ;
168182 this .errorCallback = errorCallback ;
169183 this .stateCallback = stateCallback ;
170184 this .volumeLogger = enableVolumeLogger ? new VolumeLogger (audioManager ) : null ;
185+ this .audioSamplesReadyCallback = audioSamplesReadyCallback ;
171186 this .useLowLatency = useLowLatency ;
172187 Logging .d (TAG , "ctor" + WebRtcAudioUtils .getThreadInfo ());
173188 }
0 commit comments