diff --git a/.idea/.name b/.idea/.name
index 99bfd3e..a2ffb41 100644
--- a/.idea/.name
+++ b/.idea/.name
@@ -1 +1 @@
-VideoStreaming
\ No newline at end of file
+VideoStream
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 51d40c0..8dc6a51 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -8,6 +8,8 @@
+
+
diff --git a/.idea/libraries/android_rmtp_client_0_3.xml b/.idea/libraries/android_rmtp_client_0_3.xml
new file mode 100644
index 0000000..6ef6155
--- /dev/null
+++ b/.idea/libraries/android_rmtp_client_0_3.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/commons_lang3_3_1.xml b/.idea/libraries/commons_lang3_3_1.xml
new file mode 100644
index 0000000..93a2ca9
--- /dev/null
+++ b/.idea/libraries/commons_lang3_3_1.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/mina_core_2_0_7.xml b/.idea/libraries/mina_core_2_0_7.xml
new file mode 100644
index 0000000..5a80e66
--- /dev/null
+++ b/.idea/libraries/mina_core_2_0_7.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/slf4j_api_1_6_6.xml b/.idea/libraries/slf4j_api_1_6_6.xml
new file mode 100644
index 0000000..d27e51f
--- /dev/null
+++ b/.idea/libraries/slf4j_api_1_6_6.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index cb50892..c87e5fc 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,6 +3,9 @@
+
+
+
@@ -13,7 +16,7 @@
-
+
@@ -25,6 +28,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -52,19 +68,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 684f749..829884e 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -1,7 +1,13 @@
-
+
+
+
+
+
+
+
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index e10de87..9910758 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -52,103 +52,111 @@
-
-
+
+
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
+
+
-
+
-
-
+
+
@@ -172,16 +180,24 @@
-
+
-
+
+
+
+
+
+
+
+
+
@@ -195,9 +211,1525 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -282,7 +1814,7 @@
-
+
@@ -351,13 +1883,21 @@
+
+
+
+
+
+
+
+
-
+
-
+
@@ -426,13 +1966,21 @@
+
+
+
+
+
+
+
+
-
+
-
+
@@ -503,7 +2051,7 @@
-
+
@@ -584,89 +2132,89 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
@@ -688,7 +2236,6 @@
-
@@ -700,14 +2247,24 @@
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
@@ -735,369 +2292,427 @@
-
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
+
@@ -1107,13 +2722,15 @@
-
-
-
-
-
+
+
+
+
+
+
+
@@ -1281,9 +2898,51 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1306,36 +2965,36 @@
-
-
+
+
+
+
+
-
+
+
+
-
+
+
-
-
-
-
-
-
@@ -1359,56 +3018,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1445,9 +3054,7 @@
-
-
-
+
@@ -1468,15 +3075,15 @@
+
+
+
-
-
-
@@ -1529,9 +3136,7 @@
-
-
-
+
@@ -1544,15 +3149,15 @@
+
+
+
-
-
-
@@ -1607,19 +3212,12 @@
-
-
-
-
-
-
-
-
-
+
+
@@ -1639,15 +3237,15 @@
+
+
+
-
-
-
@@ -1721,8 +3319,127 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VideoStream.iml b/VideoStream.iml
new file mode 100644
index 0000000..135c0f9
--- /dev/null
+++ b/VideoStream.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rtmp_video_publisher/.gitignore b/rtmp_video_publisher/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/rtmp_video_publisher/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/rtmp_video_publisher/build.gradle b/rtmp_video_publisher/build.gradle
new file mode 100644
index 0000000..7349cc3
--- /dev/null
+++ b/rtmp_video_publisher/build.gradle
@@ -0,0 +1,24 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 'android-L'
+ buildToolsVersion "20.0.0"
+
+ defaultConfig {
+ applicationId "com.c77.videopublisher.rtmp_video_publisher"
+ minSdkVersion 15
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ runProguard false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile 'org.red5:android-rmtp-client:0.3'
+}
diff --git a/rtmp_video_publisher/proguard-rules.pro b/rtmp_video_publisher/proguard-rules.pro
new file mode 100644
index 0000000..0e13397
--- /dev/null
+++ b/rtmp_video_publisher/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /opt/android-studio/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/rtmp_video_publisher/rtmp_video_publisher.iml b/rtmp_video_publisher/rtmp_video_publisher.iml
new file mode 100644
index 0000000..0e3ed7d
--- /dev/null
+++ b/rtmp_video_publisher/rtmp_video_publisher.iml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rtmp_video_publisher/src/androidTest/java/com/c77/videopublisher/rtmp_video_publisher/ApplicationTest.java b/rtmp_video_publisher/src/androidTest/java/com/c77/videopublisher/rtmp_video_publisher/ApplicationTest.java
new file mode 100644
index 0000000..410e4bb
--- /dev/null
+++ b/rtmp_video_publisher/src/androidTest/java/com/c77/videopublisher/rtmp_video_publisher/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.c77.videopublisher.rtmp_video_publisher;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/rtmp_video_publisher/src/main/AndroidManifest.xml b/rtmp_video_publisher/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..dccf5f7
--- /dev/null
+++ b/rtmp_video_publisher/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rtmp_video_publisher/src/main/ic_launcher-web.png b/rtmp_video_publisher/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..4b14629
Binary files /dev/null and b/rtmp_video_publisher/src/main/ic_launcher-web.png differ
diff --git a/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/VideoPublisherMainActivity.java b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/VideoPublisherMainActivity.java
new file mode 100644
index 0000000..f1ceb57
--- /dev/null
+++ b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/VideoPublisherMainActivity.java
@@ -0,0 +1,89 @@
+package com.c77.videopublisher.rtmp_video_publisher;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.c77.videopublisher.rtmp_video_publisher.manager.ClientManager;
+
+public class VideoPublisherMainActivity extends Activity implements View.OnClickListener {
+
+ public static final int STOPPED = 0;
+ public static final int RECORDING = 1;
+
+ ClientManager clientManager = new ClientManager();
+ Button startButton = null;
+ Button stopButton = null;
+ Button exitButon = null;
+ //TextView textView = null;
+ int status = STOPPED;
+
+ public void onClick(View v) {
+ if (v == startButton) {
+ this.setTitle("Started!");
+ if(status == STOPPED){
+ clientManager.setRecording(true);
+ status = RECORDING;
+ }
+ }
+ if (v == stopButton) {
+ this.setTitle("stoped");
+ if(status == RECORDING){
+ clientManager.setRecording(false);
+ status = STOPPED;
+ }
+ }
+ if (v == exitButon) {
+ clientManager.setRecording(false);
+ clientManager.setRunning(false);
+ System.exit(0);
+ }
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ startButton = new Button(this);
+ stopButton = new Button(this);
+ exitButon = new Button(this);
+ //textView = new TextView(this);
+
+ startButton.setText("Start");
+ stopButton.setText("Stop");
+ exitButon.setText("Exit");
+ /*textView.setText("Android Recorder ChangeLog£º" +
+ "\n(1)Get PCM data." +
+ "\n(2)Encode with speex." +
+ "\n(3)Package in flv format" +
+ "\n(4)Publish audio to server." +
+ "\n(5)Record both local and server side.");*/
+
+ startButton.setOnClickListener(this);
+ stopButton.setOnClickListener(this);
+ exitButon.setOnClickListener(this);
+
+ LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ //layout.addView(textView);
+ layout.addView(startButton);
+ layout.addView(stopButton);
+ layout.addView(exitButon);
+ this.setContentView(layout);
+
+ clientManager.setMode(ClientManager.NETANDFILE);
+ clientManager.setRunning(true);
+ Thread cmThread = new Thread(clientManager);
+ cmThread.start();
+
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+}
\ No newline at end of file
diff --git a/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/Consumer.java b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/Consumer.java
new file mode 100644
index 0000000..c36d4a2
--- /dev/null
+++ b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/Consumer.java
@@ -0,0 +1,10 @@
+package com.c77.videopublisher.rtmp_video_publisher.io;
+
+public interface Consumer {
+
+ public void putData(long ts, byte[] buf, int size);
+
+ public void setRecording(boolean isRecording);
+
+ public boolean isRecording();
+}
diff --git a/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/file/FileClient.java b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/file/FileClient.java
new file mode 100644
index 0000000..a9f80c8
--- /dev/null
+++ b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/file/FileClient.java
@@ -0,0 +1,110 @@
+package com.c77.videopublisher.rtmp_video_publisher.io.file;
+
+import java.io.File;
+import org.apache.mina.core.buffer.IoBuffer;
+import org.red5.io.IStreamableFile;
+import org.red5.io.ITagWriter;
+import org.red5.io.IoConstants;
+import org.red5.io.flv.FLVService;
+import org.red5.io.flv.Tag;
+import org.red5.server.net.rtmp.message.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A client write tags to local file.
+ */
+public class FileClient implements Constants {
+ private static Logger log = LoggerFactory.getLogger(FileClient.class);
+
+ private String saveAsFileName;
+ private ITagWriter tagWriter;
+ private int prevSize = 0;
+ private Tag tag;
+ private int currentTime = 0;
+ private long timeBase = 0;
+ private int sampleRate = 0;
+ private int channle;
+
+ public FileClient() {
+
+ }
+
+ public void start(String saveAsFileName) {
+ this.saveAsFileName = saveAsFileName;
+ init();
+ }
+
+ private void init() {
+ File file = new File(saveAsFileName);
+ FLVService flvService = new FLVService();
+ flvService.setGenerateMetadata(true);
+ try {
+ IStreamableFile flv = flvService.getStreamableFile(file);
+ tagWriter = flv.getWriter();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void stop() {
+ if (tagWriter != null) {
+ tagWriter.close();
+ tagWriter = null;
+ }
+ log.debug("writer closed!");
+ }
+
+ public void writeTag(byte[] buf, int size, long ts) {
+ if (timeBase == 0) {
+ timeBase = ts;
+ }
+ currentTime = (int) (ts - timeBase);
+
+ tag = new Tag(IoConstants.TYPE_AUDIO, currentTime, size + 1, null,
+ prevSize);
+ prevSize = size + 1;
+
+ byte tagType = (byte) ((IoConstants.FLAG_FORMAT_SPEEX << 4))
+ | (IoConstants.FLAG_SIZE_16_BIT << 1);
+
+ switch (sampleRate) {
+ case 44100:
+ tagType |= IoConstants.FLAG_RATE_44_KHZ << 2;
+ break;
+ case 22050:
+ tagType |= IoConstants.FLAG_RATE_22_KHZ << 2;
+ break;
+ case 11025:
+ tagType |= IoConstants.FLAG_RATE_11_KHZ << 2;
+ break;
+ default:
+ tagType |= IoConstants.FLAG_RATE_5_5_KHZ << 2;
+ }
+
+ tagType |= (channle == 2 ? IoConstants.FLAG_TYPE_STEREO
+ : IoConstants.FLAG_TYPE_MONO);
+
+ IoBuffer body = IoBuffer.allocate(tag.getBodySize());
+ body.setAutoExpand(true);
+ body.put(tagType);
+ body.put(buf);
+ body.flip();
+ body.limit(size + 1);
+ tag.setBody(body);
+
+ try {
+ tagWriter.writeTag(tag);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void setSampleRate(int sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+
+ public void setChannle(int channle) {
+ this.channle = channle;
+ }
+}
diff --git a/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/net/NetClient.java b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/net/NetClient.java
new file mode 100644
index 0000000..3c8cef1
--- /dev/null
+++ b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/io/net/NetClient.java
@@ -0,0 +1,235 @@
+package com.c77.videopublisher.rtmp_video_publisher.io.net;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.mina.core.buffer.IoBuffer;
+import org.red5.io.IoConstants;
+import org.red5.io.flv.Tag;
+import org.red5.io.utils.ObjectMap;
+import org.red5.server.messaging.IMessage;
+import org.red5.server.net.rtmp.INetStreamEventHandler;
+import org.red5.server.net.rtmp.RTMPClient;
+import org.red5.server.net.rtmp.event.AudioData;
+import org.red5.server.net.rtmp.event.FlexStreamSend;
+import org.red5.server.net.rtmp.event.IRTMPEvent;
+import org.red5.server.net.rtmp.event.Invoke;
+import org.red5.server.net.rtmp.event.Notify;
+import org.red5.server.net.rtmp.event.Unknown;
+import org.red5.server.net.rtmp.event.VideoData;
+import org.red5.server.net.rtmp.message.Constants;
+import org.red5.server.net.rtmp.status.StatusCodes;
+import org.red5.server.service.IPendingServiceCall;
+import org.red5.server.service.IPendingServiceCallback;
+import org.red5.server.stream.message.RTMPMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A publish client to publish stream to server.
+ */
+public class NetClient implements INetStreamEventHandler,
+ IPendingServiceCallback {
+
+ private static Logger log = LoggerFactory.getLogger(NetClient.class);
+
+ private List frameBuffer = new ArrayList();
+
+ public static final int STOPPED = 0;
+
+ public static final int CONNECTING = 1;
+
+ public static final int STREAM_CREATING = 2;
+
+ public static final int PUBLISHING = 3;
+
+ public static final int PUBLISHED = 4;
+
+ private String host;
+
+ private int port;
+
+ private String app;
+
+ private int state;
+
+ private String publishName;
+
+ private int streamId;
+
+ private String publishMode;
+
+ private RTMPClient rtmpClient;
+
+ private int prevSize = 0;
+
+ private Tag tag;
+
+ private int currentTime = 0;
+
+ private long timeBase = 0;
+
+ private int sampleRate = 0;
+
+ private int channle;
+
+ public int getState() {
+ return state;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public void setSampleRate(int sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+
+ public void setChannle(int channle) {
+ this.channle = channle;
+ }
+
+ public synchronized void start(String publishName, String publishMode,
+ Object[] params) {
+ state = CONNECTING;
+ this.publishName = publishName;
+ this.publishMode = publishMode;
+ rtmpClient = new RTMPClient();
+
+ Map defParams = rtmpClient.makeDefaultConnectionParams(
+ host, port, app);
+ rtmpClient.connect(host, port, defParams, this, params);
+ }
+
+ public synchronized void stop() {
+ if (state >= STREAM_CREATING) {
+ rtmpClient.disconnect();
+ }
+ state = STOPPED;
+ }
+
+ public void writeTag(byte[] buf, int size, long ts) {
+ if (timeBase == 0) {
+ timeBase = ts;
+ }
+ currentTime = (int) (ts - timeBase);
+ tag = new Tag(IoConstants.TYPE_AUDIO, currentTime, size + 1, null,
+ prevSize);
+ prevSize = size + 1;
+
+ byte tagType = (byte) ((IoConstants.FLAG_FORMAT_SPEEX << 4))
+ | (IoConstants.FLAG_SIZE_16_BIT << 1);
+ switch (sampleRate) {
+ case 44100:
+ tagType |= IoConstants.FLAG_RATE_44_KHZ << 2;
+ break;
+ case 22050:
+ tagType |= IoConstants.FLAG_RATE_22_KHZ << 2;
+ break;
+ case 11025:
+ tagType |= IoConstants.FLAG_RATE_11_KHZ << 2;
+ break;
+ default:
+ tagType |= IoConstants.FLAG_RATE_5_5_KHZ << 2;
+ }
+
+ tagType |= (channle == 2 ? IoConstants.FLAG_TYPE_STEREO
+ : IoConstants.FLAG_TYPE_MONO);
+
+ IoBuffer body = IoBuffer.allocate(tag.getBodySize());
+ body.setAutoExpand(true);
+ body.put(tagType);
+ body.put(buf);
+ body.flip();
+ body.limit(tag.getBodySize());
+ tag.setBody(body);
+
+ IMessage msg = makeMessageFromTag(tag);
+ try {
+ pushMessage(msg);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public IMessage makeMessageFromTag(Tag tag) {
+ IRTMPEvent msg = null;
+ switch (tag.getDataType()) {
+ case Constants.TYPE_AUDIO_DATA:
+ msg = new AudioData(tag.getBody());
+ break;
+ case Constants.TYPE_VIDEO_DATA:
+ msg = new VideoData(tag.getBody());
+ break;
+ case Constants.TYPE_INVOKE:
+ msg = new Invoke(tag.getBody());
+ break;
+ case Constants.TYPE_NOTIFY:
+ msg = new Notify(tag.getBody());
+ break;
+ case Constants.TYPE_FLEX_STREAM_SEND:
+ msg = new FlexStreamSend(tag.getBody());
+ break;
+ default:
+ log.warn("Unexpected type? {}", tag.getDataType());
+ msg = new Unknown(tag.getDataType(), tag.getBody());
+ }
+ msg.setTimestamp(tag.getTimestamp());
+ RTMPMessage rtmpMsg = new RTMPMessage();
+ rtmpMsg.setBody(msg);
+ rtmpMsg.getBody();
+ return rtmpMsg;
+ }
+
+ synchronized public void pushMessage(IMessage message) throws IOException {
+ if (state >= PUBLISHED && message instanceof RTMPMessage) {
+ RTMPMessage rtmpMsg = (RTMPMessage) message;
+ rtmpClient.publishStreamData(streamId, rtmpMsg);
+ } else {
+ frameBuffer.add(message);
+ }
+ }
+
+ public synchronized void onStreamEvent(Notify notify) {
+ log.debug("onStreamEvent: {}", notify);
+ ObjectMap, ?> map = (ObjectMap, ?>) notify.getCall().getArguments()[0];
+ String code = (String) map.get("code");
+ log.debug("<:{}", code);
+ if (StatusCodes.NS_PUBLISH_START.equals(code)) {
+ state = PUBLISHED;
+ while (frameBuffer.size() > 0) {
+ rtmpClient.publishStreamData(streamId, frameBuffer.remove(0));
+ }
+ }
+ }
+
+ public synchronized void resultReceived(IPendingServiceCall call) {
+ log.debug("resultReceived:> {}", call.getServiceMethodName());
+ if ("connect".equals(call.getServiceMethodName())) {
+ state = STREAM_CREATING;
+ rtmpClient.createStream(this);
+ } else if ("createStream".equals(call.getServiceMethodName())) {
+ state = PUBLISHING;
+ Object result = call.getResult();
+ if (result instanceof Integer) {
+ Integer streamIdInt = (Integer) result;
+ streamId = streamIdInt.intValue();
+ rtmpClient.publish(streamIdInt.intValue(), publishName,
+ publishMode, this);
+ } else {
+ rtmpClient.disconnect();
+ state = STOPPED;
+ }
+ }
+ }
+}
diff --git a/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/manager/ClientManager.java b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/manager/ClientManager.java
new file mode 100644
index 0000000..f166c02
--- /dev/null
+++ b/rtmp_video_publisher/src/main/java/com/c77/videopublisher/rtmp_video_publisher/manager/ClientManager.java
@@ -0,0 +1,189 @@
+package com.c77.videopublisher.rtmp_video_publisher.manager;
+
+import com.c77.videopublisher.rtmp_video_publisher.io.Consumer;
+import com.c77.videopublisher.rtmp_video_publisher.io.file.FileClient;
+import com.c77.videopublisher.rtmp_video_publisher.io.net.NetClient;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClientManager implements Runnable, Consumer {
+ private Logger log = LoggerFactory.getLogger(ClientManager.class);
+
+ private final Object mutex = new Object();
+ public static final int NETONLY = 1;
+ public static final int FILEONLY = 2;
+ public static final int NETANDFILE = 3;
+ private int mode = NETONLY;
+ private int seq = 0;
+ private volatile boolean isRecording;
+ private volatile boolean isRunning;
+ private processedData pData;
+ private List list;
+ private String publishNameBase = "test";
+ private String publishName;
+ private String fileNameBase = "/mnt/sdcard/test";
+ private String fileName;
+ private NetClient netClient = new NetClient();
+ private FileClient fileClient = new FileClient();
+
+ public ClientManager() {
+ super();
+ list = Collections.synchronizedList(new LinkedList());
+ }
+
+ private void netClientInit() {
+ netClient.setHost("192.168.1.200");
+ netClient.setPort(1935);
+ netClient.setApp("live");
+ netClient.setChannle(1);
+ netClient.setSampleRate(8000);
+ }
+
+ private void fileClientInit() {
+ fileClient.setChannle(1);
+ fileClient.setSampleRate(8000);
+ }
+
+ public void setMode(int mode) {
+ this.mode = mode;
+ }
+
+ public void run() {
+ log.debug("publish thread runing");
+
+ netClientInit();
+ fileClientInit();
+
+ while (this.isRunning()) {
+ synchronized (mutex) {
+ while (!this.isRecording) {
+ try {
+ mutex.wait();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Wait() interrupted!",
+ e);
+ }
+ }
+ }
+
+ setupFileName();
+ startClient();
+ startPcmRecorder();
+
+ while (this.isRecording()) {
+ if (list.size() > 0) {
+ writeTag();
+ log.debug("list size = {}", list.size());
+ } else {
+ try {
+ Thread.sleep(20);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // recorder.stop();
+ while(list.size() > 0){
+ writeTag();
+ log.debug("list size = {}", list.size());
+ }
+ stop();
+ }
+ }
+
+ private void setupFileName(){
+ fileName = fileNameBase + seq +".flv";
+ publishName = publishNameBase + seq;
+ seq++;
+ log.info("setup file name done");
+ }
+
+ private void startClient() {
+ switch (this.mode) {
+ case NETONLY:
+ netClient.start(publishName, "record", null);
+ break;
+ case FILEONLY:
+ fileClient.start(fileName);
+ break;
+ case NETANDFILE:
+ netClient.start(publishName, "record", null);
+ fileClient.start(fileName);
+ break;
+ default:
+ netClient.start(publishName, "record", null);
+ }
+ }
+
+ private void startPcmRecorder(){
+ /*recorder = new PcmRecorder(this);
+ recorder.setRecording(true);
+ Thread th = new Thread(recorder);
+ th.start();*/
+ }
+
+ private void writeTag() {
+ pData = list.remove(0);
+ if(this.mode == NETONLY || this.mode == NETANDFILE){
+ netClient.writeTag(pData.processed, pData.size, pData.ts);
+ }
+ if(this.mode == FILEONLY || this.mode == NETANDFILE){
+ fileClient.writeTag(pData.processed, pData.size, pData.ts);
+ }
+ }
+
+ public void putData(long ts, byte[] buf, int size) {
+ processedData data = new processedData();
+ data.ts = ts;
+ data.size = size;
+ System.arraycopy(buf, 0, data.processed, 0, size);
+ list.add(data);
+ }
+
+ private void stop() {
+ netClient.stop();
+ fileClient.stop();
+
+ }
+
+ public boolean isRunning() {
+ synchronized (mutex) {
+ return isRunning;
+ }
+ }
+
+ public void setRunning(boolean isRunning) {
+ synchronized (mutex) {
+ this.isRunning = isRunning;
+ if (this.isRunning) {
+ mutex.notify();
+ }
+ }
+ }
+
+ public void setRecording(boolean isRecording) {
+ synchronized (mutex) {
+ this.isRecording = isRecording;
+ if (this.isRecording) {
+ mutex.notify();
+ }
+ }
+ }
+
+ public boolean isRecording() {
+ synchronized (mutex) {
+ return isRecording;
+ }
+ }
+
+ class processedData {
+ private long ts;
+ private int size;
+ private byte[] processed = new byte[256];
+ }
+}
diff --git a/rtmp_video_publisher/src/main/res/drawable-hdpi/ic_launcher.png b/rtmp_video_publisher/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..c1b44cc
Binary files /dev/null and b/rtmp_video_publisher/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/rtmp_video_publisher/src/main/res/drawable-mdpi/ic_launcher.png b/rtmp_video_publisher/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..a1bf709
Binary files /dev/null and b/rtmp_video_publisher/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/rtmp_video_publisher/src/main/res/drawable-xhdpi/ic_launcher.png b/rtmp_video_publisher/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..3b5ae5b
Binary files /dev/null and b/rtmp_video_publisher/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/rtmp_video_publisher/src/main/res/drawable-xxhdpi/ic_launcher.png b/rtmp_video_publisher/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b7df51b
Binary files /dev/null and b/rtmp_video_publisher/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/rtmp_video_publisher/src/main/res/layout/activity_video_publisher_main.xml b/rtmp_video_publisher/src/main/res/layout/activity_video_publisher_main.xml
new file mode 100644
index 0000000..e49182c
--- /dev/null
+++ b/rtmp_video_publisher/src/main/res/layout/activity_video_publisher_main.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/rtmp_video_publisher/src/main/res/menu/video_publisher_main.xml b/rtmp_video_publisher/src/main/res/menu/video_publisher_main.xml
new file mode 100644
index 0000000..f6e57b0
--- /dev/null
+++ b/rtmp_video_publisher/src/main/res/menu/video_publisher_main.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/rtmp_video_publisher/src/main/res/values-w820dp/dimens.xml b/rtmp_video_publisher/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/rtmp_video_publisher/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/rtmp_video_publisher/src/main/res/values/dimens.xml b/rtmp_video_publisher/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/rtmp_video_publisher/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/rtmp_video_publisher/src/main/res/values/strings.xml b/rtmp_video_publisher/src/main/res/values/strings.xml
new file mode 100644
index 0000000..609b668
--- /dev/null
+++ b/rtmp_video_publisher/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+
+
+ VideoPublisher
+ Hello world!
+ Settings
+
+
diff --git a/rtmp_video_publisher/src/main/res/values/styles.xml b/rtmp_video_publisher/src/main/res/values/styles.xml
new file mode 100644
index 0000000..ff6c9d2
--- /dev/null
+++ b/rtmp_video_publisher/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/rtmp_video_receiver/.gitignore b/rtmp_video_receiver/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/rtmp_video_receiver/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/rtmp_video_receiver/build.gradle b/rtmp_video_receiver/build.gradle
new file mode 100644
index 0000000..548309f
--- /dev/null
+++ b/rtmp_video_receiver/build.gradle
@@ -0,0 +1,24 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 'android-L'
+ buildToolsVersion "20.0.0"
+
+ defaultConfig {
+ applicationId "com.c77.videoreceiver.rtmp_video_receiver"
+ minSdkVersion 15
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ runProguard false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile 'org.red5:android-rmtp-client:0.3'
+}
diff --git a/rtmp_video_receiver/proguard-rules.pro b/rtmp_video_receiver/proguard-rules.pro
new file mode 100644
index 0000000..0e13397
--- /dev/null
+++ b/rtmp_video_receiver/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /opt/android-studio/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/rtmp_video_receiver/rtmp_video_receiver.iml b/rtmp_video_receiver/rtmp_video_receiver.iml
new file mode 100644
index 0000000..a0e78ec
--- /dev/null
+++ b/rtmp_video_receiver/rtmp_video_receiver.iml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rtmp_video_receiver/src/androidTest/java/com/c77/videoreceiver/rtmp_video_receiver/ApplicationTest.java b/rtmp_video_receiver/src/androidTest/java/com/c77/videoreceiver/rtmp_video_receiver/ApplicationTest.java
new file mode 100644
index 0000000..79a89dc
--- /dev/null
+++ b/rtmp_video_receiver/src/androidTest/java/com/c77/videoreceiver/rtmp_video_receiver/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.c77.videoreceiver.rtmp_video_receiver;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/rtmp_video_receiver/src/main/AndroidManifest.xml b/rtmp_video_receiver/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..357fe84
--- /dev/null
+++ b/rtmp_video_receiver/src/main/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rtmp_video_receiver/src/main/ic_launcher-web.png b/rtmp_video_receiver/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..4b14629
Binary files /dev/null and b/rtmp_video_receiver/src/main/ic_launcher-web.png differ
diff --git a/rtmp_video_receiver/src/main/java/com/c77/videoreceiver/rtmp_video_receiver/VideoReceiverMainActivity.java b/rtmp_video_receiver/src/main/java/com/c77/videoreceiver/rtmp_video_receiver/VideoReceiverMainActivity.java
new file mode 100644
index 0000000..f235389
--- /dev/null
+++ b/rtmp_video_receiver/src/main/java/com/c77/videoreceiver/rtmp_video_receiver/VideoReceiverMainActivity.java
@@ -0,0 +1,84 @@
+package com.c77.videoreceiver.rtmp_video_receiver;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.widget.Button;
+import android.widget.EditText;
+
+
+public class VideoReceiverMainActivity extends Activity implements View.OnClickListener {
+
+ WebView webView;
+
+ String bodyHtml;
+ String rtmpUrl;
+ String fileName;
+ Button refreshButton;
+ String htmlPost = "