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


Vector<VideoEncoderCap*> mVideoEncoders;
複製程式碼
而mVideoEncoders本質上是一個Vector向量陣列,繼續看VideoEncoderCap frameworks/av/media/libmedia/MediaProfiles.cpp

那麼繼續跟進這個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);
···
}
複製程式碼

事實上,最終定位:
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" />
複製程式碼