-
确认摄像头是否支持4K
指令 adb shell dumpsys media.camera | grep picture-size
adb shell
rk3588_s:/ # dumpsys media.camera | grep picture-size
picture-size: 3840x2160
picture-size-values: 3840x2160,2592x1944,1920x1080,1280x960,1280x720,640x480,320x240,176x144
rk3588_s:/ #
可以看到当前摄像头是支持4K的
2、查看录像设置分辨率列表
可以看到目前最高支持480p分辨率,开始跟踪代码
3、跟踪列表加载代码
packages/apps/Camera2/src/com/android/camera/settings/CameraSettingsActivity.java文件中加载的list
private void setSummary(Preference preference) {
if (!(preference instanceof ListPreference)) {
return;
}
ListPreference listPreference = (ListPreference) preference;
if (listPreference.getKey().equals(Keys.KEY_PICTURE_SIZE_BACK)) {
setSummaryForSelection(mPictureSizes.backCameraSizes,
listPreference);
} else if (listPreference.getKey().equals(Keys.KEY_PICTURE_SIZE_FRONT)) {
setSummaryForSelection(mPictureSizes.frontCameraSizes,
listPreference);
} else if (listPreference.getKey().equals(Keys.KEY_VIDEO_QUALITY_BACK)) {
setSummaryForSelection(mPictureSizes.videoQualitiesBack.orNull(), listPreference);
} else if (listPreference.getKey().equals(Keys.KEY_VIDEO_QUALITY_FRONT)) {
setSummaryForSelection(mPictureSizes.videoQualitiesFront.orNull(), listPreference);
} else if (listPreference.getKey().equals(Keys.KEY_MEDIA_SAVE_PATH)) {
/*listPreference.setSummary(listPreference.getEntry());
String value = listPreference.getValue();
if (FLASH.equals(value))
Storage.DIRECTORY = Storage.DEFAULT_DIRECTORY;
else if (SDCARD.equals(value)) {
String state = Environment.getStorageState(new File(Storage.EXTENAL_SD));
Log.i(TAG,"getSecondVolumeStorageState = " + state);
if (!Environment.MEDIA_MOUNTED.equalsIgnoreCase(state)) {
mSettingsManager.setToDefault(SettingsManager.SCOPE_GLOBAL, Keys.KEY_MEDIA_SAVE_PATH);
restoreMediaSavePath();
Toast.makeText(getActivity(), R.string.external_sd_unmounted, Toast.LENGTH_SHORT).show();
} else {
Storage.DIRECTORY = Storage.EXTERNAL_DIRECTORY;
}
}
Log.i(TAG, "setSummary Storage.DIRECTORY = " + Storage.DIRECTORY);*/
} else {
listPreference.setSummary(listPreference.getEntry());
}
}
搜索KEY_VIDEO_QUALITY_BACK,加载list的值是mPictureSizes.videoQualitiesBack,继续查看videoQualitiesBack加载过程
packages/apps/Camera2/src/com/android/camera/settings/PictureSizeLoader.java
private Optional<SelectedVideoQualities> computeQualitiesForCamera(
CameraDeviceSelector facingSelector) {
int cameraId = SettingsUtil.getCameraId(mCameraDeviceInfo, facingSelector);
if (cameraId >= 0) {
// This is guaranteed not to be null/absent.
return Optional.of(SettingsUtil.getSelectedVideoQualities(cameraId));
}
return Optional.absent();
}
SettingsUtil.getSelectedVideoQualities(cameraId)); 这个地方获取分辨率list
static SelectedVideoQualities getSelectedVideoQualities(int cameraId) {
if (sCachedSelectedVideoQualities.get(cameraId) != null) {
return sCachedSelectedVideoQualities.get(cameraId);
}
// Go through the sizes in descending order, see if they are supported,
// and set large/medium/small accordingly.
// If no quality is supported at all, the first call to
// getNextSupportedQuality will throw an exception.
// If only one quality is supported, then all three selected qualities
// will be the same.
int largeIndex = getNextSupportedVideoQualityIndex(cameraId, -1);
int mediumIndex = getNextSupportedVideoQualityIndex(cameraId, largeIndex);
int smallIndex = getNextSupportedVideoQualityIndex(cameraId, mediumIndex);
SelectedVideoQualities selectedQualities = new SelectedVideoQualities();
selectedQualities.large = sVideoQualities[largeIndex];
selectedQualities.medium = sVideoQualities[mediumIndex];
selectedQualities.small = sVideoQualities[smallIndex];
sCachedSelectedVideoQualities.put(cameraId, selectedQualities);
return selectedQualities;
}
largeIndex mediumIndex smallIndex 大 中 小 列表中的三个值,需要继续一层层的跟下去,getNextSupportedVideoQualityIndex里面有个判断把4K分辨率过滤掉了,这个判断需要打开
private static boolean isVideoQualitySupported(int videoQuality) {
// 4k is only supported on L or higher but some devices falsely report
// to have support for it on K, see b/18172081.
if (!ApiHelper.isLOrHigher() && videoQuality == CamcorderProfile.QUALITY_2160P) {
return false;
}
return true;
}
&& videoQuality == CamcorderProfile.QUALITY_2160P 这个条件判断去掉
getNextSupportedVideoQualityIndex是获取的接口,代码都贴出来太多,整个调用顺序好了。
getNextSupportedVideoQualityIndex -> hasProfile -> native_has_camcorder_profile -> android_media_MediaProfiles_native_has_camcorder_profile -> sProfiles->hasCamcorderProfile -> getCamcorderProfileIndex
int MediaProfiles::getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const
{
int index = -1;
for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
if (mCamcorderProfiles[i]->mCameraId == cameraId &&
mCamcorderProfiles[i]->mQuality == quality) {
index = i;
break;
}
}
return index;
}
mCamcorderProfiles 加载过程就很重要了,MediaProfiles.cpp初始化的时候会去加载它
/*static*/ MediaProfiles*
MediaProfiles::getInstance()
{
ALOGV("getInstance");
Mutex::Autolock lock(sLock);
if (!sIsInitialized) {
char value[PROPERTY_VALUE_MAX];
if (property_get("media.settings.xml", value, NULL) <= 0) {
const char* xmlFile = nullptr;
for (auto const& f : getXmlPaths()) {
if (checkXmlFile(f)) {
xmlFile = f;
break;
}
}
if (xmlFile == nullptr) {
ALOGW("Could not find a validated xml file. "
"Using the default instance instead.");
sInstance = createDefaultInstance();
} else {
sInstance = createInstanceFromXmlFile(xmlFile);
}
} else {
sInstance = createInstanceFromXmlFile(value);
}
CHECK(sInstance != NULL);
sInstance->checkAndAddRequiredProfilesIfNecessary();
sIsInitialized = true;
}
getprop 了下没有media.settings.xml,所有走 <= 0这条路了,getXmlPaths接口会去搜索product/etc/ odm/etc/ vendor/etc/ system/etc 路径下有没有media_profiles_V1_0.xml文件,查看后在vendor/etc有这个文件,那就是要修改这个xml文件。
4、解决方法
修改media_profiles_V1_0.xml
#添加 注意区分camera0和camera1
<EncoderProfile quality="2160p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="6000000"
width="3840"
height="2160"
frameRate="30" />
<Audio codec="aac"
bitRate="61000"
sampleRate="44100"
channels="1" />
</EncoderProfile>
把h264编解码的最大分辨率改下,之前最大支持是1920
<VideoEncoderCap name="h264" enabled="true"
minBitRate="64000" maxBitRate="6000000"
minFrameWidth="176" maxFrameWidth="3840"
minFrameHeight="144" maxFrameHeight="2160"
minFrameRate="1" maxFrameRate="30" />
改后后直接push到vendor/etc目录下,重启后验证ok,可以录4K的视频了。
设置界面也可以看到4K选项。我自己也添加了1920×1080,都是一样的方法。
红色标注是修改的地方,不能遗漏。