Added Orientation change support and video capture preview
This commit is contained in:
parent
0fd0a01e52
commit
ef01a009d5
7 changed files with 72 additions and 13 deletions
|
@ -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>
|
||||||
|
|
11
res/layout-land/videocall.xml
Normal file
11
res/layout-land/videocall.xml
Normal 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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue