Browse files

video stream working...

  • Loading branch information...
1 parent cf15670 commit 6817668588764143a93c360e9bbb52da5f01b881 @jonasb committed Apr 5, 2012
View
4 .gitignore
@@ -1,5 +1,7 @@
-local.properties
.idea/
bin/
gen/
+libs/
+obj/
out/
+local.properties
View
3 AndroidManifest.xml
@@ -3,6 +3,7 @@
package="se.forskningsavd"
android:versionCode="1"
android:versionName="1.0">
+ <uses-sdk android:minSdkVersion="3" />
<uses-permission android:name="android.permission.INTERNET"/>
<application android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar">
<activity android:name="MainActivity"
@@ -14,4 +15,4 @@
</intent-filter>
</activity>
</application>
-</manifest>
+</manifest>
View
6 AutomatonBrain.iml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<module type="ANDROID_MODULE" version="4">
+<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
@@ -20,6 +20,10 @@
<option name="RUN_PROCESS_RESOURCES_MAVEN_TASK" value="true" />
<option name="GENERATE_UNSIGNED_APK" value="false" />
<option name="CUSTOM_DEBUG_KEYSTORE_PATH" value="" />
+ <option name="PACK_TEST_CODE" value="false" />
+ <option name="RUN_PROGUARD" value="false" />
+ <option name="PROGUARD_CFG_PATH" value="/proguard.cfg" />
+ <resOverlayFolders />
</configuration>
</facet>
</component>
View
19 jni/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := decoder-jni
+LOCAL_CPPFLAGS := -D__STDC_CONSTANT_MACROS
+LOCAL_C_INCLUDES := ffmpeg-android/build/ffmpeg/${TARGET_ARCH_ABI}/include
+LOCAL_SRC_FILES := decoder-jni.c
+LOCAL_STATIC_LIBRARIES += \
+ avcodec \
+ avcore \
+ avutil \
+ swscale \
+#
+LOCAL_LDLIBS += \
+ -ljnigraphics \
+#
+include $(BUILD_SHARED_LIBRARY)
+
+include ffmpeg-android/Android.mk
View
71 jni/decoder-jni.c
@@ -0,0 +1,71 @@
+#include <jni.h>
+#include <libavcodec/avcodec.h>
+#include <libswscale/swscale.h>
+#include <stdbool.h>
+#include <android/bitmap.h>
+
+AVCodecContext *pCodecCtx; // FFMPEG codec context
+AVCodec *pCodec; // Pointer to FFMPEG codec (H264)
+AVFrame *pFrame; // Used in the decoding process
+struct SwsContext *convertCtx; // Used in the scaling/conversion process
+AVPacket avpkt; // Used in the decoding process
+int temp; // Various uses
+
+
+bool Java_se_forskningsavd_Decoder_init(JNIEnv* env, jobject thiz) {
+ avcodec_init();
+ avcodec_register_all();
+ pCodecCtx = avcodec_alloc_context();
+ pCodec = avcodec_find_decoder( CODEC_ID_H264 );
+ av_init_packet( &avpkt );
+ if( !pCodec ) {
+ return false;
+ //printf( "RoboCortex [error]: Unable to initialize decoder\n" );
+ //exit( EXIT_DECODER );
+ }
+ avcodec_open( pCodecCtx, pCodec );
+
+ // Allocate decoder frame
+ pFrame = avcodec_alloc_frame();
+ return true;
+}
+
+bool Java_se_forskningsavd_Decoder_decode(JNIEnv *env, jobject thiz, jbyteArray frame, jobject bitmap) {
+ AndroidBitmapInfo bitmapInfo;
+ if (AndroidBitmap_getInfo(env, bitmap, &bitmapInfo) != 0) {
+ return false;
+ }
+
+ uint8_t *dest_data = 0; //TODO
+ avpkt.data = (*env)->GetByteArrayElements(env, frame, 0);
+ avpkt.size = (*env)->GetArrayLength(env, frame);
+ avpkt.flags = AV_PKT_FLAG_KEY;
+ int len = avcodec_decode_video2( pCodecCtx, pFrame, &temp, &avpkt );
+ (*env)->ReleaseByteArrayElements(env, frame, avpkt.data, JNI_ABORT);
+
+ if (len < 0 ) {
+ return false;
+ //printf( "RoboCortex [info]: Decoding error (packet loss)\n" );
+ } else {
+ void *bitmapData;
+ AndroidBitmap_lockPixels(env, bitmap, &bitmapData);
+ const uint8_t * data[1] = { bitmapData };
+ int linesize[1] = { bitmapInfo.stride };
+
+ // Create scaling & color-space conversion context
+ convertCtx = sws_getContext( pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
+ bitmapInfo.width, bitmapInfo.height, PIX_FMT_BGRA, SWS_AREA, NULL, NULL, NULL);
+
+ // Scale and convert the frame
+ sws_scale( convertCtx, (const uint8_t**) pFrame->data, pFrame->linesize, 0,
+ pCodecCtx->height, (uint8_t * const*) data, linesize );
+
+ // Cleanup
+ sws_freeContext( convertCtx );
+
+ //
+ AndroidBitmap_unlockPixels(env, bitmap);
+ }
+ return true;
+}
+
View
53 src/se/forskningsavd/Communicator.java
@@ -1,5 +1,8 @@
package se.forskningsavd;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Message;
import android.util.Log;
import java.io.IOException;
@@ -11,33 +14,52 @@
import java.util.ArrayList;
class Communicator {
+ public interface Callback {
+ public void onTargetImageChanged(Bitmap bitmap);
+ }
+
static class ReceiverThread extends Thread {
private final DatagramSocket mSocket;
private boolean mRunning = true;
private final SenderThread mSenderThread;
+ private final Decoder mDecoder;
+ private final Bitmap mTargetBitmap;
+ private final Handler mHandler;
- public ReceiverThread(DatagramSocket socket, SenderThread senderThread) {
+ public ReceiverThread(DatagramSocket socket, SenderThread senderThread, Decoder decoder, Bitmap targetBitmap, Handler handler) {
mSocket = socket;
mSenderThread = senderThread;
+ mDecoder = decoder;
+ mTargetBitmap = targetBitmap;
+ mHandler = handler;
}
@Override
public void run() {
- byte[] buf = new byte[1000];
- DatagramPacket dp = new DatagramPacket(buf, buf.length);
+ byte[] buf = new byte[3000];
while (mRunning) {
try {
+ DatagramPacket dp = new DatagramPacket(buf, buf.length);
mSocket.receive(dp);
StringBuilder debug = new StringBuilder();
- for (int i = 0; i < dp.getLength(); i++) {
- debug.append(String.format("%02x", dp.getData()[i]));
+ final int length = dp.getLength();
+ if (length < 1000) {
+ for (int i = 0; i < length; i++) {
+ debug.append(String.format("%02x", dp.getData()[i]));
+ }
}
- String rcvd = "rcvd from " + dp.getAddress() + ", " + dp.getPort() + ": "
+ String rcvd = "rcvd from " + dp.getAddress() + ", " + dp.getPort() + ", " + length + " bytes : "
+ debug;
Log.d("XXX", rcvd);
ByteBuffer data = ByteBuffer.wrap(dp.getData());
- if (data.get(0) == 'D' &&
+ if (data.get(0) == 0 &&
+ data.get(1) == 0 &&
+ data.get(2) == 0 &&
+ data.get(3) == 1) {
+ Log.d("decode", "h264 frame decode= " + mDecoder.decode(data.array(), mTargetBitmap));
+ mHandler.sendEmptyMessage(0);
+ } else if (data.get(0) == 'D' &&
data.get(1) == 'A' &&
data.get(2) == 'T' &&
data.get(3) == 'A') {
@@ -188,9 +210,13 @@ public void addTrustedMessage(byte[] ident, byte[] message) {
private ReceiverThread mReceiverThread;
private SenderThread mSenderThread;
private final Navigator mNavigator;
+ private final Bitmap mTargetBitmap;
+ private final Callback mCallback;
- public Communicator(Navigator nav) {
+ public Communicator(Navigator nav, Bitmap target, Callback callback) {
mNavigator = nav;
+ mTargetBitmap = target;
+ mCallback = callback;
}
public void connect() {
@@ -206,7 +232,16 @@ public void connect() {
mSenderThread = new SenderThread(socket, mNavigator);
mSenderThread.start();
- mReceiverThread = new ReceiverThread(socket, mSenderThread);
+ Decoder d = new Decoder();
+ Log.d("decode", "init(): " + d.init());
+
+ final Handler handler = new Handler(new Handler.Callback() {
+ public boolean handleMessage(Message message) {
+ mCallback.onTargetImageChanged(mTargetBitmap);
+ return false;
+ }
+ });
+ mReceiverThread = new ReceiverThread(socket, mSenderThread, d, mTargetBitmap, handler);
mReceiverThread.start();
}
View
12 src/se/forskningsavd/Decoder.java
@@ -0,0 +1,12 @@
+package se.forskningsavd;
+
+import android.graphics.Bitmap;
+
+public class Decoder {
+ public native boolean init();
+ public native boolean decode(byte[] frame, Bitmap target);
+
+ static {
+ System.loadLibrary("decoder-jni");
+ }
+}
View
22 src/se/forskningsavd/MainActivity.java
@@ -1,11 +1,13 @@
package se.forskningsavd;
import android.app.Activity;
+import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.LinearLayout.LayoutParams;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -15,9 +17,15 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ final ImageView video = new ImageView(this);
Navigator nav = new Navigator();
- mCommunicator = new Communicator(nav);
+ Bitmap target = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888);
+ mCommunicator = new Communicator(nav, target, new Communicator.Callback() {
+ public void onTargetImageChanged(Bitmap bitmap) {
+ video.invalidate();
+ }
+ });
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
@@ -41,9 +49,15 @@ public void onClick(View view) {
});
layout.addView(helloWorld);
+ FrameLayout frame = new FrameLayout(this);
+
+ video.setImageBitmap(target);
+ frame.addView(video);
+
NavigationView navigationView = new NavigationView(this, nav);
- LayoutParams p = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
- layout.addView(navigationView, p);
+ frame.addView(navigationView);
+
+ layout.addView(frame, MATCH_PARENT, MATCH_PARENT);
setContentView(layout);
}

0 comments on commit 6817668

Please sign in to comment.