如何同时显示2个相机预览?

我正在尝试构build一个Cardboard Android应用程序,并排显示2个摄像头视图。 [就像相机视图适用于VRCinema Android应用程序]

VRCinema屏幕截图

所以我研究GitHub中的Cardboard代码,做了一些修改,到目前为止我能够使用imageView并行地复制相同的图像。

imageView并排复制相同的图像

目前的守则看起来像这样。

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.vrtoolkit.cardboard.samples.treasurehunt" > <uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> <uses-feature android:name="android.hardware.camera.front" android:required="false" /> <uses-sdk android:minSdkVersion="14"/> <uses-feature android:glEsVersion="0x00020000" android:required="true" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:screenOrientation="landscape" android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

common_ui.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ui_layout" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <com.google.vrtoolkit.cardboard.CardboardView android:id="@+id/cardboard_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" /> <com.google.vrtoolkit.cardboard.samples.treasurehunt.CardboardOverlayView android:id="@+id/overlay" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_centerInParent="true" /> </RelativeLayout> 

CardboardOverlayView.java

 package com.google.vrtoolkit.cardboard.samples.treasurehunt; import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; /** * Contains two sub-views to provide a simple stereo HUD. */ public class CardboardOverlayView extends LinearLayout { private static final String TAG = CardboardOverlayView_bkp1.class.getSimpleName(); private final CardboardOverlayEyeView mLeftView; private final CardboardOverlayEyeView mRightView; private AlphaAnimation mTextFadeAnimation; public CardboardOverlayView(Context context, AttributeSet attrs) { super(context, attrs); setOrientation(HORIZONTAL); LayoutParams params = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f); params.setMargins(0, 0, 0, 0); mLeftView = new CardboardOverlayEyeView(context, attrs); mLeftView.setLayoutParams(params); addView(mLeftView); mRightView = new CardboardOverlayEyeView(context, attrs); mRightView.setLayoutParams(params); addView(mRightView); // Set some reasonable defaults. setDepthOffset(0.016f); setColor(Color.rgb(150, 255, 180)); setVisibility(View.VISIBLE); mTextFadeAnimation = new AlphaAnimation(1.0f, 0.0f); mTextFadeAnimation.setDuration(5000); } public void show3DToast(String message) { setText(message); setTextAlpha(1f); mTextFadeAnimation.setAnimationListener(new EndAnimationListener() { @Override public void onAnimationEnd(Animation animation) { setTextAlpha(0f); } }); startAnimation(mTextFadeAnimation); } public void show3DImage() { setImg(); } private abstract class EndAnimationListener implements Animation.AnimationListener { @Override public void onAnimationRepeat(Animation animation) {} @Override public void onAnimationStart(Animation animation) {} } private void setDepthOffset(float offset) { mLeftView.setOffset(offset); mRightView.setOffset(-offset); } //--------------------------------------------------------------------------------------------- private void setImg(){ mLeftView.imageView.setImageResource(R.drawable.mona_lisa); mRightView.imageView.setImageResource(R.drawable.mona_lisa); } //------------------------------------------------------------------------------------------ private void setText(String text) { mLeftView.setText(text); mRightView.setText(text); } private void setTextAlpha(float alpha) { mLeftView.setTextViewAlpha(alpha); mRightView.setTextViewAlpha(alpha); } private void setColor(int color) { mLeftView.setColor(color); mRightView.setColor(color); } /** * A simple view group containing some horizontally centered text underneath a horizontally * centered image. * * This is a helper class for CardboardOverlayView. */ private class CardboardOverlayEyeView extends ViewGroup { private final ImageView imageView; private final TextView textView; private float offset; public CardboardOverlayEyeView(Context context, AttributeSet attrs) { super(context, attrs); imageView = new ImageView(context, attrs); imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setAdjustViewBounds(true); // Preserve aspect ratio. addView(imageView); textView = new TextView(context, attrs); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14.0f); textView.setTypeface(textView.getTypeface(), Typeface.BOLD); textView.setGravity(Gravity.CENTER); textView.setShadowLayer(3.0f, 0.0f, 0.0f, Color.DKGRAY); addView(textView); } public void setColor(int color) { //imageView.setColorFilter(color); textView.setTextColor(color); } public void setText(String text) { textView.setText(text); } public void setTextViewAlpha(float alpha) { textView.setAlpha(alpha); } public void setOffset(float offset) { this.offset = offset; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // Width and height of this ViewGroup. final int width = right - left; final int height = bottom - top; // The size of the image, given as a fraction of the dimension as a ViewGroup. We multiply // both width and heading with this number to compute the image's bounding box. Inside the // box, the image is the horizontally and vertically centered. final float imageSize = 1.0f; // The fraction of this ViewGroup's height by which we shift the image off the ViewGroup's // center. Positive values shift downwards, negative values shift upwards. final float verticalImageOffset = -0.07f; // Vertical position of the text, specified in fractions of this ViewGroup's height. final float verticalTextPos = 0.52f; // Layout ImageView float imageMargin = (1.0f - imageSize) / 2.0f; float leftMargin = (int) (width * (imageMargin + offset)); float topMargin = (int) (height * (imageMargin + verticalImageOffset)); imageView.layout( (int) leftMargin, (int) topMargin, (int) (leftMargin + width * imageSize), (int) (topMargin + height * imageSize)); // Layout TextView leftMargin = offset * width; topMargin = height * verticalTextPos; textView.layout( (int) leftMargin, (int) topMargin, (int) (leftMargin + width), (int) (topMargin + height * (1.0f - verticalTextPos))); } } } 

MainActivity.Java

 package com.google.vrtoolkit.cardboard.samples.treasurehunt; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.hardware.Camera; import android.net.Uri; import android.os.Bundle; import android.os.Vibrator; import android.util.Log; import android.widget.ImageView; import com.google.vrtoolkit.cardboard.*; import javax.microedition.khronos.egl.EGLConfig; import java.nio.FloatBuffer; /** * A Cardboard sample application. */ public class MainActivity extends CardboardActivity implements CardboardView.StereoRenderer { private static final int CAMERA_REQUEST = 1888; private static final String TAG = "MainActivity"; private static final int CAPTURE_IMAGE_ACTIVITY_REQ = 0; Uri fileUri = null; ImageView photoImage = null; private static final float CAMERA_Z = 0.01f; private static final float TIME_DELTA = 0.3f; private static final float YAW_LIMIT = 0.12f; private static final float PITCH_LIMIT = 0.12f; // We keep the light always position just above the user. private final float[] mLightPosInWorldSpace = new float[]{0.0f, 2.0f, 0.0f, 1.0f}; private final float[] mLightPosInEyeSpace = new float[4]; private static final int COORDS_PER_VERTEX = 3; private final WorldLayoutData DATA = new WorldLayoutData(); private FloatBuffer mFloorVertices; private FloatBuffer mFloorColors; private FloatBuffer mFloorNormals; private FloatBuffer mCubeVertices; private FloatBuffer mCubeColors; private FloatBuffer mCubeFoundColors; private FloatBuffer mCubeNormals; private int mGlProgram; private int mPositionParam; private int mNormalParam; private int mColorParam; private int mModelViewProjectionParam; private int mLightPosParam; private int mModelViewParam; private int mModelParam; private int mIsFloorParam; private float[] mModelCube; private float[] mCamera; private float[] mView; private float[] mHeadView; private float[] mModelViewProjection; private float[] mModelView; private float[] mModelFloor; private int mScore = 0; private float mObjectDistance = 12f; private float mFloorDepth = 20f; private Vibrator mVibrator; private CardboardOverlayView mOverlayView; public MainActivity() { } /** * Sets the view to our CardboardView and initializes the transformation matrices we will use * to render our scene. * //@param savedInstanceState */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.common_ui); CardboardView cardboardView = (CardboardView) findViewById(R.id.cardboard_view); cardboardView.setRenderer(this); setCardboardView(cardboardView); mModelCube = new float[16]; mCamera = new float[16]; mView = new float[16]; mModelViewProjection = new float[16]; mModelView = new float[16]; mModelFloor = new float[16]; mHeadView = new float[16]; mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); mOverlayView = (CardboardOverlayView) findViewById(R.id.overlay); mOverlayView.show3DToast("Pull the magnet when you find an object."); mOverlayView.show3DImage(); } @Override public void onRendererShutdown(){Log.i(TAG, "onRendererShutdown"); } @Override public void onSurfaceChanged(int width, int height) { Log.i(TAG, "onSurfaceChanged"); } /** * Creates the buffers we use to store information about the 3D world. OpenGL doesn't use Java * arrays, but rather needs data in a format it can understand. Hence we use ByteBuffers. * * @param config The EGL configuration used when creating the surface. */ @Override public void onSurfaceCreated(EGLConfig config) { Log.i(TAG, "onSurfaceCreated"); } /** * Prepares OpenGL ES before we draw a frame. * * @param headTransform The head transformation in the new frame. */ @Override public void onNewFrame(HeadTransform headTransform) { } /** * Draws a frame for an eye. The transformation for that eye (from the camera) is passed in as * a parameter. * * @param transform The transformations to apply to render this eye. */ @Override public void onDrawEye(EyeTransform transform) { } @Override public void onFinishFrame(Viewport viewport) { } } 

我已经注意到的几点:

  • 我不想要一个意图,我需要相机预览,以便以后我可以像拍照一样做其他事情。
  • 如果我尝试用surfaceViewreplaceimageView,我在common_ui.xml中出现了一个错误:“无法find渲染问题类:CardboardOverlayView.java”。 但该文件在那里,这是一个已知和报告的错误。
  • 另外一个我能想到的做法是每秒捕获并保存图像,并用图像更新2个图像视图。 然而,我不确定这是否是正确的方式来做到这一点或如何做到这一点。

我也检查了最近3天以来堆栈溢出中可用的所有链接。 最接近我的问题是Android多重相机预览 – 但它不完全解决我的问题。 我也浏览了Android – Camera文档,了解了他们如何使用cameraPreview和surfaceView。

所以我的问题是我现在需要做什么,以便能够看到CameraPreview [或者包含CameraPreview的surfaceView]而不是Imageview,以便我可以在横向模式下提供像分屏一样的实时相机馈送?

我希望这个问题足够详细,如果你需要更多的信息,请问。

Solutions Collecting From Web of "如何同时显示2个相机预览?"