使用Grafika CameraCapture代码拉伸Android相机预览

时间:2016-04-13 10:23:22

标签: android opengl-es android-camera glsurfaceview grafika

我正在寻找有关使用Grafika's CameraCaptureActivity代码遇到的问题的帮助。我想构建一个可以记录相机并显示预览的应用程序,所以这个样本和代码看起来就像我想要的那样,到目前为止它很棒,这个问题可以解决。

我遇到的问题是,当相机预览尺寸与用于显示预览的GLSurfaceView的确切尺寸不相符时,它会显示拉伸的预览。

以下是它的外观:

Preview stretched

正如你所看到的那样它是水平拉伸的,因为音符表是一个完美的正方形。

对于Samsung Galaxy S4的精确示例,相机预览尺寸为1280x720(使用Camera2 API从可用的预览尺寸中提取),GLSurfaceView为{{1}覆盖整个屏幕。

什么时候出现?

当SurfaceView与Camera输出相比进行放大时会出现此问题,即使我始终确保比率保持正确(1920x1080 = 1,5 * 1920x1080)。

您使用的代码是什么?

我使用Grafika的代码,包括:

有些日志?

这是SurfaceFlinger转储的样子:

1280x720

相机预览尺寸代码?

Hardware Composer state (version 01030000):
  mDebugForceFakeVSync=0
  Display[0] configurations (* current):
    * 0: 1080x1920, xdpi=442.450989, ydpi=439.351013, secure=1 refresh=16666667
  numHwLayers=3, flags=00000000
    type   |  handle  | hint | flag | tr | blnd |  format     |     source crop(l,t,r,b)       |           frame        |      dirtyRect         |  name 
------------+----------+----------+----------+----+-------+----------+-----------------------------------+---------------------------+-------------------
       HWC | b3b12ba0 | 0002 | 0000 | 00 | 0100 | RGB_888     |    0.0,    0.0, 1080.0, 1920.0 |    0,    0, 1080, 1920 | [    0,    0, 1080, 1920] | SurfaceView
       HWC | b3d12740 | 0002 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0, 1065.0, 1905.0 |    0,    0, 1065, 1905 | [    0,    0, 1065, 1905] | com.mybundle.myapp/com.mybundle.myapp.activity.MyActivity
 FB TARGET | b6a55c40 | 0000 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0, 1080.0, 1920.0 |    0,    0, 1080, 1920 | [    0,    0,    0,    0] | HWC_FRAMEBUFFER_TARGET

Layer 0xb4094000 (SurfaceView)
  Region transparentRegion (this=0xb4094160, count=1)
    [  0,   0,   0,   0]
  Region visibleRegion (this=0xb4094008, count=1)
    [  0,   0, 1920, 1080]
      layerStack=   0, z=    21015, pos=(0,0), size=(1920,1080), crop=(   0,   0,1920,1080), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]
      client=0xb66190c0
      format= 4, activeBuffer=[1080x1920:1536,  3], queued-frames=0, mRefreshPending=0
            mTexName=116 mCurrentTexture=0
            mCurrentCrop=[0,0,0,0] mCurrentTransform=0x7
            mAbandoned=0
            -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[1920x1080], default-format=4, transform-hint=04, FIFO(0)={}
            >[00:0xb1c18500] state=ACQUIRED, 0xb3b12ba0 [1080x1920:1536,  3]

您尝试了什么?

我首先认为这是一个StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); // Retrieve display size WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Point displaySize = new Point(); display.getSize(displaySize); // Choose the sizes for camera preview mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), displaySize.x, displaySize.y, captureWidth, captureHeight); private static Size chooseOptimalSize(Size[] choices, int screenWidth, int screenHeight, int captureWidth, int captureHeight) { // Collect the supported resolutions that are at least as big as the screen && wanted capture size List<Size> bigEnough = new ArrayList<>(); // Collect the supported resolutions that are at least as big as the wanted capture size but < to screensize List<Size> smallerButEnough = new ArrayList<>(); for (Size option : choices) { if (option.getHeight() == option.getWidth() * captureHeight / captureWidth) { if( option.getWidth() >= screenWidth && option.getHeight() >= screenHeight ) { bigEnough.add(option); } else { smallerButEnough.add(option); } } } // Pick the smallest of those, assuming we found any if (bigEnough.size() > 0) { return Collections.min(bigEnough, new CompareSizesByArea()); } // Pick the biggest of those, assuming we found any else if( smallerButEnough.size() > 0 ) { return Collections.max(smallerButEnough, new CompareSizesByArea()); } else { Log.e(TAG, "Couldn't find any suitable preview size"); return choices[0]; } } 问题,所以我尝试只使用旧的Camera API,但结果是一样的。

然后我认为这是一个比率问题,但正如你所看到的,这里的比例在水平和垂直方向都可以。

我敢打赌,当Surface调整大小时,有一个OpenGL转换应用,但我在OpenGL中是一个纯粹的菜鸟,所以我找不到任何可行的东西。我尝试添加这些行,但它没有帮助:

Camera2

另一个例子,来自Grafika:

这是Grafika应用程序中的另一个问题示例。

电话:Galaxy S3 Neo(@Override public void onSurfaceChanged(GL10 gl, int width, int height) { Log.d(TAG, "onSurfaceChanged " + width + "x" + height); gl.glViewport(0, 0, width, height); gl.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT); } ) - Android 4.4.2

手机有一个GT-I9301L屏幕,相机以1280x720分辨率打开,显示在640x480。这是它的外观:

Stretching on GS3 Neo

SurfaceFlinger记录:

573x430

Grafika的应用程序日志:

Hardware Composer state (version  1030000):
  mDebugForceFakeVSync=0
  Display[0] : 720x1280, xdpi=304.799011, ydpi=306.716003, refresh=16666667
  numHwLayers=4, flags=00000000
    type    |  handle  |   hints  |   flags  | tr | blend |  format  |          source crop            |           frame           name 
------------+----------+----------+----------+----+-------+----------+---------------------------------+--------------------------------
        HWC | b84a3d18 | 00000002 | 00000000 | 00 | 00100 | 00000002 | [    0.0,    0.0,  430.0,  573.0] | [   32,  353,  462,  926] SurfaceView
        HWC | b841b080 | 00000002 | 00000000 | 00 | 00105 | 00000001 | [    0.0,    0.0,  670.0, 1280.0] | [    0,    0,  670, 1280] com.android.grafika/com.android.grafika.CameraCaptureActivity
        HWC | b8423250 | 00000002 | 00000000 | 00 | 00105 | 00000001 | [    0.0,    0.0,   50.0, 1280.0] | [  670,    0,  720, 1280] StatusBar
  FB TARGET | b8412d50 | 00000000 | 00000000 | 00 | 00105 | 00000001 | [    0.0,    0.0,  720.0, 1280.0] | [    0,    0,  720, 1280] HWC_FRAMEBUFFER_TARGET


+ Layer 0xb8416080 (SurfaceView) id=112
  Region transparentRegion (this=0xb84169d0, count=1)
    [  0,   0,   0,   0]
  Region visibleRegion (this=0xb8416088, count=1)
    [353, 258, 926, 688]
      layerStack=   0, z=    21015, pos=(353,258), size=( 573, 430), crop=(   0,   0, 573, 430), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
      client=0xb841d7c8
      format= 4, activeBuffer=[ 430x 573: 448,  2], queued-frames=0, mRefreshPending=0
            mTexName=95 mCurrentTexture=1
            mCurrentCrop=[0,0,0,0] mCurrentTransform=0x7
            mAbandoned=0
            -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[573x430], default-format=4, transform-hint=04, FIFO(0)={}
             [00:0xb84439a8] state=FREE    , 0xb849a528 [ 430x 573: 448,  2]
            >[01:0xb8421128] state=ACQUIRED, 0xb84a3d18 [ 430x 573: 448,  2]
             [02:0xb84238e8] state=FREE    , 0xb84432f8 [ 430x 573: 448,  2]

因此...

如果你们其中一个人知道如何让它发挥作用,我很乐意听取他的意见。

谢谢!

1 个答案:

答案 0 :(得分:0)

对不起我的最后一个答案,这是愚蠢的,并没有解决问题。但我创建了另一种解决方案,并使用不同的相机宽高比在5台设备上进行了测试。 据我所知,你使用的是Grafika代码。尝试删除parms.setRecordingHint(true); 所以现在我只使用 param.setPictureSize() param.setPreviewSize() 在相机参数中具有相同的纵横比。 另外我用这个方面设置了gl视图的大小,我自己做了。在grafika它使用固定大小,afaik。 希望它能帮到你。