"本文转载自:[VNanyesheshou]的Android MultiMedia框架——OMX服务启动"
1.概述
hw/android.hardware.media.omx@1.0-service和audioserver进程类似,也是通过init进程加载rc文件的方式,启动service。rc配置文件:frameworks/av/services/mediacodec/android.hardware.media.omx@1.0-service.rc
service vendor.media.omx /vendor/bin/hw/android.hardware.media.omx@1.0-service
class main
user mediacodec
group camera drmrpc mediadrm
ioprio rt 4
writepid /dev/cpuset/foreground/tasks
OMX服务流程图如下:
01.png看一下其内部实现:
- main_codecservice.cpp
int main(int argc __unused, char** argv)
{
//(1)修改进程名
strcpy(argv[0], "media.codec");
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
android::ProcessState::initWithDriver("/dev/vndbinder");
android::ProcessState::self()->startThreadPool();
::android::hardware::configureRpcThreadpool(64, false);
//(2)定制编解码器服务
void *registrantLib = dlopen(
"libmedia_codecserviceregistrant.so",
RTLD_NOW | RTLD_LOCAL);
if (registrantLib) {
RegisterCodecServicesFunc registerCodecServices =
reinterpret_cast<RegisterCodecServicesFunc>(
dlsym(registrantLib, "RegisterCodecServices"));
if (registerCodecServices) {
registerCodecServices();
} else {
LOG(WARNING) << "Cannot register additional services "
"-- corrupted library.";
}
} else {
// Default codec services
// (3)默认codec services
using namespace ::android::hardware::media::omx::V1_0;
//(4)创建OmxStore,并注册服务
sp<IOmxStore> omxStore = new implementation::OmxStore();
if (omxStore == nullptr) {
LOG(ERROR) << "Cannot create IOmxStore HAL service.";
} else if (omxStore->registerAsService() != OK) {
LOG(ERROR) << "Cannot register IOmxStore HAL service.";
}
//(5)创建Omx,并注册服务
sp<IOmx> omx = new implementation::Omx();
if (omx == nullptr) {
LOG(ERROR) << "Cannot create IOmx HAL service.";
} else if (omx->registerAsService() != OK) {
LOG(ERROR) << "Cannot register IOmx HAL service.";
} else {
LOG(INFO) << "IOmx HAL service created.";
}
}
::android::hardware::joinRpcThreadpool();
}
上述代码主要实现了以下操作:
(1)strcpy修改进程名为media.codec;修改后的进程信息为:
mediacodec 910 1 1 19:08:07 ? 00:00:00 media.codec hw/android.hardware.media.omx@1.0-service
(2)加载libmedia_codecserviceregistrant.so,判断是否有定制编解码器服务;
(3)默认codec services;
(4)创建OmxStore,并注册服务;
(5)创建Omx,并注册服务。
2.OmxStore
查看OMXStore初始化方法:
OmxStore::OmxStore(
const char* owner,
const char* const* searchDirs,
const char* mainXmlName,
const char* performanceXmlName,
const char* profilingResultsXmlPath) {
MediaCodecsXmlParser parser(searchDirs,
mainXmlName,
performanceXmlName,
profilingResultsXmlPath);
mParsingStatus = toStatus(parser.getParsingStatus());
const auto& serviceAttributeMap = parser.getServiceAttributeMap();
mServiceAttributeList.resize(serviceAttributeMap.size());
size_t i = 0;
for (const auto& attributePair : serviceAttributeMap) {
ServiceAttribute attribute;
attribute.key = attributePair.first;
attribute.value = attributePair.second;
mServiceAttributeList[i] = std::move(attribute);
++i;
}
const auto& roleMap = parser.getRoleMap();
mRoleList.resize(roleMap.size());
i = 0;
//.......
mPrefix = parser.getCommonPrefix();
}
OMXStore初始化通过MediaCodecsXmlParser加载media_codecs.xml、media_codecs_performance.xml,并将信息保存在mServiceAttributeList、mRoleList中,通过日志观察下大致数据:
(1)mServiceAttributeList
attribute key: 'max-video-encoder-input-buffers', value: '11'
(2)mRoleList
03-19 19:53:19.510 D/OmxStore( 909): role:'audio_decoder.aac', type:audio/mp4a-latm, isEncoder:0, preferPlatformNodes:1
03-19 19:53:19.510 D/OmxStore( 909): node name:'OMX.google.aac.decoder', owner: default
03-19 19:53:19.510 D/OmxStore( 909): ----------------------
03-19 19:53:19.510 D/OmxStore( 909): role:'audio_decoder.amrnb', type:audio/3gpp, isEncoder:0, preferPlatformNodes:1
03-19 19:53:19.510 D/OmxStore( 909): node name:'OMX.google.amrnb.decoder', owner: default
03-19 19:53:19.510 D/OmxStore( 909): ----------------------
03-19 19:53:19.510 D/OmxStore( 909): role:'audio_decoder.amrwb', type:audio/amr-wb, isEncoder:0, preferPlatformNodes:1
03-19 19:53:19.510 D/OmxStore( 909): node name:'OMX.google.amrwb.decoder', owner: default
......
mPrefix 为 OMX。
下面再看一下media_codecs.xml文件:
<MediaCodecs>
<Include href="media_codecs_google_audio.xml" />
<Include href="media_codecs_google_telephony.xml" />
<Settings>
<Setting name="max-video-encoder-input-buffers" value="11" />
</Settings>
<Encoders>
<!-- Audio Hardware -->
<!-- Audio Software -->
<!-- Video Hardware -->
<MediaCodec name="OMX.qcom.video.encoder.avc" type="video/avc" >
<Quirk name="requires-allocate-on-input-ports" />
<Quirk name="requires-allocate-on-output-ports" />
<Quirk name="requires-loaded-to-idle-after-allocation" />
<Limit name="size" min="96x64" max="4096x4096" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-34560" /> <!-- max 4096x2160 -->
<Limit name="blocks-per-second" min="1" max="979200" />
<Limit name="bitrate" range="1-100000000" />
<Limit name="frame-rate" range="1-240" />
<Limit name="concurrent-instances" max="16" />
</MediaCodec>
//......
</Encoders>
<Decoders>
<!-- Video Hardware -->
<MediaCodec name="OMX.qcom.video.decoder.avc" type="video/avc" >
<Quirk name="requires-allocate-on-input-ports" />
<Quirk name="requires-allocate-on-output-ports" />
<Limit name="size" min="64x64" max="4096x4096" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-34560" /> <!-- max 4096x2160 -->
<Limit name="blocks-per-second" min="1" max="1958400" />
<Limit name="bitrate" range="1-100000000" />
<Feature name="adaptive-playback" />
<Limit name="concurrent-instances" max="16" />
</MediaCodec>
//..........
<!-- Audio Software -->
</Decoders>
<Include href="media_codecs_google_video.xml" />
</MediaCodecs>
3.Omx
查看Omx 初始化:
Omx::Omx() :
mMaster(new OMXMaster()),
mParser() {
}
这里创建了OMXMaster,xml 解析类。
(1)OMXMaster管理plugin,包括硬编码和软编码。
OMXMaster::OMXMaster()
: mVendorLibHandle(NULL) {
pid_t pid = getpid();
char filename[20];
snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
int fd = open(filename, O_RDONLY);
if (fd < 0) {
ALOGW("couldn't determine process name");
strlcpy(mProcessName, "<unknown>", sizeof(mProcessName));
} else {
ssize_t len = read(fd, mProcessName, sizeof(mProcessName));
if (len < 2) {
ALOGW("couldn't determine process name");
strlcpy(mProcessName, "<unknown>", sizeof(mProcessName));
} else {
// the name is newline terminated, so erase the newline
mProcessName[len - 1] = 0;
}
close(fd);
}
addVendorPlugin();
addPlugin(new SoftOMXPlugin);
}
- 读取processName,删除换行符;
xxx:/proc/924 # cat comm
omx@1.0-service
- addVendorPlugin 添加厂商实现的硬件编码 plugin;
- addPlugin(new SoftOMXPlugin) 添加软件编码 plugin。
3.1 Vendor硬件plugin
接着看addVendorPlugin:
void OMXMaster::addVendorPlugin() {
addPlugin("libstagefrighthw.so");
}
void OMXMaster::addPlugin(const char *libname) {
mVendorLibHandle = android_load_sphal_library(libname, RTLD_NOW);
if (mVendorLibHandle == NULL) {
return;
}
typedef OMXPluginBase *(*CreateOMXPluginFunc)();
CreateOMXPluginFunc createOMXPlugin =
(CreateOMXPluginFunc)dlsym(
mVendorLibHandle, "createOMXPlugin");
if (!createOMXPlugin)
createOMXPlugin = (CreateOMXPluginFunc)dlsym(
mVendorLibHandle, "_ZN7android15createOMXPluginEv");
if (createOMXPlugin) {
addPlugin((*createOMXPlugin)());
}
}
addVendorPlugin加载共享库libstagefrighthw.so,查找createOMXPlugin函数,并调用createOMXPlugin 获得OMXPluginBase类型对象。
OMXPluginBase *createOMXPlugin() {
return new QComOMXPlugin;
}
接着看addPlugin((*createOMXPlugin)()):
void OMXMaster::addPlugin(OMXPluginBase *plugin) {
Mutex::Autolock autoLock(mLock);
mPlugins.push_back(plugin);
OMX_U32 index = 0;
char name[128];
OMX_ERRORTYPE err;
while ((err = plugin->enumerateComponents(
name, sizeof(name), index++)) == OMX_ErrorNone) {
String8 name8(name);
if (mPluginByComponentName.indexOfKey(name8) >= 0) {
ALOGE("A component of name '%s' already exists, ignoring this one.",
name8.string());
continue;
}
mPluginByComponentName.add(name8, plugin);
}
if (err != OMX_ErrorNoMore) {
ALOGE("OMX plugin failed w/ error 0x%08x after registering %zu "
"components", err, mPluginByComponentName.size());
}
}
while循环plugin中的components,并将name 和plugin对应关系保存在在向量mPluginByComponentName中。
3.2 Soft软件plugin
addPlugin(new SoftOMXPlugin)对应上述函数,加载其包含的components。这里主要是获取其mName属性, 如下:
static const struct {
const char *mName;
const char *mLibNameSuffix;
const char *mRole;
} kComponents[] = {
// two choices for aac decoding.
// configurable in media/libstagefright/data/media_codecs_google_audio.xml
// default implementation
{ "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },
// alternate implementation
{ "OMX.google.xaac.decoder", "xaacdec", "audio_decoder.aac" },
{ "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },
{ "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },
{ "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" },
{ "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" },
{ "OMX.google.amrwb.encoder", "amrwbenc", "audio_encoder.amrwb" },
{ "OMX.google.h264.decoder", "avcdec", "video_decoder.avc" },
{ "OMX.google.h264.encoder", "avcenc", "video_encoder.avc" },
{ "OMX.google.hevc.decoder", "hevcdec", "video_decoder.hevc" },
{ "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" },
{ "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" },
{ "OMX.google.mpeg2.decoder", "mpeg2dec", "video_decoder.mpeg2" },
{ "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },
{ "OMX.google.h263.encoder", "mpeg4enc", "video_encoder.h263" },
{ "OMX.google.mpeg4.decoder", "mpeg4dec", "video_decoder.mpeg4" },
{ "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" },
{ "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
{ "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },
{ "OMX.google.opus.decoder", "opusdec", "audio_decoder.opus" },
{ "OMX.google.vp8.decoder", "vpxdec", "video_decoder.vp8" },
{ "OMX.google.vp9.decoder", "vpxdec", "video_decoder.vp9" },
{ "OMX.google.vp8.encoder", "vpxenc", "video_encoder.vp8" },
{ "OMX.google.vp9.encoder", "vpxenc", "video_encoder.vp9" },
{ "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },
{ "OMX.google.flac.decoder", "flacdec", "audio_decoder.flac" },
{ "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" },
{ "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" },
};
4.总结
omx service启动主要创建OmxStore和Omx两个服务,加载解析media_codec相关配置文件,添加硬件、软件插件,并保存plugin与支持的component对应关系。
网友评论