iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android音视频开发MediaFrameWork框架源码解析
  • 334
分享到

Android音视频开发MediaFrameWork框架源码解析

Android音视频MediaFrameWorkAndroidMediaFrameWork 2022-12-28 18:12:02 334人浏览 薄情痞子
摘要

目录一、Media FrameWork背景二、Media Framework“路线图”2.1 代理端2.2 服务端2.2.1 Source2.2.2 Deco

一、Media FrameWork背景

Media Framework (媒体函数库):此函数库让Android 可以播放与录制许多常见的音频与视频文件,支持的文件类型包括MPEG4、H.264、MP3、AAC、AMR、JPG 与PNG 等。 Surface Manager (外观管理函数库):管理图形界面的操作与2D、3D 图层的显示。

二、Media Framework“路线图”

我们可以看到用红色框框圈起来的地方。一个是app应用Gallery(也可以为第三方player);另外一个是Media Framework。对,没错,讲了这么多,我们的主角“Media Framework”登场了。让我们来看看它的庐山真面目, 如图所示:

接下来,给大家简单介绍下它。看的顺序是→ ↓ ← ↓ →(肿么都觉得是在打表情符号:-D)

2.1 代理端

这一端做的事情只是将下面复杂的逻辑进行封装(java),然后透过jni调用底下的native层方法来实现具体功能。并且,这些个具体的功能是在服务端实现的,他们分属不同的进程,通过Binder来通信,最终通过调用服务端的方法实现具体的逻辑处理。(有童鞋问:Binder是个什么东东呢? 小弟有时间会讲解的,现在就理解它是一个进程间通信的一种方式就好,求甚解的朋友们可以百度下_)

2.2 服务端

这边的主要任务就是在MediaPlayerFactory中,创建出NuplayerDriver(这个不是底层驱动啦,我们理解为一个抽象出来的NuPlayer的基类就好啦)。 然后Nuplayer中,我们可以看到有三大模块。

2.2.1 Source

这里是为咱们的播放器提供数据源的(解协议,解封装在这里)。

2.2.2 Decoder

这里是解码数据的地方(解码在这里)

2.2.3 Renderer

这里是用来做Display的,里面涉及到A/V同步的问题。

2.2.4 Foundation

这个部分是基础类。在后面的分析当中,我们会知道在NuPlayer中会启动相当多的线程,这些线程如何异步/同步的通信,需要依靠AMessage/ALooper/AHandler来支持

之后, 通过接口类IOMX来通过Binder进程间通信,远程调用具体的decoder来实现解码。

2.3 OMX端

这一端就比较靠近底层了,里面会有各种各样的插件注册其中。它还链接这Codec Driver,这里面就是放的各种具体的解码器啦。

2.4 Kernel端

最后, OMX的具体解码器在启动Kernel层的A/V Codec Driver完成解码操作。

三、media播放的流程

在framework中涉及media播放的流程头文件如下:IMediaPlayer.h mediaplayer.h IMediaPlayerClient.h

其中IMediaPlayer.h 定义了binder通信相关的接口。 定义了:

class BnMediaPlayer: public BnInterface
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};
​

IMediaPlayer.cpp 是binder通信接口的实现。

class BpMediaPlayer: public BpInterface; status_t BnMediaPlayer::onTransact();

mediaplayer.h 是定义binder通信的客户端。在mediaplayer.cpp中如下代码获取BpMediaPlayer:

status_t MediaPlayer::setDataSource(
        const char *url, const KeyedVector *headers)
{
    LOGV("setDataSource(%s)", url);
    status_t err = BAD_VALUE;
    if (url != NULL) {
        const sp& service(getMediaPlayerService());
        if (service != 0) {
            sp player(
                    service->create(getpid(), this, url, headers));
            err = setDataSource(player);
        }
    }
    return err;
}
​

服务端在MediaPlayerService中。在MediaPlayerService.h中如下定义:

class Client : public BnMediaPlayer 在MediaPlayerService.cpp中,create函数创建了BnMediaPlayer:

sp MediaPlayerService::create(
​
        pid_t pid, const sp& client, const char* url,
        const KeyedVector *headers)
{
    int32_t connId = Android_atomic_inc(&mNextConnId);
    sp c = new Client(this, pid, connId, client);
    LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
    if (NO_ERROR != c->setDataSource(url, headers))
    {
        c.clear();
        return c;
    }
    wp w = c;
    Mutex::Autolock lock(mLock);
    mClients.add(w);
    return c;
}

再来看一下MediaPlayer这个类的定义:

class MediaPlayer : public BnMediaPlayerClient, public virtual IMediaDeathNotifier{}

很奇怪:在binder通信的客户端又有了一个binder通信的服务端: BnMediaPlayerClient 在IMediaPlayerClient.h 中这个binder通信只有一个接口:

class IMediaPlayerClient: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaPlayerClient);​
    virtual void notify(int msg, int ext1, int ext2) = 0;
};

这个binder通信服务为谁提供呢?在回来看一下MediaPlayerServer中的create函数:

sp MediaPlayerService::create( pid_t pid, const sp& client, const char* url, const KeyedVector *headers)

客户端就在这里。这个binder通信的实质是一个消息回调函数。framework的media框架式一个双向binder通信框架。

以seek接口为例分析一下:

在mediaplayer.cpp 中调用seek 接口:

MediaPlayer (seek)->IMediaPlayer.cpp(bpMediaPlayer.cpp )->IMediaPlayer.cpp(bnMediaPlayer.cpp )

在这里其实已经达到了MediaPlayerServer中的client类。当底层的media 完成seek 以后会抛出来一消息,这个消息通过 const sp& client 通知给MediaPlayer。

在media相关的头文件中还有一个MediaPlayerInterface.h 。这个头文件定义了底层播放器的接口。

四、Media FrameWork源码分析

首先,针对android.media.MediaPlayer进行分析。

里面有很多native代码,我们找到native_setup这个jni调用,就可以找到整个框架的入口。

我们查看

android_media_MediaPlayer_native_setup@framworks/base/media/jni/android_media_MediaPlayer.cpp

`static` `void` `android_media_MediaPlayer_native_setup(
    JNIEnv *env, jobject thiz, jobject weak_this
    )``
    {
        ``  ``
    LOGV(``"native_setup"``);
        ``  ``sp mp = ``new` `MediaPlayer();
        ``  ``
        if` `(mp == NULL) {
        ``    ``
        jniThrowException(
            env, ``"java/lang/RuntimeException"``, 
            ``"Out of memory"``);
            ``    
            ``return``;
            ``  ``
            
        }
            ` `  ``
            // create new listener and give it to MediaPlayer
            ``  ``
            sp listener = ``new` `JNIMediaPlayerListener(
                env, thiz, weak_this);
                ``  ``
                mp->setListener(listener);
                ` `  ``
                // Stow our new c++ MediaPlayer in an opaque field in the Java object.
                ``  ``
                setMediaPlayer(env, thiz, mp);
                ``
        
    }
        `

从这里的这段代码我们可以看到,android在这里实例化了一个变量mp:MediaPlayer。

并且为其设置了一个listener:JNIMediaPlayerListener

在后面我们会看到对mp的调用,现在让我们先看看MediaPlayer是什么东东。

MediaPlayer@framworks/base/include/media/mediaplayer.h MediaPlayer@framworks/base/media/libmedia/mediaplayer.cpp

在这里我们终于找到了MediaPlayer:BnMediaPlayerClient:IMediaPlayerClient

原来他也是对Bind Native的一个封装,而他本身提供了很多方法用于访问,包括start等。下面是start的cpp代码:

status_t MediaPlayer::start()
{
    LOGV("start");
    Mutex::Autolock _l(mLock);
    if (mCurrentState & MEDIA_PLAYER_STARTED)
        return NO_ERROR;
    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
                    MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
        mPlayer->setLooping(mLoop);
        mPlayer->setVolume(mLeftVolume, mRightVolume);
        mCurrentState = MEDIA_PLAYER_STARTED;
        status_t ret = mPlayer->start();
        if (ret != NO_ERROR) {
            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
        } else {
            if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
                LOGV("playback completed immediately following start()");
            }
        }
        return ret;
    }
    LOGE("start called in state %d", mCurrentState);
    return INVALID_OPERATION;
}

原来这里又调用了mPlayer:sp

从这里我们发现最终的服务,还是由IMediaPlayer这个东西提供的,而IMediaPlayer@framworks/base/include/media/IMediaPlayer.h

实际上是如下定义的一个类,它继承了IInterface@framworks/base/include/binder/IInterface.h这个类(注意虽然名字是Interface,但是它确实是个类!:-))

class IMediaPlayer: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaPlayer);
    virtual void            disconnect() = 0;
    virtual status_t        setVideoSurface(const sp<ISurface>& surface) = 0;
    virtual status_t        prepareAsync() = 0;
    virtual status_t        start() = 0;
    virtual status_t        stop() = 0;
    virtual status_t        pause() = 0;
    virtual status_t        isPlaying(bool* state) = 0;
    virtual status_t        seekTo(int msec) = 0;
    virtual status_t        getCurrentPosition(int* msec) = 0;
    virtual status_t        getDuration(int* msec) = 0;
    virtual status_t        reset() = 0;
    virtual status_t        setAudiOStreamType(int type) = 0;
    virtual status_t        setLooping(int loop) = 0;
    virtual status_t        setVolume(float leftVolume, float rightVolume) = 0;
    virtual status_t        invoke(const Parcel& request, Parcel *reply) = 0;
    virtual status_t        setMetadataFilter(const Parcel& filter) = 0;
    virtual status_t        getMetadata(bool update_only,
                                        bool apply_filter,
                                        Parcel *metadata) = 0;
};

为了弄清楚,在什么地方产生的mPlayer,我转而分析MediaPlayerService@framworks/base/media/libmediaplayerservice/MediaPlayerService.h

其中有如下代码

virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid);
void    removeMediaRecorderClient(wp<MediaRecorderClient> client);
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
// House keeping for media player clients
virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url);
virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);

原来在这个地方会创建你sp对象。

以上就是Android音视频开发Media FrameWork框架源码解析的详细内容,更多关于Android音视频Media FrameWork的资料请关注编程网其它相关文章!

--结束END--

本文标题: Android音视频开发MediaFrameWork框架源码解析

本文链接: https://www.lsjlt.com/news/176130.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android音视频开发MediaFrameWork框架源码解析
    目录一、Media FrameWork背景二、Media Framework“路线图”2.1 代理端2.2 服务端2.2.1 Source2.2.2 Deco...
    99+
    2022-12-28
    Android音视频Media FrameWork Android Media FrameWork
  • Android开发之音视频协议分析
    这篇文章主要介绍“Android开发之音视频协议分析”,在日常操作中,相信很多人在Android开发之音视频协议分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android开发之音视频协议分析”的疑惑有所...
    99+
    2023-06-30
  • Android 音视频开发—MediaPlayer音频与视频的播放介绍
    Android多媒体中的——MediaPlayer,我们可以通过这个API来播放音频和视频该类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最小的步骤来获取,解码和播放音视频。 它支持...
    99+
    2023-09-21
    android 音视频
  • Android音视频开发只硬件解码组件MediaCodec讲解
    目录一、介绍以及编解码流程二、生命周期三、API 接口五、封装(kotlin)一、介绍以及编解码流程 MediaCodec 类可用于访问低级媒体编解码器,即编码器/解码器组件。它是 ...
    99+
    2023-01-06
    Android MediaCodec Android 硬件解码组件 MediaCodec Android音视频
  • 解析Android框架之OkHttp3源码
    目录OkHttp流程图OkHttp基本使用OkHttp源码分析OkHttp流程图 OkHttp基本使用 gradle依赖 implementation 'com.squareup...
    99+
    2024-04-02
  • 解析Android框架之Volley源码
    目录Volley简单使用Volley执行原理Volley简单使用 我这里是以依赖架包的形式 ,大家也可以以gradle的形式进行依赖。 好了,接下来上代码了..... //获取...
    99+
    2024-04-02
  • Android开发之音视频协议介绍
    目录什么是视频文件什么是264了解音视频协议有啥用?两大电信联盟ITU-TISOITU-T 视频编码发展历程H.26X系列(由ITU[国际电传视讯联盟]主导)其他音视频协议Googl...
    99+
    2024-04-02
  • iOS 短视频源码开发MPMoviePlayerController
    文:布谷惠泽/来源:山东布谷鸟网络MPMoviePlayerController用来播放视频,在iOS9之后被弃用(iOS9之后苹果推荐我们使用AVPlayer,AVPlayer相对复杂但灵活),由于APP往往要兼容iOS9之前的版本,所有...
    99+
    2023-06-02
  • 基于ThinkPHP5框架开发的付费短视频魅思V20系统+APP源码+H5源码
    源码介绍 基于ThinkPHP5框架开发的付费短视频 魅思V20系统+APP源码+H5源码,支持三级分销功能,含有APP源码、H5源码,采用国内最流行的ThinkPHP5框架开发。 主要功能如下: 短视频APP:原生APP,支持安卓、苹果双...
    99+
    2023-09-12
    php mysql
  • Android音视频开发之MediaExtactor怎么使用
    本文小编为大家详细介绍“Android音视频开发之MediaExtactor怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android音视频开发之MediaExtactor怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢...
    99+
    2023-06-30
  • Android音视频开发之MediaPlayer使用教程
    目录MediaPlayer简单使用缺陷AndroidMediaPlayer播放器封装状态机编写内部类初始化函数方法和回调小结MediaPlayer Android多媒体框架支持播放提...
    99+
    2024-04-02
  • Android音视频开发之VideoView使用指南
    目录VideoView介绍MediaController使用源码分析进度显示播放尺寸适配VideoView介绍 之前介绍过使用MediaPlayer+SurfaceView实现播放视...
    99+
    2024-04-02
  • Android音视频开发中VideoView怎么使用
    这篇文章主要介绍“Android音视频开发中VideoView怎么使用”,在日常操作中,相信很多人在Android音视频开发中VideoView怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Andro...
    99+
    2023-06-30
  • Android音视频开发之MediaExtactor使用教程
    目录前言MediaExtactor使用MediaExtactor加载音视频文件代码获取轨道代码提取轨道数据信息一些源码细节分析前言 在之前学习如何使用MediaPlayer后,了解到...
    99+
    2024-04-02
  • Android音视频开发之MediaCodec的使用教程
    目录前言MediaCodec编解码流程生命周期接口简介前言 获取到音视频轨道(编解码格式),知道设备支持哪些编解码器,下一步就是创建编解码器去实现数据流的编解码过程了。在Androi...
    99+
    2024-04-02
  • 【Django】REST_Framework框架——视图集ViewSet和ModelViewSet源码解析
    一、ViewSet 继承APIView和ViewSetMixin; 作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。 ViewSet在开发接口中不经常用 1、ViewSet源...
    99+
    2023-09-12
    django python 后端
  • Android开发Retrofit源码分析
    目录项目结构retrofit 使用Retrofit #createServiceMethod #parseAnnotationsHttpServiceMethod#parseAnno...
    99+
    2024-04-02
  • Android开发中线程池源码解析
    线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了...
    99+
    2024-04-02
  • 怎么解析jQuery框架源码
    怎么解析jQuery框架源码,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。对于jQuery只停留在应用是可悲的,在做项目的过程,jquer...
    99+
    2024-04-02
  • JavaOkHttp框架源码深入解析
    目录1.OkHttp发起网络请求可以通过OkHttpClient发起一个网络请求通过Retrofit发起一个OkHttp请求2.OkHttp的连接器1.OkHttp发起网络请求 可以...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作