diff --git a/example4/AndroidManifest.xml b/example4/AndroidManifest.xml
new file mode 100644
index 0000000..03a48c1
--- /dev/null
+++ b/example4/AndroidManifest.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example4/res/drawable-hdpi/ic_launcher.png b/example4/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
Binary files /dev/null and b/example4/res/drawable-hdpi/ic_launcher.png differ
diff --git a/example4/res/drawable-mdpi/ic_launcher.png b/example4/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
Binary files /dev/null and b/example4/res/drawable-mdpi/ic_launcher.png differ
diff --git a/example4/res/drawable-xhdpi/ic_launcher.png b/example4/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
Binary files /dev/null and b/example4/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/example4/res/drawable-xxhdpi/ic_launcher.png b/example4/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4df1894
Binary files /dev/null and b/example4/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/example4/res/layout/main_activity_layout.xml b/example4/res/layout/main_activity_layout.xml
new file mode 100644
index 0000000..b284fb6
--- /dev/null
+++ b/example4/res/layout/main_activity_layout.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/example4/res/values-w820dp/dimens.xml b/example4/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/example4/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/example4/res/values/dimens.xml b/example4/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/example4/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/example4/res/values/strings.xml b/example4/res/values/strings.xml
new file mode 100644
index 0000000..bf9688f
--- /dev/null
+++ b/example4/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ example4
+
diff --git a/example4/res/values/styles.xml b/example4/res/values/styles.xml
new file mode 100644
index 0000000..ff6c9d2
--- /dev/null
+++ b/example4/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/example4/src/net/majorkernelpanic/example4/MainActivity.java b/example4/src/net/majorkernelpanic/example4/MainActivity.java
new file mode 100644
index 0000000..8a1b180
--- /dev/null
+++ b/example4/src/net/majorkernelpanic/example4/MainActivity.java
@@ -0,0 +1,145 @@
+package net.majorkernelpanic.example4;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+import net.majorkernelpanic.streaming.MediaStream;
+import net.majorkernelpanic.streaming.Session;
+import net.majorkernelpanic.streaming.SessionBuilder;
+import net.majorkernelpanic.streaming.audio.AudioQuality;
+import net.majorkernelpanic.streaming.gl.SurfaceView;
+import net.majorkernelpanic.streaming.video.VideoQuality;
+import net.majorkernelpanic.streaming.video.VideoStream;
+
+public class MainActivity extends Activity implements SurfaceHolder.Callback, Session.Callback {
+
+ private static final String TAG = "example4";
+
+ // TODO: change this IP with the destination IP of the video streaming
+ private static final String DESTINATION_IP = "10.34.0.162";
+
+ private byte mediaCodec;
+
+ private SurfaceView surfaceView;
+ private Session session;
+ private final int BITRATE = 900000; // 1500000
+ private final int FRAMERATE = 15; // 30
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mediaCodec = MediaStream.MODE_MEDIACODEC_API;
+
+ ViewGroup root = (ViewGroup) getLayoutInflater().inflate(R.layout.main_activity_layout, null);
+
+ // create dummy surface to avoid having a preview in the server side
+ surfaceView = new SurfaceView(this);
+ RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
+ VideoStream.VIDEO_WIDTH_INPUT, VideoStream.VIDEO_HEIGHT_INPUT);
+
+ root.addView(surfaceView, layoutParams);
+ surfaceView.getHolder().addCallback(this);
+ surfaceView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ if (session.isStreaming()) {
+ session.stop();
+ Toast.makeText(MainActivity.this, "Stopping publisher", Toast.LENGTH_SHORT).show();
+ } else {
+ session.configure();
+ }
+ return false;
+ }
+ });
+
+ setContentView(root);
+
+ initializeSession();
+ }
+
+ private void initializeSession() {
+ VideoQuality quality = new VideoQuality(
+ VideoStream.VIDEO_WIDTH_INPUT, VideoStream.VIDEO_HEIGHT_INPUT,
+ FRAMERATE, BITRATE);
+
+ session = SessionBuilder.getInstance()
+ .setCallback(this)
+ .setSurfaceView(surfaceView)
+ .setPreviewOrientation(0)
+ .setContext(getApplicationContext())
+ .setAudioEncoder(SessionBuilder.AUDIO_NONE)
+ .setAudioQuality(new AudioQuality(16000, 32000))
+ .setVideoEncoder(SessionBuilder.VIDEO_H264)
+ .setVideoQuality(quality)
+ .build();
+ }
+
+ private void startStreaming() {
+ session.setDestination(DESTINATION_IP);
+ session.getVideoTrack().setStreamingMethod(mediaCodec);
+ Log.i(TAG, "Streaming to IP: " + DESTINATION_IP);
+ if (!session.isStreaming()) {
+ Log.i(TAG, "Configure session!");
+ session.configure();
+ } else {
+ session.stop();
+ }
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ startStreaming();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ session.stop();
+ }
+
+ @Override
+ public void onBitrateUpdate(long bitrate) {
+
+ }
+
+ @Override
+ public void onSessionError(int reason, int streamType, Exception e) {
+
+ }
+
+ @Override
+ public void onPreviewStarted() {
+
+ }
+
+ @Override
+ public void onSessionConfigured() {
+ Log.i(TAG, "Session started");
+ Toast.makeText(this, "Starting publisher", Toast.LENGTH_SHORT).show();
+ session.start();
+ }
+
+ @Override
+ public void onSessionStarted() {
+ }
+
+ @Override
+ public void onSessionStopped() {
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ session.release();
+ }
+}