├── .gitignore ├── .idea ├── compiler.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── jarRepositories.xml ├── migrations.xml ├── misc.xml ├── modules.xml ├── modules │ └── app │ │ ├── streaming-android.app.androidTest.iml │ │ ├── streaming-android.app.iml │ │ ├── streaming-android.app.main.iml │ │ └── streaming-android.app.unitTest.iml └── vcs.xml ├── LICENSE ├── README.md ├── TestAndroidProject.iml ├── android-streaming-testbed.iml ├── app ├── .gitignore ├── build.gradle ├── libs │ └── red5streaming.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── red5pro │ │ └── org │ │ └── testandroidproject │ │ ├── ParamTableActivity.java │ │ ├── PublishTestListener.java │ │ ├── TestDetailFragment.java │ │ ├── TestListActivity.java │ │ ├── TestListFragment.java │ │ └── tests │ │ ├── BandwidthDetectionDownloadOnlyTest │ │ ├── BandwidthDetectionDownloadOnlyTest.java │ │ └── README.md │ │ ├── BandwidthDetectionTest │ │ ├── BandwidthDetectionTest.java │ │ └── README.md │ │ ├── BandwidthDetectionUploadOnlyTest │ │ ├── BandwidthDetectionUploadOnlyTest.java │ │ └── README.md │ │ ├── ConferenceStreamManagerTest │ │ ├── ConferenceStreamManagerTest.java │ │ └── README.md │ │ ├── ConferenceTest │ │ ├── ConferenceTest.java │ │ ├── README.md │ │ └── WebSocketProvider.java │ │ ├── Home │ │ └── Home.java │ │ ├── ParamTable │ │ └── ParamTable.java │ │ ├── PublishABRTest │ │ ├── PublishABRTest.java │ │ └── README.md │ │ ├── PublishAspectTest │ │ ├── PublishAspectTest.java │ │ └── README.md │ │ ├── PublishAuthTest │ │ ├── PublishAuthTest.java │ │ └── README.md │ │ ├── PublishBackgroundTest │ │ ├── PublishBackgroundTest.java │ │ ├── PublishService.java │ │ └── README.md │ │ ├── PublishCamera2Test │ │ ├── PublishCamera2Test.java │ │ └── README.md │ │ ├── PublishCameraDeviceOrientationTest │ │ ├── PublishCameraDeviceOrientationTest.java │ │ └── README.md │ │ ├── PublishCameraSwapBlinkTest │ │ ├── PublishCameraSwapBlinkTest.java │ │ └── README.md │ │ ├── PublishCameraSwapTest │ │ ├── PublishCameraSwapTest.java │ │ └── README.md │ │ ├── PublishCustomMicTest │ │ ├── PublishCustomMicTest.java │ │ └── Readme.md │ │ ├── PublishCustomSourceTest │ │ ├── CustomVideoSource.java │ │ ├── PublishCustomSourceTest.java │ │ └── Readme.md │ │ ├── PublishDeviceOrientationTest │ │ ├── PublishDeviceOrientationTest.java │ │ └── README.md │ │ ├── PublishEncryptedTest │ │ ├── PublishEncryptedTest.java │ │ └── README.md │ │ ├── PublishHQAudioTest │ │ ├── PublishHQAudioTest.java │ │ └── README.md │ │ ├── PublishImageTest │ │ ├── PublishImageTest.java │ │ └── README.md │ │ ├── PublishLocalRecordTest │ │ ├── PublishLocalRecordTest.java │ │ └── README.md │ │ ├── PublishOrientationTest │ │ ├── PublishOrientationTest.java │ │ └── README.md │ │ ├── PublishPauseTest │ │ ├── PublishPauseTest.java │ │ └── README.md │ │ ├── PublishRemoteCallTest │ │ ├── PublishRemoteCallTest.java │ │ └── README.md │ │ ├── PublishSMEncryptedTest │ │ ├── PublishSMEncryptedTest.java │ │ └── README.md │ │ ├── PublishSMEncryptedTest_SM1 │ │ ├── PublishSMEncryptedTest_SM1.java │ │ └── README.md │ │ ├── PublishStreamManagerTest │ │ ├── PublishStreamManagerTest.java │ │ └── README.md │ │ ├── PublishStreamManagerTest_SM1 │ │ ├── PublishStreamManagerTest_SM1.java │ │ └── README.md │ │ ├── PublishStreamManagerTranscodeTest │ │ ├── PublishStreamManagerTranscodeTest.java │ │ ├── PublishTranscoderData.java │ │ ├── PublishTranscoderForm.java │ │ └── README.md │ │ ├── PublishStreamManagerTranscodeTest_SM1 │ │ ├── PublishStreamManagerTranscodeTest_SM1.java │ │ ├── PublishTranscoderData_SM1.java │ │ ├── PublishTranscoderForm_SM1.java │ │ └── README.md │ │ ├── PublishTest │ │ ├── PublishTest.java │ │ └── README.md │ │ ├── RecordedTest │ │ ├── Readme.md │ │ └── RecordedTest.java │ │ ├── SharedObjectStreamlessTest │ │ ├── README.md │ │ └── SharedObjectStreamlessTest.java │ │ ├── SharedObjectTest │ │ ├── README.md │ │ └── SharedObjectTest.java │ │ ├── Subscribe360Test │ │ ├── CustomVideoViewRenderer.java │ │ └── Subscribe360Test.java │ │ ├── SubscribeAspectTest │ │ ├── README.md │ │ └── SubscribeAspectTest.java │ │ ├── SubscribeAuthTest │ │ ├── README.md │ │ └── SubscribeAuthTest.java │ │ ├── SubscribeBackgroundTest │ │ ├── README.md │ │ ├── SubscribeBackgroundTest.java │ │ └── SubscribeService.java │ │ ├── SubscribeBandwidthTest │ │ ├── README.md │ │ └── SubscribeBandwidthTest.java │ │ ├── SubscribeCluster │ │ ├── README.md │ │ └── SubscribeCluster.java │ │ ├── SubscribeEncryptedTest │ │ ├── README.md │ │ └── SubscribeEncryptedTest.java │ │ ├── SubscribeHardwareAccelerationTest │ │ ├── README.md │ │ └── SubscribeHardwareAccelerationTest.java │ │ ├── SubscribeImageTest │ │ ├── README.md │ │ └── SubscribeImageTest.java │ │ ├── SubscribeMuteTest │ │ ├── README.md │ │ └── SubscribeMuteTest.java │ │ ├── SubscribeNoViewTest │ │ ├── README.md │ │ └── SubscribeNoViewTest.java │ │ ├── SubscribeReconnectTest │ │ ├── README.md │ │ └── SubscribeReconnectTest.java │ │ ├── SubscribeRemoteCallTest │ │ ├── README.md │ │ └── SubscribeRemoteCallTest.java │ │ ├── SubscribeRendererRGBScalarTest │ │ ├── README.md │ │ └── SubscribeRendererRGBScalarTest.java │ │ ├── SubscribeSMEncryptedTest │ │ ├── README.md │ │ └── SubscribeSMEncryptedTest.java │ │ ├── SubscribeSMEncryptedTest_SM1 │ │ ├── README.md │ │ └── SubscribeSMEncryptedTest_SM1.java │ │ ├── SubscribeSetVolumeTest │ │ ├── README.md │ │ └── SubscribeSetVolumeTest.java │ │ ├── SubscribeStreamManagerTest │ │ ├── README.md │ │ └── SubscribeStreamManagerTest.java │ │ ├── SubscribeStreamManagerTest_SM1 │ │ ├── README.md │ │ └── SubscribeStreamManagerTest_SM1.java │ │ ├── SubscribeStreamManagerTranscoderTest │ │ ├── README.md │ │ └── SubscribeStreamManagerTranscoderTest.java │ │ ├── SubscribeStreamManagerTranscoderTest_SM1 │ │ ├── README.md │ │ └── SubscribeStreamManagerTranscoderTest_SM1.java │ │ ├── SubscribeTest │ │ ├── README.md │ │ └── SubscribeTest.java │ │ ├── SubscribeTwoStreamTest │ │ ├── Readme.md │ │ └── SubscribeTwoStreamTest.java │ │ └── TestContent.java │ ├── jniLibs │ ├── arm64-v8a │ │ ├── libred5android.so │ │ └── libred5streaming.so │ ├── armeabi-v7a │ │ ├── libred5android.so │ │ └── libred5streaming.so │ └── x86 │ │ ├── libred5android.so │ │ └── libred5streaming.so │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ └── ic_launcher.png │ ├── layout-sw600dp │ └── activity_test_list.xml │ ├── layout │ ├── activity_param_table.xml │ ├── activity_test_list.xml │ ├── bg_publish_test.xml │ ├── bg_subscribe_test.xml │ ├── conference_test.xml │ ├── double_view.xml │ ├── fragment_param_table.xml │ ├── fragment_test_detail.xml │ ├── home_screen.xml │ ├── param_table_row_editable.xml │ ├── publish_sm_transcoder_test.xml │ ├── publish_test.xml │ ├── shared_object_streamless_test.xml │ ├── shared_object_test.xml │ ├── subscribe_mute_test.xml │ ├── subscribe_scrub_test.xml │ ├── subscribe_sm_transcoder_test.xml │ ├── subscribe_test.xml │ └── twoway_test.xml │ ├── raw │ └── tests.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── git-hooks ├── README.md └── pre-commit ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── scripts ├── LICENSE_INJECT └── license_inject.sh ├── settings.gradle └── streaming-android.iml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # Explicitly allow the following files # 12 | !red5streaming.jar 13 | 14 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 15 | hs_err_pid* 16 | 17 | .gradle 18 | /local.properties 19 | /.idea/workspace.xml 20 | /.idea/libraries 21 | .DS_Store 22 | /build 23 | /.idea/caches 24 | /.idea/codeStyles 25 | /.idea/copilot 26 | /.idea/deploymentTargetDropDown.xml 27 | /.idea/migrations.xml 28 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 39 | 40 | 44 | 45 | 49 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/modules/app/streaming-android.app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2015 Infrared5, Inc. All rights reserved. 2 | 3 | The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 4 | is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 5 | license terms and conditions. Access, use, modification, or redistribution of the accompanying 6 | code constitutes your acceptance of the following license terms and conditions. 7 | 8 | Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 9 | files (collectively, the "Software") without restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 11 | persons to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 14 | user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 15 | An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 16 | 17 | The above copyright notice and this license shall be included in all copies or portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 20 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /TestAndroidProject.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /android-streaming-testbed.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | android { 3 | compileSdkVersion 30 4 | buildToolsVersion '19.1.0' 5 | defaultConfig { 6 | applicationId "red5pro.org.testandroidproject" 7 | minSdkVersion 26 8 | targetSdkVersion 30 9 | versionCode 9000 10 | versionName "10.9.0.0" 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | } 18 | lintOptions { 19 | checkReleaseBuilds false 20 | // Or, if you prefer, you can continue to check for errors in release builds, 21 | // but continue the build even when errors are found: 22 | abortOnError false 23 | } 24 | // productFlavors { 25 | // 26 | // armv7 { 27 | // ndk { 28 | // abiFilters "armeabi-v7a" 29 | // } 30 | // } 31 | // 32 | //// x86{ 33 | //// ndk{ 34 | //// abiFilters "x86" 35 | //// } 36 | //// } 37 | // 38 | // } 39 | buildToolsVersion '28.0.3' 40 | useLibrary 'org.apache.http.legacy' 41 | } 42 | dependencies { 43 | implementation fileTree(include: ['*.jar'], dir: 'libs') 44 | implementation 'org.java-websocket:Java-WebSocket:1.5.2' 45 | implementation 'ch.qos.logback:logback-classic:1.2.3' 46 | implementation 'ch.qos.logback:logback-core:1.2.3' 47 | implementation 'org.apache.mina:mina-core:2.1.3' 48 | implementation 'org.slf4j:slf4j-api:1.7.28' 49 | implementation 'com.googlecode.mp4parser:isoparser:1.1.22' 50 | implementation 'com.google.code.gson:gson:2.8.6' 51 | implementation 'androidx.legacy:legacy-support-core-ui:1.0.0' 52 | } 53 | -------------------------------------------------------------------------------- /app/libs/red5streaming.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/libs/red5streaming.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | #-keep class com.red5pro.streaming.** { *; } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 21 | 22 | 27 | 28 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 49 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/ParamTableActivity.java: -------------------------------------------------------------------------------- 1 | package red5pro.org.testandroidproject; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.WindowManager; 6 | 7 | public class ParamTableActivity extends Activity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_param_table); 12 | 13 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 14 | 15 | // Show the Up button in the action bar. 16 | getActionBar().setDisplayHomeAsUpEnabled(true); 17 | 18 | // savedInstanceState is non-null when there is fragment state 19 | // saved from previous configurations of this activity 20 | // (e.g. when rotating the screen from portrait to landscape). 21 | // In this case, the fragment will automatically be re-added 22 | // to its container so we don't need to manually add it. 23 | // For more information, see the Fragments API guide at: 24 | // 25 | // http://developer.android.com/guide/components/fragments.html 26 | // 27 | if (savedInstanceState == null) { 28 | // Create the detail fragment and add it to the activity 29 | // using a fragment transaction. 30 | // Bundle arguments = new Bundle(); 31 | // arguments.putString(TestDetailFragment.ARG_ITEM_ID, 32 | // getIntent().getStringExtra(TestDetailFragment.ARG_ITEM_ID)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/PublishTestListener.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject; 27 | 28 | /** 29 | * Created by toddanderson on 8/10/17. 30 | */ 31 | 32 | public interface PublishTestListener { 33 | void onPublishFlushBufferStart(); 34 | void onPublishFlushBufferComplete(); 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/BandwidthDetectionDownloadOnlyTest/README.md: -------------------------------------------------------------------------------- 1 | # Bandwidth Detection (Download) with Red5 Pro 2 | 3 | This example shows how to easily detect download bandwidth with Red5 Pro prior to subscribing to a stream. 4 | 5 | ## Example Code 6 | 7 | * **_[TestDetailFragment.java](../../TestDetailFragment.java)_** 8 | * **_[BandwidthDetectionDownloadOnlyTest.java](BandwidthDetectionDownloadOnlyTest.java)_** 9 | 10 | ## How to Check Bandwidth 11 | 12 | Checking the download bandwidth prior to subscribing to a stream is relatively simple, requiring only a few pieces of setup. 13 | 14 | 1. One must [instantiate an `R5BandwidthDetection` instance](BandwidthDetectionDownloadOnlyTest.java#L75) 15 | 2. One must then [utilize the `checkDownloadSpeed` method](BandwidthDetectionDownloadOnlyTest.java#L77) of that instance 16 | 3. Doing so requires passing in: 17 | 1. The base url (usually the same as the `host` you would provide to your `R5Configuration`) 18 | 2. How long you wish the total bandwidth test to take, in seconds 19 | 3. Callback blocks for the successful and unsuccessful attempts at checking the bandwidth 20 | 21 | A simplified example of this would be: 22 | 23 | ```java 24 | R5BandwidthDetection detection = new R5BandwidthDetection(this); // Or your listener that implements R5BandwidthDetection.CallbackListener 25 | try { 26 | detection.checkDownloadSpeed("your-host-here", 2.5); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | ``` 31 | 32 | The rest of this example is based on [SubscribeTest.java](../SubscribeTest/) and ensures that a [minimum bandwidth](BandwidthDetectionDownloadOnlyTest.java#L153) (as [defined by the `tests.xml` file](../../../../../../res/raw/tests.xml#L3)) is met prior to subscribing to the stream. 33 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/BandwidthDetectionTest/README.md: -------------------------------------------------------------------------------- 1 | # Bandwidth Detection with Red5 Pro 2 | 3 | This example shows how to easily detect upload and download bandwidth with Red5 Pro prior to beginning a stream. 4 | 5 | ## Example Code 6 | 7 | * **_[TestDetailFragment.java](../../TestDetailFragment.java)_** 8 | * **_[BandwidthDetectionTest.java](BandwidthDetectionTest.java)_** 9 | 10 | ## How to Check Bandwidth 11 | 12 | Checking the bandwidth (download and upload simultaneously) prior to beginning a stream is relatively simple, requiring only a few pieces of setup. 13 | 14 | 1. One must [instantiate an `R5BandwidthDetection` instance](BandwidthDetectionTest.java#L75) 15 | 2. One must then [utilize the `checkSpeeds` method](BandwidthDetectionTest.java#L77) of that instance 16 | 3. Doing so requires passing in: 17 | 1. The base url (usually the same as the `host` you would provide to your `R5Configuration`) 18 | 2. How long you wish the total bandwidth test to take, in seconds 19 | 3. Callback blocks for the successful and unsuccessful attempts at checking the bandwidth 20 | 21 | A simplified example of this would be: 22 | 23 | ```java 24 | R5BandwidthDetection detection = new R5BandwidthDetection(this); // Or your listener that implements R5BandwidthDetection.CallbackListener 25 | try { 26 | detection.checkSpeeds("your-host-here", 2.5); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | ``` 31 | 32 | The rest of this example is based on [SubscribeTest.java](../SubscribeTest/) and ensures that a [minimum bandwidth](BandwidthDetectionTest.java#L158) (as [defined by the `tests.xml` file](../../../../../../res/raw/tests.xml#L3)) is met prior to subscribing to the stream. 33 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/BandwidthDetectionUploadOnlyTest/README.md: -------------------------------------------------------------------------------- 1 | # Bandwidth Detection (Upload) with Red5 Pro 2 | 3 | This example shows how to easily detect upload bandwidth with Red5 Pro prior to publishing a stream. 4 | 5 | ## Example Code 6 | 7 | * **_[TestDetailFragment.java](../../TestDetailFragment.java)_** 8 | * **_[BandwidthDetectionUploadOnlyTest.java](BandwidthDetectionUploadOnlyTest.java)_** 9 | 10 | ## How to Check Bandwidth 11 | 12 | Checking the upload bandwidth prior to publishing a stream is relatively simple, requiring only a few pieces of setup. 13 | 14 | 1. One must [instantiate an `R5BandwidthDetection` instance](BandwidthDetectionUploadOnlyTest.java#L92) 15 | 2. One must then [utilize the `checkUploadSpeed` method](BandwidthDetectionUploadOnlyTest.java#L94) of that instance 16 | 3. Doing so requires passing in: 17 | 1. The base url (usually the same as the `host` you would provide to your `R5Configuration`) 18 | 2. How long you wish the total bandwidth test to take, in seconds 19 | 3. Callback blocks for the successful and unsuccessful attempts at checking the bandwidth 20 | 21 | A simplified example of this would be: 22 | 23 | ```java 24 | R5BandwidthDetection detection = new R5BandwidthDetection(this); // Or your listener that implements R5BandwidthDetection.CallbackListener 25 | try { 26 | detection.checkUploadSpeed("your-host-here", 2.5); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | ``` 31 | 32 | The rest of this example is based on [PublishTest.java](../PublishTest/) and ensures that a [minimum bandwidth](BandwidthDetectionUploadOnlyTest.java#L214) (as [defined by the `tests.xml` file](../../../../../../res/raw/tests.xml#L3)) is met prior to publishing to the stream. 33 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/ConferenceStreamManagerTest/README.md: -------------------------------------------------------------------------------- 1 | # Conference Chat 2 | 3 | This example demonstrates multi-party communication using Red5 Pro. It should be used in conjunction with a conference WebSocket host such as [this example](https://github.com/red5pro/red5pro-conference-host). 4 | 5 | It is recommended to view this example as part of the `webrtcexamples` webapp shipped with the [Red5 Pro Server](https://account.red5pro.com/download). 6 | 7 | ## Basic Publisher 8 | 9 | **Please refer to the [Basic Publisher Documentation](../PublishTest/README.md) to learn more about the basic setup of a publisher.** 10 | 11 | ## Basic Subscriber 12 | 13 | **Please refer to the [Basic Subscriber Documentation](../SubscribeTest/README.md) to learn more about the basic setup of a subscriber.** 14 | 15 | ## Example Code 16 | 17 | - **[ConferenceTest.java](ConferenceTest.java)** 18 | - **[WebSocketProvider.java](WebSocketProvider.java)** 19 | 20 | # Setup 21 | 22 | ## WebSocket Conference Host 23 | 24 | The `WebSocket Conference Host` refers to the socket endpoint that manages the list of active streams and their scopes for a given conference session. 25 | 26 | We have provided a basic example at [https://github.com/red5pro/red5pro-conference-host](https://github.com/red5pro/red5pro-conference-host). 27 | 28 | The endpoint for the `WebSocket Conference Host` is defined in the **tests.xml** as the `conference_host` property. By default it is set to a local IP address and port on your network (e.g., `ws://10.0.0.75:8001`). Change this to either the local IP or the remote IP of the machine that you launch the `WebSocket Conference Host` on. 29 | 30 | > The reason it is defined as a local IP on your network and not `localhost` is because `localhost` would refer to the actual device that the testbed is launched on. We assume you would not also be running the `WebSocket Conference Host` NodeJS server on your iOS device :) 31 | 32 | Once a publish session has begun, a connection to the `WebSocket Conference Host` is established and messages with regards to active stream listing are handled: 33 | 34 | ```java 35 | public void connectSocket () { 36 | final String sRoomName = this.roomName; 37 | String host = TestContent.GetPropertyString("conference_host") 38 | .replace("http:", "ws:") 39 | .replace("https:", "wss:"); 40 | String url = host + "?room=" + sRoomName + "&streamName=" + this.pubName; 41 | mWebSocketProvider = new WebSocketProvider(url); 42 | mWebSocketProvider.connect(new WebSocketProvider.OnWebSocketListener() { 43 | @Override 44 | public void onWebSocketMessage(String room, ArrayList streams) { 45 | if (room.equals(sRoomName)) { 46 | String streamNames = TextUtils.join(",", streams); 47 | stringToQueue(streamNames); 48 | } 49 | } 50 | }); 51 | } 52 | ``` 53 | 54 | ## Java-WebSocket 55 | 56 | By default, the WebSocket implementation used is the [Java-WebSocket](https://github.com/TooTallNate/Java-WebSocket) Java library. It is installed via `gradle`. 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/ConferenceTest/README.md: -------------------------------------------------------------------------------- 1 | # Conference Chat 2 | 3 | This example demonstrates multi-party communication using Red5 Pro. It should be used in conjunction with a conference WebSocket host such as [this example](https://github.com/red5pro/red5pro-conference-host). 4 | 5 | It is recommended to view this example as part of the `webrtcexamples` webapp shipped with the [Red5 Pro Server](https://account.red5pro.com/download). 6 | 7 | ## Basic Publisher 8 | 9 | **Please refer to the [Basic Publisher Documentation](../PublishTest/README.md) to learn more about the basic setup of a publisher.** 10 | 11 | ## Basic Subscriber 12 | 13 | **Please refer to the [Basic Subscriber Documentation](../SubscribeTest/README.md) to learn more about the basic setup of a subscriber.** 14 | 15 | ## Example Code 16 | 17 | - **[ConferenceTest.java](ConferenceTest.java)** 18 | - **[WebSocketProvider.java](WebSocketProvider.java)** 19 | 20 | # Setup 21 | 22 | ## WebSocket Conference Host 23 | 24 | The `WebSocket Conference Host` refers to the socket endpoint that manages the list of active streams and their scopes for a given conference session. 25 | 26 | We have provided a basic example at [https://github.com/red5pro/red5pro-conference-host](https://github.com/red5pro/red5pro-conference-host). 27 | 28 | The endpoint for the `WebSocket Conference Host` is defined in the **tests.xml** as the `conference_host` property. By default it is set to a local IP address and port on your network (e.g., `ws://10.0.0.75:8001`). Change this to either the local IP or the remote IP of the machine that you launch the `WebSocket Conference Host` on. 29 | 30 | > The reason it is defined as a local IP on your network and not `localhost` is because `localhost` would refer to the actual device that the testbed is launched on. We assume you would not also be running the `WebSocket Conference Host` NodeJS server on your iOS device :) 31 | 32 | Once a publish session has begun, a connection to the `WebSocket Conference Host` is established and messages with regards to active stream listing are handled: 33 | 34 | ```java 35 | public void connectSocket () { 36 | final String sRoomName = this.roomName; 37 | String host = TestContent.GetPropertyString("conference_host") 38 | .replace("http:", "ws:") 39 | .replace("https:", "wss:"); 40 | String url = host + "?room=" + sRoomName + "&streamName=" + this.pubName; 41 | mWebSocketProvider = new WebSocketProvider(url); 42 | mWebSocketProvider.connect(new WebSocketProvider.OnWebSocketListener() { 43 | @Override 44 | public void onWebSocketMessage(String room, ArrayList streams) { 45 | if (room.equals(sRoomName)) { 46 | String streamNames = TextUtils.join(",", streams); 47 | stringToQueue(streamNames); 48 | } 49 | } 50 | }); 51 | } 52 | ``` 53 | 54 | ## Java-WebSocket 55 | 56 | By default, the WebSocket implementation used is the [Java-WebSocket](https://github.com/TooTallNate/Java-WebSocket) Java library. It is installed via `gradle`. 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/ConferenceTest/WebSocketProvider.java: -------------------------------------------------------------------------------- 1 | package red5pro.org.testandroidproject.tests.ConferenceTest; 2 | 3 | import android.util.Log; 4 | 5 | import org.java_websocket.client.WebSocketClient; 6 | import org.java_websocket.handshake.ServerHandshake; 7 | import org.json.JSONArray; 8 | import org.json.JSONObject; 9 | 10 | import java.net.URI; 11 | import java.net.URISyntaxException; 12 | import java.util.ArrayList; 13 | 14 | public class WebSocketProvider { 15 | 16 | private String url; 17 | private WebSocketClient mWebSocketClient; 18 | 19 | interface OnWebSocketListener { 20 | void onWebSocketMessage(String room, ArrayList streams); 21 | } 22 | 23 | public WebSocketProvider (String url) { 24 | this.url = url; 25 | } 26 | 27 | private URI generateURI (String url) { 28 | try { 29 | return new URI(url); 30 | } catch (URISyntaxException e) { 31 | e.printStackTrace(); 32 | return null; 33 | } 34 | } 35 | 36 | public void connect (final WebSocketProvider.OnWebSocketListener callback) { 37 | URI uri = generateURI(url); 38 | if (uri == null) return; 39 | 40 | mWebSocketClient = new WebSocketClient(uri) { 41 | 42 | @Override 43 | public void onOpen(ServerHandshake handshakedata) {} 44 | 45 | @Override 46 | public void onMessage(String message) { 47 | Log.d("MESSAGE", message); 48 | try { 49 | JSONObject payload = new JSONObject(message); 50 | String room = payload.getString("room"); 51 | JSONArray streams = payload.getJSONArray("streams"); 52 | ArrayList streamNames = new ArrayList(); 53 | if (streams != null) { 54 | for (int i=0; i params) { 68 | Iterator iterator = params.entrySet().iterator(); 69 | while (iterator.hasNext()) { 70 | Map.Entry mapElement = (Map.Entry)iterator.next(); 71 | addFilledEntry((String)mapElement.getKey(), (String)mapElement.getValue()); 72 | } 73 | } 74 | 75 | private void addFilledEntry (String name, String value) { 76 | final View row = inflater.inflate(R.layout.param_table_row_editable, null,false); 77 | EditText nameField = (EditText) row.findViewById(R.id.name_field); 78 | EditText valueField = (EditText) row.findViewById(R.id.value_field); 79 | Button removeButton = (Button) row.findViewById(R.id.remove_button); 80 | removeButton.setOnClickListener(new View.OnClickListener() { 81 | @Override 82 | public void onClick(View v) { 83 | table.removeView(row); 84 | } 85 | }); 86 | nameField.setText(name); 87 | valueField.setText(value); 88 | table.addView(row); 89 | } 90 | 91 | private void addEmptyEntry () { 92 | final View row = inflater.inflate(R.layout.param_table_row_editable, null,false); 93 | Button removeButton = (Button) row.findViewById(R.id.remove_button); 94 | removeButton.setOnClickListener(new View.OnClickListener() { 95 | @Override 96 | public void onClick(View v) { 97 | table.removeView(row); 98 | } 99 | }); 100 | table.addView(row); 101 | } 102 | 103 | private boolean onAddTouch(MotionEvent e ) { 104 | if( e.getAction() == MotionEvent.ACTION_DOWN ) { 105 | addEmptyEntry(); 106 | } 107 | return true; 108 | } 109 | 110 | @Override 111 | public void onDestroy () { 112 | serializeConnectionParams(table); 113 | super.onDestroy(); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishABRTest/README.md: -------------------------------------------------------------------------------- 1 | # Adaptive Bitrate Publishing 2 | 3 | This example demonstrates the AdaptiveBitrateController, which provides a mechanism to dynamically adjust the video publishing bitrate to adjust quality to meet the bandwidth restrictions of the network connection or encoding hardware. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishABRTest.java](PublishABRTest.java)*** 9 | 10 | ### Setup 11 | 12 | The AdaptiveBitrateController is simple to setup. You simply create a new instance of the controller and attach the stream you wish to control. It will monitor the stream and make all adjustments automatically for you. 13 | 14 | ```Java 15 | R5AdaptiveBitrateController adaptor = new R5AdaptiveBitrateController(); 16 | adaptor.AttachStream(publish); 17 | ``` 18 | 19 | [PublishABRTest.java #56](PublishABRTest.java#L56) 20 | 21 | The controller will continuously adjust the video bitrate until the stream has closed. 22 | 23 | ### Range 24 | 25 | The AdaptiveBitrateController will dynamically adjust the video bitrate between the lowest possible bitrate the encoder can encode at, and the value set on the R5VideoSource (typically an R5Camera) on the stream. In this case, the value is assigned according to the value in tests.xml 26 | 27 | ```Java 28 | camera.setBitrate(TestContent.GetPropertyInt("bitrate")); 29 | ``` 30 | 31 | [PublishABRTest.java #53](PublishABRTest.java#L53) 32 | 33 | The controller will adjust the bitrate ~200 kbps every 2 seconds to achieve the best possible video quality. 34 | 35 | Video will be turned off if the stream is unable to maintain a smooth connection at the lowest possible bitrate. You can force video to be included with the `AdaptiveBitrateController.requiresVideo` flag. -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishAspectTest/PublishAspectTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishAspectTest; 27 | 28 | import android.os.Bundle; 29 | import android.view.MotionEvent; 30 | import android.view.View; 31 | 32 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 33 | 34 | /** 35 | * Created by davidHeimann on 11/20/17. 36 | */ 37 | 38 | public class PublishAspectTest extends PublishTest { 39 | 40 | public void onActivityCreated(Bundle savedInstanceState) { 41 | super.onActivityCreated(savedInstanceState); 42 | 43 | preview.setOnTouchListener(new View.OnTouchListener() { 44 | @Override 45 | public boolean onTouch(View v, MotionEvent event) { 46 | return onPublishTouch(event); 47 | } 48 | }); 49 | } 50 | 51 | private boolean onPublishTouch(MotionEvent e ) { 52 | 53 | if( e.getAction() == MotionEvent.ACTION_DOWN ) { 54 | int sMode = publish.getScaleMode(); 55 | 56 | sMode++; 57 | if(sMode == 3) sMode = 0; 58 | 59 | publish.setScaleMode(sMode); 60 | } 61 | 62 | return true; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishAspectTest/README.md: -------------------------------------------------------------------------------- 1 | # Publisher Aspect Ratio 2 | 3 | `R5VideoViewController.scaleMode` controls the display mode of the content that is being pushed to it. Depending on the value the content will scale to the appropriate fill value. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishAspectTest.java](PublishAspectTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Touch the screen at any time while streaming to change the scale mode, affecting how the stream is display on the user's end. 13 | 14 | ## Using scaleMode 15 | 16 | R5VideoViewController.scaleMode has 3 potential enum values. 17 | 18 | ```sh 19 | r5_scale_to_fill: scale to fill and maintain aspect ratio (cropping will occur) 20 | r5_scale_to_fit: scale to fit inside view (letterboxing will occur) 21 | r5_scale_fill: scale to fill view (will not respect aspect ratio of video) 22 | ``` 23 | 24 | By default, this value is `r5_scale_to_fill` and the android SDK handles this enum through raw int value (0,1,2) This example cycles through these values when it receives a tap. 25 | 26 | ```Java 27 | int sMode = subscribe.getScaleMode(); 28 | 29 | sMode++; 30 | //A value of 3 or larger won't parse correctly to the enum, so it's reset to 0 31 | if(sMode == 3) sMode = 0; 32 | 33 | subscribe.setScaleMode(sMode); 34 | ``` 35 | 36 | [PublishAspectTest.java #34](PublishAspectTest.java#L29) 37 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishAuthTest/README.md: -------------------------------------------------------------------------------- 1 | # Publisher Authentication using Red5 Pro 2 | 3 | This is an example of authenticating a Broadcast for stream playback. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishAuthTest.java](PublishAuthTest.java)*** 9 | 10 | > This example requires you to enable the `SimpleAuthentication` Plugin for the `live` webapp. More information: [https://www.red5pro.com/docs/](https://www.red5pro.com/docs/). 11 | 12 | ## Authenticating 13 | 14 | With the username and password known from the Red5 Pro Server `webapps/live/WEB-INF/simple-auth-plugin.credentials` file (if following the basic auth setup of the Red5 Pro Server), those values are provided to the `parameters` attribute of the `R5Configuration` instance delimited and appended with a semicolon (`;`). 15 | 16 | For example, if you have defined the authorization of a username `foo` with a password `bar`, the configuration addition would look like the following: 17 | 18 | ```java 19 | config.setParameters("username=foo;password=bar;"); 20 | ``` 21 | 22 | ### Example 23 | 24 | In the example, the `username` and `password` values are defined in the [test.xml](../../res/raw/test.xml#L123-L133) file entry for the *Publish - Auth* test. They are accessed and provided to the `R5Configuration` instance prior to establishing a connection: 25 | 26 | ```java 27 | String auth = "username=" + TestContent.GetPropertyString("username") + ";"; 28 | auth += "password=" + TestContent.GetPropertyString("password") + ";"; 29 | //Create the configuration from the values.xml 30 | R5Configuration config = new R5Configuration(R5StreamProtocol.RTSP, 31 | TestContent.GetPropertyString("host"), 32 | TestContent.GetPropertyInt("port"), 33 | TestContent.GetPropertyString("context"), 34 | TestContent.GetPropertyFloat("publish_buffer_time"), 35 | auth); 36 | config.setLicenseKey(TestContent.GetPropertyString("license_key")); 37 | config.setBundleID(getActivity().getPackageName()); 38 | ``` 39 | 40 | [PublishAuthTest.java #33](PublishAuthTest.java#L33) 41 | 42 | If the provided credentials match those defined for the `live` webapp in its Simple Authentication properties, then the broadcast will begin as normal. If the credentials _do not_ match, the broadcast will be rejected. 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCamera2Test/README.md: -------------------------------------------------------------------------------- 1 | # Publish Camera2 2 | 3 | Android's Camera2 api offers a robust suit of controls for the camera, but it needs to be handled significatnly differently than the deprecated Camera object. While most applications can use the standard Camera object for its simplicity, this is an example of using Camera2. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishCamera2Test.java](Publish2Test.java)*** 9 | 10 | ## Using R5Camera2 11 | 12 | Note that the Camera2 interface was added in Android API 21, with additional features included in API 22 - meaning that the minimum API for this class is higher than the rest of our SDK. 13 | 14 | The biggest change that you'll notice from the base publish example is that unlike a camera, a CameraDevice can't be opened syncronously, and so the creation of the R5Camera2 object and triggering of the publisher has to be done after Android has returned the device to you. 15 | To call for the device, you have to get the CameraManager, ask that for the list of cameras, identify the camera you want, and then open the camera from the manager. 16 | 17 | ```Java 18 | CameraManager manager = (CameraManager)getActivity().getSystemService(Context.CAMERA_SERVICE); 19 | try { 20 | String[] camList = manager.getCameraIdList(); 21 | for(String id : camList){ 22 | CameraCharacteristics info = manager.getCameraCharacteristics(id); 23 | if(info.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT){ 24 | camInfo = info; 25 | manager.openCamera(id, new CameraDevice.StateCallback() { 26 | @Override 27 | public void onOpened(@NonNull CameraDevice camera) { 28 | if(preview == null) 29 | return; 30 | startPublish(camera); 31 | } 32 | 33 | @Override 34 | public void onDisconnected(@NonNull CameraDevice camera) {} 35 | 36 | @Override 37 | public void onError(@NonNull CameraDevice camera, int error) {} 38 | }, null); 39 | break; 40 | } 41 | } 42 | 43 | } catch (CameraAccessException e) { 44 | e.printStackTrace(); 45 | } 46 | ``` 47 | 48 | [PublishCamera2Test.java #86](PublishCamera2Test.java#L86) 49 | 50 | Two things to note - 51 | 52 | * One, the CameraCharacteristics object to refer to the camera you're passing to the publisher must also be passed, so it's best to retain it here. 53 | * Two, the thread that the camera returns on won't necesarily be the UI thread, hence why the publisher is mostly set up before calling openCamera. 54 | 55 | After recieving the camera, the steps are similar to initializing an R5Camera object, with the addition of the CameraCharacteristics object in the constructor. 56 | 57 | ```Java 58 | camera2 = new R5Camera2(camera, camInfo, TestContent.GetPropertyInt("camera_width"), TestContent.GetPropertyInt("camera_height")); 59 | camera2.setBitrate(TestContent.GetPropertyInt("bitrate")); 60 | camera2.setOrientation(90); 61 | camera2.setFramerate(TestContent.GetPropertyInt("fps")); 62 | 63 | publish.attachCamera(camera2); 64 | ``` 65 | 66 | [PublishCamera2Test.java #122](PublishCamera2Test.java#L122) 67 | 68 | After that, the stream can be started as normal. 69 | 70 | ## Special Addendum - Capture Request Builder 71 | 72 | In addition to the basic functionality to mirror our implementation of the Camera interface, we have also added the ability for developers to take advantage of the advanced features of the Camera2 api. To reiterate, these additional features won't be of benefit to 99% of live streaming use cases, but the option is available for those few cases that need it. 73 | 74 | R5Camera2.setCaptureRequestBuilder will accept a CaptureRequest.Builder object and open a capture session with it. For any calculations that need to know the image format, we are using ImageFormat.YUV_420_888. Note that most of the advanced functionality of Camera2 has not been implemented by the manufactures of most phones, so take care when creating a builder. 75 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCameraDeviceOrientationTest/README.md: -------------------------------------------------------------------------------- 1 | # Publish Camera Device Orientation 2 | 3 | This example combines the `Camera Swap` and `Device Orientation` examples. For more information about either functionality, please refer to the separate tests. 4 | 5 | ### Example Code 6 | - ***[PublishCameraDeviceOrientationTest.java](PublishCameraDeviceOrientationTest.java)*** 7 | 8 | ### Separate Tests 9 | - ***[Publish - Camera Swap](../PublishCameraSwapTest)*** 10 | - ***[Publish - Device Orientation](../PublishDeviceOrientationTest)*** 11 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCameraSwapBlinkTest/README.md: -------------------------------------------------------------------------------- 1 | # Publish Camera Swap 2 | 3 | This example expands on the `Camera Swap` test by providing a customized form of the camera object to clear the screen while the camera device is being swapped. The front and back cameras of most devices are flipped from each other, meaning changes in camera selection often include changes in orientation. Since the changed metadata and new video data won't arrive at exactly the same time, this example is meant to prevent the subscriber from seeing upside-down images when the changes don't happen simultaneously. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[../PublishCameraSwapTest](PublishCameraSwapTest)*** 9 | - ***[PublishCameraSwapBlinkTest.java](PublishCameraSwapBlinkTest.java)*** 10 | 11 | ## Running the example 12 | 13 | Touch the screen at any time while streaming to switch between broadcasting from the front facing and back facing camera. 14 | 15 | ## Replacing Video Data 16 | 17 | To display a black frame instead of the image from either camera, muting the video isn't enough - the last image sent will still be displayed. Instead, the image heading to the encoder needs to be replaced with the data that's supposed to be displayed instead. While intercepting the data in `onPreviewFrame` is an option for the R5Camera, it's easier - and more universally aplicable - to replace the data as it's passed to the encoder. 18 | 19 | ```Java 20 | @Override 21 | public synchronized void encode(byte[] input, long time, boolean reset) { 22 | // Replacing data here instead of onPreviewFrame to prevent interrupting the output buffer swaps 23 | if(coverCam){ 24 | input = blackData; 25 | } 26 | 27 | super.encode(input, time, reset); 28 | } 29 | ``` 30 | 31 | [PublishCameraSwapBlinkTest.java #129](PublishCameraSwapBlinkTest.java#L129) 32 | 33 | `blackData` in this case is just an array of bytes that's been pre-populated with the yuv data for a black frame of the appropriate size. This technique can be used to display graphics for intermissions or other cases as well. 34 | 35 | After setting the camera to a black frame, it's important to wait at least 2 frames before and after swapping cameras, to give the system enough time to capture and apply the changes. Also remember that many devices don't allow apps to access the camera unless the code that's doing so is running on the main thread. 36 | 37 | ```Java 38 | ((R5BlinkCamera)camera).coverCam = true; 39 | 40 | // Wait for two frames, guarantees at least one black frame is sent pre- and post- swap 41 | final int waitMS = 2000/camera.getFramerate(); 42 | 43 | System.out.println(" TESTING - On Publish Touch - " + waitMS + "ms set"); 44 | 45 | new Thread(new Runnable() { 46 | @Override 47 | public void run() { 48 | try { 49 | Thread.sleep(waitMS); 50 | }catch (Exception e){ 51 | return; 52 | } 53 | 54 | Handler mainLoop = new Handler(Looper.getMainLooper()); 55 | mainLoop.post(new Runnable() { 56 | @Override 57 | public void run() { 58 | 59 | if(publish == null){ 60 | return; 61 | } 62 | 63 | PublishCameraSwapBlinkTest.super.onPublishTouch(e); 64 | 65 | System.out.println(" TESTING - On Publish Touch - swapping"); 66 | 67 | new Thread(new Runnable() { 68 | @Override 69 | public void run() { 70 | try{ 71 | Thread.sleep(waitMS); 72 | } catch (Exception e) { 73 | return; 74 | } 75 | if(publish == null){ 76 | return; 77 | } 78 | 79 | ((R5BlinkCamera)camera).coverCam = false; 80 | 81 | System.out.println(" TESTING - On Publish Touch - done"); 82 | 83 | swapping = false; 84 | } 85 | }).start(); 86 | } 87 | }); 88 | } 89 | }).start(); 90 | ``` 91 | 92 | [PublishCameraSwapBlinkTest.java #28](PublishCameraSwapBlinkTest.java#L28) -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCameraSwapTest/README.md: -------------------------------------------------------------------------------- 1 | # Publish Camera Swap 2 | 3 | `R5Camera.setCamera` allows the user to change the video source for a stream without interupting the broadcast. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishCameraSwapTest.java](PublishCameraSwapTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Touch the screen at any time while streaming to switch between broadcasting from the front facing and back facing camera. 13 | 14 | ## Using R5Camera.device 15 | 16 | `R5Camera.setCamera` will allow you to hot-swap sources for the stream. Once streaming, simply call: 17 | 18 | ```Java 19 | R5Camera publishCam = (R5Camera)publish.getVideoSource(); 20 | ``` 21 | 22 | [PublishCameraSwapTest.java #32](PublishCameraSwapTest.java#L32) 23 | 24 | ```Java 25 | publishCam.setCamera(newCam); 26 | ``` 27 | 28 | [PublishCameraSwapTest.java #59](PublishCameraSwapTest.java#L59) -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCustomMicTest/PublishCustomMicTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishCustomMicTest; 27 | 28 | import com.red5pro.streaming.source.R5Microphone; 29 | 30 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 31 | 32 | /** 33 | * Created by davidHeimann on 12/22/17. 34 | */ 35 | 36 | public class PublishCustomMicTest extends PublishTest { 37 | 38 | @Override 39 | protected void attachMic() { 40 | 41 | R5Microphone mic = new gainWobbleMic(); 42 | publish.attachMic(mic); 43 | } 44 | 45 | public class gainWobbleMic extends R5Microphone { 46 | 47 | private float gain = 1.0f; 48 | private int mod = 1; 49 | private double lastTime = 0; 50 | 51 | @Override 52 | public void processData(byte[] samples, double streamtimeMill) { 53 | 54 | modifyGain(streamtimeMill - lastTime); 55 | lastTime = streamtimeMill; 56 | 57 | int s; 58 | for(int i = 0; i < samples.length; i++){ 59 | 60 | s = (int) (samples[i] * gain); 61 | samples[i] = (byte) Math.min(s, 0xff); 62 | } 63 | 64 | super.processData(samples, streamtimeMill); 65 | } 66 | 67 | private void modifyGain(double time){ 68 | //causes the gain to increase to double volume and decrease to 0 volume, then back 69 | gain += mod * (time/2000); 70 | if( gain >= 2 || gain <= 0 ){ 71 | System.out.println("gain at: " + gain); 72 | gain = Math.max(2.0f * mod, 0.0f); 73 | mod *= -1; 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCustomMicTest/Readme.md: -------------------------------------------------------------------------------- 1 | # Custom Microphone Publishing 2 | 3 | This example demonstrates passing custom video data into the R5Stream. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishCustomMicTest.java](PublishCustomMicTest.java)*** 9 | 10 | ### Setup 11 | 12 | To view this example, you simply need to open the example and subscribe to your stream from a second device. All video will be recorded, and the microphone audio will have its volume modified before being sent out. 13 | 14 | #### Attach a Custom Audio Source 15 | 16 | Instead of using an R5Microphone, this example uses a custom video source, the `gainWobbleMic`. This increases and decreases the gain between double volume to muted and back. It does this by extending the R5Microphone class and intercepting the `processData` method. 17 | 18 | This method recieves a byte array of raw audio samples - each byte being a single, mono sample - and a timestamp in milliseconds with the 0 point being the start of the stream. The array is passed by reference, so it needs to be modified in place - by assigning new values to items in the array, and not assiging a new array - which would just overwrite the reference. 19 | 20 | ```Java 21 | int s; 22 | for(int i = 0; i < samples.length; i++){ 23 | 24 | s = (int) (samples[i] * gain); 25 | samples[i] = (byte) Math.min(s, 0xff); 26 | } 27 | ``` 28 | 29 | [PublishCustomMicTest.java #82](PublishCustomMicTest.java#L82) 30 | 31 | This example amplifies the value of each byte according to the gain value - clamping the value to keep it from wrapping around when being converted back to a byte. This function could be used as a timing device to provide completely separate audio. 32 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishCustomSourceTest/Readme.md: -------------------------------------------------------------------------------- 1 | # Custom Publishing on Red5 Pro 2 | 3 | This example demonstrates passing custom video data into the R5Stream. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishCustomSourceTest.java](PublishCustomSourceTest.java)*** 8 | - ***[CustomVideoSource.java](CustomVideoSource.java)*** 9 | 10 | ### Setup 11 | 12 | To view this example, you simply need to open the example and subscribe to your stream from a second device. All audio will be recorded, and instead of camera input, a simply plasma style effect is rendered. 13 | 14 | #### Attach a Custom Video Source 15 | 16 | Instead of using an R5Camera, this example uses a custom video source, the `CustomVideoSource`. This device 17 | 18 | ```Java 19 | CustomVideoSource source = new CustomVideoSource(); 20 | publish.attachCamera(source); 21 | ``` 22 | 23 | [PublishCustomSourceTest.java #54](PublishCustomSourceTest.java#L54) 24 | 25 | This device automatically polls and pushes to the encoder when new pixels are ready to be published. There are several steps that are needed to properly feed data to the encoder. 26 | 27 | 1. **Make sure all bytes are in the YUV420 or YV12 pixel format.** `CustomVideoSource` uses RGBA data, so it has a special function `encodeYUV420` which converts RGB data to this format. This method can be seen at [CustomVideoSource.java #47](CustomVideoSource.java#L47). 28 | 2. **Call `prepareFrame`**. This method will convert the YUV data into the proper format for the encoder. `CustomVideoSource` has two buffers, and copies the properly prepared frames to the output buffer at [CustomVideoSource.java #183](CustomVideoSource.java#L183). 29 | 3. **Get the timestamp.** The timestamp can be gotten from the AudioEngine if you are publishing audio, or can be localled tracked. [CustomVideoSource.java #187](CustomVideoSource.java#L187). 30 | 4. **Encode the data!** This last call to `encode` will send the data to the encoder and pass to the stream when ready. [CustomVideoSource.java #192](CustomVideoSource.java#L192). 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishEncryptedTest/PublishEncryptedTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishEncryptedTest; 27 | 28 | import com.red5pro.streaming.R5Connection; 29 | import com.red5pro.streaming.R5Stream; 30 | import com.red5pro.streaming.R5StreamProtocol; 31 | import com.red5pro.streaming.config.R5Configuration; 32 | 33 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 34 | import red5pro.org.testandroidproject.tests.TestContent; 35 | 36 | public class PublishEncryptedTest extends PublishTest { 37 | 38 | @Override 39 | protected void publish(){ 40 | 41 | String b = getActivity().getPackageName(); 42 | 43 | //Create the configuration from the values.xml 44 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, 45 | TestContent.GetPropertyString("host"), 46 | TestContent.GetPropertyInt("port"), 47 | TestContent.GetPropertyString("context"), 48 | TestContent.GetPropertyFloat("publish_buffer_time")); 49 | config.setLicenseKey(TestContent.GetPropertyString("license_key")); 50 | config.setBundleID(b); 51 | 52 | String params = TestContent.getConnectionParams(); 53 | if (params != null) { 54 | config.setParameters(params); 55 | } 56 | 57 | R5Connection connection = new R5Connection(config); 58 | 59 | //setup a new stream using the connection 60 | publish = new R5Stream(connection); 61 | 62 | publish.audioController.sampleRate = TestContent.GetPropertyInt("sample_rate"); 63 | 64 | //show all logging 65 | publish.setLogLevel(R5Stream.LOG_LEVEL_DEBUG); 66 | 67 | if(TestContent.GetPropertyBool("audio_on")) { 68 | //attach a microphone 69 | attachMic(); 70 | } 71 | 72 | preview.attachStream(publish); 73 | 74 | if(TestContent.GetPropertyBool("video_on")) { 75 | //attach a camera video source 76 | attachCamera(); 77 | } 78 | 79 | preview.showDebugView(TestContent.GetPropertyBool("debug_view")); 80 | 81 | publish.setListener(this); 82 | publish.publish(TestContent.GetPropertyString("stream1"), getPublishRecordType()); 83 | 84 | if(TestContent.GetPropertyBool("video_on")) { 85 | cam.startPreview(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishEncryptedTest/README.md: -------------------------------------------------------------------------------- 1 | # Adding security to Red5 Pro streams 2 | 3 | While a lot of streaming applications are intended to be as public as possible, many are intended for more descrete audiences - or decidedly confidential. For those situations, SRTP can give a piece of mind that traffic can't be spyed on uninvited. 4 | 5 | > **NOTE:** SRTP Support requires Red5 Pro Server version 5.5.0 or higher 6 | 7 | ### Example Code 8 | 9 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 10 | - ***[PublishEncryptedTest.java](PublishEncryptedTest.java)*** 11 | 12 | ## SRTP 13 | 14 | The Red5 Pro SDK has included the option to wrap its streams in `SRTP` - a Secure variation of the `RTP` (Real-time Transport Protocol) that is normally used to wrap `RTSP` (Real-time Streaming Protocol) that the SDK operates on. Specifically, once negotiation with the server is complete, everything sent between the SDK and server (or vice versa) is encrypted and authenticated to ensure that a third party can't view the stream or modify data without detection. 15 | 16 | Also, as part of the SRTP specification, we support "null key" SRTP. Refered to in the sdk as `Null SRTP` - it's essentially taking the authentication protection to prevent outside tampering with the stream in situations that don't require the extra overhead for the view-protection of encryption. 17 | 18 | Note that while the encryption suite used is relatively fast where cryptograhpy is concerned, it does still introduce some overhead. Even Null SRTP still requires processing all data before transmition, and mobile devices aren't the most powerful of computers. This overhead will scale roughly with bitrate settings, and may lower the framerate of a stream. 19 | 20 | ### Enable Encryption 21 | 22 | As complicated as encryption is, it's implementation couldn't be simpler - simply set the `protocol` property of the R5Configuration (the first value of its constructor) to the correct value before initializing the connection and the SDK will take care of the rest. 23 | 24 | ```Java 25 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, 26 | ``` 27 | 28 | [PublishEncryptedTest.java #19](PublishEncryptedTest.java#L19) 29 | 30 | To set Null SRTP instead, use `NULL_SRTP` - and of course, the default of `RTSP` is still available where security isn't such a concern. 31 | 32 | ### New Events 33 | 34 | As part of the new protocols, two new events have been added to differentiate between an issue specific to the SRTP setup and the SDK in general. 35 | 36 | `R5ConnectionEvent.SRTP_KEY_GEN_ERROR` - This indicates that something has prevented the device from generating its part of the key exchange. The chance of seeing this error should be zero - barring a manufacturing fault or software malfunction. 37 | 38 | `R5ConnectionEvent.SRTP_KEY_HANDLE_ERROR` - This indicates that there has been a fault between the server and the SDK. Either that there's been some fault that prevented the key exchange from happening cleanly - or that the server is using an old version and doesn't support SRTP. 39 | 40 | For both of these errors, the message that accompanies them will include more detail on what exactly hasn't worked. 41 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishHQAudioTest/README.md: -------------------------------------------------------------------------------- 1 | # Publishing High Quality Audio 2 | 3 | `R5AudioController.sampleRate` allows the user to increase the number of times per second that a device grabs a signal from the microphone. Higher values can improve the quality of a broadcast. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishHQAudioTest.java](PublishHQAudioTest.java)*** 9 | 10 | ## Using R5Microphone.sampleRate 11 | 12 | `R5AudioController.sampleRate` is by default set to 8000 - or 8khz, which is decent for most applications, but far from archival quality, especially when it comes to music. Note that setting this value higher will also require a higher bitrate. Increasing the bitrate without increasing the sample rate will only get you so far in reducing compression on the audio, but increasing the sample rate without increasing the bitrate will increase how much each sample is compressed, which could lead to a worse sound. 13 | 14 | ```Java 15 | mic.setBitRate(128);//kbps 16 | R5AudioController.getInstance().sampleRate = 44100;//hz (samples/second) 17 | ``` 18 | 19 | [PublishHQAudioTest.java #65](PublishHQAudioTest.java#L65) 20 | 21 | This must be set before you start publishing, and changing the value after calling `R5Stream.publish` will not effect the sample rate. 22 | 23 | ## Receiving HQ Audio 24 | 25 | Android has issues playing audio from raw data, and thus currently can't play back audio at sample rates other than 8khz. Other sample rates will be up or downsampled to play at that rate. 26 | 27 | ## Two Way and HQ Audio 28 | 29 | Two way applications require echo cancellation to minimize feedback, and in order for the device to cancel playback that's received by the microphone, the two signals need to meet certain settings. In order for it to work correctly, the sample rates of the publisher and subscriber should be the same, and since playback is locked to 8khz, the publisher should be as well. 30 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishImageTest/PublishImageTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishImageTest; 27 | 28 | import android.graphics.Bitmap; 29 | import android.graphics.Matrix; 30 | import android.os.Bundle; 31 | import android.view.MotionEvent; 32 | import android.view.View; 33 | import android.widget.FrameLayout; 34 | import android.widget.ImageView; 35 | 36 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 37 | 38 | /** 39 | * Created by davidHeimann on 2/10/16. 40 | */ 41 | public class PublishImageTest extends PublishTest { 42 | ImageView screenShot; 43 | 44 | @Override 45 | public void onActivityCreated(Bundle savedInstanceState) { 46 | super.onActivityCreated(savedInstanceState); 47 | 48 | preview.setOnTouchListener(new View.OnTouchListener() { 49 | @Override 50 | public boolean onTouch(View v, MotionEvent event) { 51 | return onSubscribeTouch(event); 52 | } 53 | }); 54 | } 55 | 56 | private boolean onSubscribeTouch( MotionEvent e ){ 57 | 58 | if( e.getAction() == MotionEvent.ACTION_DOWN ){ 59 | if( screenShot != null ){ 60 | ((FrameLayout)preview.getParent()).removeView(screenShot); 61 | } 62 | screenShot = new ImageView( preview.getContext() ); 63 | FrameLayout.LayoutParams position = new FrameLayout.LayoutParams( preview.getWidth()/2, preview.getHeight()/2 ); 64 | position.setMargins(preview.getWidth() / 2, preview.getHeight() / 2, 0, 0); 65 | screenShot.setLayoutParams(position); 66 | 67 | screenShot.setScaleType(ImageView.ScaleType.FIT_CENTER); 68 | 69 | Bitmap streamImage = publish.getStreamImage(); 70 | Matrix manip = new Matrix(); 71 | manip.setRotate(camOrientation); 72 | streamImage = Bitmap.createBitmap(streamImage, 0, 0, streamImage.getWidth(), streamImage.getHeight(), manip, true ); 73 | manip.setScale( -1f, 1f ); 74 | streamImage = Bitmap.createBitmap(streamImage, 0, 0, streamImage.getWidth(), streamImage.getHeight(), manip, true ); 75 | 76 | screenShot.setImageBitmap(streamImage); 77 | 78 | ((FrameLayout)preview.getParent()).addView(screenShot); 79 | } 80 | 81 | return true; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishImageTest/README.md: -------------------------------------------------------------------------------- 1 | # Publish Image Capture 2 | 3 | `R5Stream.getStreamImage` allows the user to capture a screenshot of the stream at any time. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishImageTest.java](PublishImageTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Touch the screen at any time while streaming to popup a temporary overlay containing the UIImage that is returned from the Red5 Pro SDK. 13 | 14 | ## Using getStreamImage 15 | 16 | `R5Stream.getStreamImage` returns a UIImage containing a screenshot of the current stream. The image dimensions match the incoming stream dimensions, and contain RGB data. Once streaming, simply call: 17 | 18 | ```Java 19 | Bitmap streamImage = publish.getStreamImage(); 20 | ``` 21 | 22 | [PublishImageTest.java #44](PublishImageTest.java#L44) 23 | 24 | 25 | The UIImage can be saved to disk, displayed with a UIImageView, or processed in any way that is needed. -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishLocalRecordTest/PublishLocalRecordTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishLocalRecordTest; 27 | 28 | import com.red5pro.streaming.R5Stream; 29 | 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 34 | import red5pro.org.testandroidproject.tests.TestContent; 35 | 36 | /** 37 | * Created by davidHeimann on 7/28/17. 38 | */ 39 | 40 | public class PublishLocalRecordTest extends PublishTest { 41 | 42 | @Override 43 | protected void publish() { 44 | super.publish(); 45 | 46 | Map props = new HashMap<>(); 47 | props.put(R5Stream.VideoBitrateKey, TestContent.GetPropertyInt("bitrate") * 2); 48 | props.put(R5Stream.AudioBitrateKey, publish.getAudioSource().getBitRate() * 2); 49 | //other potential properties (all properties are optional): 50 | // props.put(R5Stream.RecordDirectoryKey, "some/location/on/this/device"); //where to store the media 51 | // props.put(R5Stream.RecordMediaScanKey, true); //should the media be scanned into the OS's media apps (default: true) 52 | 53 | publish.beginLocalRecordingWithProperties(getActivity().getApplicationContext(), "r5pro/testRecord", props); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishOrientationTest/PublishOrientationTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishOrientationTest; 27 | 28 | import android.os.Bundle; 29 | import android.view.MotionEvent; 30 | import android.view.View; 31 | 32 | import com.red5pro.streaming.source.R5Camera; 33 | 34 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 35 | 36 | /** 37 | * Created by davidHeimann on 2/10/16. 38 | */ 39 | public class PublishOrientationTest extends PublishTest { 40 | 41 | public void onActivityCreated(Bundle savedInstanceState) { 42 | super.onActivityCreated(savedInstanceState); 43 | 44 | preview.setOnTouchListener(new View.OnTouchListener() { 45 | @Override 46 | public boolean onTouch(View v, MotionEvent event) { 47 | return onPublishTouch(event); 48 | } 49 | }); 50 | } 51 | 52 | private boolean onPublishTouch( MotionEvent e ) { 53 | 54 | if( e.getAction() == MotionEvent.ACTION_UP && publish != null) { 55 | R5Camera publishCam = (R5Camera)publish.getVideoSource(); 56 | publishCam.setOrientation( publishCam.getOrientation() + 90 ); 57 | } 58 | 59 | return true; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishOrientationTest/README.md: -------------------------------------------------------------------------------- 1 | # Publish Orientation 2 | 3 | `R5Camera.orientation` allows the user to rotate the video source for a stream without interupting the broadcast. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[PublishOrientationTest.java](PublishOrientationTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Touch the screen at any time while streaming to rotate the video source by 90 degrees. It's sugested that you verify this change with a separate device. 13 | 14 | ## Using R5Camera.orientation 15 | 16 | `R5Camera.orientation` will tell you how much the current video source is rotated from how it's coming into the application. By getting the instance of R5Camera attached to the R5Stream object and changing its orientation property, this can be modified live for the stream. Once streaming, simply call: 17 | 18 | ```Swift 19 | R5Camera publishCam = (R5Camera)publish.getVideoSource(); 20 | publishCam.setOrientation( publishCam.getOrientation() + 90 ); 21 | ``` 22 | 23 | [PublishOrientationTest.java #30](PublishOrientationTest.java#L30) -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishPauseTest/README.md: -------------------------------------------------------------------------------- 1 | # Publish Mute/Unmute 2 | 3 | The `R5Stream:restrainAudio` and `R5Stream:restrainVideo` methods allow for a broadcast stream to be muted and unmuted of audio and video separately. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishPauseTest.java](PublishPauseTest.java)*** 8 | 9 | ## Running the example 10 | 11 | The `PublishPauseTest` launches in a broadcast session with Audio & Video inputs enabled and streaming. 12 | 13 | Touch the screen at any time while streaming to toggle between muted and unmuted states of each Audio and Video input. Subscribe to the stream on another device to see how the muted states affect the broadcast. 14 | 15 | The toggle sequence is as follows when you tap the screen multiple times: 16 | 17 | 1. The first tap will mute the audio being sent. 18 | 2. The second tap will unmute the audio from _Tap 1_ and mute the video. 19 | 3. The third tap will mute the audio again - muting both video and audio at the same time. 20 | 4. The fourth tap will unmute both audio and video, returning to its original state on launch of test and broadcast. 21 | 22 | ## Using RStream:restrainAudio and R5Stream:restrainVideo 23 | 24 | `R5Stream:restrainAudio` and `R5Stream:restrainVideo` are methods that can be invoked to mute or unmute the audio and video of a stream, repectively. They each take a `boolean` argument. Passing `true` will mute the media in the stream, passing `false` will unmute the media. 25 | 26 | ```java 27 | preview.setOnTouchListener(new View.OnTouchListener() { 28 | @Override 29 | public boolean onTouch(View v, MotionEvent event) { 30 | 31 | if (event.getAction() == MotionEvent.ACTION_DOWN) { 32 | 33 | muteEnum = muteEnum + 1; 34 | if (muteEnum > 3) { 35 | muteEnum = 0; 36 | } 37 | 38 | switch (muteEnum) { 39 | case 1: 40 | // mute audio 41 | publish.restrainAudio(true); 42 | publish.restrainVideo(false); 43 | Log.d("PublisherPause", "Mute Audio"); 44 | break; 45 | case 2: 46 | // mute video 47 | publish.restrainAudio(false); 48 | publish.restrainVideo(true); 49 | Log.d("PublisherPause", "Mute Video"); 50 | break; 51 | case 3: 52 | // mute audio & video 53 | publish.restrainAudio(true); 54 | publish.restrainVideo(true); 55 | Log.d("PublisherPause", "Mute Audio & Video"); 56 | break; 57 | case 0: 58 | // unmute audio & video 59 | publish.restrainAudio(false); 60 | publish.restrainVideo(false); 61 | Log.d("PublisherPause", "Umute all"); 62 | break; 63 | } 64 | 65 | } 66 | 67 | return true; 68 | } 69 | }); 70 | ``` 71 | 72 | [PublishPauseTest.java #31](PublishPauseTest.javat#L31) 73 | 74 | ## Listening for mute on a Subscriber stream 75 | 76 | Calling the `R5Stream:restrainAudio` and `R5Stream:restrainVideo` methods change the `streamingMode` value of the metadata that is additionally broadcast to subscribers of the stream. As a subscriber, you can listen for their respective mute and unmute states of a broadcast stream from the status codes defined for [R5ConnectionListener](https://www.red5pro.com/docs/static/android-streaming/interfacecom_1_1red5pro_1_1streaming_1_1event_1_1_r5_connection_listener.html). 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishRemoteCallTest/PublishRemoteCallTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishRemoteCallTest; 27 | 28 | import android.os.Bundle; 29 | import android.view.MotionEvent; 30 | import android.view.View; 31 | 32 | import com.red5pro.streaming.event.R5ConnectionEvent; 33 | import com.red5pro.streaming.event.R5ConnectionListener; 34 | 35 | import java.util.Hashtable; 36 | 37 | import red5pro.org.testandroidproject.tests.PublishTest.PublishTest; 38 | 39 | /** 40 | * Created by davidHeimann on 4/25/16. 41 | */ 42 | public class PublishRemoteCallTest extends PublishTest { 43 | 44 | @Override 45 | public void onActivityCreated(Bundle savedInstanceState) { 46 | super.onActivityCreated(savedInstanceState); 47 | 48 | publish.setListener(this); 49 | } 50 | 51 | @Override 52 | public void onConnectionEvent(R5ConnectionEvent r5ConnectionEvent) { 53 | 54 | super.onConnectionEvent(r5ConnectionEvent); 55 | if(r5ConnectionEvent == R5ConnectionEvent.START_STREAMING ) { 56 | preview.setOnTouchListener(new View.OnTouchListener() { 57 | @Override 58 | public boolean onTouch(View v, MotionEvent event) { 59 | 60 | if (event.getAction() == MotionEvent.ACTION_DOWN) { 61 | Hashtable map = new Hashtable(); 62 | map.put("message", "The streamer wants your attention"); 63 | map.put("touchX", Float.toString(event.getRawX() / preview.getWidth()) ); 64 | map.put("touchY", Float.toString(event.getRawY() / preview.getHeight()) ); 65 | 66 | publish.send("whateverFunctionName", map); 67 | } 68 | 69 | return true; 70 | } 71 | }); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishRemoteCallTest/README.md: -------------------------------------------------------------------------------- 1 | # Remote Procedure Calls 2 | 3 | `R5Stream.send` allows the publisher to send messages to the server to be sent to all subscribers. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishRemoteCallTest.java](PublishRemoteCallTest.java)*** 8 | - ***[SubscribeRemoteCallTest.java](../SubscribeRemoteCallTest/SubscribeRemoteCallTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Two devices are required to run this example. One as a publisher, and the other as a subscriber. 13 | 14 | Connect the first device (publisher) with the Publish - Remote Call example. On the second device (subscriber) use the Subscribe - Remote Call example. 15 | 16 | Touch the preview on the publisher screen to display a label on the subscriber screen where the publisher touched. 17 | 18 | ## Using the R5Stream send 19 | 20 | Once the stream has connected you are able to dispatch messages to any connected subscribers. Sending the message is a simple call that takes a map object: 21 | 22 | ```Java 23 | publish.send("whateverFunctionName", map); 24 | ``` 25 | 26 | [PublishRemoteCallTest.java #40](PublishRemoteCallTest.java#L40) 27 | 28 | ### Send Message Format 29 | 30 | The publisher send takes any object that implements the Map interface that uses a string as both the key and value. This example uses a Hashtable. 31 | 32 | ```Java 33 | Hashtable map = new Hashtable(); 34 | map.put("key", "value"); 35 | ``` 36 | 37 | The R5RemoteCallContainer will automatically handle turning the map into a strin of the following format, which is how it will be received by the subscriber's client. 38 | 39 | ```Java 40 | "key1=value1;key2=value2;key3=value3;" 41 | ``` 42 | 43 | ## Receiving R5Stream send calls 44 | 45 | In order to handle `R5Stream.send` calls from the publisher, the `R5Stream.client` delegate must be set. This delegate will receive all `R5Stream.send` messages via appropriately named methods. 46 | 47 | ```Java 48 | subscribe.client = this; 49 | ``` 50 | 51 | [SubscribeRemoteCallTest.java #27](../SubscribeRemoteCallTest/SubscribeRemoteCallTest.java#L27) 52 | 53 | Because the publisher will be sending **whateverFunctionName**, the subscriber client delegate will need a matching method signature. As the name implies, the function can be named anything as long as it is publicly accessible. All methods receive a single string argument containing the variable map provided by the publisher. This map can easily be parsed. 54 | 55 | ```Java 56 | public void whateverFunctionName( String message ){ 57 | 58 | System.out.println("Recieved message from publisher: " + message); 59 | 60 | String[] parsedMessage = message.split(";"); 61 | Hashtable map = new Hashtable(); 62 | for (String s : parsedMessage) { 63 | String key = s.split("=")[0]; 64 | String value = s.split("=")[1]; 65 | System.out.println("Received key: " + key + "; with value: " + value); 66 | 67 | map.put(key,value); 68 | } 69 | ``` 70 | 71 | [SubscribeRemoteCallTest.java #30](../SubscribeRemoteCallTest/SubscribeRemoteCallTest.java#L30) 72 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishSMEncryptedTest/README.md: -------------------------------------------------------------------------------- 1 | # Encrypted Stream Manager Publishing 2 | 3 | Using a stream manager doesn't prevent your streams from being encrypted - the same configuration can be used to protect the contents of your broadcasts in any server configuration. 4 | 5 | ## Example Code 6 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 7 | - ***[PublishStreamManagerTest.java](../PublishStreamManagerTest/PublishStreamManagerTest.java)*** 8 | - ***[PublishSMEncryptedTest.swift](PublishSMEncryptedTest.swift)*** 9 | 10 | ## The One Change 11 | The only change from the [basic Stream Manager example](../PublishStreamManagerTest/) is that value that the `protocol` setting of the configuration is set to. Setting the protocol to use `R5StreamProtocol.SRTP` is all you need to do to signal the SDK to negotiate an encrypted session. 12 | 13 | ```Java 14 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, ...) 15 | ``` 16 | 17 | ### Further Security Concerns 18 | As with the basic Encryption example, it's suggested that some form of stream authentication is used. Additionally, it's suggested that the innitial negotiation to find the server to broadcast to be done over HTTPS (iOS defaults to HTTPS where available) to prevent a malicious party from publishing to the returned server first. Note - SRTP does not require the server to have an SSL certificate, and so this example is set to run without HTTPS to run on more servers, but HTTPS will require the server to be set up with an appropriate SSL certificate, and the port must not be added to the Stream Manager API request for it to connect correctly. 19 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishSMEncryptedTest_SM1/README.md: -------------------------------------------------------------------------------- 1 | # Encrypted Stream Manager Publishing 2 | 3 | Using a stream manager doesn't prevent your streams from being encrypted - the same configuration can be used to protect the contents of your broadcasts in any server configuration. 4 | 5 | ## Example Code 6 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 7 | - ***[PublishStreamManagerTest.java](../PublishStreamManagerTest/PublishStreamManagerTest.java)*** 8 | - ***[PublishSMEncryptedTest.swift](PublishSMEncryptedTest.swift)*** 9 | 10 | ## The One Change 11 | The only change from the [basic Stream Manager example](../PublishStreamManagerTest/) is that value that the `protocol` setting of the configuration is set to. Setting the protocol to use `R5StreamProtocol.SRTP` is all you need to do to signal the SDK to negotiate an encrypted session. 12 | 13 | ```Java 14 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, 15 | ``` 16 | 17 | [PublishSMEncryptedTest.java #24](PublishSMEncryptedTest.java#L24) 18 | 19 | 20 | ### Further Security Concerns 21 | As with the basic Encryption example, it's suggested that some form of stream authentication is used. Additionally, it's suggested that the innitial negotiation to find the server to broadcast to be done over HTTPS (iOS defaults to HTTPS where available) to prevent a malicious party from publishing to the returned server first. Note - SRTP does not require the server to have an SSL certificate, and so this example is set to run without HTTPS to run on more servers, but HTTPS will require the server to be set up with an appropriate SSL certificate, and the port must not be added to the Stream Manager API request for it to connect correctly. 22 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishStreamManagerTest/README.md: -------------------------------------------------------------------------------- 1 | # Stream Manager Publishing 2 | 3 | With clustering, we need to determine which red5 pro instance the client will use. The other examples used a static configuration ip for streaming endpoints. Basic clustering uses more than one stream endpoint for subscribers. Advanced clustering uses more than one endpoint for publishers also. 4 | 5 | With the Stream Manager, our configuration IP will be used similarly for publishers and subscribers. Both publishers and subscribers will call a web service to receive the IP that should be used. Since this is an HTTP call, you can use a DNS Name for the `host` value. 6 | 7 | ### Example Code 8 | 9 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 10 | - ***[PublishStreamManagerTest.java](PublishStreamManagerTest.java)*** 11 | 12 | ### Setup 13 | 14 | In order to publish, you first need to connect to the Origin server of your deployment. The Stream Manager will know which edges are active and provide the one that needs to be published to. 15 | 16 | ```Java 17 | // url format: "\(host)\(portURI)/as/\(version)/streams/stream/\(nodeGroup)/publish/\(context)/\(streamName)" 18 | String host = TestContent.GetPropertyString("host"); 19 | String version = TestContent.GetPropertyString("sm_version"); 20 | String nodeGroup = TestContent.GetPropertyString("sm_nodegroup"); 21 | String context = TestContent.GetPropertyString("context"); 22 | String streamName = TestContent.GetPropertyString("stream1"); 23 | 24 | String url = String.format("https://%s/as/%s/streams/stream/%s/publish/%s/%s", 25 | host, 26 | version, 27 | nodeGroup, 28 | context, 29 | streamName); 30 | HttpClient httpClient = new DefaultHttpClient(); 31 | HttpResponse response = httpClient.execute(new HttpGet(url)); 32 | StatusLine statusLine = response.getStatusLine(); 33 | 34 | if (statusLine.getStatusCode() == HttpStatus.SC_OK) { 35 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 36 | response.getEntity().writeTo(out); 37 | String responseString = out.toString(); 38 | out.close(); 39 | 40 | JSONArray origins = new JSONArray(responseString); 41 | JSONObject data = origins.getJSONObject(0); 42 | final String outURL = data.getString("serverAddress"); 43 | } 44 | ``` 45 | 46 | The service returns a JSON array of Origin nodes available to connect to; in typical deployments, this will be of a length of one. 47 | 48 | ```Java 49 | JSONArray origins = new JSONArray(responseString); 50 | JSONObject data = origins.getJSONObject(0); 51 | final String outURL = data.getString("serverAddress"); 52 | ``` 53 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishStreamManagerTest_SM1/README.md: -------------------------------------------------------------------------------- 1 | # Stream Manager Publishing 2 | 3 | With clustering, we need to determine which red5 pro instance the client will use. The other examples used a static configuration ip for streaming endpoints. Basic clustering uses more than one stream endpoint for subscribers. Advanced clustering uses more than one endpoint for publishers also. 4 | 5 | With the Stream Manager, our configuration IP will be used similarly for publishers and subscribers. Both publishers and subscribers will call a web service to receive the IP that should be used. Since this is an HTTP call, you can use a DNS Name for the `host` value. 6 | 7 | ### Example Code 8 | 9 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 10 | - ***[PublishStreamManagerTest.java](PublishStreamManagerTest.java)*** 11 | 12 | ### Setup 13 | 14 | In order to publish, you first need to connect to the origin server's Stream Manager. The Stream Manager will know which edges are active and provide the one that needs to be published to. 15 | 16 | ```Java 17 | String url = "https://" + 18 | TestContent.GetPropertyString("host") + "/streammanager/api/3.1/event/" + 19 | TestContent.GetPropertyString("context") + "/" + 20 | TestContent.GetPropertyString("stream1") + "?action=broadcast"; 21 | 22 | HttpClient httpClient = new DefaultHttpClient(); 23 | HttpResponse response = httpClient.execute(new HttpGet(url)); 24 | StatusLine statusLine = response.getStatusLine(); 25 | 26 | if (statusLine.getStatusCode() == HttpStatus.SC_OK) { 27 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 28 | response.getEntity().writeTo(out); 29 | String responseString = out.toString(); 30 | out.close(); 31 | ``` 32 | 33 | [PublishStreamManagerTest.java #46](PublishStreamManagerTest.java#L46) 34 | 35 | The service returns a json object with the information needed to connect to publish. 36 | 37 | ```Java 38 | JSONObject data = new JSONObject(responseString); 39 | String outURL = data.getString("serverAddress"); 40 | ``` 41 | 42 | [PublishStreamManagerTest.java #63](PublishStreamManagerTest.java#L63) 43 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishStreamManagerTranscodeTest/PublishTranscoderData.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishStreamManagerTranscodeTest; 27 | 28 | import com.google.gson.Gson; 29 | 30 | import java.util.ArrayList; 31 | import java.util.Arrays; 32 | import java.util.HashMap; 33 | import java.util.List; 34 | 35 | public class PublishTranscoderData { 36 | public String streamGuid; 37 | public String messageType = "ProvisionCommand"; 38 | public Credentials credentials; 39 | public List streams = new ArrayList(); 40 | 41 | public static class Credentials { 42 | public String username; 43 | public String password; 44 | 45 | public Credentials(String user, String pass) { 46 | username = user; 47 | password = pass; 48 | } 49 | } 50 | 51 | public static class StreamVariant { 52 | public String streamGuid; 53 | public Integer abrLevel; 54 | public VideoParams videoParams; 55 | 56 | public StreamVariant(String guid, Integer abr, VideoParams params) { 57 | streamGuid = guid; 58 | abrLevel = abr; 59 | videoParams = params; 60 | } 61 | } 62 | 63 | public static class VideoParams { 64 | public Integer videoWidth; 65 | public Integer videoHeight; 66 | public Integer videoBitRate; 67 | 68 | public VideoParams(Integer width, Integer height, Integer bitRate) { 69 | videoWidth = width; 70 | videoHeight = height; 71 | videoBitRate = bitRate; 72 | } 73 | } 74 | 75 | public PublishTranscoderData (String streamGuid) { 76 | this.streamGuid = streamGuid; 77 | } 78 | 79 | public PublishTranscoderData (String streamGuid, List streams) { 80 | this.streamGuid = streamGuid; 81 | this.streams = streams; 82 | } 83 | 84 | public StreamVariant getVariantByLevel (int level) { 85 | for(int i = 0; i < streams.size(); i++) { 86 | StreamVariant variant = streams.get(i); 87 | if (variant.abrLevel == level) { 88 | return variant; 89 | } 90 | } 91 | return null; 92 | } 93 | 94 | public StreamVariant getVariantByName (String streamGuid) { 95 | for(int i = 0; i < streams.size(); i++) { 96 | StreamVariant variant = streams.get(i); 97 | if (variant.streamGuid.equals(streamGuid)) { 98 | return variant; 99 | } 100 | } 101 | return null; 102 | } 103 | 104 | public String toJSON () { 105 | return new Gson().toJson(this); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishStreamManagerTranscodeTest_SM1/PublishTranscoderData_SM1.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.PublishStreamManagerTranscodeTest_SM1; 27 | 28 | import com.google.gson.Gson; 29 | 30 | import java.util.ArrayList; 31 | import java.util.Arrays; 32 | import java.util.HashMap; 33 | 34 | public class PublishTranscoderData_SM1 { 35 | 36 | public HashMap meta; 37 | 38 | public PublishTranscoderData_SM1(ArrayList> variants) { 39 | 40 | HashMap authMap = new HashMap<>(); 41 | authMap.put("username", ""); 42 | authMap.put("password", ""); 43 | HashMap geoMap = new HashMap<>(); 44 | geoMap.put("regions", new ArrayList<>(Arrays.asList("US", "UK"))); 45 | geoMap.put("restricted", false); 46 | 47 | 48 | meta = new HashMap<>(); 49 | meta.put("authentication", authMap); 50 | meta.put("georules", geoMap); 51 | meta.put("stream", variants); 52 | meta.put("qos", 3); 53 | 54 | } 55 | 56 | public HashMap getVariantByName (String name) { 57 | ArrayList> variants = (ArrayList>)this.meta.get("stream"); 58 | for(int i = 0; i < variants.size(); i++) { 59 | HashMap variant = variants.get(i); 60 | if (variant.get("name").equals(name)) { 61 | return variant; 62 | } 63 | } 64 | return null; 65 | } 66 | 67 | public String toJSON () { 68 | return new Gson().toJson(this); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/PublishStreamManagerTranscodeTest_SM1/README.md: -------------------------------------------------------------------------------- 1 | # Stream Manager Publishing with Transcoder 2 | 3 | With clustering, we need to determine which Red5 Pro instance the client will use. The other examples used a static configuration address for streaming endpoints. Basic clustering uses more than one stream endpoint for subscribers. Advanced clustering uses more than one endpoint for publishers also. 4 | 5 | With the Stream Manager, our configuration IP will be used similarly for publishers and subscribers. Both publishers and subscribers will call a web service to receive the IP that should be used. 6 | 7 | ## Transcoder Support 8 | 9 | To enable Adaptive Bitrate (ABR) control of a stream being played back by a consumer, you need to POST a provision to the Stream Manager detailing the variants at which you will be broadcasting. 10 | 11 | For scenarios in which the broadcaster does not have the capability of publishing the variants of the provision, the broadcaster can request that the server does the Transcoding to the variants. 12 | 13 | To do so, the broadcast most locate the server address of the Transcoder using the transcode=true query param, from which one of the variants will be broadcast to. The tTranscoder will that generate the additional variants for consumption. 14 | 15 | > To learn more about the `transcode` query for API, please visit the documentation: [Stream Manager REST API](https://www.red5pro.com/docs/autoscale/streammanagerapi.html#rest-api-for-streams). 16 | 17 | ## Example Code 18 | 19 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 20 | - ***[PublishStreamManagerTranscodeTest.java](PublishStreamManagerTranscodeTest.java)*** 21 | 22 | # Setup 23 | 24 | In order to publish using the transcoder, you need to request to endpoint for the transcoder from the Stream Manager just as you would in accessing the Origin endpoint in a normal Stream Manager request for broadcast. To do so, append the `transcode=true` query param on the end of the API request. 25 | 26 | ```Java 27 | String url = "http://" + 28 | TestContent.GetPropertyString("host") + ":5080/streammanager/api/1.0/event/" + 29 | TestContent.GetPropertyString("context") + "/" + 30 | TestContent.GetPropertyString("stream1") + "?action=broadcast&transcode=true"; 31 | 32 | HttpClient httpClient = new DefaultHttpClient(); 33 | HttpResponse response = httpClient.execute(new HttpGet(url)); 34 | StatusLine statusLine = response.getStatusLine(); 35 | 36 | if (statusLine.getStatusCode() == HttpStatus.SC_OK) { 37 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 38 | response.getEntity().writeTo(out); 39 | String responseString = out.toString(); 40 | out.close(); 41 | ``` 42 | 43 | [PublishStreamManagerTranscodeTest.java #54](PublishStreamManagerTranscodeTest.java#L54) 44 | 45 | The service returns a JSON object with the information needed to connect and publish to the transcoder. 46 | 47 | ```Java 48 | JSONObject data = new JSONObject(responseString); 49 | String outURL = data.getString("serverAddress"); 50 | ``` 51 | 52 | [PublishStreamManagerTranscodeTest.java #69](PublishStreamManagerTranscodeTest.java#L69) 53 | 54 | ## Broadcast Stream Name 55 | 56 | When using the Transcoder, a set of provisioning variants needs to be provided to the server (as mentioned in the documentation: [Stream Manager REST API](https://www.red5pro.com/docs/autoscale/streammanagerapi.html#rest-api-for-streams)). 57 | 58 | When you start a broadcast to the Transcoder, it is recommended you configure your broadcast session with the details from the highest variant and start the stream with the associated stream name of the variant; in the case of this example, it is the `stream1` configuration name appended with `_1` (i.e., `mystream_1`). 59 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/RecordedTest/Readme.md: -------------------------------------------------------------------------------- 1 | # Published Stream Recording 2 | 3 | `R5Stream.RecordType.Record` signals for the server to record the stream. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 8 | - ***[RecordTest.java](RecordTest.java)*** 9 | 10 | ## Recording 11 | 12 | The only difference between this example and the publish test is that in the publish command you send a different RecordType flag: 13 | 14 | ```Java 15 | publish.publish(TestContent.GetPropertyString("stream1"), R5Stream.RecordType.Record); 16 | ``` 17 | 18 | [RecordTest.java #64](RecordTest.java#L64) -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SharedObjectStreamlessTest/README.md: -------------------------------------------------------------------------------- 1 | # Shared Object Streamless Test 2 | 3 | This example builds off the [SharedObjectTest](../SharedObjectTest) example, yet, instead of relying on establishing a connection to a Shared Object based on a previously established RTSP connection through a Stream, it utilizes the `startDataOnlyStream` method of the `R5Connection` instance to connect to a Shared Object without a Stream: 4 | 5 | ```java 6 | R5Configuration config = new R5Configuration(R5StreamProtocol.RTSP, 7 | TestContent.GetPropertyString("host"), 8 | TestContent.GetPropertyInt("port"), 9 | TestContent.GetPropertyString("context"), 10 | TestContent.GetPropertyFloat("publish_buffer_time")); 11 | config.setLicenseKey(TestContent.GetPropertyString("license_key")); 12 | config.setBundleID(b); 13 | 14 | connection = new R5Connection(config); 15 | 16 | connection.addListener(this); 17 | connection.startDataOnlyStream() 18 | ``` 19 | 20 | > Please refer to the [SharedObject](../SharedObject) example for using the Shared Object API for connection and method and property handling. 21 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeAspectTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscriber Aspect Ratio 2 | 3 | `R5VideoViewController.scaleMode` controls the display mode of the content that is being pushed to it. Depending on the value the content will scale to the apropriate fill value. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 8 | - ***[SubscribeImageTest.java](SubscribeImageTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Begin by publishing to **stream1** from a second device. **stream1** is the default stream1 name that is used by this example. 13 | 14 | Touch the screen at any time while streaming to change the scale mode, affecting how the stream is display on the user's end. 15 | 16 | ## Using scaleMode 17 | 18 | R5VideoViewController.scaleMode has 3 potential enum values. 19 | 20 | ``` 21 | r5_scale_to_fill: scale to fill and maintain aspect ratio (cropping will occur) 22 | r5_scale_to_fit: scale to fit inside view (letterboxing will occur) 23 | r5_scale_fill: scale to fill view (will not respect aspect ratio of video) 24 | ``` 25 | 26 | By default, this value is `r5_scale_to_fill` and the android SDK handles this enum through raw int value (0,1,2) This example cycles through these values when it receives a tap. 27 | 28 | ```Java 29 | int sMode = subscribe.getScaleMode(); 30 | 31 | sMode++; 32 | //A value of 3 or larger won't parse correctly to the enum, so it's reset to 0 33 | if(sMode == 3) sMode = 0; 34 | 35 | subscribe.setScaleMode(sMode); 36 | ``` 37 | 38 | [SubscribeImageTest.java #34](SubscribeImageTest.java#L34) -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeAspectTest/SubscribeAspectTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.SubscribeAspectTest; 27 | 28 | import android.hardware.Camera; 29 | import android.os.Bundle; 30 | import android.view.MotionEvent; 31 | import android.view.View; 32 | import android.view.ViewGroup; 33 | import android.widget.FrameLayout; 34 | import android.widget.Switch; 35 | 36 | import com.red5pro.streaming.source.R5Camera; 37 | 38 | import red5pro.org.testandroidproject.tests.SubscribeTest.SubscribeTest; 39 | 40 | /** 41 | * Created by davidHeimann on 2/10/16. 42 | */ 43 | public class SubscribeAspectTest extends SubscribeTest { 44 | 45 | public void onActivityCreated(Bundle savedInstanceState) { 46 | super.onActivityCreated(savedInstanceState); 47 | 48 | display.setOnTouchListener(new View.OnTouchListener() { 49 | @Override 50 | public boolean onTouch(View v, MotionEvent event) { 51 | return onSubscribeTouch(event); 52 | } 53 | }); 54 | } 55 | 56 | private boolean onSubscribeTouch( MotionEvent e ) { 57 | 58 | if( e.getAction() == MotionEvent.ACTION_DOWN ) { 59 | int sMode = subscribe.getScaleMode(); 60 | 61 | sMode++; 62 | if(sMode == 3) sMode = 0; 63 | 64 | subscribe.setScaleMode(sMode); 65 | } 66 | 67 | return true; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeAuthTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscriber Authentication using Red5 Pro 2 | This is an example of authenticating a stream for playback of an authenticated broadcast. 3 | 4 | ### Example Code 5 | 6 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 7 | - ***[SubscribeAuthTest.java](SubscribeAuthTest.java)*** 8 | 9 | > This example requires you to enable the `SimpleAuthentication` Plugin for the `live` webapp. More information: [https://www.red5pro.com/docs/](https://www.red5pro.com/docs/). 10 | 11 | ## Authenticating 12 | 13 | With the username and password known from the Red5 Pro Server `webapps/live/WEB-INF/simple-auth-plugin.credentials` file (if following the basic auth setup of the Red5 Pro Server), those values are provided to the `parameters` attribute of the `R5Configuration` instance delimited and appended with a semicolon (`;`). 14 | 15 | For example, if you have defined the authorization of a username `foo` with a password `bar`, the configuration addition would look like the following: 16 | 17 | ```java 18 | config.setParameters("username=foo;password=bar;"); 19 | ``` 20 | 21 | ### Example 22 | 23 | In the example, the `username` and `password` values are defined in the [test.xml](../../res/raw/test.xml#L181-L191) file entry for the *Subscribe - Authentication* test. They are accessed and provided to the `R5Configuration` instance prior to establishing a connection: 24 | 25 | ```java 26 | String auth = "username=" + TestContent.GetPropertyString("username") + ";"; 27 | auth += "password=" + TestContent.GetPropertyString("password") + ";"; 28 | //Create the configuration from the values.xml 29 | R5Configuration config = new R5Configuration(R5StreamProtocol.RTSP, 30 | TestContent.GetPropertyString("host"), 31 | TestContent.GetPropertyInt("port"), 32 | TestContent.GetPropertyString("context"), 33 | TestContent.GetPropertyFloat("publish_buffer_time"), 34 | auth); 35 | config.setLicenseKey(TestContent.GetPropertyString("license_key")); 36 | config.setBundleID(getActivity().getPackageName()); 37 | ``` 38 | 39 | [SubscribeAuthTest.java #77](SubscribeAuthTest.java#L77) 40 | 41 | If the provided credentials match those defined for the `live` webapp in its Simple Authentication properties, then the playback will begin as normal. If the credentials _do not_ match, the playback request will be rejected. 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeAuthTest/SubscribeAuthTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.SubscribeAuthTest; 27 | 28 | import com.red5pro.streaming.R5Connection; 29 | import com.red5pro.streaming.R5Stream; 30 | import com.red5pro.streaming.R5StreamProtocol; 31 | import com.red5pro.streaming.config.R5Configuration; 32 | import com.red5pro.streaming.media.R5AudioController; 33 | 34 | import red5pro.org.testandroidproject.tests.SubscribeTest.SubscribeTest; 35 | import red5pro.org.testandroidproject.tests.TestContent; 36 | 37 | /** 38 | * Created by toddanderson on 4/5/17. 39 | */ 40 | 41 | public class SubscribeAuthTest extends SubscribeTest { 42 | 43 | public void Subscribe() { 44 | 45 | String params = TestContent.getConnectionParams(); 46 | String auth = params != null ? params : ""; 47 | auth += "username=" + TestContent.GetPropertyString("username") + ";"; 48 | auth += "password=" + TestContent.GetPropertyString("password") + ";"; 49 | 50 | //Create the configuration from the tests.xml 51 | R5Configuration config = new R5Configuration(R5StreamProtocol.RTSP, 52 | TestContent.GetPropertyString("host"), 53 | TestContent.GetPropertyInt("port"), 54 | TestContent.GetPropertyString("context"), 55 | TestContent.GetPropertyFloat("subscribe_buffer_time"), 56 | auth); 57 | config.setLicenseKey(TestContent.GetPropertyString("license_key")); 58 | config.setBundleID(getActivity().getPackageName()); 59 | 60 | R5Connection connection = new R5Connection(config); 61 | 62 | //setup a new stream using the connection 63 | subscribe = new R5Stream(connection); 64 | 65 | subscribe.audioController = new R5AudioController(); 66 | subscribe.audioController.sampleRate = TestContent.GetPropertyInt("sample_rate"); 67 | 68 | subscribe.client = this; 69 | subscribe.setListener(this); 70 | 71 | //show all logging 72 | subscribe.setLogLevel(R5Stream.LOG_LEVEL_DEBUG); 73 | 74 | //display.setZOrderOnTop(true); 75 | display.attachStream(subscribe); 76 | 77 | display.showDebugView(TestContent.GetPropertyBool("debug_view")); 78 | 79 | subscribe.play(TestContent.GetPropertyString("stream1")); 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeBandwidthTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscriber Bandwidth Test 2 | 3 | `onConnectionEvent` is a method called by the R5Stream on its assigned `R5ConnectionListener` object. This function allows a developer to gain status information events to monitor the stream. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 8 | - ***[SubscribeBandwidthTest.java](SubscribeBandwidthTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Begin by publishing to **stream1** from a second device. **stream1** is the default stream1 name that is used by this example. 13 | 14 | While streaming, upon receipt of a flag indicationg that the current net connection has insufficient bandwidth to properly display the stream, the stream view will appear to darken. If it instead receives a flag saying there is enough bandwidth, the screen will return to normal. 15 | 16 | To see the effects, the stream should be published in high quality, and the example should be run from a poor network. 17 | 18 | ## Using onR5StreamStatus 19 | 20 | `onConnectionEvent` is a method of the `R5ConnectionListener` interface. Any object that impliments this interface can be assigned to the stream with the `R5Stream.setListener` method of an active stream. In this example, `SubscribeBandwidthTest` impliments `R5ConnectionListener` allowing us to use the object as the delegate for its own stream. 21 | 22 | ```Java 23 | subscribe.setListener(this); 24 | ``` 25 | 26 | [SubscribeBandwidthTest.java #22](SubscribeBandwidthTest.java#L22) 27 | 28 | In order to add functionality, the `onConnectionEvent` function from `R5ConnectionListener` needs to be overridden. This overridden function can then parse the message sent to it to determine what action, if any, needs to be taken. 29 | 30 | ```Java 31 | public void onConnectionEvent(R5ConnectionEvent r5ConnectionEvent) { 32 | if ( R5ConnectionEvent.NET_STATUS.value() == r5ConnectionEvent.value() ) { 33 | if( r5ConnectionEvent.message == "NetStream.Play.SufficientBW" ){ 34 | overlay.setAlpha( 0f ); 35 | } 36 | else if( r5ConnectionEvent.message == "NetStream.Play.InSufficientBW" ){ 37 | overlay.setAlpha( 0.5f ); 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | [SubscribeBandwidthTest.java #36](SubscribeBandwidthTest.java#L36) -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeBandwidthTest/SubscribeBandwidthTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.SubscribeBandwidthTest; 27 | 28 | import android.os.Bundle; 29 | import android.view.View; 30 | import android.widget.FrameLayout; 31 | 32 | import com.red5pro.streaming.event.R5ConnectionEvent; 33 | import com.red5pro.streaming.event.R5ConnectionListener; 34 | 35 | import red5pro.org.testandroidproject.tests.SubscribeTest.SubscribeTest; 36 | 37 | /** 38 | * Created by davidHeimann on 2/10/16. 39 | */ 40 | public class SubscribeBandwidthTest extends SubscribeTest { 41 | private View overlay; 42 | 43 | @Override 44 | public void onActivityCreated(Bundle savedInstanceState) { 45 | super.onActivityCreated(savedInstanceState); 46 | 47 | subscribe.setListener(this); 48 | 49 | overlay = new View( display.getContext() ); 50 | FrameLayout.LayoutParams position = new FrameLayout.LayoutParams( display.getWidth(), display.getHeight() ); 51 | position.setMargins(0, 0, 0, 0); 52 | overlay.setLayoutParams(position); 53 | overlay.setBackgroundColor(0xFF000000); 54 | overlay.postInvalidate(); 55 | overlay.setAlpha( 0f ); 56 | 57 | ((FrameLayout)display.getParent()).addView( overlay ); 58 | } 59 | 60 | @Override 61 | public void onConnectionEvent(R5ConnectionEvent r5ConnectionEvent) { 62 | super.onConnectionEvent(r5ConnectionEvent); 63 | if ( R5ConnectionEvent.NET_STATUS.value() == r5ConnectionEvent.value() ) { 64 | if( r5ConnectionEvent.message == "NetStream.Play.SufficientBW" ){ 65 | overlay.setAlpha( 0f ); 66 | } 67 | else if( r5ConnectionEvent.message == "NetStream.Play.InSufficientBW" ){ 68 | overlay.setAlpha( 0.5f ); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeCluster/README.md: -------------------------------------------------------------------------------- 1 | # Subscribing To a Cluster Server 2 | 3 | # Publishing and subscribing with Red5 Pro clusters 4 | 5 | With clustering, we need to determine which red5 pro instance the client will use. The other examples used a static configuration ip for streaming endpoints. Basic clustering uses more than one stream endpoint for subscribers. Advanced clustering uses more than one endpoint for publishers also. 6 | 7 | In the basic clustering scenario, our configuration ip will be used differently for publishers and subscribers. Publishers will stream directly to the configuration ip. Subscribers will not. Instead, subscribers will call a web service to receive the ip that should be used. 8 | 9 | ### Example Code 10 | 11 | - ***[SubscribeCluster.java](SubscribeCluster.java)*** 12 | 13 | ## Configuration of the server 14 | 15 | The cluster.xml file located in the conf directory. If the server is an edge, add an ip for its origin(s) within the origins list. Every server in your cluster must use the same password or core connections are denied. Set the public facing ip and port. 16 | Origins provide round robin, and you can exclude instances from it by setting the privateInstance property to true on the edge. The hidden edge can be used for other purposes such as being a repeater origin. 17 | 18 | ```xml 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 0.0.0.0:1935 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ``` 43 | 44 | The round robin servlet is defined in web.xml of your webapp. It is the service point subscribers use to get a playback-ip. 45 | 46 | ```xml 47 | 48 | 49 | cluster 50 | 51 | 52 | 53 | com.red5pro.cluster.plugin.agent.ClusterWebService 54 | 55 | 56 | 57 | 2 58 | 59 | 60 | 61 | cluster 62 | 63 | /cluster 64 | 65 | 66 | ``` 67 | 68 | The uri would be http://YOUR_IP:5080/YOURAPP/cluster. 69 | 70 | ## How to Publish 71 | 72 | Publishers must use the origin ip in their configuration. The stream is distributed to the edges from the origin. Use the publish example or a flash broadcaster to provide a live stream. 73 | 74 | ## How to Subscribe 75 | 76 | Subscribers call the cluster servlet, and use the return data as the configuration ip. The origin will know which edges are active and provide the next in sequence. 77 | 78 | ```Java 79 | HttpClient httpClient = new DefaultHttpClient(); 80 | HttpResponse response = httpClient.execute(new HttpGet("http://" + TestContent.GetPropertyString("host") + ":5080/cluster")); 81 | StatusLine statusLine = response.getStatusLine(); 82 | if (statusLine.getStatusCode() == HttpStatus.SC_OK) { 83 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 84 | response.getEntity().writeTo(out); 85 | String responseString = out.toString(); 86 | out.close(); 87 | //the return is the host ip and rtmp port. we are only interested in the host ip. 88 | String[] bits = responseString.split(":"); 89 | edgeIP = bits[0]; 90 | Log.i("cluster", "round robin ip: " + edgeIP); 91 | ``` 92 | 93 | [SubscribeCluster.java #48](SubscribeCluster.java#L48) 94 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeEncryptedTest/README.md: -------------------------------------------------------------------------------- 1 | # Adding security to Red5 Pro streams 2 | 3 | While a lot of streaming applications are intended to be as public as possible, many are intended for more descrete audiences - or decidedly confidential. For those situations, SRTP can give a piece of mind that traffic can't be spyed on uninvited. 4 | 5 | > **NOTE:** SRTP Support requires Red5 Pro Server version 5.5.0 or higher 6 | 7 | ### Example Code 8 | 9 | - ***[SubscribeTest.java](../PublishTest/PublishTest.java)*** 10 | - ***[SubscribeEncryptedTest.java](PublishEncryptedTest.java)*** 11 | 12 | ## SRTP 13 | 14 | The Red5 Pro SDK has included the option to wrap its streams in `SRTP` - a Secure variation of the `RTP` (Real-time Transport Protocol) that is normally used to wrap `RTSP` (Real-time Streaming Protocol) that the SDK operates on. Specifically, once negotiation with the server is complete, everything sent between the SDK and server (or vice versa) is encrypted and authenticated to ensure that a third party can't view the stream or modify data without detection. 15 | 16 | Also, as part of the SRTP specification, we support "null key" SRTP. Refered to in the sdk as `Null SRTP` - it's essentially taking the authentication protection to prevent outside tampering with the stream in situations that don't require the extra overhead for the view-protection of encryption. 17 | 18 | Note that while the encryption suite used is relatively fast where cryptograhpy is concerned, it does still introduce some overhead. Even Null SRTP still requires processing all data before transmition, and mobile devices aren't the most powerful of computers. This overhead will scale roughly with bitrate settings, and may lower the framerate of a stream. 19 | 20 | ### Enable Encryption 21 | 22 | As complicated as encryption is, it's implementation couldn't be simpler - simply set the `protocol` property of the R5Configuration (the first value of its constructor) to the correct value before initializing the connection and the SDK will take care of the rest. 23 | 24 | ```Java 25 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, 26 | ``` 27 | 28 | [SubscribeEncryptedTest.java #18](SubscribeEncryptedTest.java#L18) 29 | 30 | To set Null SRTP instead, use `NULL_SRTP` - and of course, the default of `RTSP` is still available where security isn't such a concern. 31 | 32 | ### New Events 33 | 34 | As part of the new protocols, two new events have been added to differentiate between an issue specific to the SRTP setup and the SDK in general. 35 | 36 | `R5ConnectionEvent.SRTP_KEY_GEN_ERROR` - This indicates that something has prevented the device from generating its part of the key exchange. The chance of seeing this error should be zero - barring a manufacturing fault or software malfunction. 37 | 38 | `R5ConnectionEvent.SRTP_KEY_HANDLE_ERROR` - This indicates that there has been a fault between the server and the SDK. Either that there's been some fault that prevented the key exchange from happening cleanly - or that the server is using an old version and doesn't support SRTP. 39 | 40 | For both of these errors, the message that accompanies them will include more detail on what exactly hasn't worked. 41 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeEncryptedTest/SubscribeEncryptedTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.SubscribeEncryptedTest; 27 | 28 | import com.red5pro.streaming.R5Connection; 29 | import com.red5pro.streaming.R5Stream; 30 | import com.red5pro.streaming.R5StreamProtocol; 31 | import com.red5pro.streaming.config.R5Configuration; 32 | import com.red5pro.streaming.media.R5AudioController; 33 | 34 | import red5pro.org.testandroidproject.tests.SubscribeTest.SubscribeTest; 35 | import red5pro.org.testandroidproject.tests.TestContent; 36 | 37 | public class SubscribeEncryptedTest extends SubscribeTest { 38 | 39 | @Override 40 | public void Subscribe() { 41 | 42 | //Create the configuration from the tests.xml 43 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, 44 | TestContent.GetPropertyString("host"), 45 | TestContent.GetPropertyInt("port"), 46 | TestContent.GetPropertyString("context"), 47 | TestContent.GetPropertyFloat("subscribe_buffer_time")); 48 | config.setLicenseKey(TestContent.GetPropertyString("license_key")); 49 | config.setBundleID(getActivity().getPackageName()); 50 | 51 | String params = TestContent.getConnectionParams(); 52 | if (params != null) { 53 | config.setParameters(params); 54 | } 55 | 56 | R5Connection connection = new R5Connection(config); 57 | 58 | //setup a new stream using the connection 59 | subscribe = new R5Stream(connection); 60 | 61 | //Some devices can't handle rapid reuse of the audio controller, and will crash 62 | //Recreation of the controller assures that the example will always be stable 63 | subscribe.audioController = new R5AudioController(); 64 | subscribe.audioController.sampleRate = TestContent.GetPropertyInt("sample_rate"); 65 | 66 | subscribe.client = this; 67 | subscribe.setListener(this); 68 | 69 | //show all logging 70 | subscribe.setLogLevel(R5Stream.LOG_LEVEL_DEBUG); 71 | 72 | //display.setZOrderOnTop(true); 73 | display.attachStream(subscribe); 74 | 75 | display.showDebugView(TestContent.GetPropertyBool("debug_view")); 76 | 77 | 78 | subscribe.play(TestContent.GetPropertyString("stream1"), TestContent.GetPropertyBool("hwAccel_on")); 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeHardwareAccelerationTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscribing to playback with Hardware Accelerated Video Decode 2 | 3 | This example shows how to playback a stream using the Hardware Accelerated decode of the video data. 4 | 5 | ## Example Code 6 | 7 | - ***[SubscribeHardwareAccelerationTest.java](SubscribeHardwareAccelerationTest.java)*** 8 | 9 | # Video Decoding 10 | 11 | In Mobile SDK versions prior to `6.0.0`, the SDK defaulted to decoding incoming video frames on the CPU using an RGB scalar. The default for `6.0.0` and forward is to move the video decode operation to the GPU. This generates YUV420p (tri-planar) data. 12 | 13 | Additionally, you can request to use **hardware accelerated** decode capabilities of the target platform; in the case of iOS, that is `MediaCodec`. The result of using **hardware acceleration** for decode is the generation of a YUV420v data represented as a an array of `byte` array length of 2 (1 plane for `Y`, the other for `UV`). 14 | 15 | ## play:withHardwareAcceleration 16 | 17 | The API to turn on hardware accelerated video frame decoding is `play` with the second argument being `true` to turn on hardware acceleration: 18 | 19 | ```java 20 | subscribe.play(TestContent.GetPropertyString("stream1"), true); 21 | ``` 22 | 23 | [SubscribeHardwareAccelerationTest #71](SubscribeHardwareAccelerationTest.java#L71) 24 | 25 | ## setFrameListener 26 | 27 | Because there are a few different possibilities in requesting decode format as of the `6.0.0` release, the `setFrameListener` callback API of `R5FrameListener` interface has been updated to include the format of the data being sent. 28 | 29 | ```java 30 | subscribe.setFrameListener(new R5FrameListener() { 31 | @Override 32 | public void onFrameReceived(Object o, R5StreamFormat r5StreamFormat, int w, int h) { 33 | int format = r5StreamFormat.value(); // 3 - YUV Bi-Planar 34 | if (r5StreamFormat.equals(R5StreamFormat.YUV_BIPLANAR)) { 35 | byte[][] yuv_frames = (byte[][]) o; // Cast and access data in 2 planes as byte array. (byte[2][]) 36 | } 37 | } 38 | }); 39 | ``` 40 | 41 | [SubscribeHardwareAccelerationTest #104](SubscribeHardwareAccelerationTest.java#L104) 42 | 43 | The `R5StreamFormat` enumeration is: 44 | 45 | * `UNKNOWN` : an unknown/unspecified format 46 | * `RGB` : RGB. The `data` argument is a single block of data. 47 | * `YUV_PLANAR` : YUV420p, tri-planar. The `data` is an array of data in 3 planes (Y, U, V, respectively). 48 | * `YUV_BIPLANAR` : YUV420v. The `data` argument is an array of data in 2 planes (Y and UV, respectively). 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeImageTest/README.md: -------------------------------------------------------------------------------- 1 | # Subcriber Image Capture 2 | 3 | `R5Stream.getStreamImage` allows the user to capture a screenshot of the stream at any time. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 8 | - ***[SubscribeImageTest.java](SubscribeImageTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Begin by publishing to **stream1** from a second device. **stream1** is the default stream1 name that is used by this example. Select the **SubscribeStreamImageTest** option to open a subscriber view. 13 | 14 | Touch the screen at any time while streaming to popup a temporary overlay containing the UIImage that is returned from the Red5 Pro SDK. 15 | 16 | ## Using getStreamImage 17 | 18 | `R5Stream.getStreamImage` returns a UIImage containing a screenshot of the current stream. The image dimensions match the incoming stream dimensions, and contain RGB data. Once streaming, simply call: 19 | 20 | ```Java 21 | screenShot.setImageBitmap(subscribe.getStreamImage()); 22 | ``` 23 | 24 | [SubscribeImageTest.java #43](SubscribeImageTest.java#L43) 25 | 26 | The UIImage can be saved to disk, displayed with a UIImageView, or processed in any way that is needed. -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeImageTest/SubscribeImageTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.SubscribeImageTest; 27 | 28 | import android.os.Bundle; 29 | import android.view.MotionEvent; 30 | import android.view.View; 31 | import android.widget.AbsoluteLayout; 32 | import android.widget.FrameLayout; 33 | import android.widget.ImageView; 34 | import android.widget.RelativeLayout; 35 | 36 | import red5pro.org.testandroidproject.tests.SubscribeTest.SubscribeTest; 37 | 38 | /** 39 | * Created by davidHeimann on 2/10/16. 40 | */ 41 | public class SubscribeImageTest extends SubscribeTest { 42 | ImageView screenShot; 43 | 44 | @Override 45 | public void onActivityCreated(Bundle savedInstanceState) { 46 | super.onActivityCreated(savedInstanceState); 47 | 48 | display.setOnTouchListener(new View.OnTouchListener() { 49 | @Override 50 | public boolean onTouch(View v, MotionEvent event) { 51 | return onSubscribeTouch(event); 52 | } 53 | }); 54 | } 55 | 56 | private boolean onSubscribeTouch( MotionEvent e ){ 57 | 58 | if( e.getAction() == MotionEvent.ACTION_DOWN ){ 59 | if( screenShot != null ){ 60 | ((FrameLayout)display.getParent()).removeView(screenShot); 61 | } 62 | screenShot = new ImageView( display.getContext() ); 63 | FrameLayout.LayoutParams position = new FrameLayout.LayoutParams( display.getWidth()/2, display.getHeight()/2 ); 64 | position.setMargins( display.getWidth()/2, display.getHeight()/2, 0, 0 ); 65 | screenShot.setLayoutParams(position); 66 | 67 | screenShot.setScaleType(ImageView.ScaleType.FIT_CENTER); 68 | screenShot.setImageBitmap(subscribe.getStreamImage()); 69 | 70 | ((FrameLayout)display.getParent()).addView(screenShot); 71 | } 72 | 73 | return true; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeMuteTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscribe Mute Test 2 | 3 | `R5AudioController.setPlaybackGain` can be used to adjust the playback volume of a stream. The range is from `0.0` to `1.0`. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 8 | - ***[SubscribeMuteTest.java](SubscribeMuteTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Begin by publishing to **stream1** from a second device. **stream1** is the default stream1 name that is used by this example. 13 | 14 | Touch the screen at any time while streaming to toggle mute of audio in playback. 15 | 16 | ## Using setPlaybackGain 17 | 18 | `R5AudioController.setPlaybackGain` takes a value from `0.0` to `1.0`. In this example, the value is toggled between `0.0` and `1.0` to mute and set full volume, respectively. 19 | 20 | ```java 21 | mIsMuted = !mIsMuted; 22 | subscribe.audioController.setPlaybackGain(mIsMuted ? 0.0f : 1.0f); 23 | ``` 24 | 25 | [SubscribeMuteTest.java #88](SubscribeMuteTest.java#L88) 26 | 27 | ## Note 28 | 29 | The volume button mute is locked down by Apple. 30 | 31 | The only solution found for this has been either using the "ambient" playback category - which doesn't allow recording - or switching from `AVAudioSessionCategoryPlayback` category to `AVAudioSessionCategoryPlayAndRecord` within the same session, which messes with AEC (echo cancellation). 32 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeNoViewTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscriber With No View 2 | 3 | Streams don't need to be connected to a view in order to work. While that will prevent them from displaying video, if a stream is audio-only, it will still play completely. The example will look very similar to the basic subscribe example, with the notable exception that a display doesn't need to be created or attached. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeNoViewTest.java](SubscribeNoViewTest.java)*** 8 | 9 | ## Running the example 10 | 11 | Begin by publishing to **stream1** from a second device. This stream should be audio only, but if it has video, that won't prevent the audio from playing. 12 | 13 | Select the example and it should begin playing any audio that is picked up by the other device. -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeRemoteCallTest/README.md: -------------------------------------------------------------------------------- 1 | # Remote Procedure Calls 2 | 3 | `R5Stream.send` allows the publisher to send messages to the server to be sent to all subscribers. 4 | 5 | ### Example Code 6 | 7 | - ***[PublishRemoteCallTest.java](../PublishRemoteCallTest/PublishRemoteCallTest.java)*** 8 | - ***[SubscribeRemoteCallTest.java](SubscribeRemoteCallTest.java)*** 9 | 10 | ## Running the example 11 | 12 | Two devices are required to run this example. One as a publisher, and the other as a subscriber. 13 | 14 | Connect the first device (publisher) with the Publish - Remote Call example. On the second device (subscriber) use the Subscribe - Remote Call example. 15 | 16 | Touch the preview on the publisher screen to display a label on the subscriber screen where the publisher touched. 17 | 18 | ## Using the R5Stream send 19 | 20 | Once the stream has connected you are able to dispatch messages to any connected subscribers. Sending the message is a simple call that takes a map object: 21 | 22 | ```Java 23 | publish.send("whateverFunctionName", map); 24 | ``` 25 | 26 | [PublishRemoteCallTest.java #40](../PublishRemoteCallTest/PublishRemoteCallTest.java#L40) 27 | 28 | ### Send Message Format 29 | 30 | The publisher send takes any object that implements the Map interface that uses a string as both the key and value. This example uses a Hashtable. 31 | 32 | ```Java 33 | Hashtable map = new Hashtable(); 34 | map.put("key", "value"); 35 | ``` 36 | 37 | The R5RemoteCallContainer will automatically handle turning the map into a strin of the following format, which is how it will be received by the subscriber's client. 38 | 39 | ```Java 40 | "key1=value1;key2=value2;key3=value3;" 41 | ``` 42 | 43 | ## Receiving R5Stream send calls 44 | 45 | In order to handle `R5Stream.send` calls from the publisher, the `R5Stream.client` delegate must be set. This delegate will receive all `R5Stream.send` messages via appropriately named methods. 46 | 47 | ```Java 48 | subscribe.client = this; 49 | ``` 50 | 51 | [SubscribeRemoteCallTest.java #27](SubscribeRemoteCallTest.java#L27) 52 | 53 | Because the publisher will be sending **whateverFunctionName**, the subscriber client delegate will need a matching method signature. As the name implies, the function can be named anything as long as it is publicly accessible. All methods receive a single string argument containing the variable map provided by the publisher. This map can easily be parsed. 54 | 55 | ```Java 56 | public void whateverFunctionName( String message ){ 57 | 58 | System.out.println("Recieved message from publisher: " + message); 59 | 60 | String[] parsedMessage = message.split(";"); 61 | Hashtable map = new Hashtable(); 62 | for (String s : parsedMessage) { 63 | String key = s.split("=")[0]; 64 | String value = s.split("=")[1]; 65 | System.out.println("Received key: " + key + "; with value: " + value); 66 | 67 | map.put(key,value); 68 | } 69 | ``` 70 | 71 | [SubscribeRemoteCallTest.java #30](SubscribeRemoteCallTest.java#L30) 72 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeRendererRGBScalarTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscribing to playback with RGB decode 2 | 3 | This example shows how to playback a stream using the CPU decode of video frames to RGB. 4 | 5 | ## Example Code 6 | 7 | - ***[SubscribeRendererRGBScalarTest.java](SubscribeRendererRGBScalarTest.java)*** 8 | 9 | # Video Decoding 10 | 11 | In Mobile SDK versions prior to `6.0.0`, the SDK defaulted to decoding incoming video frames on the CPU using an RGB scalar. There were other API from the SDK that related to accessing these frames that you may have been using in your project(s). As such, providing an API to request to decode to RGB and access that RGB data is preserved for backward-compatiblity. 12 | 13 | As of the `6.0.0` release of the Mobile SDKs, video decoding has been moved to the GPU to provide better playback. By default, the video frames are now decoded to YUV420v which is 3 planes of frame data. 14 | 15 | Additionally, you can request to use hardware accelerated decode of the platform. In the case of Android, that uses `MediaCodec` and produces a YUV420v representation with 2 planes (`Y` and `UV`). 16 | 17 | > For **Hardware Acceleration** usage, see [SubscribeHardwareAcceleration](../SubscribeHardwareAccelerationTest). 18 | 19 | ## play:withForcedRGBScalar 20 | 21 | The API to support backward compatibility in generating and accessing the RGB video frame is `playWithForcedRGBScalar`: 22 | 23 | ```java 24 | subscribe.playWithForcedRGBScalar(TestContent.GetPropertyString("stream1")); 25 | ``` 26 | 27 | [SubscribeRendererRGBScalarTest #64](SubscribeRendererRGBScalarTest.java#L64) 28 | 29 | > The `R5Stream` API of `play` (which previously would produce RGB frame data) now defaults to offloading the video decode to the GPU to generate YUV420p (tri-planar) data. 30 | 31 | ## setFrameListener 32 | 33 | Because there are a few different possibilities in requesting decode format as of the `6.0.0` release, the `setFrameListener` callback API of the `R5FrameListener` interface has been updated to include the format of the data being sent. 34 | 35 | ```java 36 | subscribe.setFrameListener(new R5FrameListener() { 37 | @Override 38 | public void onFrameReceived(Object o, R5StreamFormat r5StreamFormat, int w, int h) { 39 | int format = r5StreamFormat.value(); // 1 - RGB 40 | if (r5StreamFormat.equals(R5StreamFormat.RGB)) { 41 | byte[] rgb_frame = (byte[]) o; // Cast and access data plane as byte array. 42 | } 43 | } 44 | }); 45 | }) 46 | ``` 47 | 48 | [SubscribeRendererRGBScalarTest #101](SubscribeRendererRGBScalarTest.swift#L101) 49 | 50 | The `R5StreamFormat` enumeration is: 51 | 52 | * `UNKNOWN` : an unknown/unspecified format 53 | * `RGB` : RGB. The `data` argument is a single block of data. 54 | * `YUV_PLANAR` : YUV420p, tri-planar. The `data` is an array of data in 3 planes (Y, U, V, respectively). 55 | * `YUV_BIPLANAR` : YUV420v. The `data` argument is an array of data in 2 planes (Y and UV, respectively). 56 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeSMEncryptedTest/README.md: -------------------------------------------------------------------------------- 1 | # Encrypted Stream Manager Subscribing 2 | 3 | Using a stream manager doesn't prevent your streams from being encrypted - the same configuration can be used to protect the contents of your broadcasts in any server configuration. 4 | 5 | ## Example Code 6 | 7 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 8 | - ***[SubscribeStreamManagerTest.java](../SubscribeStreamManagerTest/SubscribeStreamManagerTest.java)*** 9 | - ***[SubscribeSMEncryptedTest.swift](SubscribeSMEncryptedTest.swift)*** 10 | 11 | ## The One Change 12 | 13 | The only change from the [basic Stream Manager example](../SubscribeStreamManagerTest/) is that value that the `protocol` setting of the configuration is set to. Setting the protocol to use `R5StreamProtocol.SRTP` is all you need to do to signal the SDK to negotiate an encrypted session. 14 | 15 | ```Java 16 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, ...) 17 | ``` 18 | 19 | ## Further Security Concerns 20 | 21 | As with the basic Encryption example, it's suggested that some form of stream authentication is used. Additionally, it's suggested that the innitial negotiation to find the server to broadcast to be done over HTTPS to prevent a malicious party from connecting to the returned server first. Note - SRTP does not require the server to have an SSL certificate, and so this example is set to run without HTTPS to run on more servers, but HTTPS will require the server to be set up with an appropriate SSL certificate, and the port must not be added to the Stream Manager API request for it to connect correctly. 22 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeSMEncryptedTest_SM1/README.md: -------------------------------------------------------------------------------- 1 | # Encrypted Stream Manager Subscribing 2 | 3 | Using a stream manager doesn't prevent your streams from being encrypted - the same configuration can be used to protect the contents of your broadcasts in any server configuration. 4 | 5 | ### Example Code 6 | - ***[SubscribeTest.java](../SubscribeTest/SubscribeTest.java)*** 7 | - ***[SubscribeStreamManagerTest.java](../SubscribeStreamManagerTest/SubscribeStreamManagerTest.java)*** 8 | - ***[SubscribeSMEncryptedTest.swift](SubscribeSMEncryptedTest.swift)*** 9 | 10 | ### The One Change 11 | The only change from the [basic Stream Manager example](../SubscribeStreamManagerTest/) is that value that the `protocol` setting of the configuration is set to. Setting the protocol to use `R5StreamProtocol.SRTP` is all you need to do to signal the SDK to negotiate an encrypted session. 12 | 13 | ```Java 14 | R5Configuration config = new R5Configuration(R5StreamProtocol.SRTP, 15 | ``` 16 | 17 | [SubscribeSMEncryptedTest.java #24](SubscribeSMEncryptedTest.java#L24) 18 | 19 | ### Further Security Concerns 20 | As with the basic Encryption example, it's suggested that some form of stream authentication is used. Additionally, it's suggested that the innitial negotiation to find the server to broadcast to be done over HTTPS to prevent a malicious party from connecting to the returned server first. Note - SRTP does not require the server to have an SSL certificate, and so this example is set to run without HTTPS to run on more servers, but HTTPS will require the server to be set up with an appropriate SSL certificate, and the port must not be added to the Stream Manager API request for it to connect correctly. 21 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeSetVolumeTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscribe Volume Test 2 | 3 | `R5AudioController.setPlaybackGain` can be used to adjust the playback volume of a stream. The range is from `0.0` to `1.0`. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeSetVolumeTest.java](SubscribeSetVolumeTest.java)*** 8 | 9 | ## Running the example 10 | 11 | 1. Begin by publishing to **stream1** from a second device. **stream1** is the default stream1 name that is used by this example. 12 | 2. Use the slider UI to adjust the playback volume of the stream. 13 | 14 | ## Using setPlaybackGain 15 | 16 | `R5AudioController.setPlaybackGain:` takes a value from `0.0` to `1.0`. In this example, the value is changed based on the user input from the slider control. 17 | 18 | ```java 19 | slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 20 | @Override 21 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) { 22 | float value = i/100f; 23 | Log.d("Subscriber", ":setVolume=" + value); 24 | subscribe.audioController.setPlaybackGain(value); 25 | } 26 | } 27 | ``` 28 | 29 | [SubscribeSetVolumeTest.java #46](SubscribeSetVolumeTest.java#L46) 30 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeSetVolumeTest/SubscribeSetVolumeTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2015 Infrared5, Inc. All rights reserved. 3 | // 4 | // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") 5 | // is licensed to you by Infrared5 Inc. in consideration of your agreement to the following 6 | // license terms and conditions. Access, use, modification, or redistribution of the accompanying 7 | // code constitutes your acceptance of the following license terms and conditions. 8 | // 9 | // Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation 10 | // files (collectively, the "Software") without restriction, including without limitation the rights to use, 11 | // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 12 | // persons to whom the Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end 15 | // user license agreement (the "EULA"), which must be executed with Infrared5, Inc. 16 | // An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt. 17 | // 18 | // The above copyright notice and this license shall be included in all copies or portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | package red5pro.org.testandroidproject.tests.SubscribeSetVolumeTest; 27 | 28 | import android.os.Bundle; 29 | import android.util.Log; 30 | import android.view.LayoutInflater; 31 | import android.view.MotionEvent; 32 | import android.view.View; 33 | import android.view.ViewGroup; 34 | import android.widget.AbsoluteLayout; 35 | import android.widget.FrameLayout; 36 | import android.widget.ImageView; 37 | import android.widget.RelativeLayout; 38 | import android.widget.SeekBar; 39 | 40 | import com.red5pro.streaming.view.R5VideoView; 41 | 42 | import red5pro.org.testandroidproject.R; 43 | import red5pro.org.testandroidproject.tests.SubscribeTest.SubscribeTest; 44 | 45 | /** 46 | * Created by toddanderson on 08/30/2018. 47 | */ 48 | public class SubscribeSetVolumeTest extends SubscribeTest { 49 | 50 | private SeekBar slider; 51 | 52 | @Override 53 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 54 | 55 | View view = inflater.inflate(R.layout.subscribe_scrub_test, container, false); 56 | 57 | //find the view and attach the stream 58 | display = (R5VideoView) view.findViewById(R.id.videoView); 59 | slider = (SeekBar) view.findViewById(R.id.seekBar); 60 | slider.setProgress(100); 61 | 62 | Subscribe(); 63 | 64 | return view; 65 | } 66 | 67 | @Override 68 | public void onActivityCreated(Bundle savedInstanceState) { 69 | super.onActivityCreated(savedInstanceState); 70 | 71 | slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 72 | @Override 73 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) { 74 | float value = i/100f; 75 | Log.d("Subscriber", ":setVolume=" + value); 76 | subscribe.audioController.setPlaybackGain(value); 77 | } 78 | 79 | @Override 80 | public void onStartTrackingTouch(SeekBar seekBar) { 81 | 82 | } 83 | 84 | @Override 85 | public void onStopTrackingTouch(SeekBar seekBar) { 86 | 87 | } 88 | }); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeStreamManagerTest/README.md: -------------------------------------------------------------------------------- 1 | # Stream Manager Subscribing 2 | 3 | With clustering, we need to determine which Red5 Pro instance the client will use. The other examples used a static configuration ip for streaming endpoints. Basic clustering uses more than one stream endpoint for subscribers. Advanced clustering uses more than one endpoint for publishers also. 4 | 5 | With the Stream Manager, our configuration IP will be used similarly for publishers and subscribers. Both publishers and subscribers will call a web service to receive the IP that should be used. Since this is an HTTP call, you can use a DNS Name for the `host` value. 6 | 7 | ### Example Code 8 | 9 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 10 | - ***[SubscribeStreamManagerTest.java](SubscribeStreamManagerTest.java)*** 11 | 12 | ## Setup 13 | 14 | In order to subscribe, you first need to connect to the origin server's Stream Manager. The Stream Manager will know which edges are active and provide the one that you need to subscribe from. 15 | 16 | ```Java 17 | //url format: "\(host)\(portURI)/as/\(version)/streams/stream/\(nodeGroup)/publish/\(context)/\(streamName)" 18 | String host = TestContent.GetPropertyString("host"); 19 | String version = TestContent.GetPropertyString("sm_version"); 20 | String nodeGroup = TestContent.GetPropertyString("sm_nodegroup"); 21 | String context = TestContent.GetPropertyString("context"); 22 | String streamName = TestContent.GetPropertyString("stream1"); 23 | 24 | String url = String.format("https://%s/as/%s/streams/stream/%s/subscribe/%s/%s", 25 | host, 26 | version, 27 | nodeGroup, 28 | context, 29 | streamName); 30 | HttpClient httpClient = new DefaultHttpClient(); 31 | HttpResponse response = httpClient.execute(new HttpGet(url)); 32 | StatusLine statusLine = response.getStatusLine(); 33 | 34 | if (statusLine.getStatusCode() == HttpStatus.SC_OK) { 35 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 36 | response.getEntity().writeTo(out); 37 | String responseString = out.toString(); 38 | out.close(); 39 | 40 | JSONArray edges = new JSONArray(responseString); 41 | JSONObject data = edges.getJSONObject(0); 42 | final String outURL = data.getString("serverAddress"); 43 | } 44 | ``` 45 | 46 | The service returns a JSON array of Edge nodes available to connect to; in typical deployments, this will be of a length of one. 47 | 48 | ```Java 49 | JSONArray origins = new JSONArray(responseString); 50 | JSONObject data = origins.getJSONObject(0); 51 | final String outURL = data.getString("serverAddress"); 52 | ``` 53 | 54 | The Edge address is then used as the `host` configuration property in order to subscriber to the stream. 55 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeStreamManagerTest_SM1/README.md: -------------------------------------------------------------------------------- 1 | # Stream Manager Subscribing 2 | 3 | With clustering, we need to determine which red5 pro instance the client will use. The other examples used a static configuration ip for streaming endpoints. Basic clustering uses more than one stream endpoint for subscribers. Advanced clustering uses more than one endpoint for publishers also. 4 | 5 | With the Stream Manager, our configuration IP will be used similarly for publishers and subscribers. Both publishers and subscribers will call a web service to receive the IP that should be used. Since this is an HTTP call, you can use a DNS Name for the `host` value. 6 | 7 | ### Example Code 8 | 9 | - ***[PublishTest.java](../PublishTest/PublishTest.java)*** 10 | - ***[SubscribeStreamManagerTest.java](SubscribeStreamManagerTest.java)*** 11 | 12 | ## Setup 13 | 14 | In order to subscribe, you first need to connect to the origin server's Stream Manager. The Stream Manager will know which edges are active and provide the one that you need to subscribe from. 15 | 16 | ```Java 17 | String url = "https://" + 18 | TestContent.GetPropertyString("host") + "/streammanager/api/3.1/event/" + 19 | TestContent.GetPropertyString("context") + "/" + 20 | TestContent.GetPropertyString("stream1") + "?action=subscribe"; 21 | 22 | HttpClient httpClient = new DefaultHttpClient(); 23 | HttpResponse response = httpClient.execute(new HttpGet(url)); 24 | StatusLine statusLine = response.getStatusLine(); 25 | 26 | if (statusLine.getStatusCode() == HttpStatus.SC_OK) { 27 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 28 | response.getEntity().writeTo(out); 29 | String responseString = out.toString(); 30 | out.close(); 31 | ``` 32 | 33 | [SubscribeStreamManagerTest.java #46](SubscribeStreamManagerTest.java#L46) 34 | 35 | The service returns a json object with the information needed to connect to subscribe. 36 | 37 | ```Java 38 | JSONObject data = new JSONObject(responseString); 39 | String outURL = data.getString("serverAddress"); 40 | ``` 41 | 42 | [SubscribeStreamManagerTest.java #48](SubscribeStreamManagerTest.java#L48) 43 | 44 | > **Note:** you will want to start the stream on the main thread. 45 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeStreamManagerTranscoderTest_SM1/README.md: -------------------------------------------------------------------------------- 1 | # Subscribing to Transcoded Stream over Stream Manager 2 | 3 | This example show how to rquest a provision list for a transcoded video over Stream Manager and select playback. 4 | 5 | ## Example Code 6 | 7 | - ***[SubscribeStreamManagerTranscoderTest.java](SubscribeStreamManagerTranscoderTest.java)*** 8 | 9 | # Setup 10 | 11 | You will first need to define a provision and begin publishing to the highest variant with a supported broadcaster. 12 | 13 | > For ease we have provided an publisher example to do so: [PublishStreamManagerTranscode](../PublishStreamManagerTranscode) 14 | 15 | # Requesting Transcoder Provision 16 | 17 | In the example, a request for the transcoder provision is made prior to: 18 | 19 | 1. Making a subsequent request for the Edge to which to subscribe. 20 | 2. Requesting subscription for playback. 21 | 22 | To access the provision held on the server, use the Stream Manager API for event metadata: 23 | 24 | ```java 25 | String port = TestContent.getFormattedPortSetting(TestContent.GetPropertyString("server_port")); 26 | String protocol = (port.isEmpty() || port.equals("443")) ? "https" : "http"; 27 | String token = TestContent.GetPropertyString("sm_access_token"); 28 | String url = protocol + "://" + 29 | TestContent.GetPropertyString("host") + port + "/streammanager/api/4.0" + 30 | "/admin/event/meta/" + 31 | TestContent.GetPropertyString("context") + "/" + 32 | streamNameGUID + "?action=subscribe&accessToken=" + token; 33 | 34 | HttpClient httpClient = new DefaultHttpClient(); 35 | HttpResponse response = httpClient.execute(new HttpGet(url)); 36 | ``` 37 | 38 | If you are requesting to subscribe to a stream named `mystream`, the above endpoint API URL would look something similar to: 39 | 40 | ```ssh 41 | https://myserver.com/streammanager/api/3.1/admin/event/meta/live/mystream?action=subscribe&accessToken=123 42 | ``` 43 | 44 | In a successful response, a JSON array with variant stream names is provided. 45 | 46 | > With a GUID of `mystream`, you will likely see a list of variant names such as the following: `mystream_1`, `mystream_2`, `mystream_3` - representing 3 levels of transcoded broadcast for consumption. 47 | 48 | # Subscribing to a Variant 49 | 50 | From the JSON list returned, the example provides the user to select which variant to being subscribing to. Upon selection: 51 | 52 | 1. A request on the Stream Manager is made to get the available Edge(s) that have the desired stream variant. 53 | 2. If successful, a request to being playback of the stream on the provided Edge(s). 54 | 55 | > The above is how one would normally subscribe to a stream over [Stream Manager](../SubscribeStreamManager), only using the variant name (e.g, `mystream_1`) instead of the GUID (`mystream`). 56 | 57 | The server will handle when to switch the stream variant on the client based on bandwidth and network availability. 58 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeTest/README.md: -------------------------------------------------------------------------------- 1 | # Subscribing on Red5 Pro 2 | 3 | This example shows how to easily subscribe to a Red5 Pro stream. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeTest.java](SubscribeTest.java)*** 8 | 9 | ## How to Subscribe 10 | 11 | Subscribing to a Red5 Pro stream requires a few components to function fully. 12 | 13 | ### Setup R5Connection 14 | 15 | The R5Connection manages the connection that the stream utilizes. You will need to setup a configuration and intialize a new connection. 16 | 17 | ```Java 18 | //Create the configuration from the tests.xml 19 | R5Configuration config = new R5Configuration(R5StreamProtocol.RTSP, 20 | TestContent.GetPropertyString("host"), 21 | TestContent.GetPropertyInt("port"), 22 | TestContent.GetPropertyString("context"), 23 | TestContent.GetPropertyFloat("subscribe_buffer_time")); 24 | R5Connection connection = new R5Connection(config); 25 | ``` 26 | 27 | [SubscribeTest.java #33](SubscribeTest.java#L33) 28 | 29 | ### Setup R5Stream 30 | 31 | The `R5Stream` handles both subscribing and publishing. Creating one simply requires the connection already created. 32 | 33 | ```Java 34 | //setup a new stream using the connection 35 | subscribe = new R5Stream(connection); 36 | ``` 37 | 38 | [SubscribeTest.java #41](SubscribeTest.java#L41) 39 | 40 | The `R5StreamDelegate` that is assigned to the `R5Stream` will receive status events for that stream, including connecting, disconnecting, and errors. 41 | 42 | ### Preview the Subscriber 43 | 44 | The `R5VideoView` will present subscribed streams. To view the subscribing stream, it simply needs to attach the `R5Stream`. 45 | 46 | A `R5VideoView` can be set in any View, or created programmatically 47 | 48 | ```Java 49 | display = (R5VideoView) view.findViewById(R.id.videoView); 50 | ``` 51 | 52 | [SubscribeTest.java #48](SubscribeTest.java#L48) 53 | 54 | Lastly, we attach the Stream to the R5VideoView to see the streaming content. 55 | 56 | ```Java 57 | display.attachStream(subscribe); 58 | ``` 59 | 60 | [SubscribeTest.java #49](SubscribeTest.java#L49) 61 | 62 | ### Start Subscribing 63 | 64 | The `R5Stream.Subscribe` method will establish the server connection and begin Subscribing. 65 | 66 | ```Java subscribe.play(TestContent.GetPropertyString("stream1")); 67 | ``` 68 | 69 | [SubscribeTest.java #51](SubscribeTest.java#L51) 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/java/red5pro/org/testandroidproject/tests/SubscribeTwoStreamTest/Readme.md: -------------------------------------------------------------------------------- 1 | # Subscribe To Two Streams 2 | 3 | This example demonstrates Subscribing to two different sources at once. 4 | 5 | ### Example Code 6 | 7 | - ***[SubscribeTwoStreamTest.java](SubscribeTwoStreamTest.java)*** 8 | 9 | ## Setup 10 | 11 | This is intended to be used with two others using the two-way example to put on a presentation, allowing anyone using this client to watch them converse. 12 | 13 | ### Managing Streams 14 | 15 | Of special note for subscribing to two streams at once is that each stream needs its own R5AudioController. Note that the first stream can still use the default R5AudioController, but any additional streams need a separate one. 16 | 17 | ```Java 18 | secondSubscribe.audioController = new R5AudioController(); 19 | ``` 20 | 21 | [SubscribeTwoStreamTest.java #79](SubscribeTwoStreamTest.java#L79) 22 | 23 | In addition, each stream needs a small ammount of time in between calls to subscribe. 24 | 25 | ```Java 26 | new Thread(new Runnable() { 27 | @Override 28 | public void run() { 29 | 30 | try { 31 | Thread.sleep(1000); 32 | 33 | Looper.prepare(); 34 | 35 | R5Configuration config2 = new R5Configuration(R5StreamProtocol.RTSP, 36 | TestContent.GetPropertyString("host"), 37 | TestContent.GetPropertyInt("port"), 38 | TestContent.GetPropertyString("context"), 39 | TestContent.GetPropertyFloat("subscribe_buffer_time")); 40 | 41 | R5Connection secondConnection = new R5Connection(config2); 42 | 43 | secondSubscribe = new R5Stream(secondConnection); 44 | 45 | secondDisplay.attachStream(secondSubscribe); 46 | secondDisplay.showDebugView(TestContent.GetPropertyString("debug_view").equals("true")); 47 | 48 | secondSubscribe.audioController = new R5AudioController(); 49 | secondSubscribe.play(TestContent.GetPropertyString("stream2")); 50 | 51 | }catch (Exception e){ 52 | e.printStackTrace(); 53 | } 54 | } 55 | }).start(); 56 | ``` 57 | 58 | [SubscribeTwoStreamTest.java #57](SubscribeTwoStreamTest.java#L57) -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libred5android.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/jniLibs/arm64-v8a/libred5android.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libred5streaming.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/jniLibs/arm64-v8a/libred5streaming.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libred5android.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/jniLibs/armeabi-v7a/libred5android.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libred5streaming.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/jniLibs/armeabi-v7a/libred5streaming.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libred5android.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/jniLibs/x86/libred5android.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libred5streaming.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/jniLibs/x86/libred5streaming.so -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/red5pro/streaming-android/2c8796a5f87512a0c23983945e7724da386d436a/app/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout-sw600dp/activity_test_list.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_param_table.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_test_list.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/layout/bg_publish_test.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_test_detail.xml: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/param_table_row_editable.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 17 | 18 | 24 | 28 | 29 | 30 | 31 | 35 | 36 | 42 | 46 | 47 | 48 | 49 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/publish_test.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/shared_object_test.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 12 | 13 | 19 | 20 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 43 | 44 |