文章目录
- 1 内容
- 2 加载及使用
-
- 2.1 文件加载log
- 2.2 解析文件
- 2.3 使用
- 3 小结
1 内容
文件路径:
code:android/device/qcom/msm8996(平台名)或者android/frameworks/av/media/libstagefright/data
设备:/vendor/etc/media_codecs.xml
<MediaCodec name="OMX.google.amrnb.encoder" type="audio/3gpp"><Limit name="channel-count" max="1" /><Limit name="sample-rate" ranges="8000" /><Limit name="bitrate" range="4750-12200" /><Feature name="bitrate-modes" value="CBR" /></MediaCodec>
定义当前设备所支持的编码器配置。
还有另一款"c2.android.amrnb.encoder"
2 加载及使用
2.1 文件加载log
2.2 解析文件
关于mediacodec.xml文件的解析,查看log可以发现有多处。
首先,存放media_codec.xml的文件夹有多个,所以会先查找对应的文件夹
然后,获取到了文件路径,对xml文件进行解析
重点是MediaCodecsXmlParser::parseXmlPath函数进行处理的。
最终调用到MediaCodecsXmlParser::Impl::Parser::parseXmlFile函数中,打开并遍历xml文件的节点,将xml文件中的数据存入parser中。
//处理xml文件
status_t MediaCodecsXmlParser::Impl::parseXmlPath(const std::string &path) {
std::lock_guard<std::mutex> guard(mLock);//1. 获取路径std::string vendorPath = getVendorXmlPath(path);// save state (even though we should always be at toplevel here)State::RestorePoint rp = mState.createRestorePoint();Parser parser(&mState, vendorPath);//2. 解析xml文件parser.parseXmlFile();mState.restore(rp);if (parser.getStatus() != OK) {
ALOGD("parseXmlPath(%s) failed with %s", vendorPath.c_str(), asString(parser.getStatus()));}mParsingStatus = combineStatus(mParsingStatus, parser.getStatus());return parser.getStatus();
}//获取文件路径
std::string getVendorXmlPath(const std::string &path) {
std::string vendorPath;std::string result = path;if (!strncmp(path.c_str(), "/vendor/etc/media_codecs.xml",strlen("/vendor/etc/media_codecs.xml"))) {
vendorPath = "/vendor/etc/media_codecs_vendor";} else if (!strncmp(path.c_str(), "/vendor/etc/media_codecs_performance.xml",strlen("/vendor/etc/media_codecs_performance.xml"))) {
vendorPath = "/vendor/etc/media_codecs_performance";}
}//解析xml文件
void MediaCodecsXmlParser::Impl::Parser::parseXmlFile() {
const char *path = mPath.c_str();ALOGD("parsing %s...", path);FILE *file = fopen(path, "r");mParser = std::shared_ptr<XML_ParserStruct>(::XML_ParserCreate(nullptr),[](XML_ParserStruct *parser) {
::XML_ParserFree(parser); });LOG_FATAL_IF(!mParser, "XML_MediaCodecsXmlParserCreate() failed.");::XML_SetUserData(mParser.get(), this);::XML_SetElementHandler(mParser.get(), StartElementHandlerWrapper, EndElementHandlerWrapper);static constexpr int BUFF_SIZE = 512;while (mStatus == OK) {
void *buff = ::XML_GetBuffer(mParser.get(), BUFF_SIZE);int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);XML_Status status = ::XML_ParseBuffer(mParser.get(), bytes_read, bytes_read == 0);}mParser.reset();fclose(file);
}
根据代码查看,发现是OmxStore::OmxStore调用的。
OmxStore::OmxStore(){
MediaCodecsXmlParser parser;parser.parseXmlFilesInSearchDirs(xmlNames, searchDirs);if (profilingResultsXmlPath != nullptr) {
parser.parseXmlPath(profilingResultsXmlPath);}mParsingStatus = toStatus(parser.getParsingStatus());
}
怀疑:
mediacodec创建的时候会执行MediaCodecList::getInstance,目前怀疑MediaCodecList应该会和omxstore有关联,代码后续继续追。
status_t MediaCodec::init(const AString &name, bool nameIsType) {
const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();for (const AString &codecName : {
name, tmp }) {
ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());mCodecInfo = mcl->getCodecInfo(codecIdx);}
}sp<IMediaCodecList> MediaCodecList::getInstance() {
sRemoteList = getLocalInstance();
}sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
MediaCodecList *codecList = new MediaCodecList(GetBuilders());
}
2.3 使用
先看下使用。
经过了mediaprofile的筛选,根据app传下来codec类型,匹配得到两个encoder,最终录制选择OMX.google.amrnb.encoder,选择哪个encoder应该是有一个打分机制,后续再追。
3 小结
目前只追到了OmxStore初始化的时候加载media_codec.xml文件,并存放到MediaCodecsXmlParser parser中。
根据log来看,实际使用的时候是再mediacodeclist中寻找匹配的encoder,所以怀疑最终omxstore会和mediacodeclist相关联,这个后续再追。