diff --git a/src/video_engine/main/test/android_test/jni/org_webrtc_videoengineapp_vie_android_java_api.h b/src/video_engine/main/test/android_test/jni/org_webrtc_videoengineapp_vie_android_java_api.h index 28c2cd529..f2beb409a 100644 --- a/src/video_engine/main/test/android_test/jni/org_webrtc_videoengineapp_vie_android_java_api.h +++ b/src/video_engine/main/test/android_test/jni/org_webrtc_videoengineapp_vie_android_java_api.h @@ -219,6 +219,22 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_EnablePL JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_SetCallback (JNIEnv *, jobject, jint, jobject); +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: StartIncomingRTPDump + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_StartIncomingRTPDump + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: StopIncomingRTPDump + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_StopIncomingRTPDump + (JNIEnv *, jobject, jint); + /* * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI * Method: VoE_Create @@ -429,6 +445,38 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Set JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1SetNSStatus (JNIEnv *, jobject, jboolean); +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StartDebugRecording + * Signature: (Ljava/lang/String)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StartDebugRecording + (JNIEnv *, jobject, jstring); + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StopDebugRecording + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StopDebugRecording + (JNIEnv *, jobject); + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StartIncomingRTPDump + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StartIncomingRTPDump + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StopIncomingRTPDump + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StopIncomingRTPDump + (JNIEnv *, jobject, jint); + #ifdef __cplusplus } #endif diff --git a/src/video_engine/main/test/android_test/jni/vie_android_java_api.cc b/src/video_engine/main/test/android_test/jni/vie_android_java_api.cc index 93e1e4486..4b44aa337 100644 --- a/src/video_engine/main/test/android_test/jni/vie_android_java_api.cc +++ b/src/video_engine/main/test/android_test/jni/vie_android_java_api.cc @@ -21,6 +21,7 @@ #include "voe_audio_processing.h" #include "voe_volume_control.h" #include "voe_hardware.h" +#include "voe_rtp_rtcp.h" #include "vie_base.h" #include "vie_codec.h" @@ -76,6 +77,14 @@ return -1; \ } +#define VALIDATE_RTP_POINTER \ + if (!voeData.rtp) \ + { \ + __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \ + "rtp pointer doesn't exist"); \ + return -1; \ + } + using namespace webrtc; //Forward declaration. @@ -94,6 +103,7 @@ typedef struct VoEAudioProcessing* apm; VoEVolumeControl* volume; VoEHardware* hardware; + VoERTP_RTCP* rtp; JavaVM* jvm; } VoiceEngineData; @@ -1031,6 +1041,57 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_SetCallb return 0; } +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: StartIncomingRTPDump + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_StartIncomingRTPDump( + JNIEnv* env, + jobject, + jint channel, + jstring filename) { + if (NULL == vieData.rtp) { + __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "video RTP_RTCP interface is null"); + return -1; + } + const char* file = env->GetStringUTFChars(filename, NULL); + if (!file) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Video StartRTPDump file name error"); + return -1; + } + if (vieData.rtp->StartRTPDump(channel, file, kRtpIncoming) != 0) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Video StartRTPDump error"); + return -1; + } + return 0; +} + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: StopIncomingRTPDump + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_StopIncomingRTPDump( + JNIEnv *, + jobject, + jint channel) { + if (NULL == vieData.rtp) { + __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "video RTP_RTCP interface is null"); + return -1; + } + if (vieData.rtp->StopRTPDump(channel, kRtpIncoming) != 0) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Video StopRTPDump error"); + return -1; + } + return 0; +} + // // VoiceEngine API wrapper functions // @@ -1569,6 +1630,91 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Set return 0; } +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StartDebugRecording + * Signature: (Ljava/lang/String)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StartDebugRecording( + JNIEnv* env, + jobject, + jstring filename) { + VALIDATE_APM_POINTER; + + const char* file = env->GetStringUTFChars(filename, NULL); + if (!file) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Voice StartDebugRecording file error"); + return -1; + } + if (voeData.apm->StartDebugRecording(file) != 0) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Voice StartDebugRecording error"); + return -1; + } + return 0; +} + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StopDebugRecording + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StopDebugRecording( + JNIEnv *, + jobject) { + VALIDATE_APM_POINTER; + if (voeData.apm->StopDebugRecording() < 0) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Voice StopDebugRecording error"); + return -1; + } + return 0; +} + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StartIncomingRTPDump + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StartIncomingRTPDump( + JNIEnv* env, + jobject, + jint channel, + jstring filename) { + VALIDATE_RTP_POINTER; + const char* file = env->GetStringUTFChars(filename, NULL); + if (!file) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Voice StartRTPDump file error"); + return -1; + } + if (voeData.rtp->StartRTPDump(channel, file, kRtpIncoming) != 0) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Voice StartRTPDump error"); + return -1; + } + return 0; +} + +/* + * Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI + * Method: VoE_StopRTPDump + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1StopRTPDump( + JNIEnv *, + jobject, + jint channel) { + VALIDATE_RTP_POINTER; + if (voeData.rtp->StopRTPDump(channel) < 0) { + __android_log_print(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Voice StopRTPDump error"); + return -1; + } + return 0; +} + // // local function // @@ -1633,6 +1779,14 @@ bool VE_GetSubApis() { getOK = false; } + // RTP + voeData.rtp = VoERTP_RTCP::GetInterface(voeData.ve); + if (!voeData.rtp) { + __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Get rtp sub-API failed"); + getOK = false; + } + return getOK; } @@ -1724,5 +1878,16 @@ bool VE_ReleaseSubApis() { } } + if (voeData.rtp) { + if (0 != voeData.rtp->Release()) { + __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, + "Release rtp sub-API failed"); + releaseOK = false; + } + else { + voeData.rtp = NULL; + } + } + return releaseOK; } diff --git a/src/video_engine/main/test/android_test/res/layout/aconfig.xml b/src/video_engine/main/test/android_test/res/layout/aconfig.xml index df6016f5a..5f995c6fb 100644 --- a/src/video_engine/main/test/android_test/res/layout/aconfig.xml +++ b/src/video_engine/main/test/android_test/res/layout/aconfig.xml @@ -71,6 +71,17 @@ android:id="@+id/cbSpeaker" android:text="@string/speaker"> + + + + + diff --git a/src/video_engine/main/test/android_test/res/layout/vconfig.xml b/src/video_engine/main/test/android_test/res/layout/vconfig.xml index 5270c1080..d72f25720 100644 --- a/src/video_engine/main/test/android_test/res/layout/vconfig.xml +++ b/src/video_engine/main/test/android_test/res/layout/vconfig.xml @@ -62,6 +62,12 @@ android:layout_height="wrap_content" android:id="@+id/cbNack" android:text="@string/nack"> - + + + + diff --git a/src/video_engine/main/test/android_test/res/values/strings.xml b/src/video_engine/main/test/android_test/res/values/strings.xml index 796491b69..82760b0a3 100644 --- a/src/video_engine/main/test/android_test/res/values/strings.xml +++ b/src/video_engine/main/test/android_test/res/values/strings.xml @@ -33,6 +33,8 @@ StopCall Exit Speaker +APMRecord +rtpdump SurfaceView OpenGL diff --git a/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/ViEAndroidJavaAPI.java b/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/ViEAndroidJavaAPI.java index f4a8c7293..9fd060eeb 100644 --- a/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/ViEAndroidJavaAPI.java +++ b/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/ViEAndroidJavaAPI.java @@ -81,6 +81,9 @@ public class ViEAndroidJavaAPI { // Enable stats callback public native int SetCallback(int channel, IViEAndroidCallback callback); + public native int StartIncomingRTPDump(int channel, String file); + public native int StopIncomingRTPDump(int channel); + // Voice Engine API // Create and Delete functions public native boolean VoE_Create(); @@ -132,8 +135,12 @@ public class ViEAndroidJavaAPI { public native String[] VoE_GetCodecs(); public native int VoE_SetSendCodec(int channel, int index); - //VE funtions + //VoiceEngine funtions public native int VoE_SetECStatus(boolean enable); public native int VoE_SetAGCStatus(boolean enable); public native int VoE_SetNSStatus(boolean enable); + public native int VoE_StartDebugRecording(String file); + public native int VoE_StopDebugRecording(); + public native int VoE_StartIncomingRTPDump(int channel, String file); + public native int VoE_StopIncomingRTPDump(int channel); } diff --git a/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/WebRTCDemo.java b/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/WebRTCDemo.java index 0db9fa88b..b5bbc93b6 100644 --- a/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/WebRTCDemo.java +++ b/src/video_engine/main/test/android_test/src/org/webrtc/videoengineapp/WebRTCDemo.java @@ -10,6 +10,7 @@ package org.webrtc.videoengineapp; +import java.io.File; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -34,6 +35,7 @@ import android.graphics.Rect; import android.hardware.SensorManager; import android.media.AudioManager; import android.os.Bundle; +import android.os.Environment; import android.os.PowerManager; import android.os.PowerManager.WakeLock; @@ -136,6 +138,7 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, private int destinationPortVideo = 11111; private CheckBox cbEnableNack; private boolean enableNack = false; + private CheckBox cbEnableVideoRTPDump; // Audio settings private Spinner spVoiceCodecType; @@ -152,6 +155,8 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, private boolean enableAECM = false; private CheckBox cbEnableNS; private boolean enableNS = false; + private CheckBox cbEnableDebugAPM; + private CheckBox cbEnableVoiceRTPDump; // Stats variables private int frameRateI; @@ -160,9 +165,13 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, private int frameRateO; private int bitRateO; + // Variable for storing variables + private String webrtcName = "/webrtc"; + private String webrtcDebugDir = null; + private WakeLock wakeLock; - private boolean usingFrontCamera = false; + private boolean usingFrontCamera = true; private String[] mVideoCodecsStrings = null; private String[] mVideoCodecsSizeStrings = { "176x144", "320x240", @@ -261,6 +270,18 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, }; orientationListener.enable (); + // Create a folder named webrtc in /scard for debugging + webrtcDebugDir = Environment.getExternalStorageDirectory().toString() + + webrtcName; + File webrtcDir = new File(webrtcDebugDir); + if (!webrtcDir.exists() && webrtcDir.mkdir() == false) { + Log.v(TAG, "Failed to create " + webrtcDebugDir); + } + else if (!webrtcDir.isDirectory()) { + Log.v(TAG, webrtcDebugDir + " exists but not a folder"); + webrtcDebugDir = null; + } + StartMain(); return; } @@ -494,6 +515,15 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, cbEnableNS = (CheckBox) findViewById(R.id.cbNoiseSuppression); cbEnableNS.setChecked(enableNS); + cbEnableDebugAPM = (CheckBox) findViewById(R.id.cbDebugRecording); + cbEnableDebugAPM.setChecked(false); // Disable APM debugging by default + + cbEnableVideoRTPDump = (CheckBox) findViewById(R.id.cbVideoRTPDump); + cbEnableVideoRTPDump.setChecked(false); // Disable Video RTP Dump + + cbEnableVoiceRTPDump = (CheckBox) findViewById(R.id.cbVoiceRTPDump); + cbEnableVoiceRTPDump.setChecked(false); // Disable Voice RTP Dump + etRemoteIp.setOnClickListener(this); cbLoopback.setOnClickListener(this); cbStats.setOnClickListener(this); @@ -502,6 +532,9 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, cbEnableAECM.setOnClickListener(this); cbEnableAGC.setOnClickListener(this); cbEnableNS.setOnClickListener(this); + cbEnableDebugAPM.setOnClickListener(this); + cbEnableVideoRTPDump.setOnClickListener(this); + cbEnableVoiceRTPDump.setOnClickListener(this); if (loopbackMode) { remoteIp = LOOPBACK_IP; @@ -807,6 +840,42 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback, RouteAudio(enableSpeaker); } break; + case R.id.cbDebugRecording: + if(voERunning && webrtcDebugDir != null) { + if (cbEnableDebugAPM.isChecked() ) { + ViEAndroidAPI.VoE_StartDebugRecording( + webrtcDebugDir + String.format("/apm_%d.dat", + System.currentTimeMillis())); + } + else { + ViEAndroidAPI.VoE_StopDebugRecording(); + } + } + break; + case R.id.cbVoiceRTPDump: + if(voERunning && webrtcDebugDir != null) { + if (cbEnableVoiceRTPDump.isChecked() ) { + ViEAndroidAPI.VoE_StartIncomingRTPDump(channel, + webrtcDebugDir + String.format("/voe_%d.rtp", + System.currentTimeMillis())); + } + else { + ViEAndroidAPI.VoE_StopIncomingRTPDump(channel); + } + } + break; + case R.id.cbVideoRTPDump: + if(viERunning && webrtcDebugDir != null) { + if (cbEnableVideoRTPDump.isChecked() ) { + ViEAndroidAPI.StartIncomingRTPDump(channel, + webrtcDebugDir + String.format("/vie_%d.rtp", + System.currentTimeMillis())); + } + else { + ViEAndroidAPI.StopIncomingRTPDump(channel); + } + } + break; case R.id.cbAutoGainControl: enableAGC=cbEnableAGC.isChecked(); if(voERunning) {