确认摄像头是否支持4K
指令 adb shell dumpsys media.camera | grep picture-size
adb shell
rk3588_s:/ # dumpsys media.camera | grep picture-size picture-size: 3840x2160picture-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选项。我自己也添加了1920x1080,都是一样的方法。
红色标注是修改的地方,不能遗漏。