(1)出错Log以及代码分析
最近测试反馈一款三方Camera应用发现无法打开Video Mode预览画面,预览画面是黑屏,从Log看到如下报错:
04-25 10:35:25.228 667 1136 E Camera2-Parameters: set: Requested preview size 1280 x 720 is not supported
从字面意思可以看出,应该是无法下达preview size从而导致无法预览,我们来看一下报错这里的Code。
(A)首先查看代码中获取不同Size列表的条件
//frameworks/av/services/camera/libcameraservice/api1/client2/Parameters.cpp
//(1)根据条件获取支持的Jpeg Size列表
Vector<Parameters::Size> Parameters::getPreferredJpegSizes() const {
return getPreferredFilteredSizes(
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT,
HAL_PIXEL_FORMAT_BLOB);
}
//(2)根据条件获取支持的Preview Size列表(这里的条件很重要,这题的根本原因所在)
Vector<Parameters::Size> Parameters::getPreferredPreviewSizes() const {
return getPreferredFilteredSizes(
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
}
//(3)根据条件获取支持的Video Size列表
Vector<Parameters::Size> Parameters::getPreferredVideoSizes() const {
return getPreferredFilteredSizes(
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
}
//(4)通过getPreferredFilteredSizes函数获取相应条件的Size列表
Vector<Parameters::Size> Parameters::getPreferredFilteredSizes(int32_t usecaseId,
int32_t format) const {
Vector<Parameters::Size> sizes;
Vector<StreamConfiguration> scs = getPreferredStreamConfigurations(usecaseId);
for (const auto &it : scs) {
if (it.format == format) {
sizes.add({it.width, it.height});
}
}
return sizes;
}
(B)以Preview Size为例,来查看最终获取到的Size列表
//frameworks/av/services/camera/libcameraservice/api1/client2/Parameters.cpp
//(1)maxPreviewSize最大预览Size的默认是1920x1920
static const unsigned int MAX_PREVIEW_WIDTH = 1920;
static const unsigned int MAX_PREVIEW_HEIGHT = 1920;
Size maxPreviewSize = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT };
//(2)根据条件重新设置最大预览Size(这里获取的值为960 x 540)
maxPreviewSize = getMaxSize(getPreferredPreviewSizes());
//根据最大预览Size,初始化可得到的Preview Size列表
res = getFilteredSizes(maxPreviewSize, &availablePreviewSizes);
for (size_t i = 0; i < availablePreviewSizes.size(); i++) {
ALOGE("dxf_availablePreviewSizes_1 : width = %d , height = %d\n", availablePreviewSizes[i].width ,availablePreviewSizes[i].height);
}
//打印的Log
04-25 16:18:46.953 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 960 , height = 540
04-25 16:18:46.953 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 960 , height = 480
04-25 16:18:46.953 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 720 , height = 480
04-25 16:18:46.953 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 640 , height = 480
04-25 16:18:46.953 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 352 , height = 288
04-25 16:18:46.953 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 320 , height = 240
04-25 16:18:46.957 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_1 : width = 176 , height = 144
由于最大的Preview Size已经被固定为960 x 540,从而导致这里拿到的预览Size列表只能为如上Log打印所示。
(C)根据上面的Size列表来判断当前的下的Preview Size(1280 x 720)是否支持
//frameworks/av/services/camera/libcameraservice/api1/client2/Parameters.cpp
status_t Parameters::set(const String8& paramString) {
status_t res;
//(1)上层设置下来的参数
CameraParameters2 newParams(paramString);
size_t i;
Parameters validatedParams(*this);
// (2)PREVIEW_SIZE——赋值预览Size
newParams.getPreviewSize(&validatedParams.previewWidth,
&validatedParams.previewHeight);
if (validatedParams.previewWidth != previewWidth ||
validatedParams.previewHeight != previewHeight) {
if (state >= PREVIEW) {
ALOGE("%s: Preview size cannot be updated when preview "
"is active! (Currently %d x %d, requested %d x %d",
__FUNCTION__,
previewWidth, previewHeight,
validatedParams.previewWidth, validatedParams.previewHeight);
return BAD_VALUE;
}
//(3)获取可支持的Preview Size列表
for (i = 0; i < availablePreviewSizes.size(); i++) {
ALOGE("dxf_availablePreviewSizes_2 = list.width = %d , list.height = %d , param.width = %d , param.height = %d , i = %d , size = %d\n",
availablePreviewSizes[i].width,availablePreviewSizes[i].height,
validatedParams.previewWidth,validatedParams.previewHeight,
i,availablePreviewSizes.size());
if ((availablePreviewSizes[i].width ==
validatedParams.previewWidth) &&
(availablePreviewSizes[i].height ==
validatedParams.previewHeight)) break;
}
//(4)判断设置下来的预览Size是否在可支持Preview Size列表中
if (i == availablePreviewSizes.size()) {
ALOGE("%s: Requested preview size %d x %d is not supported",
__FUNCTION__, validatedParams.previewWidth,
validatedParams.previewHeight);
return BAD_VALUE;
}
}
//打印的Log
04-25 16:18:47.105 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 960 , list.height = 540 , param.width = 1280 , param.height = 720 , i = 0 , size = 7
04-25 16:18:47.106 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 960 , list.height = 480 , param.width = 1280 , param.height = 720 , i = 1 , size = 7
04-25 16:18:47.106 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 720 , list.height = 480 , param.width = 1280 , param.height = 720 , i = 2 , size = 7
04-25 16:18:47.108 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 640 , list.height = 480 , param.width = 1280 , param.height = 720 , i = 3 , size = 7
04-25 16:18:47.108 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 352 , list.height = 288 , param.width = 1280 , param.height = 720 , i = 4 , size = 7
04-25 16:18:47.108 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 320 , list.height = 240 , param.width = 1280 , param.height = 720 , i = 5 , size = 7
04-25 16:18:47.108 661 4325 E Camera2-Parameters: dxf_availablePreviewSizes_2 = list.width = 176 , list.height = 144 , param.width = 1280 , param.height = 720 , i = 6 , size = 7
04-25 16:18:47.108 661 4325 E Camera2-Parameters: set: Requested preview size 1280 x 720 is not supported
现在就是步骤(4)出错了,因为1280 x 720不在预览Size的列表中,综上其实根本原因就是MaxPreviewSize = 960 x 540导致的。
(2)解决方案
这里看一下之前分析的代码,MaxPreviewSize来源如下:
//usecaseId = ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW
//format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
Vector<Parameters::Size> Parameters::getPreferredPreviewSizes() const {
return getPreferredFilteredSizes(
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
}
//根据条件重新设置最大预览Size(这里获取的值为960 x 540)
maxPreviewSize = getMaxSize(getPreferredPreviewSizes());
通过如上代码就能看出来是如下metadata配置导致的。
CONFIG_ENTRY_VALUE(1920, MINT32)
CONFIG_ENTRY_VALUE(1088, MINT32)
CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT , MINT32)
CONFIG_ENTRY_VALUE(1920, MINT32)
CONFIG_ENTRY_VALUE(1080, MINT32)
CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT , MINT32)
CONFIG_ENTRY_VALUE(1600, MINT32)
CONFIG_ENTRY_VALUE(1200, MINT32)
CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT , MINT32)
CONFIG_ENTRY_VALUE(1280, MINT32)
CONFIG_ENTRY_VALUE(720, MINT32)
CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT , MINT32)
CONFIG_ENTRY_VALUE( 960, MINT32)
CONFIG_ENTRY_VALUE( 540, MINT32)
CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, MINT32)
CONFIG_ENTRY_VALUE(MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT , MINT32)
需要将其他几个Size都要添加上MTK_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW的属性。