1.参数支持
很多参数设置首先要硬件支持,如果设置失败则可能使用的是默认的参数,或者黑掉。
关键参数查看:支持分辨率,帧率,对焦模式等。
可以查看:
Camera.Parameters parameters = cameraTest.getParameters();
List<Integer> previewFrameRates = parameters.getSupportedPreviewFrameRates();
for (int a : previewFrameRates) {
Log.e(TAG, "getSupportedPreviewFrameRates--" + a);
}
List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
for (Camera.Size s : pictureSizes) {
Log.e(TAG, "getSupportedPictureSizes--" + s.width + "--" + s.height);
}
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
for (Camera.Size s : previewSizes) {
Log.e(TAG, "getSupportedPreviewSizes--" + s.width + "--" + s.height);
}
List<int[]> previewFpsRange = parameters.getSupportedPreviewFpsRange();
for (int[] ints : previewFpsRange) {
for (int a : ints) {
Log.e(TAG, "getSupportedPreviewFpsRange--" + a);
}
}
int minExposureCompensation = parameters.getMinExposureCompensation();
int maxExposureCompensation = parameters.getMaxExposureCompensation();
Log.e(TAG, "minExposureCompensation--" + minExposureCompensation);
Log.e(TAG, "maxExposureCompensation--" + maxExposureCompensation);
List<String> whiteBalance = parameters.getSupportedWhiteBalance();
for (String ss : whiteBalance) {
Log.e(TAG, "whiteBalance--" + ss);
}
List<String> antibanding = parameters.getSupportedAntibanding();
for (String ss : antibanding) {
Log.e(TAG, "antibanding--" + ss);
}
List<String> supportedFocusModes = parameters.getSupportedFocusModes();
for (String ss : supportedFocusModes) {
Log.e(TAG, "supportedFocusModes--" + ss);
}
List<Camera.Size> supportedVideoSizes = parameters.getSupportedVideoSizes();
for (Camera.Size s : supportedVideoSizes) {
Log.e(TAG, "getSupportedVideoSizes--" + s.width + "--" + s.height);
}
List<String> supportedSceneModes = parameters.getSupportedSceneModes();
for (String ss : supportedSceneModes) {
Log.e(TAG, "supportedSceneModes--" + ss);
}
Log.e(TAG, "parameters.flatten()--" + parameters.flatten());
2.B帧编码
B帧作为双向预测帧,不能适用在实时流,否则会造成画面一顿一顿。
解决方案:编码采用AVCProfileBaseline不编B帧。
mFormat.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
3.帧率
光线强度会影响帧率,目前设置有两种如果一种不生效尝试另外种
parameters.setPreviewFrameRate(fps);
或
parameters.setPreviewFpsRange( fps * 1000, fps * 1000);
部分设备设置帧率可能不会生效,且造成偏暗需要设置动态帧率范围:
光线弱,曝光时间要长。光线越弱,需要感光时间越长,帧率也就越低
parameters.setPreviewFpsRange(min * 1000,30 * 1000);
min 是支持的最低帧率。
4.h265编码支持
检测是否支持H.265硬编解码
/**
* 是否支持 hevc 硬解
*
* @return
*/
public static boolean isH265HWDecoderSupport() {
MediaCodecList codecList = new MediaCodecList(REGULAR_CODECS);
// 获取设备支持的所有 codec 信息
MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
for (int i = 0; i < codecInfos.length; i++) {
MediaCodecInfo codecInfo = codecInfos[i];
Log.e(TAG, codecInfo.getName());
// 解码codec & 解码器名称包含'hevc' & 不是软件codec
if (!codecInfo.isEncoder() && (codecInfo.getName().contains("hevc")
&& !isSWCodec(codecInfo.getName()))) {
return true;
}
}
return false;
}
public static void decoderSupport() {
MediaCodecList codecList = new MediaCodecList(REGULAR_CODECS);
// 获取设备支持的所有 codec 信息
MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
for (int i = 0; i < codecInfos.length; i++) {
MediaCodecInfo codecInfo = codecInfos[i];
Log.e(TAG, codecInfo.getName());
}
}
/**
* 是否为软件 codec
*
* @param codecName
* @return
*/
public static boolean isSWCodec(String codecName) {
if (codecName.startsWith("OMX.google.")) {
return true;
}
if (codecName.startsWith("OMX.")) {
return false;
}
return true;
}
5.旋转
拍照角度设置参数即可:
Camera.Parameters parameters = mCamera.getParameters();
try {
parameters.setRotation(90);
mCamera.setParameters(parameters);
} catch (Exception e) {
e.printStackTrace();
}
视频预览方向,有些设备摄像头固定,预览的移动画布 GLES20.glVertexAttribPointer绘制直接更新矩阵旋转:
private static final float FULL_RECTANGLE_TEX_COORDS_BACK[] = {
0.0f, 1.0f, // 0 bottom left
1.0f, 1.0f, // 1 bottom right
0.0f, 0.0f, // 2 top left
1.0f, 0.0f, // 3 top right
};
斜的直接转90°
private static final float FULL_RECTANGLE_TEX_COORDS[] = {
1.0f, 1.0f, // 2 top left
1.0f, 0.0f, // 0 bottom left
0.0f, 1.0f, // 3 top right
0.0f, 0.0f, // 1 bottom right
};
如果涉及到部分显示需要裁剪需要注意比例关系和坐标和Android是相反的。
比如:在一个默认输出是1280720 显示的是一个旋转90°的画面。如果直接旋转后显示会造成画面被挤压拉伸比例不对,需要按比例截取中间显示部分后旋转,以1280720的比例:
绘制矩阵改为:
//720*720/1280=405 (1280-405)/2=437.5 437.5+405=842.5
private static float f1 = (float) 842.5 / 1280;//
private static float f2 = (float) 437.5 / 1280;
private static final float[] FULL_RECTANGLE_TEX_COORDS_Resize = {
//这个是反的 因为 坐标系相反,
f2, 1.0f, // 2 top left
f2, 0.0f, // 0 bottom left
f1, 1.0f, // 3 top right
f1, 0.0f, // 1 bottom right
};
private static final float[] FULL_RECTANGLE_TEX_COORDS_Resize2 = {
f1, 1.0f, // 2 top left
f1, 0.0f, // 0 bottom left
f2, 1.0f, // 3 top right
f2, 0.0f, // 1 bottom right
};