diff options
Diffstat (limited to 'webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaEngine.java')
-rw-r--r-- | webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaEngine.java | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaEngine.java b/webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaEngine.java new file mode 100644 index 0000000000..a7036914ff --- /dev/null +++ b/webrtc/examples/android/media_demo/src/org/webrtc/webrtcdemo/MediaEngine.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc.webrtcdemo; + +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; +import android.os.Environment; +import android.util.Log; +import android.view.OrientationEventListener; +import java.io.File; + +public class MediaEngine { + private static final String LOG_DIR = "webrtc"; + + // Checks for and communicate failures to user (logcat and popup). + private void check(boolean value, String message) { + if (value) { + return; + } + Log.e("WEBRTC-CHECK", message); + AlertDialog alertDialog = new AlertDialog.Builder(context).create(); + alertDialog.setTitle("WebRTC Error"); + alertDialog.setMessage(message); + alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, + "OK", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + return; + } + } + ); + alertDialog.show(); + } + + + // Shared Audio/Video members. + private final Context context; + private String remoteIp; + private boolean enableTrace; + + // Audio + private VoiceEngine voe; + private int audioChannel; + private boolean audioEnabled; + private boolean voeRunning; + private int audioCodecIndex; + private int audioTxPort; + private int audioRxPort; + + private boolean speakerEnabled; + private boolean headsetPluggedIn; + private boolean enableAgc; + private boolean enableNs; + private boolean enableAecm; + + private BroadcastReceiver headsetListener; + + private boolean audioRtpDump; + private boolean apmRecord; + + private int inFps; + private int inKbps; + private int outFps; + private int outKbps; + private int inWidth; + private int inHeight; + + public MediaEngine(Context context) { + this.context = context; + voe = new VoiceEngine(); + check(voe.init() == 0, "Failed voe Init"); + audioChannel = voe.createChannel(); + check(audioChannel >= 0, "Failed voe CreateChannel"); + check(audioChannel >= 0, "Failed voe CreateChannel"); + + check(voe.setAecmMode(VoiceEngine.AecmModes.SPEAKERPHONE, false) == 0, + "VoE set Aecm speakerphone mode failed"); + + // Set audio mode to communication + AudioManager audioManager = + ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)); + audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + // Listen to headset being plugged in/out. + IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); + headsetListener = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().compareTo(Intent.ACTION_HEADSET_PLUG) == 0) { + headsetPluggedIn = intent.getIntExtra("state", 0) == 1; + updateAudioOutput(); + } + } + }; + context.registerReceiver(headsetListener, receiverFilter); + } + + public void dispose() { + check(!voeRunning && !voeRunning, "Engines must be stopped before dispose"); + context.unregisterReceiver(headsetListener); + check(voe.deleteChannel(audioChannel) == 0, "VoE delete channel failed"); + voe.dispose(); + } + + public void start() { + if (audioEnabled) { + startVoE(); + } + } + + public void stop() { + stopVoe(); + } + + public boolean isRunning() { + return voeRunning; + } + + public void setRemoteIp(String remoteIp) { + this.remoteIp = remoteIp; + UpdateSendDestination(); + } + + public String remoteIp() { return remoteIp; } + + private String getDebugDirectory() { + // Should create a folder in /scard/|LOG_DIR| + return Environment.getExternalStorageDirectory().toString() + "/" + + LOG_DIR; + } + + private boolean createDebugDirectory() { + File webrtc_dir = new File(getDebugDirectory()); + if (!webrtc_dir.exists()) { + return webrtc_dir.mkdir(); + } + return webrtc_dir.isDirectory(); + } + + public void startVoE() { + check(!voeRunning, "VoE already started"); + check(voe.startListen(audioChannel) == 0, "Failed StartListen"); + check(voe.startPlayout(audioChannel) == 0, "VoE start playout failed"); + check(voe.startSend(audioChannel) == 0, "VoE start send failed"); + voeRunning = true; + } + + private void stopVoe() { + check(voeRunning, "VoE not started"); + check(voe.stopSend(audioChannel) == 0, "VoE stop send failed"); + check(voe.stopPlayout(audioChannel) == 0, "VoE stop playout failed"); + check(voe.stopListen(audioChannel) == 0, "VoE stop listen failed"); + voeRunning = false; + } + + public void setAudio(boolean audioEnabled) { + this.audioEnabled = audioEnabled; + } + + public boolean audioEnabled() { return audioEnabled; } + + public int audioCodecIndex() { return audioCodecIndex; } + + public void setAudioCodec(int codecNumber) { + audioCodecIndex = codecNumber; + CodecInst codec = voe.getCodec(codecNumber); + check(voe.setSendCodec(audioChannel, codec) == 0, "Failed setSendCodec"); + codec.dispose(); + } + + public String[] audioCodecsAsString() { + String[] retVal = new String[voe.numOfCodecs()]; + for (int i = 0; i < voe.numOfCodecs(); ++i) { + CodecInst codec = voe.getCodec(i); + retVal[i] = codec.toString(); + codec.dispose(); + } + return retVal; + } + + private CodecInst[] defaultAudioCodecs() { + CodecInst[] retVal = new CodecInst[voe.numOfCodecs()]; + for (int i = 0; i < voe.numOfCodecs(); ++i) { + retVal[i] = voe.getCodec(i); + } + return retVal; + } + + public int getIsacIndex() { + CodecInst[] codecs = defaultAudioCodecs(); + for (int i = 0; i < codecs.length; ++i) { + if (codecs[i].name().contains("ISAC")) { + return i; + } + } + return 0; + } + + public void setAudioTxPort(int audioTxPort) { + this.audioTxPort = audioTxPort; + UpdateSendDestination(); + } + + public int audioTxPort() { return audioTxPort; } + + public void setAudioRxPort(int audioRxPort) { + check(voe.setLocalReceiver(audioChannel, audioRxPort) == 0, + "Failed setLocalReceiver"); + this.audioRxPort = audioRxPort; + } + + public int audioRxPort() { return audioRxPort; } + + public boolean agcEnabled() { return enableAgc; } + + public void setAgc(boolean enable) { + enableAgc = enable; + VoiceEngine.AgcConfig agc_config = + new VoiceEngine.AgcConfig(3, 9, true); + check(voe.setAgcConfig(agc_config) == 0, "VoE set AGC Config failed"); + check(voe.setAgcStatus(enableAgc, VoiceEngine.AgcModes.FIXED_DIGITAL) == 0, + "VoE set AGC Status failed"); + } + + public boolean nsEnabled() { return enableNs; } + + public void setNs(boolean enable) { + enableNs = enable; + check(voe.setNsStatus(enableNs, + VoiceEngine.NsModes.MODERATE_SUPPRESSION) == 0, + "VoE set NS Status failed"); + } + + public boolean aecmEnabled() { return enableAecm; } + + public void setEc(boolean enable) { + enableAecm = enable; + check(voe.setEcStatus(enable, VoiceEngine.EcModes.AECM) == 0, + "voe setEcStatus"); + } + + public boolean speakerEnabled() { + return speakerEnabled; + } + + public void setSpeaker(boolean enable) { + speakerEnabled = enable; + updateAudioOutput(); + } + + // Debug helpers. + public boolean apmRecord() { return apmRecord; } + + public boolean audioRtpDump() { return audioRtpDump; } + + public void setDebuging(boolean enable) { + apmRecord = enable; + if (!enable) { + check(voe.stopDebugRecording() == 0, "Failed stopping debug"); + return; + } + if (!createDebugDirectory()) { + check(false, "Unable to create debug directory."); + return; + } + String debugDirectory = getDebugDirectory(); + check(voe.startDebugRecording(debugDirectory + String.format("/apm_%d.dat", + System.currentTimeMillis())) == 0, + "Failed starting debug"); + } + + public void setIncomingVoeRtpDump(boolean enable) { + audioRtpDump = enable; + if (!enable) { + check(voe.stopRtpDump(audioChannel, + VoiceEngine.RtpDirections.INCOMING) == 0, + "voe stopping rtp dump"); + return; + } + String debugDirectory = getDebugDirectory(); + check(voe.startRtpDump(audioChannel, debugDirectory + + String.format("/voe_%d.rtp", System.currentTimeMillis()), + VoiceEngine.RtpDirections.INCOMING) == 0, + "voe starting rtp dump"); + } + + private void updateAudioOutput() { + boolean useSpeaker = !headsetPluggedIn && speakerEnabled; + AudioManager audioManager = + ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)); + audioManager.setSpeakerphoneOn(useSpeaker); + } + + private void UpdateSendDestination() { + if (remoteIp == null) { + return; + } + if (audioTxPort != 0) { + check(voe.setSendDestination(audioChannel, audioTxPort, + remoteIp) == 0, "VoE set send destination failed"); + } + } + + MediaEngineObserver observer; + public void setObserver(MediaEngineObserver observer) { + this.observer = observer; + } +} |