Android相机预览始终是侧面的

【Android相机预览始终是侧面的】业无高卑志当坚,男儿有求安得闲?这篇文章主要讲述Android相机预览始终是侧面的相关的知识,希望能为你提供帮助。
我正在编写一个android插件,它将从相机预览中获取数据并将其发送到Unity。 (由于各种原因,我无法使用Unity WebCamTexture)我能够获取相机预览数据并将其发送到Unity,但是,图像始终旋转90度。我的Unity应用程序设置为始终处于纵向模式。
在我的Pixel XL上,正面和背面图像以相反的方向旋转。这是使用前置和后置摄像头时我的应用程序的照片。

Android相机预览始终是侧面的

文章图片
Android相机预览始终是侧面的

文章图片

我在NativeCamera.java中创建了函数AdjustOrientation以尝试修复方向,但调用它似乎没有任何效果。
我找到了一些地方的链接,这些地方说要添加类似于AdjustOrientation函数中的代码来修复问题,但是没有一个能解决问题。
这是我调查的一个链接,但没有解决我的问题。
Android - Camera preview is sideways
我尝试了不同的变化
mCamera.setDisplayOrientation() params.setRotation()

但没有运气。
我只需要图像处于正确的方向
public void onPreviewFrame(byte[] data, Camera camera)

保存的图像是颠倒还是旋转并不重要。我只是将数据传递给我的Unity项目,Android插件的唯一目的是将相机数据传递给Unity。只要OnPreviewFrame中的图像数据正确,我就会全部设置好。
我知道有一个较新的Camera2 API,它不赞成原来的Camera,但我真的希望能够用我现有的插件解决这个问题,而不必编写一个使用Camera2的新插件。
这是我项目的链接。
https://drive.google.com/open?id=1MD-NRVf0YhhVIiRUOiBptvSwh9wtK3V7
提前致谢。
约翰劳里
更新。这是我的.java文件的源代码,以便于参考。如果您查看AdjustOrientation,您可以看到我有一些代码来尝试调整displayorientation。它似乎没有效果。
package com.test.camerapreview; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.opengl.GLES11Ext; import android.opengl.GLES20; import android.support.annotation.Dimension; import android.util.Log; import android.util.Size; import android.view.Display; import android.view.Surface; import com.unity3d.player.UnityPlayer; import com.google.gson.Gson; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class NativeCamera implements Camera.PreviewCallback {public static NativeCamera instance; public static String gameObjectTargetName; private static Activity myActivity; Camera mCamera; SurfaceTexture texture; int nativeTexturePointer = -1; int prevHeight; int prevWidth; // // Call this function first. // public static void Setup(String gameObjectName, Activity theActivity){ gameObjectTargetName = gameObjectName; myActivity = theActivity; instance = new NativeCamera(); }public int startCamera(int idx, int width, int height) { nativeTexturePointer = createExternalTexture(); texture = new SurfaceTexture(nativeTexturePointer); mCamera = Camera.open(idx); setupCamera(idx, width, height); try { mCamera.setPreviewTexture(texture); mCamera.setPreviewCallback(this); AdjustOrientation(width, height); mCamera.startPreview(); Log.i("Unity", "JAVA: camera started"); } catch (IOException ioe) { Log.w("Unity", "JAVA: CAM LAUNCH FAILED"); } return nativeTexturePointer; }public void stopCamera() { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); Log.i("Unity", "JAVA: Camera stopped"); }private int createExternalTexture() { int[] textureIdContainer = new int[1]; GLES20.glGenTextures(1, textureIdContainer, 0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureIdContainer[0]); return textureIdContainer[0]; }@SuppressLint("NewApi") private void setupCamera(int cameraID, int width, int height) { Camera.Parameters params = mCamera.getParameters(); params.setRecordingHint(true); //params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); params.setPreviewFormat(17); params.setZoom(0); // 16 ~ NV16 ~ YCbCr // 17 ~ NV21 ~ YCbCr ~ DEFAULT * // 4~ RGB_565 // 256~ JPEG // 20 ~ YUY2 ~ YcbCr ... // 842094169 ~ YV12 ~ 4:2:0 YCrCb comprised of WXH Y plane, W/2xH/2 Cr & Cb. see documentation * //params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); Camera.Size previewSize = getOptimalSize(width, height, mCamera.getParameters().getSupportedPreviewSizes()); int previewWidth = previewSize.width; int previewHeight = previewSize.height; params.setPictureSize(previewWidth, previewHeight); params.setPreviewSize(previewWidth, previewHeight); params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO); params.setExposureCompensation(0); // // Fix the orientation. // //int orientation = detectCameraDisplayOrientation(cameraID); //mCamera.setDisplayOrientation(orientation); //params.setRotation(orientation); //Camera.CameraInfo info = new Camera.CameraInfo(); //Camera.getCameraInfo(cameraID, info); //Log.d("Unity", "info.orientation = " + info.orientation); //params.setRotation(-90); //mCamera.setDisplayOrientation(-90); //mCamera.setDisplayOrientation(90); //params.setRotation(90); try{ mCamera.setParameters(params); } catch (Exception e){ Log.i("Unity", "ERROR: " + e.getMessage()); }Camera.Size mCameraPreviewSize = params.getPreviewSize(); prevWidth = mCameraPreviewSize.width; prevHeight = mCameraPreviewSize.height; int[] fpsRange = new int[2]; params.getPreviewFpsRange(fpsRange); String previewFacts = mCameraPreviewSize.width + "x" + mCameraPreviewSize.height; if (fpsRange[0] == fpsRange[1]) { previewFacts += " @" + (fpsRange[0] / 1000.0) + "fps"; } else { previewFacts += " @[" + (fpsRange[0] / 1000.0) + " - "+ (fpsRange[1] / 1000.0) + "] fps"; } Log.i("Unity", "JAVA: previewFacts=" + previewFacts); }private void AdjustOrientation(int width, int height) { Camera.Parameters parameters = mCamera.getParameters(); Display display = myActivity.getWindowManager().getDefaultDisplay(); if(display.getRotation() == Surface.ROTATION_0) { Camera.Size previewSize = getOptimalSize(height, width, mCamera.getParameters().getSupportedPreviewSizes()); prevWidth = previewSize.width; prevHeight = previewSize.height; mCamera.setDisplayOrientation(90); }else if(display.getRotation() == Surface.ROTATION_90) { Camera.Size previewSize = getOptimalSize(width, height, mCamera.getParameters().getSupportedPreviewSizes()); prevWidth = previewSize.width; prevHeight = previewSize.height; }else if(display.getRotation() == Surface.ROTATION_180) { Camera.Size previewSize = getOptimalSize(height, width, mCamera.getParameters().getSupportedPreviewSizes()); prevWidth = previewSize.width; prevHeight = previewSize.height; }else { //if(display.getRotation() == Surface.ROTATION_270) { Camera.Size previewSize = getOptimalSize(width, height, mCamera.getParameters().getSupportedPreviewSizes()); prevWidth = previewSize.width; prevHeight = previewSize.height; mCamera.setDisplayOrientation(180); }parameters.setPreviewSize(prevWidth, prevHeight); mCamera.setParameters(parameters); }private Camera.Size getOptimalSize(int width, int height, List< Camera.Size> sizes) { if(mCamera == null) return null; final double ASPECT_TOLERANCE = 0.1; double targetRatio=(double)width / height; if (sizes == null) return null; Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetWidth = width; for (Camera.Size size : sizes) { double ratio = (double) size.width / size.height; Log.i("Unity", "RES: size=" + size.width + "/" + size.height + " Aspect Ratio: " + ratio + " target width: " + width + " target height: " + height); if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) { continue; }if (Math.abs(size.width - targetWidth) < minDiff) { optimalSize = size; minDiff = Math.abs(size.width - targetWidth); } }if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Camera.Size size : sizes) { if (Math.abs(size.width - targetWidth) < minDiff) { optimalSize = size; minDiff = Math.abs(size.width - targetWidth); } } } Log.i("Unity", "optimal size=" + optimalSize.width + "/" + optimalSize.height + "/ Aspect Ratio: " + (double) optimalSize.width / optimalSize.height); return optimalSize; }public int getPreviewSizeWidth() { return prevWidth; }public int getPreviewSizeHeight() { return prevHeight; }public String GetPreviewSizes(int id) { Camera cam = Camera.open(id); Camera.Parameters params = cam.getParameters(); Gson gson = new Gson(); String JSON = gson.toJson(params.getSupportedPreviewSizes()); cam.release(); Log.d("Unity", "Supported sizes are " + JSON); return JSON; }public byte[] bytes; @Override public void onPreviewFrame(byte[] data, Camera camera) { bytes = data; UnityPlayer.UnitySendMessage(gameObjectTargetName, "GetBuffer", ""); }}

答案尽管花了很多时间试图让相机用SetDisplayOrientation旋转图像,但由于某些原因,这些都没有任何效果。我最终做了Alex Cohen所建议的,并在OnPreviewFrame中手动旋转了图像
这是指向如何旋转图像的代码页面的链接。
Rotate an YUV byte array on Android
另一答案在相机预览中...设置`Camera.setPreviewDisplay(holder);
mCamera = Camera.open(0); mCamera.setPreviewDisplay(holder); mCamera.startPreview(); mCamera.setDisplayOrientation(90); `

另一答案Camera.setDisplayOrientation仅影响传递给Camera.setPreviewDisplay或Camera.setPreviewTexture的预览输出。这在API reference中为setDisplayOrientation记录:
这不会影响onPreviewFrame(byte [],Camera),JPEG图片或录制视频中传递的字节数组的顺序。
如果你需要调整onPreviewFrame的输出,那么你需要自己做。您需要应用的旋转与您按顺时针方向传递给setDisplayOrientation的值相同。

    推荐阅读