【Camera专题】Qcom-如何修改Camera预览、拍照、视频时支持的分辨率

1,665 阅读3分钟

一.知识点

如何在预览、拍照、录制视频时,提供一组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

image
这里是打印log的地方,我们跟进这个maxFrameHeight变量, int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.max", mVideoEncoder); 继续跟进getVideoEncoderParamByName函数 frameworks/av/media/libmedia/MediaProfiles.cpp
image
这个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);
···
}

image
这个路径是保存在系统下的,最终应该是通过配置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"  />

Stay Hungry,Stay Foolish!