package org.webrtc.voiceengine; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Process; import java.nio.ByteBuffer; import org.webrtc.ContextUtils; import org.webrtc.Logging; import org.webrtc.ThreadUtils; /* loaded from: classes3.dex */ public class WebRtcAudioTrack { private static final long AUDIO_TRACK_THREAD_JOIN_TIMEOUT_MS = 2000; private static final int BITS_PER_SAMPLE = 16; private static final int BUFFERS_PER_SECOND = 100; private static final int CALLBACK_BUFFER_SIZE_MS = 10; private static final boolean DEBUG = false; private static final int DEFAULT_USAGE; private static final String TAG = "WebRtcAudioTrack"; private static ErrorCallback errorCallback; private static WebRtcAudioTrackErrorCallback errorCallbackOld; private static volatile boolean speakerMute; private static int usageAttribute; private final AudioManager audioManager; private AudioTrackThread audioThread; private AudioTrack audioTrack; private ByteBuffer byteBuffer; private byte[] emptyBytes; private final long nativeAudioTrack; private final ThreadUtils.ThreadChecker threadChecker; /* loaded from: classes3.dex */ public enum AudioTrackStartErrorCode { AUDIO_TRACK_START_EXCEPTION, AUDIO_TRACK_START_STATE_MISMATCH } /* loaded from: classes3.dex */ public interface ErrorCallback { void onWebRtcAudioTrackError(String str); void onWebRtcAudioTrackInitError(String str); void onWebRtcAudioTrackStartError(AudioTrackStartErrorCode audioTrackStartErrorCode, String str); } @Deprecated /* loaded from: classes3.dex */ public interface WebRtcAudioTrackErrorCallback { void onWebRtcAudioTrackError(String str); void onWebRtcAudioTrackInitError(String str); void onWebRtcAudioTrackStartError(String str); } private int channelCountToConfiguration(int i) { return i == 1 ? 4 : 12; } private static int getDefaultUsageAttribute() { return 2; } private native void nativeCacheDirectBufferAddress(ByteBuffer byteBuffer, long j); /* JADX INFO: Access modifiers changed from: private */ public native void nativeGetPlayoutData(int i, long j); static { int defaultUsageAttribute = getDefaultUsageAttribute(); DEFAULT_USAGE = defaultUsageAttribute; usageAttribute = defaultUsageAttribute; } public static synchronized void setAudioTrackUsageAttribute(int i) { synchronized (WebRtcAudioTrack.class) { Logging.w(TAG, "Default usage attribute is changed from: " + DEFAULT_USAGE + " to " + i); usageAttribute = i; } } @Deprecated public static void setErrorCallback(WebRtcAudioTrackErrorCallback webRtcAudioTrackErrorCallback) { Logging.d(TAG, "Set error callback (deprecated"); errorCallbackOld = webRtcAudioTrackErrorCallback; } public static void setErrorCallback(ErrorCallback errorCallback2) { Logging.d(TAG, "Set extended error callback"); errorCallback = errorCallback2; } /* loaded from: classes3.dex */ private class AudioTrackThread extends Thread { private volatile boolean keepAlive; public AudioTrackThread(String str) { super(str); this.keepAlive = true; } @Override // java.lang.Thread, java.lang.Runnable public void run() { Process.setThreadPriority(-19); Logging.d(WebRtcAudioTrack.TAG, "AudioTrackThread" + WebRtcAudioUtils.getThreadInfo()); WebRtcAudioTrack.assertTrue(WebRtcAudioTrack.this.audioTrack.getPlayState() == 3); int capacity = WebRtcAudioTrack.this.byteBuffer.capacity(); while (this.keepAlive) { WebRtcAudioTrack webRtcAudioTrack = WebRtcAudioTrack.this; webRtcAudioTrack.nativeGetPlayoutData(capacity, webRtcAudioTrack.nativeAudioTrack); WebRtcAudioTrack.assertTrue(capacity <= WebRtcAudioTrack.this.byteBuffer.remaining()); if (WebRtcAudioTrack.speakerMute) { WebRtcAudioTrack.this.byteBuffer.clear(); WebRtcAudioTrack.this.byteBuffer.put(WebRtcAudioTrack.this.emptyBytes); WebRtcAudioTrack.this.byteBuffer.position(0); } int writeBytes = writeBytes(WebRtcAudioTrack.this.audioTrack, WebRtcAudioTrack.this.byteBuffer, capacity); if (writeBytes != capacity) { Logging.e(WebRtcAudioTrack.TAG, "AudioTrack.write played invalid number of bytes: " + writeBytes); if (writeBytes < 0) { this.keepAlive = false; WebRtcAudioTrack.this.reportWebRtcAudioTrackError("AudioTrack.write failed: " + writeBytes); } } WebRtcAudioTrack.this.byteBuffer.rewind(); } if (WebRtcAudioTrack.this.audioTrack != null) { Logging.d(WebRtcAudioTrack.TAG, "Calling AudioTrack.stop..."); try { WebRtcAudioTrack.this.audioTrack.stop(); Logging.d(WebRtcAudioTrack.TAG, "AudioTrack.stop is done."); } catch (IllegalStateException e) { Logging.e(WebRtcAudioTrack.TAG, "AudioTrack.stop failed: " + e.getMessage()); } } } private int writeBytes(AudioTrack audioTrack, ByteBuffer byteBuffer, int i) { return audioTrack.write(byteBuffer, i, 0); } public void stopThread() { Logging.d(WebRtcAudioTrack.TAG, "stopThread"); this.keepAlive = false; } } WebRtcAudioTrack(long j) { ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.ThreadChecker(); this.threadChecker = threadChecker; threadChecker.checkIsOnValidThread(); Logging.d(TAG, "ctor" + WebRtcAudioUtils.getThreadInfo()); this.nativeAudioTrack = j; this.audioManager = (AudioManager) ContextUtils.getApplicationContext().getSystemService("audio"); } private int initPlayout(int i, int i2, double d) { this.threadChecker.checkIsOnValidThread(); Logging.d(TAG, "initPlayout(sampleRate=" + i + ", channels=" + i2 + ", bufferSizeFactor=" + d + ")"); this.byteBuffer = ByteBuffer.allocateDirect(i2 * 2 * (i / 100)); Logging.d(TAG, "byteBuffer.capacity: " + this.byteBuffer.capacity()); this.emptyBytes = new byte[this.byteBuffer.capacity()]; nativeCacheDirectBufferAddress(this.byteBuffer, this.nativeAudioTrack); int channelCountToConfiguration = channelCountToConfiguration(i2); int minBufferSize = (int) (AudioTrack.getMinBufferSize(i, channelCountToConfiguration, 2) * d); Logging.d(TAG, "minBufferSizeInBytes: " + minBufferSize); if (minBufferSize < this.byteBuffer.capacity()) { reportWebRtcAudioTrackInitError("AudioTrack.getMinBufferSize returns an invalid value."); return -1; } if (this.audioTrack != null) { reportWebRtcAudioTrackInitError("Conflict with existing AudioTrack."); return -1; } try { AudioTrack createAudioTrackOnLollipopOrHigher = createAudioTrackOnLollipopOrHigher(i, channelCountToConfiguration, minBufferSize); this.audioTrack = createAudioTrackOnLollipopOrHigher; if (createAudioTrackOnLollipopOrHigher == null || createAudioTrackOnLollipopOrHigher.getState() != 1) { reportWebRtcAudioTrackInitError("Initialization of audio track failed."); releaseAudioResources(); return -1; } logMainParameters(); logMainParametersExtended(); return minBufferSize; } catch (IllegalArgumentException e) { reportWebRtcAudioTrackInitError(e.getMessage()); releaseAudioResources(); return -1; } } private boolean startPlayout() { this.threadChecker.checkIsOnValidThread(); Logging.d(TAG, "startPlayout"); assertTrue(this.audioTrack != null); assertTrue(this.audioThread == null); try { this.audioTrack.play(); if (this.audioTrack.getPlayState() != 3) { reportWebRtcAudioTrackStartError(AudioTrackStartErrorCode.AUDIO_TRACK_START_STATE_MISMATCH, "AudioTrack.play failed - incorrect state :" + this.audioTrack.getPlayState()); releaseAudioResources(); return false; } AudioTrackThread audioTrackThread = new AudioTrackThread("AudioTrackJavaThread"); this.audioThread = audioTrackThread; audioTrackThread.start(); return true; } catch (IllegalStateException e) { reportWebRtcAudioTrackStartError(AudioTrackStartErrorCode.AUDIO_TRACK_START_EXCEPTION, "AudioTrack.play failed: " + e.getMessage()); releaseAudioResources(); return false; } } private boolean stopPlayout() { this.threadChecker.checkIsOnValidThread(); Logging.d(TAG, "stopPlayout"); assertTrue(this.audioThread != null); logUnderrunCount(); this.audioThread.stopThread(); Logging.d(TAG, "Stopping the AudioTrackThread..."); this.audioThread.interrupt(); if (!ThreadUtils.joinUninterruptibly(this.audioThread, 2000L)) { Logging.e(TAG, "Join of AudioTrackThread timed out."); WebRtcAudioUtils.logAudioState(TAG); } Logging.d(TAG, "AudioTrackThread has now been stopped."); this.audioThread = null; releaseAudioResources(); return true; } private int getStreamMaxVolume() { this.threadChecker.checkIsOnValidThread(); Logging.d(TAG, "getStreamMaxVolume"); assertTrue(this.audioManager != null); return this.audioManager.getStreamMaxVolume(0); } private boolean setStreamVolume(int i) { this.threadChecker.checkIsOnValidThread(); Logging.d(TAG, "setStreamVolume(" + i + ")"); assertTrue(this.audioManager != null); if (isVolumeFixed()) { Logging.e(TAG, "The device implements a fixed volume policy."); return false; } this.audioManager.setStreamVolume(0, i, 0); return true; } private boolean isVolumeFixed() { return this.audioManager.isVolumeFixed(); } private int getStreamVolume() { this.threadChecker.checkIsOnValidThread(); Logging.d(TAG, "getStreamVolume"); assertTrue(this.audioManager != null); return this.audioManager.getStreamVolume(0); } private void logMainParameters() { Logging.d(TAG, "AudioTrack: session ID: " + this.audioTrack.getAudioSessionId() + ", channels: " + this.audioTrack.getChannelCount() + ", sample rate: " + this.audioTrack.getSampleRate() + ", max gain: " + AudioTrack.getMaxVolume()); } private static AudioTrack createAudioTrackOnLollipopOrHigher(int i, int i2, int i3) { Logging.d(TAG, "createAudioTrackOnLollipopOrHigher"); int nativeOutputSampleRate = AudioTrack.getNativeOutputSampleRate(0); Logging.d(TAG, "nativeOutputSampleRate: " + nativeOutputSampleRate); if (i != nativeOutputSampleRate) { Logging.w(TAG, "Unable to use fast mode since requested sample rate is not native"); } if (usageAttribute != DEFAULT_USAGE) { Logging.w(TAG, "A non default usage attribute is used: " + usageAttribute); } return new AudioTrack(new AudioAttributes.Builder().setUsage(usageAttribute).setContentType(1).build(), new AudioFormat.Builder().setEncoding(2).setSampleRate(i).setChannelMask(i2).build(), i3, 1, 0); } private static AudioTrack createAudioTrackOnLowerThanLollipop(int i, int i2, int i3) { return new AudioTrack(0, i, i2, 2, i3, 1); } private void logBufferSizeInFrames() { Logging.d(TAG, "AudioTrack: buffer size in frames: " + this.audioTrack.getBufferSizeInFrames()); } private int getBufferSizeInFrames() { return this.audioTrack.getBufferSizeInFrames(); } private void logBufferCapacityInFrames() { Logging.d(TAG, "AudioTrack: buffer capacity in frames: " + this.audioTrack.getBufferCapacityInFrames()); } private void logMainParametersExtended() { logBufferSizeInFrames(); logBufferCapacityInFrames(); } private void logUnderrunCount() { Logging.d(TAG, "underrun count: " + this.audioTrack.getUnderrunCount()); } /* JADX INFO: Access modifiers changed from: private */ public static void assertTrue(boolean z) { if (!z) { throw new AssertionError("Expected condition to be true"); } } public static void setSpeakerMute(boolean z) { Logging.w(TAG, "setSpeakerMute(" + z + ")"); speakerMute = z; } private void releaseAudioResources() { Logging.d(TAG, "releaseAudioResources"); AudioTrack audioTrack = this.audioTrack; if (audioTrack != null) { audioTrack.release(); this.audioTrack = null; } } private void reportWebRtcAudioTrackInitError(String str) { Logging.e(TAG, "Init playout error: " + str); WebRtcAudioUtils.logAudioState(TAG); WebRtcAudioTrackErrorCallback webRtcAudioTrackErrorCallback = errorCallbackOld; if (webRtcAudioTrackErrorCallback != null) { webRtcAudioTrackErrorCallback.onWebRtcAudioTrackInitError(str); } ErrorCallback errorCallback2 = errorCallback; if (errorCallback2 != null) { errorCallback2.onWebRtcAudioTrackInitError(str); } } private void reportWebRtcAudioTrackStartError(AudioTrackStartErrorCode audioTrackStartErrorCode, String str) { Logging.e(TAG, "Start playout error: " + audioTrackStartErrorCode + ". " + str); WebRtcAudioUtils.logAudioState(TAG); WebRtcAudioTrackErrorCallback webRtcAudioTrackErrorCallback = errorCallbackOld; if (webRtcAudioTrackErrorCallback != null) { webRtcAudioTrackErrorCallback.onWebRtcAudioTrackStartError(str); } ErrorCallback errorCallback2 = errorCallback; if (errorCallback2 != null) { errorCallback2.onWebRtcAudioTrackStartError(audioTrackStartErrorCode, str); } } /* JADX INFO: Access modifiers changed from: private */ public void reportWebRtcAudioTrackError(String str) { Logging.e(TAG, "Run-time playback error: " + str); WebRtcAudioUtils.logAudioState(TAG); WebRtcAudioTrackErrorCallback webRtcAudioTrackErrorCallback = errorCallbackOld; if (webRtcAudioTrackErrorCallback != null) { webRtcAudioTrackErrorCallback.onWebRtcAudioTrackError(str); } ErrorCallback errorCallback2 = errorCallback; if (errorCallback2 != null) { errorCallback2.onWebRtcAudioTrackError(str); } } }