1,先看看Hal3支持哪些分辨率的尺寸:
const std::vector<int32_t> availableStreamConfigurationsProc = {
HAL_PIXEL_FORMAT_BLOB, 1920, 1080, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
。。。。。。
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1920, 1080, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
。。。。。。
HAL_PIXEL_FORMAT_YCbCr_420_888, 1920, 1080, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
};
可以看到HAL_PIXEL_FORMAT_BLOB格式就是照片支持的分辨率,HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED和HAL_PIXEL_FORMAT_YCbCr_420_888格式就是预览支持的分辨率尺寸。
2,回到上层,看Camera2原生代码。在camera open的时候会回调如下代码
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
........
updatePreviewTransform(width, height, true);
.......
}
这里的width和height就是surface的大小,一般就是屏幕的分辨率。
3,接着进入调用的接口看
private void updatePreviewTransform(int incomingWidth, int incomingHeight,
boolean forceUpdate) {
..........
mScreenWidth = incomingWidth;
mScreenHeight = incomingHeight;
updatePreviewBufferDimension();
..........
Matrix transformMatrix = mPreviewTransformCalculator.toTransformMatrix(
new Size(mScreenWidth, mScreenHeight),
new Size(mPreviewBufferWidth, mPreviewBufferHeight));
mAppController.updatePreviewTransform(transformMatrix);
..........
}
}
4,这个函数也简单,接着看里面的接口调用
private void updatePreviewBufferDimension() {
..........
Size previewBufferSize = mCamera.pickPreviewSize(mPictureSize, mUI.getActivity());
mPreviewBufferWidth = previewBufferSize.getWidth();
mPreviewBufferHeight = previewBufferSize.getHeight();
..........
updatePreviewBufferSize();
}
4.1,这里的mCamera 实际就是GenericOneCameraImpl对象,而mCamera.pickPreviewSize接口实际作用是调用mPreviewSizeSelector.pickPreviewSize(pictureSize);
4.2,而mPreviewSizeSelector也就是Camera2PreviewSizeSelector对象,该对象在创建的时候会传入supportedPreviewSizes。
4.3,那这个supportedPreviewSizes就是通过metadata获取到Hal3层里面支持的尺寸了,就是我们上面看到的支持分辨率的列表。
List<Size> supportedPreviewSizes = characteristics.getSupportedPreviewSizes();
5,接着看重点mPreviewSizeSelector.pickPreviewSize(pictureSize);
public Size pickPreviewSize(Size pictureSize) {
if (pictureSize == null) {
// TODO The default should be selected by the caller, and
// pictureSize should never be null.
pictureSize = getLargestPictureSize();
}
float pictureAspectRatio = pictureSize.getWidth() / (float) pictureSize.getHeight();
Size size = CaptureModuleUtil.getOptimalPreviewSize(
(Size[]) mSupportedPreviewSizes.toArray(new Size[mSupportedPreviewSizes.size()]),
pictureAspectRatio, null);
return size;
}
5.1,这个的pictureSize 就是前面创建对象时传进来的列表,从中找到最大的分辨率。
5.2,pictureAspectRatio 这个就是分辨率的宽高比,例如16:9或者4:3的比例了。
5.3,CaptureModuleUtil.getOptimalPreviewSize这个接口的逻辑就是先计算预览列表里面支持的分辨率的宽高比,再计算preview_rate – pictureAspectRatio < 0.02也就是找到宽高比最接近的比例,那么就找到了预览的分辨率了。
public static Size getOptimalPreviewSize(Size[] sizes,
double targetRatio, Double aspectRatioTolerance, Activity context) {
// TODO(andyhuibers): Don't hardcode this but use device's measurements.
final int MAX_ASPECT_HEIGHT = 1080;
// Count sizes with height <= 1080p to mimic camera1 api behavior.
int count = 0;
for (Size s : sizes) {
if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
count++;
}
}
ArrayList<Size> camera1Sizes = new ArrayList<Size>(count);
// Set array of all sizes with height <= 1080p
for (Size s : sizes) {
if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
camera1Sizes.add(new Size(s.getWidth(), s.getHeight()));
}
}
int optimalIndex = CameraUtil
.getOptimalPreviewSizeIndex(camera1Sizes, targetRatio,
aspectRatioTolerance, context);
if (optimalIndex == -1) {
return null;
}
Size optimal = camera1Sizes.get(optimalIndex);
for (Size s : sizes) {
if (s.getWidth() == optimal.getWidth() && s.getHeight() == optimal.getHeight()) {
return s;
}
}
return null;
}
6,总结一下,将找到的preview size设置成surfacetextview的size。就是显示窗口的大小了。其中还有个变换矩阵Matrix,这个Matrix的作用就是调整显示窗口的比例大小。首先会根据display的旋转角度设置到Matrix中做旋转,在将display的宽高通过scale操作变换成preview size。这样surface既可以设置成不同比例的显示画面。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/182001.html