开发者

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

开发者 https://www.devze.com 2022-12-29 10:18 出处:网络 作者: 慢慢529
目录一、Media FrameWork背景二、Media Framework“路线图”2.1 代理端2.2 服务端2.2.1 Sourcphpe2.2.2 Decoder2.2.3 Renderer2.2.4 Foundation2.3 OMX端2.4 Kernel端三、media播放的流程四、Media FrameW
目录
  • 一、Media FrameWork背景
  • 二、Media Framework“路线图”
    • 2.1 代理端
    • 2.2 服务端
      • 2.2.1 Sourcphpe
      • 2.2.2 Decoder
      • 2.2.3 Renderer
      • 2.2.4 Foundation
    • 2.3 OMX端
      • 2.4 Kernel端
      • 三、media播放的流程
        • 四、Media FrameWork源码分析

          一、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”登场了。让我们来看看它的庐山真面目, 如图所示:

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

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

          2.1 代理端

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

          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在这里实例化了一个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* statehttp://www.devze.com) = 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的资料请关注我们其它相关文章!

          0

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          关注公众号