我正在寻找有关使用Grafika's CameraCaptureActivity代码遇到的问题的帮助。我想构建一个可以记录相机并显示预览的应用程序,所以这个样本和代码看起来就像我想要的那样,到目前为止它很棒,这个问题可以解决。
我遇到的问题是,当相机预览尺寸与用于显示预览的GLSurfaceView
的确切尺寸不相符时,它会显示拉伸的预览。
以下是它的外观:
正如你所看到的那样它是水平拉伸的,因为音符表是一个完美的正方形。
对于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
。这是它的外观:
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]
因此...
如果你们其中一个人知道如何让它发挥作用,我很乐意听取他的意见。
谢谢!
答案 0 :(得分:0)
对不起我的最后一个答案,这是愚蠢的,并没有解决问题。但我创建了另一种解决方案,并使用不同的相机宽高比在5台设备上进行了测试。
据我所知,你使用的是Grafika代码。尝试删除parms.setRecordingHint(true);
所以现在我只使用
param.setPictureSize()
param.setPreviewSize()
在相机参数中具有相同的纵横比。
另外我用这个方面设置了gl视图的大小,我自己做了。在grafika它使用固定大小,afaik。
希望它能帮到你。