TextureView
TextureView做为SurfaceTexture和View的结合,把SurfaceTexture中的buffer内容copy到自己的Surface上显示。如图表示了Camera preview的数据是怎么显示到TextureView上的。
从图中可以看到,Camera有自己的Output Stream,这个Output Stream有特定的比例,如1280 x 720,可以根据StreamConfigurationMap#getOutputSize()来查看。
而SurfaceTexture所创建的Surface也有其大小,为SurfaceTexture中的default buffer size大小。TextureView创建时,会把SurfaceTexture的default buffer size设置为自己的宽高,当TextureView的大小改变时也会同时更新SurfaceTexture的buffer size为自己更新的宽高。也就是默认情况下SurfaceTexture所创建的Surface的大小为TextureView的大小。但我们可以通过SurfaceTexture#setDefaultBufferSize来改变这个大小。
TextureView的显示内容为什么会变形?
如上面的描述,TextureView显示的内容是SurfaceTexture创建的output Surface的内容,而SurfaceTexture所创建的Surface的内容来自Camera的output Stream。
SurfaceTexture所创建的Surface大小默认为TextureView的大小(TextureView#draw中调用SurfaceTexture#setDefaultBufferSize),当TextureView的大小改变时会同时更新SurfaceTexture的Surface大小(TextureView#onSizeChanged中调用SurfaceTexture#setDefaultBufferSize)。
Camera的output stream大小会根据它的output surface大小,从它配置的StreamConfigurationMap中选择一个最匹配的。
如图:
1. 当size2和size3的比例不一致时,size3的内容会变形放入size2中。
2. 当size1和size2的比例不一致时,size2的内容会变形放入size1中。
如何解决?
1. 通过SurfaceTexture#setDefaultBufferSize来设置SurfaceTexture的buffer size为StreamConfigurationMap中的一个,来确保SurfaceTexture的buffer size和Camera Output Stream的size比例一致。
2. 通过TextureView#setTramsform方法让TextureView显示SurfaceTexture里面符合自己大小的画面。
注:StreamConfigurationMap中的size都是横屏配置的,如2016 x 1512, 1920 x 1080等。在竖屏时,如果把SurfaceTexture的default buffer size设置为2016 x 1512,它实际显示的方式却为1512 x 2016,因此我们在设置TextureView的Tramsform时,需要和1512 x 2016做转换。
即:
SurfaceTexture#setDefaultBufferSize(bufferWidth, bufferHeight)
if landscape
TextureView scaleWith (bufferWidth, bufferHeight)
else
TextureView scaleWith (bufferHeight, bufferWidth)
其中当前所用的StreamConfigurationMap大小为Camera output stream根据它的output Surface大小选择出来的最优的。这个output Surface为放入CameraDevice#createCaptureSession Surface list中的Surface。
调试时查看这个output stream的大小可以在main log中过滤标签为"configure_stream"的log。如视频通话中,createCaptureSession放入了previewSurface、recordingSurface两个output Surface,打印出来的log有两个output Stream,stream[0]为previewSurface的信息,stream[1]为recordingSurface的信息。我们可以通过这个log查看当前这个output Surface所接收的camera stream的大小。
原创内容欢迎转载,但请注明出处,谢谢!