前言
目前有个需求需要添加一个810x720的预览和录像分辨率,测试app是晓龙相机。本文的默认要求是底层能够支持810x720的分辨率请求,另外晓龙相机使用的是api1。
一、预览更改
参考代码
public static Point getCameraPreviewSize() {
Point result = null;
if (PERSIST_CAMERA_PREVIEW_SIZE != null) {
String[] sourceStrArray = PERSIST_CAMERA_PREVIEW_SIZE.split("x");
if (sourceStrArray != null && sourceStrArray.length >= 2) {
result = new Point();
result.x = Integer.parseInt(sourceStrArray[0]);
result.y = Integer.parseInt(sourceStrArray[1]);
}
}
return result;
}
//private static final String PERSIST_CAMERA_PREVIEW_SIZE =
// SystemProperties.get("persist.sys.camera.preview.size", "");
adb shell setprop persist.sys.camera.preview.size 810x720 //设置预览分辨率
adb shell pm clear org.codeaurora.snapcam //清空原先static数据,重启app
二、录像分辨率更改
录像分辨率没有相应的属性来控制,所以考虑在UI设置中添加该项,操作起来也很麻烦
视频画质中添加810x720项,下面是具体过程
第一步 在控件中加入该项
--- a/packages/apps/SnapdragonCamera/res/values/arrays.xml
+++ b/packages/apps/SnapdragonCamera/res/values/arrays.xml
@@ -24,7 +24,8 @@
<item>@string/pref_video_quality_entry_2k</item>
<item>@string/pref_video_quality_entry_1080p</item>
<item>@string/pref_video_quality_entry_720p</item>
<item>@string/pref_video_quality_entry_480p</item>
+ <item>810x720</item>
<item>@string/pref_video_quality_entry_480p</item>
<item>@string/pref_video_quality_entry_vga</item>
<item>@string/pref_video_quality_entry_cif</item>
<item>@string/pref_video_quality_entry_qvga</item>
@@ -36,6 +37,7 @@
<item>2048x1080</item>
<item>1920x1080</item>
<item>1280x720</item>
+ <item>810x720</item>
<item>720x480</item>
<item>640x480</item>
<item>352x288</item>
--- a/packages/apps/SnapdragonCamera/src/com/android/camera/CameraSettings.java
+++ b/packages/apps/SnapdragonCamera/src/com/android/camera/CameraSettings.java
@@ -328,6 +328,7 @@ public class CameraSettings {
}
VIDEO_QUALITY_TABLE.put("1920x1080", CamcorderProfile.QUALITY_1080P);
VIDEO_QUALITY_TABLE.put("1280x720", CamcorderProfile.QUALITY_720P);
+ VIDEO_QUALITY_TABLE.put("810x720", CamcorderProfile.QUALITY_PRIV);
VIDEO_QUALITY_TABLE.put("720x480", CamcorderProfile.QUALITY_480P);
if ( CamcorderProfileWrapper.QUALITY_VGA != -1 ) {
VIDEO_QUALITY_TABLE.put("640x480", CamcorderProfileWrapper.QUALITY_VGA);
另外,这里可以设置list控件的默认值
SnapdragonCamera/res/values/strings.xml
<string name="pref_video_quality_default" translatable="false">1920x1080</string>
这里主要参考代码:
res/xml/video_preferences.xml
image.png
这个是设置界面的list控件的布局,第一张负责控制录像的视频质量,即是控制分辨率,videoQuality 是从控件的entity value中拿到的,如参考如下代码:
private void readVideoPreferences() {
// The preference stores values from ListPreference and is thus string type for all values.
// We need to convert it to int manually.
String videoQuality = mPreferences.getString(CameraSettings.KEY_VIDEO_QUALITY,
null); //通过IconListPreference拿到需要设置的分辨率大小
Log.e(TAG,"videoQuality" + videoQuality);
if (videoQuality == null) { //第一次进入取默认值
mParameters = mCameraDevice.getParameters();
String defaultQuality = mActivity.getResources().getString(
R.string.pref_video_quality_default);
if (!defaultQuality.equals("") &&
CameraUtil.isSupported(defaultQuality,
CameraSettings.getSupportedVideoQualities(
mCameraId, mParameters))){
videoQuality = defaultQuality;
} else {
// check for highest quality supported
videoQuality = CameraSettings.getSupportedHighestVideoQuality(
mCameraId, mParameters);
}
mPreferences.edit().putString(CameraSettings.KEY_VIDEO_QUALITY, videoQuality).apply();
}
......
int mappedQuality = quality;
if (mCaptureTimeLapse) {
mappedQuality = CameraSettings.getTimeLapseQualityFor(quality);
} else if (hfrRate > 0) {
mappedQuality = CameraSettings.getHighSpeedQualityFor(quality);
Log.i(TAG,"NOTE: HighSpeed quality (" + mappedQuality + ") for (" + quality + ")");
}
Log.e(TAG,"Quality " + mappedQuality);
if (CamcorderProfile.hasProfile(mCameraId, mappedQuality)) {
quality = mappedQuality;
} else {
Log.e(TAG,"NOTE: Quality " + mappedQuality + " is not supported ! Will use " + quality);
}
mProfile = CamcorderProfile.get(mCameraId, quality); //关键地方,通过CamcorderProfile得到video分辨率
getDesiredPreviewSize();
qcomReadVideoPreferences();
......
}
此处为读取配置的地方,应用数据则参考如下:
mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
第二步,添加系统支持的quality level : QUALITY_PRIV
--- a/frameworks/av/media/libmedia/MediaProfiles.cpp
+++ b/frameworks/av/media/libmedia/MediaProfiles.cpp
@@ -76,6 +76,7 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = {
{"1080p", CAMCORDER_QUALITY_1080P},
{"2160p", CAMCORDER_QUALITY_2160P},
{"qvga", CAMCORDER_QUALITY_QVGA},
+ {"priv", CAMCORDER_QUALITY_PRIV},
{"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW},
{"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH},
--- a/frameworks/av/media/libmedia/include/media/MediaProfiles.h
+++ b/frameworks/av/media/libmedia/include/media/MediaProfiles.h
@@ -34,7 +34,8 @@ enum camcorder_quality {
CAMCORDER_QUALITY_1080P = 6,
CAMCORDER_QUALITY_QVGA = 7,
CAMCORDER_QUALITY_2160P = 8,
- CAMCORDER_QUALITY_LIST_END = 8,
+ CAMCORDER_QUALITY_PRIV = 9,
+ CAMCORDER_QUALITY_LIST_END = 9,
CAMCORDER_QUALITY_TIME_LAPSE_LIST_START = 1000,
CAMCORDER_QUALITY_TIME_LAPSE_LOW = 1000,
--- a/frameworks/base/media/java/android/media/CamcorderProfile.java
+++ b/frameworks/base/media/java/android/media/CamcorderProfile.java
@@ -95,9 +96,11 @@ public class CamcorderProfile
*/
public static final int QUALITY_2160P = 8;
+ public static final int QUALITY_PRIV = 9;
+
// Start and end of quality list
private static final int QUALITY_LIST_START = QUALITY_LOW;
- private static final int QUALITY_LIST_END = QUALITY_2160P;
+ private static final int QUALITY_LIST_END = QUALITY_PRIV;
默认CamcorderProfile类是没有QUALITY_PRIV这个变量的,需要在framework层添加
最后一步,添加MediaProfiles实例对象
--- a/device/qcom/msm8937_32go/media/media_profiles_8937.xml
+++ b/device/qcom/msm8937_32go/media/media_profiles_8937.xml
@@ -185,6 +185,18 @@
sampleRate="48000"
channels="2" />
</EncoderProfile>
+
+ <EncoderProfile quality="priv" fileFormat="mp4" duration="30">
+ <Video codec="h264"
+ bitRate="20000000"
+ width="810"
+ height="720"
+ frameRate="30" />
+ <Audio codec="aac"
+ bitRate="156000"
+ sampleRate="48000"
+ channels="2" />
+ </EncoderProfile>
<EncoderProfile quality="qcif" fileFormat="3gp" duration="30">
<Video codec="h264"
另外,需要说明一下,在list中添加了对应的项未必就能够显示出来,因为camerasetting会将VIDEO_QUALITY_TABLE中不存在的选项给过滤,另外,没有实例化CamcorderProfile的选项也会被去掉,可参考代码:
public static ArrayList<String> getSupportedVideoQualities(int cameraId,Parameters parameters) {
ArrayList<String> supported = new ArrayList<String>();
List<String> temp = sizeListToStringList(parameters.getSupportedVideoSizes());
Log.i(TAG,"strings " + temp);
for (String videoSize : temp) {
if (VIDEO_QUALITY_TABLE.containsKey(videoSize)) {
int profile = VIDEO_QUALITY_TABLE.get(videoSize);
if (CamcorderProfile.hasProfile(cameraId, profile)) {
supported.add(videoSize);
Log.i(TAG,"support " + videoSize);
}
}
}
Log.i(TAG,"supported " + supported);
return supported;
}
这也是为什么第一步需要往VIDEO_QUALITY_TABLE填充值的原因,另外,跟踪一下 mProfile = CamcorderProfile.get(mCameraId, quality);的调用流程
==>
CamcorderProfile.java
public static CamcorderProfile get(int cameraId, int quality) {
if (!((quality >= QUALITY_LIST_START &&
quality <= QUALITY_LIST_END) ||
(quality >= QUALITY_TIME_LAPSE_LIST_START &&
quality <= QUALITY_TIME_LAPSE_LIST_END) ||
(quality >= QUALITY_HIGH_SPEED_LIST_START &&
quality <= QUALITY_HIGH_SPEED_LIST_END) ||
(quality >= QUALITY_VENDOR_LIST_START &&
quality <= QUALITY_VENDOR_LIST_END))) {
String errMessage = "Unsupported quality level: " + quality;
throw new IllegalArgumentException(errMessage);
}
return native_get_camcorder_profile(cameraId, quality);
}
==>
android_media_MediaProfiles.cpp
static const JNINativeMethod gMethodsForCamcorderProfileClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_camcorder_profile", "(II)Landroid/media/CamcorderProfile;",
(void *)android_media_MediaProfiles_native_get_camcorder_profile},
{"native_has_camcorder_profile", "(II)Z",
(void *)android_media_MediaProfiles_native_has_camcorder_profile},
};
static jobject
android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject /* thiz */, jint id,
jint quality)
{
ALOGV("native_get_camcorder_profile: %d %d", id, quality);
if (!isCamcorderQualityKnown(quality)) {
jniThrowException(env, "java/lang/RuntimeException", "Unknown camcorder profile quality");
return NULL;
}
camcorder_quality q = static_cast<camcorder_quality>(quality);
int duration = sProfiles->getCamcorderProfileParamByName("duration", id, q);
int fileFormat = sProfiles->getCamcorderProfileParamByName("file.format", id, q);
int videoCodec = sProfiles->getCamcorderProfileParamByName("vid.codec", id, q);
int videoBitRate = sProfiles->getCamcorderProfileParamByName("vid.bps", id, q);
int videoFrameRate = sProfiles->getCamcorderProfileParamByName("vid.fps", id, q);
int videoFrameWidth = sProfiles->getCamcorderProfileParamByName("vid.width", id, q);
int videoFrameHeight = sProfiles->getCamcorderProfileParamByName("vid.height", id, q);
int audioCodec = sProfiles->getCamcorderProfileParamByName("aud.codec", id, q);
int audioBitRate = sProfiles->getCamcorderProfileParamByName("aud.bps", id, q);
int audioSampleRate = sProfiles->getCamcorderProfileParamByName("aud.hz", id, q);
int audioChannels = sProfiles->getCamcorderProfileParamByName("aud.ch", id, q);
// Check on the values retrieved
if (duration == -1 || fileFormat == -1 || videoCodec == -1 || audioCodec == -1 ||
videoBitRate == -1 || videoFrameRate == -1 || videoFrameWidth == -1 || videoFrameHeight == -1 ||
audioBitRate == -1 || audioSampleRate == -1 || audioChannels == -1) {
jniThrowException(env, "java/lang/RuntimeException", "Error retrieving camcorder profile params");
return NULL;
}
jclass camcorderProfileClazz = env->FindClass("android/media/CamcorderProfile");
jmethodID camcorderProfileConstructorMethodID = env->GetMethodID(camcorderProfileClazz, "<init>", "(IIIIIIIIIIII)V");
return env->NewObject(camcorderProfileClazz,
camcorderProfileConstructorMethodID,
duration,
quality,
fileFormat,
videoCodec,
videoBitRate,
videoFrameRate,
videoFrameWidth,
videoFrameHeight,
audioCodec,
audioBitRate,
audioSampleRate,
audioChannels);
}
==>
CamcorderProfile.java
private CamcorderProfile(int duration,
int quality,
int fileFormat,
int videoCodec,
int videoBitRate,
int videoFrameRate,
int videoWidth,
int videoHeight,
int audioCodec,
int audioBitRate,
int audioSampleRate,
int audioChannels) {
this.duration = duration;
this.quality = quality;
this.fileFormat = fileFormat;
this.videoCodec = videoCodec;
this.videoBitRate = videoBitRate;
this.videoFrameRate = videoFrameRate;
this.videoFrameWidth = videoWidth;
this.videoFrameHeight = videoHeight;
this.audioCodec = audioCodec;
this.audioBitRate = audioBitRate;
this.audioSampleRate = audioSampleRate;
this.audioChannels = audioChannels;
}
再跟踪sProfiles = MediaProfiles::getInstance实例
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 : xmlFiles) {
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 {
if (!strncmp(value, "/vendor/etc", strlen("/vendor/etc"))) {
AVMediaUtils::get()->getCustomProfileLocation(value,
PROPERTY_VALUE_MAX);
}
sInstance = createInstanceFromXmlFile(value);
}
CHECK(sInstance != NULL);
sInstance->checkAndAddRequiredProfilesIfNecessary();
sIsInitialized = true;
}
return sInstance;
}
这里就可以知道为什么最后需要更改xml文件了
MediaProfiles.h
static constexpr char const * const xmlFiles[] = {
"vendor/etc/media_profiles_V1_0.xml",
"system/etc/media_profiles.xml"
};
编译生成规则
image.png
可查看下xml内容:
<MediaSettings>
<!-- Each camcorder profile defines a set of predefined configuration parameters -->
<!-- Back Camera -->
<CamcorderProfiles cameraId="0">
<EncoderProfile quality="low" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="192000"
width="176"
height="144"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="high" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="20000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="156000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="qvga" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="512000"
width="320"
height="240"
frameRate="30" />
<Audio codec="aac"
bitRate="156000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="cif" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="720000"
width="352"
height="288"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
.....
最终使用的xml文件为media_profiles_vendor.xml,为方便调试,可直接使用该文件进行替换
网友评论