一.知识点
如何在预览、拍照、录制视频时,提供一组1080*960的新分辨率。
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/pipeline/mct_pipeline.c
//预览
static cam_dimension_t default_preview_sizes[] = {
···
+{1080 , 960},// 100w (9:8)
···
}
//拍照
static cam_dimension_t default_picture_sizes[] = {
···
+{1080 , 960},// 100w (9:8)
···
}
//动态照片
static cam_dimension_t default_liveshot_sizes[] = {
···
+{1080 , 960},// 100w (9:8)
···
}
//视频
static cam_dimension_t default_video_sizes[] = {
···
+{1080 , 960},// 100w (9:8)
···
}
二、遇到的问题:MediaRecorder: start failed: -19
添加{1080 , 960}这组参数,出现录制视频失败的现象。
log分析:
StagefrightRecorder: Intended video encoding frame height (960) is too large and will be set to (720)
E CameraSource: Video dimension (1080x720) is unsupported
D mm-camera-intf: mm_stream_read_msm_frame: VIDIOC_DQBUF buf_index 5, frame_idx 62, stream type 7, queued cnt 6
D mm-camera-intf: mm_stream_qbuf: VIDIOC_QBUF buf_index 5,stream type 7,frame_idx 62,queued cnt 7
/com.xtc.i3launcher E/MediaRecorder: start failed: -19
/com.xtc.i3launcher E/VideoRecordManager: startRecorder e = java.lang.RuntimeException: start failed.
/com.xtc.i3launcher E/MediaRecorder: stop called in an invalid state: 0
/com.xtc.i3launcher E/VideoRecordManager: stopRecorder e = java.lang.IllegalStateException
/com.xtc.i3launcher E/Camera FW: release=
/com.xtc.i3launcher E/MediaPlayer-JNI: JNIMediaPlayerFactory: bIsQCMediaPlayerPresent 0
/com.xtc.i3launcher E/MediaPlayer-JNI: JNIMediaPlayerFactory: bIsQCMediaPlayerPresent 0
/com.xtc.i3launcher E/MediaPlayer: Unable to create media player
/com.xtc.i3launcher E/VideoPlayManager: playVideo java.io.IOException: setDataSourceFD failed.: status=0x80000000
从log中看,系统目前限制了最大frame height=720,原先设置的(1080,960)被强制改成(1080,720),
而在default_video_sizes又没添加{1080 , 720}这组参数支持,因此导致了录制失败!!!
//视频
static cam_dimension_t default_video_sizes[] = {
···
+{1080 , 960},// 100w (9:8)
···
}
那么在哪里改动最大frame height=720这个值呢?
三、源码跟踪分析
frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp
这里是打印log的地方,我们跟进这个maxFrameHeight变量,
int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
“enc.vid.height.max”, mVideoEncoder);
继续跟进getVideoEncoderParamByName函数
frameworks/av/media/libmedia/MediaProfiles.cpp
这个mMaxFrameHeight是从mVideoEncoders[index]数组中拿到的,
frameworks/av/include/media/MediaProfiles.h
Vector<VideoEncoderCap*> mVideoEncoders;
而mVideoEncoders本质上是一个Vector向量数组,继续看VideoEncoderCap
frameworks/av/media/libmedia/MediaProfiles.cpp
VideoEncoderCap的初始化在MediaProfiles::createVideoEncoderCap函数中,
mMaxFrameHeight就是在这里赋值的,
mMaxFrameHeight = atoi(atts[15]);(atoi是把字符串转成init)。
那么继续跟进这个atts参数是从哪里传进来的。
调用流程如下:
//frameworks/av/media/libstagefright/MediaCodecList.cpp
void MediaCodecList::parseXMLFile(const char *path) {
FILE *file = fopen(path, "r");
···
XML_Parser parser = ::XML_ParserCreate(NULL);
CHECK(parser != NULL);
::XML_SetUserData(parser, this);
::XML_SetElementHandler(
parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
···
}
//frameworks/av/media/libstagefright/MediaCodecList.cpp
void MediaCodecList::StartElementHandlerWrapper(
void *me, const char *name, const char **attrs) {
static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs);
}
//frameworks/av/media/libmedia/MediaProfiles.cpp
MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts) {
···
profiles->mVideoEncoders.add(createVideoEncoderCap(atts));
···
}
从流程可以看出atts是从xml文件解析出来的,因此,把路径给打印出来
//frameworks/av/media/libstagefright/MediaCodecList.cpp
void MediaCodecList::parseXMLFile(const char *path) {
FILE *file = fopen(path, "r");
++ALOGW("zcf: open media codecs configuration xml file: %s", path);
···
XML_Parser parser = ::XML_ParserCreate(NULL);
···
}
这个路径是保存在系统下的,最终应该是通过配置Android.mk文件copy到/etc/这个路径下的,
事实上,最终定位:
device/qcom/[平台]/media/media_profiles_8909.xml
<VideoEncoderCap name="h264" enabled="true"
minBitRate="64000" maxBitRate="14000000"
minFrameWidth="176" maxFrameWidth="1280"
- minFrameHeight="144" maxFrameHeight="720"//这里就是720最大值
+ minFrameHeight="144" maxFrameHeight="1080"//改动成需要的值
minFrameRate="15" maxFrameRate="30"
maxHFRFrameWidth="800" maxHFRFrameHeight="480"
maxHFRMode="60" />