Added Orientation change support and video capture preview

This commit is contained in:
Guillaume Beraudo 2010-11-22 11:23:43 +01:00
parent 0fd0a01e52
commit ef01a009d5
7 changed files with 72 additions and 13 deletions

View file

@ -68,7 +68,7 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".VideoCallActivity"> <activity android:name=".VideoCallActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/video_frame" android:orientation="vertical"
android:layout_height="fill_parent" android:layout_width="fill_parent">
<SurfaceView android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></SurfaceView>
<SurfaceView android:layout_height="72px" android:layout_width="87px" android:id="@+id/video_capture_surface" android:layout_gravity="right|bottom"
android:layout_margin="20px"></SurfaceView>
</FrameLayout>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical"> android:orientation="vertical" android:layout_height="fill_parent" android:layout_width="fill_parent">
<SurfaceView android:layout_weight="1" android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></SurfaceView>
<SurfaceView android:layout_weight="100" android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_capture_surface"></SurfaceView> <SurfaceView android:layout_weight="50" android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></SurfaceView>
<SurfaceView android:layout_weight="50" android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_capture_surface"></SurfaceView>
</LinearLayout> </LinearLayout>

View file

@ -25,22 +25,49 @@ import org.linphone.core.AndroidCameraRecord;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
public class VideoCallActivity extends Activity { public class VideoCallActivity extends Activity {
SurfaceView mVideoView; SurfaceView mVideoView;
SurfaceView mVideoCaptureView; SurfaceView mVideoCaptureView;
private Handler mHandler = new Handler() ; private Handler mHandler = new Handler() ;
private static boolean firstLaunch = true;
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.videocall); setContentView(R.layout.videocall);
mVideoView = (SurfaceView) findViewById(R.id.video_surface); mVideoView = (SurfaceView) findViewById(R.id.video_surface);
LinphoneService.instance().getLinphoneCore().setVideoWindow((Object) mVideoView); LinphoneService.instance().getLinphoneCore().setVideoWindow((Object) mVideoView);
// mVideoCaptureView = new SurfaceView(getApplicationContext());
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface); mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
final int rotation = getWindowManager().getDefaultDisplay().getRotation();
AndroidCameraRecord.setOrientationCode(rotation);
hack(rotation);
AndroidCameraRecord.setSurfaceView(mVideoCaptureView, mHandler); AndroidCameraRecord.setSurfaceView(mVideoCaptureView, mHandler);
firstLaunch = false;
} }
private void hack(int rotation) {
if (rotation != 0 && !firstLaunch) {
View view = findViewById(R.id.video_frame);
if (view == null) {
Log.e("Linphone", "Android BUG: video frame not found; mix with landscape???");
return;
}
FrameLayout frame = (FrameLayout) view;
frame.removeAllViews();
frame.addView(mVideoCaptureView);
frame.addView(mVideoView);
}
}
} }

View file

@ -46,6 +46,7 @@ public abstract class AndroidCameraRecord {
private static AndroidCameraRecord instance; private static AndroidCameraRecord instance;
private static Handler handler; private static Handler handler;
private static boolean previewStarted; private static boolean previewStarted;
private static int orientationCode;
public AndroidCameraRecord() { public AndroidCameraRecord() {
// TODO check if another instance is loaded and kill it. // TODO check if another instance is loaded and kill it.
@ -66,6 +67,7 @@ public abstract class AndroidCameraRecord {
} }
} }
/* /*
* AndroidCameraRecord.setSurfaceView() should be called first, from the Activity code. * AndroidCameraRecord.setSurfaceView() should be called first, from the Activity code.
* It will start automatically * It will start automatically
@ -97,9 +99,14 @@ public abstract class AndroidCameraRecord {
parameters.setPreviewSize(width, height); parameters.setPreviewSize(width, height);
parameters.setPreviewFrameRate(fps); parameters.setPreviewFrameRate(fps);
// parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_EDOF);
camera.setParameters(parameters); camera.setParameters(parameters);
camera.setDisplayOrientation(90 * orientationCode);
// parameters.setRotation()
SurfaceHolder holder = surfaceView.getHolder(); SurfaceHolder holder = surfaceView.getHolder();
try { try {
camera.setPreviewDisplay(holder); camera.setPreviewDisplay(holder);
@ -165,7 +172,7 @@ public abstract class AndroidCameraRecord {
AndroidCameraRecord.surfaceView = null; AndroidCameraRecord.surfaceView = null;
if (camera == null) { if (camera == null) {
Log.e("AndroidCameraRecord.surfaceDestroyed", "illegal state"); Log.e("Linphone", "Video capture: illegal state: surface destroyed but camera is already null");
return; return;
} }
camera.setPreviewCallback(null); // TODO check if used whatever the SDK version camera.setPreviewCallback(null); // TODO check if used whatever the SDK version
@ -173,20 +180,23 @@ public abstract class AndroidCameraRecord {
camera.release(); camera.release();
camera=null; camera=null;
previewStarted = false; previewStarted = false;
Log.w("Linphone", "The video capture Surface view has been destroyed"); Log.w("Linphone", "Video capture Surface destroyed");
} }
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
AndroidCameraRecord.surfaceView = sv; AndroidCameraRecord.surfaceView = sv;
Log.w("Linphone", "Video capture surface created");
if (instance != null) { if (instance != null) {
instance.startPreview(); instance.startPreview();
} }
holder.isCreating();
} }
public void surfaceChanged(SurfaceHolder holder, int format, int width, public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) { int height) {
// Do nothing Log.w("Linphone", "Video capture surface changed");
} }
}); });
} }
@ -223,7 +233,14 @@ public abstract class AndroidCameraRecord {
protected void reallySetPreviewCallback(Camera camera, PreviewCallback cb) { protected void reallySetPreviewCallback(Camera camera, PreviewCallback cb) {
camera.setPreviewCallback(cb); camera.setPreviewCallback(cb);
} }
public static void setOrientationCode(int orientation) {
AndroidCameraRecord.orientationCode = (4 + 1 - orientation) % 4;
}
protected int getOrientationCode() {
return orientationCode;
}
} }

View file

@ -48,7 +48,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
} }
private native void putImage(long filterCtxPtr, byte[] buffer); private native void putImage(long filterCtxPtr, byte[] buffer, int orientation);
public void onPreviewFrame(byte[] data, Camera camera) { public void onPreviewFrame(byte[] data, Camera camera) {
@ -68,7 +68,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
long curTime = System.currentTimeMillis(); long curTime = System.currentTimeMillis();
if (lastFrameTime == 0) { if (lastFrameTime == 0) {
lastFrameTime = curTime; lastFrameTime = curTime;
putImage(filterCtxPtr, data); putImage(filterCtxPtr, data, getOrientationCode());
return; return;
} }
@ -81,7 +81,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
timeElapsedBetweenFrames = currentTimeElapsed; timeElapsedBetweenFrames = currentTimeElapsed;
// Log.d("onPreviewFrame: ", Integer.toString(data.length)); // Log.d("onPreviewFrame: ", Integer.toString(data.length));
putImage(filterCtxPtr, data); putImage(filterCtxPtr, data, getOrientationCode());
} }

View file

@ -34,9 +34,11 @@ public class AndroidVideoWindowImpl {
mSurface=holder.getSurface(); mSurface=holder.getSurface();
} }
if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this); if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this);
Log.w("Linphone", "Video display surface changed");
} }
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
Log.w("Linphone", "Video display surface created");
} }
public void surfaceDestroyed(SurfaceHolder holder) { public void surfaceDestroyed(SurfaceHolder holder) {
@ -46,6 +48,7 @@ public class AndroidVideoWindowImpl {
} }
if (mListener!=null) if (mListener!=null)
mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this); mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this);
Log.w("Linphone", "Video display surface destroyed");
} }
}); });
} }