【Camera專題】Qcom-如何修改Camera預覽、拍照、視訊時支援的解析度

c楓_擼碼的日子發表於2019-03-05

一.知識點

如何在預覽、拍照、錄製視訊時,提供一組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!

相關文章