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

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。

链接:https://pan.baidu.com/s/1uVemskxHvOPJhDx8mv-6IQ
提取码:8888

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);
    }
}

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

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/714526.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaFX 概述

要从 JavaFX 中充分受益&#xff0c;了解 JavaFX 的设计方式以及对 JavaFX 包含的功能有一个很好的概述是很有用的。本文的目的是为您提供 JavaFX 概述。本文将首先介绍一般的 JavaFX 设计&#xff0c;然后介绍 JavaFX 中的各种特性。 如果您熟悉 Flash/Flex&#xff0c;您会发…

【后端】websocket学习笔记

文章目录 1. 消息推送常见方式1.1 轮询 VS 长轮询1.2 SSE&#xff08;server-sent event)服务器发送事件 2. websocket介绍2.1 介绍2.2 原理2.3 websoket API2.3.1 客户端【浏览器】API2.3.2 服务端API 3. 代码实现3.1 流程分析3.2 pom依赖3.3 配置类3.4 消息格式3.5 消息类 参…

【Css】纯css展开、收起超出的文本

效果 展开 收起 未超出 码 -webkit-line-clamp: 3; 设置限制行数 <div class"wrap"> <inputtype"checkbox"id"exp-txt"><div class"text"><labelfor"exp-txt"class"btn"></label&g…

纷享销客常见问题FAQ

运维和安全职责边界 应用专属是部署在客户私有云或者客户公有云租户的IT环境中的&#xff0c;由纷享销客与客户共同维护系统的稳定性。一般来说客户主要负责维护IT基础环境和账号权限的管理而纷享销客则负责在客户环境中进行应用系统的部署、优化和日常运维工作。在安全方面&am…

OrangePi AIpro 机器人仿真与人工智能应用测评

系列文章目录 前言 本篇文章分为2个部分&#xff0c;第一部分主要搭建了机器人的仿真环境&#xff08;ROS2 MuJoCo等&#xff09;&#xff0c;运行了机械臂及移动机器人相关示例程序&#xff1b;第二部分运行了OrangePi AIpro系统自带的示例程序及昇腾社区官方的示例程序&#…

马克·雷伯特访谈:机器人的未来及波士顿动力的创新之路

引言 机器人技术作为现代科技的前沿领域&#xff0c;始终吸引着大量的关注与研究。波士顿动力公司作为这一领域的领军者&#xff0c;其创始人兼前CEO马克雷伯特&#xff08;Marc Raibert&#xff09;近日在主持人莱克斯弗里德曼&#xff08;Lex Fridman&#xff09;的播客节目…

机器学习笔记 - 用于3D点云数据分割的Point Net的训练

一、数据集简述 ​在本教程中,我们将学习如何在斯坦福 3D 室内场景数据集 ( S3DIS )上训练 Point Net 进行语义分割。S3DIS 是一个 3D 数据集,包含来自多栋建筑的室内空间点云,占地面积超过 6000 平方米。Point Net使用整个点云,能够执行分类和分割任务。如果你一直在关注 …

【归并排序】| 详解归并排序核心代码之合并两个有序数组 力扣88

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️专栏&#xff1a;动态规划 &#x1f397;️如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/merge-sorted-array/description/ 本道题是归并排序的…

SNAT和DNAT策略

1、SNAT策略及应用 SNAT应用环境&#xff1a;局域网主机共享单个公网IP地址接入Internet&#xff08;私有不能在Internet中被正常路由&#xff09; SNAT原理&#xff1a; 修改数据包的源地址。 SNAT转换前提条件&#xff1a; 局域网各主机已正确设置IP地址、子网掩码、默认…

库的制作 与 使用 (Linux下)

目录 动静态库的制作 前置知识 库的基本构造 问题 分析 要给什么文件 如何更好的让别人使用 库的生成 静态库的生成 makefile参考 动态库的生成 makefile参考&#xff08;包含动态库和静态库生成&#xff09; 库的使用 法一&#xff1a;放入系统路径 弊端 法二…

Android开发系列:高性能视图组件Surfaceview

一、Surfaceview概述 在Android应用开发领域&#xff0c;面对视频播放、游戏构建及相机实时预览等高性能需求场景&#xff0c;直接操控图像数据并即时展示于屏幕成为必要条件。传统View组件在此类情境下显现局限性&#xff1a; 性能瓶颈&#xff1a;传统View的绘制任务由UI主…

如何充分利用 Postgres 的内存设置

为了充分利用 PostgreSQL 的内存设置&#xff0c;你需要调整多个参数以优化数据库性能。这些参数包括共享缓冲区&#xff08;shared_buffers&#xff09;、工作内存&#xff08;work_mem&#xff09;、维护工作内存&#xff08;maintenance_work_mem&#xff09;、有效缓存大小…

命令词:引导行动的语言工具

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

《全职猎人》

《全职猎人》 [1-2]是日本漫画家富坚义博的作品。 1999年版改编电视动画由日本动画公司负责动画制作&#xff0c;于1999年10月16日&#xff0d;2001年3月30日在富士电视台播出&#xff0c;该动画的故事至贪婪之岛篇章结束&#xff0c;全92话。 该作在富坚义博老师天马行空的想…

markupsafe,一个神奇的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个神奇的 Python 库 - markupsafe。 Github地址&#xff1a;https://github.com/pallets/markupsafe 在 Web 开发和模版渲染中&#xff0c;处理用户输入的数据时&#xff0c;防止 HTML 注入是至…

【Java】Object、Objects、包装类、StringBuilder、StringJoiner

目录 1.API2.Object类3.Objects类4.包装类4.1包装类概述4.2包装类的其他常见操作 5.StringBuilder 可变字符串5.1概述5.2StringBuilder案例 6.StringJoiner 1.API API&#xff1a;应用程序编程接口&#xff0c;全称application programing interface&#xff0c;即Java已经写好…

3分钟带手把手带你了解 FL Studio v21.2.3.4004 中文免费版(附中文设置教程)安装指南

3分钟带手把手带你了解 FL Studio v21.2.3.4004 中文免费版(附中文设置教程)安装指南&#xff0c;大家我是兔八哥爱分享&#xff0c;今天你带来的安装FL Studio 21破解版&#xff0c;纯正简体中文支持&#xff01; FL Studio 21 简称FL21&#xff0c;全称Fruity Loops Studio&a…

消息队列-Rabbit运行机制

Producer(生产者) 和 Consumer(消费者) Producer(生产者) :生产消息的一方&#xff08;邮件投递者&#xff09;Consumer(消费者) :消费消息的一方&#xff08;邮件收件人&#xff09; 消息一般由 2 部分组成&#xff1a;消息头&#xff08;或者说是标签 Label&#xff09;和 …

keystone认证服务

keystone认证服务 1、keystone管理用户 1-1、简介&#xff1a; 在OpenStack云计算平台中&#xff0c;Keystone是一个核心组件&#xff0c;主要用于提供统一的认证服务。其功能包括&#xff1a; 身份验证&#xff1a;Keystone负责验证用户的身份&#xff0c;通常通过用户名和…

记录一个flink跑kafka connector遇到的问题

【报错】 D:\Java\jdk1.8.0_231\bin\java.exe "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\lib\idea_rt.jar56647:D:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\bin" -Dfile.encodingUTF-8 -classpath D:\Java\jdk1.8.0_231\jre\lib\cha…