Android多媒體框架--19:OMX服務(wù)啟動

"本文轉(zhuǎn)載自:[VNanyesheshou]的Android MultiMedia框架——OMX服務(wù)啟動"

1.概述

??hw/android.hardware.media.omx@1.0-service和audioserver進(jìn)程類似,也是通過init進(jìn)程加載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服務(wù)流程圖如下:

01.png

看一下其內(nèi)部實現(xiàn):

  • main_codecservice.cpp
int main(int argc __unused, char** argv)
{
    //(1)修改進(jìn)程名
    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)定制編解碼器服務(wù)
    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)默認(rèn)codec services
        using namespace ::android::hardware::media::omx::V1_0;
        //(4)創(chuàng)建OmxStore,并注冊服務(wù)
        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)創(chuàng)建Omx啸箫,并注冊服務(wù)
        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();
}

上述代碼主要實現(xiàn)了以下操作:
(1)strcpy修改進(jìn)程名為media.codec耸彪;修改后的進(jìn)程信息為:

mediacodec 910 1 1 19:08:07 ? 00:00:00 media.codec hw/android.hardware.media.omx@1.0-service

(2)加載libmedia_codecserviceregistrant.so,判斷是否有定制編解碼器服務(wù)忘苛;
(3)默認(rèn)codec services蝉娜;
(4)創(chuàng)建OmxStore,并注冊服務(wù)扎唾;
(5)創(chuàng)建Omx召川,并注冊服務(wù)。

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中狐榔,通過日志觀察下大致數(shù)據(jù):

(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() {
}

這里創(chuàng)建了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 添加廠商實現(xiàn)的硬件編碼 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函數(shù)咐蚯,并調(diào)用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循環(huán)plugin中的components弄贿,并將name 和plugin對應(yīng)關(guān)系保存在在向量mPluginByComponentName中春锋。

3.2 Soft軟件plugin

??addPlugin(new SoftOMXPlugin)對應(yīng)上述函數(shù),加載其包含的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.總結(jié)

??omx service啟動主要創(chuàng)建OmxStore和Omx兩個服務(wù)期奔,加載解析media_codec相關(guān)配置文件,添加硬件危尿、軟件插件呐萌,并保存plugin與支持的component對應(yīng)關(guān)系。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谊娇,一起剝皮案震驚了整個濱河市肺孤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖渠旁,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攀例,死亡現(xiàn)場離奇詭異,居然都是意外死亡顾腊,警方通過查閱死者的電腦和手機(jī)粤铭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杂靶,“玉大人梆惯,你說我怎么就攤上這事÷鹂澹” “怎么了垛吗?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烁登。 經(jīng)常有香客問我怯屉,道長,這世上最難降的妖魔是什么饵沧? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任锨络,我火速辦了婚禮,結(jié)果婚禮上狼牺,老公的妹妹穿的比我還像新娘羡儿。我一直安慰自己,他們只是感情好是钥,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布掠归。 她就那樣靜靜地躺著,像睡著了一般悄泥。 火紅的嫁衣襯著肌膚如雪虏冻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天弹囚,我揣著相機(jī)與錄音兄旬,去河邊找鬼。 笑死余寥,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悯森。 我是一名探鬼主播宋舷,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓢姻!你這毒婦竟也來了祝蝠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绎狭,沒想到半個月后细溅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡儡嘶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年喇聊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹦狂。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡誓篱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凯楔,到底是詐尸還是另有隱情窜骄,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布摆屯,位于F島的核電站邻遏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏虐骑。R本人自食惡果不足惜准验,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望富弦。 院中可真熱鬧沟娱,春花似錦、人聲如沸腕柜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盏缤。三九已至砰蠢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間唉铜,已是汗流浹背台舱。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留潭流,地道東北人竞惋。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像灰嫉,于是被迫代替她去往敵國和親拆宛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容