[QUESTION]
DreamCamera2常见预览问题
[ANSWER]
DreamCamera2 app常见预览问题修改方案
DreamCamera2 APP层预览常见问题包括预览拉伸、预览不清晰、预览黑边等,本文主要针对常见的客户问题的修改方案做出总结。
1.1 常见尺寸介绍
DreamCamera2预览相关尺寸包括图片尺寸、预览尺寸及预览框尺寸。
1.1.1 图片尺寸/视频尺寸
图片尺寸和视频尺寸是DreamCamera2 APP中,设置好的格式,见图1.1和图1.2。
图1.1 图片尺寸 图1.2 视频尺寸
1.1.2 预览尺寸
预览尺寸PreviewSize,PreviewSize设置不正确会导致预览拉伸问题。Android10中,视频和拍照的预览尺寸设置分别在PhotoModule.java和VideoModule.java中实现。
文件参考路径:
①拍照:sprdroid10_trunk_19c/vendor/sprd/platform/packages/apps/DreamCamera2/src/com/android/camera/PhotoModule.java
// Set a preview size that is closest to the viewfinder height and has
// the right aspect ratio.
List sizes = Size.convert(mCameraCapabilities
.getSupportedPreviewSizes());
Size optimalSize = CameraUtil.getOptimalPreviewSize(sizes,
(double) pictureSize.width() / pictureSize.height()); //根据照片尺寸和屏幕尺寸,查找合适的预览尺寸
Size original = new Size(mCameraSettings.getCurrentPreviewSize());//当前预
// int currentModuleId = mActivity.getCurrentModuleIndex();
// Log.d(TAG,"qtf_currentModuleId: " + currentModuleId);
if (optimalSize != null && !optimalSize.equals(original)) {
Log.i(TAG, "setting preview size. optimal: " + optimalSize
+ "original: " + original);
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize()); //设置拍照预览尺寸
}
图1.3拍照预览尺寸设置位置
②录像:sprdroid10_trunk_19c/vendor/sprd/platform/packages/apps/DreamCamera2/src/com/android/camera/VideoModule.java
protected void updateDesiredPreviewSize() {
if (mCameraDevice == null) {
return;
}
mCameraSettings = mCameraDevice.getSettings();
desiredPreviewSize = getDesiredPreviewSize(mCameraCapabilities, //获取合适的录像尺寸
mProfile, mUI.getPreviewScreenSize());
mDesiredPreviewWidth = desiredPreviewSize.x;
mDesiredPreviewHeight = desiredPreviewSize.y;
mUI.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight); //设置录像预览尺寸
if (isSlowMotionOn() && mActivity.getCameraAppUI().getSurfaceHolder() != null) {
mActivity.getCameraAppUI().getSurfaceHolder().setFixedSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
}
Log.v(TAG, "Updated DesiredPreview=" + mDesiredPreviewWidth + "x"
+ mDesiredPreviewHeight);
}
图1.4录像预览尺寸设置
值得注意的是,每一个拍照或录像的预览尺寸都是通过计算得来的。拍照预览尺寸通过getOptimalPreviewSize计算得到,得到的预览尺寸能兼容屏幕尺寸和照片尺寸,保证尽量铺满屏幕,但又不拉伸照片;同样录像尺寸最终的计算方法也是由getOptimalPreviewSize计算得到。
1.1.2.1 拍照预览尺寸设置
如下是拍照预览尺寸修改方案实例,该实例为了提高预览的清晰度,针对前后摄不同照片尺寸设置了不同的预览尺寸。
— a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -4996,7 +4996,28 @@ public class PhotoModule extends CameraModule implements PhotoController,
if (optimalSize != null && !optimalSize.equals(original)) {
Log.i(TAG, "setting preview size. optimal: " + optimalSize
+ "original: " + original);
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
//mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
float pictureRatio = (float)pictureSize.width() / (float)pictureSize.height();
-
if(DreamUtil.getRightCamera(mCameraId) == DreamUtil.BACK_CAMERA){
-
if(pictureRatio == (4f/3f)){
-
optimalSize = new Size(1280, 960);
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}else if(pictureRatio == (1280f / 720f)){
-
optimalSize = new Size(1280, 720);
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}else if(pictureRatio == (1920f / 1088f)){
-
optimalSize = new Size(1920, 1088);
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}else if(pictureRatio == (864f / 480f)){
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}
-
}else if(DreamUtil.getRightCamera(mCameraId) == DreamUtil.FRONT_CAMERA){
-
if(pictureRatio == (4f/3f)){
-
optimalSize = new Size(960, 720);
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}else if(pictureRatio == (1280f / 720f) || pictureRatio == (640f / 360f)){
-
optimalSize = new Size(1280, 720);
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}else if(pictureRatio == (720f / 544f) || pictureRatio == (864f / 480f)){
-
mCameraSettings.setPreviewSize(optimalSize.toPortabilitySize());
-
}
-
} }
1.1.2.2 录像预览尺寸设置
如下是录像录像预览尺寸修改方案实例,该实例为了提高预览的清晰度,针对不同录像尺寸设置不同的预览尺寸。
— a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -1694,8 +1694,19 @@ public class VideoModule extends CameraModule implements
desiredPreviewSize = getDesiredPreviewSize(mCameraCapabilities,
mProfile, mUI.getPreviewScreenSize());
-
mDesiredPreviewWidth = desiredPreviewSize.x;
-
mDesiredPreviewHeight = desiredPreviewSize.y;
-
// mDesiredPreviewWidth = desiredPreviewSize.x;
-
// mDesiredPreviewHeight = desiredPreviewSize.y;
-
int videoFrameResolution = mProfile.videoFrameWidth * mProfile.videoFrameHeight;
-
if(videoFrameResolution == (1280 * 720)){
-
mDesiredPreviewWidth = 1280;
-
mDesiredPreviewHeight = 720;
-
}else if (videoFrameResolution == (720 * 480)){
-
mDesiredPreviewWidth = 720;
-
mDesiredPreviewHeight = 480;
-
}else if (videoFrameResolution == (352 * 288)){
-
mDesiredPreviewWidth = 352;
-
mDesiredPreviewHeight = 288;
-
} mUI.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight); Log.v(TAG, "Updated DesiredPreview=" + mDesiredPreviewWidth + "x"
1.1.2.3 底层hal尺寸
值得注意的是:
① 1.1.2.1和1.1.2.2中设置的预览尺寸,底层hal必须支持。即底层(hal层)必须存在此预览尺寸,上层才可以设置此预览尺寸,否则会出现无法预览的错误;
② 一般在没有预览拉伸和不清晰等问题,不建议修改预览尺寸。
底层(hal层)设置预览尺寸文件(Android8、9、10)为SprdCamera3Setting.cpp (参考路径:sprdroid10_trunk_19c/vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3Setting.cpp)
修改位置:stream_info[]数组
// initStaticParametersforScalerInfo may be change min_duration and
// stall_duration
const cam_stream_info_t stream_info[] = {
{{9216, 6912}, 41666666L, 41666666L}, /* 64M */
{{6528, 4896}, 41666666L, 41666666L},
…
{{2560, 1440}, 33331760L, 33331760L},
{{2448, 2448}, 33331760L, 33331760L},
{{2320, 1740}, 33331760L, 33331760L},
{{2304, 1728}, 33331760L, 33331760L}, // L5Pro,4in1 binning size
…
{{1920, HEIGHT_2M}, 33331760L, 33331760L},
{{1920, 896}, 33331760L, 33331760L},
…
{{176, 144}, 33331760L, 33331760L}};
图1.5 stream_info[]数组
上层的预览尺寸和图片尺寸均是从stream_info[]数组里读取
1.1.3 预览框尺寸
预览框尺寸,也叫预览区域尺寸(PreviewRect),预览框设置不正确会导致预览黑边、拉伸问题。DreamCamera2中预览框尺寸是根据来计算的,两者的宽高比基本一致。
Android8,9,10中,DreamCamera2的app层设置预览框尺寸的文件为: DreamCaptureLayoutHelper.java(参考路径:sprdroid10_trunk_19c/vendor/sprd/platform/packages/apps/DreamCamera2/src/com/dream/camera/ui/DreamCaptureLayoutHelper.java)
DreamCaptureLayoutHelper.java中对预览区域包含了Photo和Video模式下预览区域的设置,相机预览区域尺寸设置本质是通过图片/视频的高宽比和屏幕高宽比来区分的。为简单描述,图片/视频的高宽比统一简写为图片的高宽比。设置思路如下图1.6。
图1.6预览区域设置的思路
在DreamCaptureLayoutHelper.java中具体预览区域设置如图1.7。
@Override
protected PositionConfiguration getPositionConfiguration(int width, int height,
float previewAspectRatio, int rotation) {
…
/预览比例==0,初始化的时候/
if (previewAspectRatio == TextureViewHelper.MATCH_SCREEN) {
config.mPreviewRect.set(0, 0, width, height);/设置预览框尺寸/
} else {
…
/***预览比例>屏幕比例(一般为屏幕宽高比 < 16/9)***/
if (remainingSpaceAlongLongerEdge <= 0) {
if (landscape) { /应用横屏,设置预览框尺寸/
config.mPreviewRect.set(0, height / 2 - previewShorterEdge / 2, previewLongerEdge,height / 2 + previewShorterEdge / 2);
} else { /应用竖屏,设置预览框尺寸/
config.mPreviewRect.set(width / 2 - previewShorterEdge / 2, 0,
width / 2 + previewShorterEdge / 2, previewLongerEdge);
}
/*预览比例比例>14:9(16:9照片,720p,1080p录像等情况) *****/
} else if (previewAspectRatio > 14f / 9f) {
// If the preview aspect ratio is large enough, simply offset the
// preview to the bottom/right.
barSize = bottomHeight - slideHeight;
previewShorterEdge = shorterEdge;
previewLongerEdge = shorterEdge * previewAspectRatio;
config.mBottomBarOverlay = true;
if (landscape) {/*****应用横屏,设置预览框尺寸***/
config.mPreviewRect.set(0, topHeight, previewLongerEdge, previewShorterEdge + topHeight);
} else {/***应用竖屏,设置预览框尺寸***/
config.mPreviewRect.set(0, topHeight, previewShorterEdge, previewLongerEdge + topHeight);
}
/***预览比例小于14:9(一般为4:3,CIF录像格式等图片尺寸)***/
} else {
..................
if (landscape) { /*****应用横屏,设置预览框尺寸***/
config.mPreviewRect.set(topHeight, 0, topHeight
+ previewLongerEdge, previewShorterEdge);
} else { /***应用竖屏,设置预览框尺寸***/
config.mPreviewRect.set(0, topHeight, previewShorterEdge, topHeight
+ previewLongerEdge);
}
}
}
round(config.mBottomBarRect);
round(config.mPreviewRect);
return config;
}
图1.7 预览区域修改位置
预览区域设置解析:
如图1.6、1.7可以看出:
① 当预览的高宽比= 0,设置预览尺寸为屏幕尺寸;
② 当预览的高宽比≠屏幕高宽比时,分为图片或录像的高宽比>屏幕高宽比和图片或录像的高宽比小于屏幕高宽比;
③ 当预览的高宽比>屏幕高宽比时,以屏幕长边为预览框长边,预览短边 = 屏幕长边×图片或录像比例;
④ 当预览的高宽比<屏幕高宽比时,以屏幕短边为预览框长边,预览长边 = 屏幕短边/图片或录像比例;
⑤ 当预览的高宽比<屏幕高宽比时,通过14f / 9f区分不同图片或录像比例下的预览框尺寸设置。如16:9的图片或录像格式,在预览比例>14f / 9f 时设置;4:3的图片或录像格式,在预览比例<14f / 9f 时设置。
1.2 常见问题解决方案
预览常见问题包括预览拉伸、预览不清晰、预览黑边等问题。预览框的尺寸是通过预览尺寸计算得来的,针对拉伸和黑边问题,修改预览尺寸和预览框尺寸均可以。针对特定格式的屏幕,也可以通过修改图片尺寸来解决此类问题。
1.2.1 预览拉伸问题
预览拉伸本质的原因是 图片比例 和 预览/预览框比例 不一致,图片比例一般不可修改,那么方案是通过修改 预览/预览框比例 来解决此问题。针对特定图片,修改预览/预览框尺寸可参考本文的1.1.2、1.1.3章节。
1.2.2 预览不清晰问题
预览不清晰问题,在tuning效果参数设置正确的前提下,app层可以考虑增加预览尺寸和适当提高预览帧率来解决此问题。预览尺寸的修改可参考本文的1.1.2章节。
1.2.3 预览黑边问题
这里的黑边指的是预览框左右黑边,预览黑边本质的原因是:预览区域高宽比 大于 屏幕尺寸高宽比,导致屏幕和和预览框没有重合,预览区域左右未能填满屏幕,此时会出现黑边问题。预览黑边现象如图1.8。
图1.8 预览黑边现象
黑边问题可以通过修改预览/预览框尺寸 可参考本文的1.1.2、1.1.3章节。
1.2.4 修改图片/视频尺寸
对于特定比例的屏幕,有时候需要添加图片尺寸,如针对长宽比为8:5屏幕;为提升视频质量,有时候需要增加视频尺寸。本章节主要介绍DreamCamera2中图片尺寸和视频尺寸的修改。
1.2.4.1 修改图片尺寸
修改图片尺寸需要在hal层和应用层分别做修改,如下是增加8:5的图片尺寸的操作。
1.2.4.1.1 底层(hal)修改
针对Android8,9,10,hal层图片尺寸的修改在SprdCamera3Setting.cpp文件中完成,在hal层需要增加图片尺寸,预览尺寸和缩略图尺寸。
文件参考路径:sprdroid10_trunk_19c/vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3Setting.cpp
添加 8:5的图片尺寸的修改方案:
const cam_stream_info_t stream_info[] = {
…
{{3264, 2448}, 33331760L, 33331760L},
{{3264, 1836}, 33331760L, 33331760L},
{{2592, 1944}, 33331760L, 33331760L},
-
{{2592, 1620}, 33331760L, 33331760L}, //for capture (图片尺寸)
{{2560, 1920}, 33331760L, 33331760L},
{{1920, HEIGHT_2M}, 33331760L, 33331760L},
{{1600, 1200}, 33331760L, 33331760L},
{{1280, 960}, 33331760L, 33331760L},
-
{{1280, 800}, 33331760L, 33331760L}, ///for capture /for preview (图片尺寸/预览尺寸)
{{1280, 720}, 33331760L, 33331760L},
{{960, 720}, 33331760L, 33331760L},
…
{{480, 480}, 33331760L, 33331760L},
{{352, 288}, 33331760L, 33331760L},
{{320, 240}, 33331760L, 33331760L},
-
{{320, 200}, 33331760L, 33331760L}, //for thumbnail (缩略图尺寸)
{{288, 352}, 33331760L, 33331760L},
{{240, 320}, 33331760L, 33331760L},
{{176, 144}, 33331760L, 33331760L}};
如上修改所示,添加图片尺寸时,thumbnail (缩略图尺寸)app中选取的是小尺寸图片,因此需要设置8:5的小尺寸{320, 200};preview (预览尺寸)app中一般选取的是中型尺寸,这里设置了{1280, 800}作为预览尺寸;capture (图片尺寸)app中选取了{1280, 800}和{2592, 1620},app应用界面会出现{1280, 800}和{2592, 1620}两组8:5图片尺寸,如图1.9。
图1.9 增加8:5预览尺寸
1.2.4.1.2 应用层(app)修改
DreamCamera2的图片尺寸修改在ResolutionUtil.java文件中完成
ResolutionUtil.java文件参考路径:sprdroid10_trunk_19c/vendor/sprd/platform/packages/apps/DreamCamera2/src/com/android/camera/settings/ResolutionUtil.java)
添加 8:5图片尺寸,并删除4:3图片尺寸的修改方案:
— a/src/com/android/camera/settings/ResolutionUtil.java
+++ b/src/com/android/camera/settings/ResolutionUtil.java
@@ -67,11 +67,12 @@ public class ResolutionUtil {
* We will also take the maximum supported resolution for full sensor image.
*/
private static Float[] sDesiredAspectRatios = {
-
16.0f / 9.0f, 4.0f / 3.0f
-
};16.0f / 9.0f, 8.0f / 5.0f
private static Size[] sDesiredAspectRatioSizes = {
-
new Size(16, 9), new Size(4, 3)
-
};new Size(16, 9), new Size(8, 5)
@@ -241,6 +241,7 @@ public class ResolutionUtil {
for (Size size : sizes) {
Float aspectRatio = (float) size.getWidth() / (float) size.getHeight(); -
if (aspectRatio < 1.6) continue; //4:3图片格式的aspectRatio(长宽比)== 1.33<1.6,因此在此处去除 // If this aspect ratio is close to a desired Aspect Ratio, // fuzz it so that they are bucketed together aspectRatio = fuzzAspectRatio(aspectRatio);
1.2.4.2 修改视频尺寸
DreamCamera2的图片尺寸修改在media_profiles.xml文件中完成(文件参考路径:sprdroid10_trunk_19c/device/sprd/sharkl5Pro/common/media_profiles.xml)
下面是添加h264视频格式480p视频的修改方案。
-
<EncoderProfile quality="480p" fileFormat="mp4" duration="60">
-
<Video codec="h264"
-
bitRate="4000000"
-
width="640"
-
height="480"
-
frameRate="30" />
-
<Audio codec="aac"
-
bitRate="64000"
-
sampleRate="44100"
-
channels="1" />
-
</EncoderProfile>
-
<EncoderProfile quality="timelapse480p" fileFormat="mp4" duration="60">
-
<Video codec="h264"
-
bitRate="4000000"
-
width="640"
-
height="480"
-
frameRate="30" />
-
<!-- audio setting is ignored -->
-
<Audio codec="aac"
-
bitRate="64000"
-
sampleRate="44100"
-
channels="1" /> </EncoderProfile> <ImageEncoding quality="95" /> <ImageEncoding quality="80" /> <ImageEncoding quality="70" /> <ImageDecoding memCap="20000000" />
需要注意的是:
① 设置的视频尺寸,hal层的SprdCamera3Setting.cpp文件必须支持,SprdCamera3Setting.cpp参考路径:sprdroid10_trunk_19c/vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3Setting.cpp
② 设置的视频尺寸,sensor必须支持,如sensor尺寸为200万(1200×1600),设置1080p(1920×1080)将会出错,因为1200×1600 = 1920000 < 1920×1080 = 2073600
③ 目前平台支持的视频格式设置包括:1080p(1920×1080),720p(1080×720),480p(720×480),CIF(352×288)。
④ 修改的适