首页 > 编程语言 >Android Media Framework(六)插件式编程与OMXStore

Android Media Framework(六)插件式编程与OMXStore

时间:2024-06-16 11:46:11浏览次数:26  
标签:插件 plugin Media void Framework so PluginInterface OMXStore

必读:Android Media Framework - 开篇

OpenMAX IL Spec阅读到上一节就结束了,这一节开始正式进入到Framework阅读阶段,我们将了解OpenMAX框架是如何与Android Framework连接的。

1、插件式编程

插件式编程(Plugin-based Programming)是一种软件开发模式,它允许开发者通过编写独立的、可插拔的模块(称为插件)来扩展应用程序的功能,而无需修改应用程序的核心代码。这种模式使得软件具有高度可扩展性、可维护性和灵活性。

插件式编程的核心思想是将应用程序的核心功能与扩展功能分离开来。核心功能负责提供基本的、必要的服务,而扩展功能则通过插件的形式添加到应用程序中,以提供额外的、可选的功能。

如何实现插件式编程?

  • 定义插件接口:定义插件需要实现的接口,明确应用程序调用插件的方式。

  • 编写插件:根据接口规范编写插件代码,实现所需的功能。

  • 加载和卸载插件:在应用程序中编写代码来动态地加载和卸载插件。

  • 调用插件功能:在应用程序中通过接口调用插件提供的功能。

举一个简单的例子:

首先定义插件需要实现的接口PluginInterface:

// PluginInterface.h
#ifndef PLUGIN_INTERFACE_H
#define PLUGIN_INTERFACE_H

class PluginInterface {
public:
    virtual void execute() = 0;
};

// 应用程序调用插件的方式
typedef PluginInterface* (*CreatePluginFunc)();
typedef void (*DestroyPluginFunc)(PluginInterface*);

#endif // PLUGIN_INTERFACE_H

接着实现两个插件,这里贴出插件1的代码:

// MyPlugin_1.cpp 
#include <iostream>
#include "PluginInterface.h"

class MyPlugin1 : public PluginInterface {
public:
    void execute() override {
        std::cout << "MyPlugin 1 executing!" << std::endl;  
    }
};

extern "C" PluginInterface* createPlugin() {
    std::cout << "create MyPlugin 1!" << std::endl;
    return new MyPlugin1();
}

extern "C" void destroyPlugin(PluginInterface* plugin) {
    std::cout << "delete MyPlugin 1!" << std::endl;
    delete plugin;
}

注意extern "C",这是为了确保C++的name mangling(名称修饰)不会影响这些函数的名称,从而能够准确获取到动态库中的函数。

最后是主程序加载卸载插件、调用插件功能:

// main.cpp
#include <iostream>
#include <dlfcn.h>
#include "PluginInterface.h"

static int loadAndExec(const char *libname) {
    void* handle = dlopen(libname, RTLD_LAZY); 
    if (!handle) {
        std::cout << "Cannot open library : " << libname << std::endl;  
        return -1;
    } 

    CreatePluginFunc createPlugin = (CreatePluginFunc)dlsym(handle, "createPlugin");
    if (!createPlugin) {
        std::cout << "Cannot load symbol 'createPlugin' of library "<< libname << std::endl;
        dlclose(handle);
        handle = NULL;
        return -1;
    }

    DestroyPluginFunc destroyPlugin = (DestroyPluginFunc)dlsym(handle, "destroyPlugin");
    if (!destroyPlugin) {
        std::cout << "Cannot load symbol 'destroyPlugin' of library "<< libname << std::endl;
        dlclose(handle);
        handle = NULL;
        return -1;
    }

    PluginInterface* plugin = createPlugin();
    plugin->execute();
    destroyPlugin(plugin);
    plugin = NULL;

    dlclose(handle);
    handle = NULL;
    return 0;
}

int main() {
    loadAndExec("./libMyPlugin_1.so");
    loadAndExec("./libMyPlugin_2.so");
    return 0;
}

代码执行结果

./test
// create MyPlugin 1!
// MyPlugin 1 executing!
// delete MyPlugin 1!
// create MyPlugin 2!
// MyPlugin 2 executing!
// delete MyPlugin 2!

在该示例中,MyPlugin1和MyPlugin2分别被编译为libMyPlugin_1.so和libMyPlugin_2.so,使用这两个插件时要用dlopen打开动态库,用dlsym获取预定义的函数。如果想用动态链接的方式链接这两个lib,由于包含同名函数,编译时就会出错了。

代码下载:公众号后台回复PluginDemo。

2、OMXStore

为了让芯片厂商能够在不修改原生代码的情况下使用硬件编解码组件,Android采用了插件式编程技术来动态加载厂商的实现。

代码参考:frameworks/av/media/libstagefright/omx/OMXStore.cpp

OMXStore::OMXStore() {
    // ......
    addVendorPlugin();
    addPlatformPlugin();
}

OMXStore的构造函数调用了两个方法:

  • addPlatformPlugin:添加平台插件,平台指的是Android系统自带/内置的;
  • addVendorPlugin:添加厂商实现的插件,厂商指的各大芯片厂商,即OMX组件实现者;
void OMXStore::addVendorPlugin() {
    addPlugin("libstagefrighthw.so");
}

void OMXStore::addPlatformPlugin() {
    addPlugin("libstagefright_softomx_plugin.so");
}

展开两个方法可以看到,OMXStore想要加载两个lib,libstagefright_softomx_plugin.so由Android平台提供,libstagefrighthw.so由厂商实现。libstagefrighthw.so应该如何实现呢?带着这个问题往下看addPlugin:

void OMXStore::addPlugin(const char *libname) {
    // 1.
    if (::android::base::GetIntProperty("vendor.media.omx", int64_t(1)) == 0) {
        return;
    }
    // 2. 打开lib
    void *libHandle = android_load_sphal_library(libname, RTLD_NOW);

    if (libHandle == NULL) {
        return;
    }
    // 3. 获取lib中的createOMXPlugin函数指针
    typedef OMXPluginBase *(*CreateOMXPluginFunc)();
    CreateOMXPluginFunc createOMXPlugin =
        (CreateOMXPluginFunc)dlsym(
                libHandle, "createOMXPlugin");
    if (!createOMXPlugin)
        createOMXPlugin = (CreateOMXPluginFunc)dlsym(
                libHandle, "_ZN7android15createOMXPluginEv");

    // 4. 
    OMXPluginBase *plugin = nullptr;
    if (createOMXPlugin) {
        plugin = (*createOMXPlugin)();
    }
    // 5. 
    if (plugin) {
        mPlugins.push_back({ plugin, libHandle });
        // 6
        addPlugin(plugin);
    } else {
        android_unload_sphal_library(libHandle);
    }
}

关注公众号《青山渺渺》阅读全文

image

标签:插件,plugin,Media,void,Framework,so,PluginInterface,OMXStore
From: https://www.cnblogs.com/rongmiao/p/18250368

相关文章

  • Android Media Framework(六)插件式编程与OMXStore
    OpenMAXILSpec阅读到上一节就结束了,这一节开始正式进入到Framework阅读阶段,我们将了解OpenMAX框架是如何与AndroidFramework连接的。1、插件式编程插件式编程(Plugin-basedProgramming)是一种软件开发模式,它允许开发者通过编写独立的、可插拔的模块(称为插件)来扩展应用......
  • Android Media Framework(五)Tunnel Mode
    本篇将聚焦AndroidTunnelMode,详细解析组件之间隧道连接过程、数据传递过程、组件销毁过程。通过阅读本篇内容,我们应能对tunneled组件的连接过程和buffer分配过程有所了解。1、TunnelMode介绍ILSpec详细描述了TunnelComponent的实现方式,但内容较为晦涩难懂,网上相关......
  • 安装ZLMediaKit流媒体服务器
    1安装ZLMediaKit#更新安装源sudoapt-getupdate#安装编译器sudoapt-getinstallbuild-essential#安装cmakesudoapt-getinstallcmake#安装依赖库(必选)sudoapt-getinstalllibssl-dev#安装依赖库(可选)sudoapt-getinstallffmpegsudoapt-getinstalll......
  • C# .NET Framework 4.0 异步
    .NETFramework4.0只能用Task.Factory.StartNew()4.0以上的则可以直接使用Task.Run()。Task.Factory.StartNew(()=>{})usingSystem;usingSystem.Threading;usingSystem.Threading.Tasks;usingMicrosoft.VisualStudio.TestTools.UnitTesting;namespacecom._80comm......
  • 本地搭建halo模板和插件开发简要步骤
    1.新建local配置文件,加载本地插件工程目录halo:plugin:runtime-mode:developmentfixed-plugin-path:#配置为插件绝对路径#-D:\myproject\hellodev\plugin-ylpro-D:\myproject\hellodev\plugin-links2.插件工程编写好处理模板的代码3.编......
  • 醒醒吧!你们的Stable Diffusion都用错了!【table Diffusion必装插件使用攻略】让你的AI
    哈喽,大家好,我是AI极客菌,今天给大家分享一下StableDiffusion的插件使用攻略。一、什么是插件StableDiffusion的插件主要是用来丰富SD的一些功能,例如C站助手,提示词助手,图片信息助手等插件都是为了增强SD的实用性。二、安装插件我们以C站助手为例,C站助手可以将从C站(civi......
  • Docker+Jenkins+Pipline如何获取git插件环境变量(提交sha、分支等)以及Jenkinsfile中
    场景Docker中部署Jenkins+Pipline流水线基础语法入门:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/139672283上面介绍了环境搭建以及Pipeline的Jenkinsfile的常用写法。如果需要通过Jenkins插件获取git相关的信息,比如上一次提交的SHA,分支名称等信息,然后需要输......
  • 【Stable Diffusion】最新SD换脸插件ReActor,视频换脸全流程!流畅丝滑!【附插件及安装报
    今天,我给大家分享一个使用“ReActor”插件来进行视频换脸的案例。视频换脸的思路其实也很简单,其实就是把视频的每一帧都提取出来,然后把每一帧的图片都进行换脸,最后重新把这些图片重新合成一个视频。废话不多说,我们先来看看效果:生成效果原视频如下:杨幂:最后的效果:......
  • 记录两个群音视频开源框架LiveKit和mediasoup
    mediasoup: https://github.com/versatica/mediasoupliveKit: https://github.com/livekit/livekit 为开发者提供的实时视频、音频和数据传输解决方案LiveKit是一个开源项目,基于WebRTC提供可扩展的多用户会议功能。它旨在为您的应用构建实时视频、音频和数据交互能力提......
  • 自定义MyBatis插件
    插件原理回顾在前面,我们通过MyBatis插件机制介绍与原理分析了MyBatis插件的基本原理,但是可能还只是理论上的分析,没有实战的锻炼可能理解的还是不够透彻。接下来,我们通过自定义插件实例来进一步深度理解MyBatis插件的插件机制。插件接口MyBatis插件接口-Interceptor有......