• mediaplayer创建(一)


            想了安卓多媒体的整体流程整体流程,理清mediaplayer、mediaplayerservice、mediacodec、omx之间的关系,还是从自己写个最简单的demo跟下流程,mediaplayer的播放其实很简单,主要分为如下6个步骤,代码如下:

     

    (1)new 一个mediaplayer对象;

    (2)调用setDataSource接口,数据流不同入参不同;

    (3)调用setSurface给mediaplayer提供视频渲染区域有;

    (4)调用prepareAsync接口,异步准备视频播放

    (5)调用start,开始视频播放;

     (6)调用stop,结束视频播放;

    1. if(mediaPlayer == null){
    2. mediaPlayer = new MediaPlayer();
    3. }
    4. try {
    5. if(!path.isEmpty()) {
    6. mediaPlayer.setDataSource(path);
    7. mediaPlayer.setSurface(surfaceHolder.getSurface());
    8. mediaPlayer.prepareAsync();
    9. mediaPlayer.setOnPreparedListener(mediaOnPreparedListener);
    10. }
    11. } catch (IOException e) {
    12. e.printStackTrace();
    13. }

    将demo跑起来后,根据demo 看看mediaplay整个过程都做了什么。

    (1)先看MediaPlayer.java,先是加载了libmedia_jni.so, 看native_init的实现也只是初始化部分的动作,

    1. static {
    2. System.loadLibrary("media_jni");
    3. native_init();
    4. }
    1. private MediaPlayer(int sessionId) {
    2. super(new AudioAttributes.Builder().build(),
    3. AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER);
    4. Looper looper;
    5. if ((looper = Looper.myLooper()) != null) {
    6. mEventHandler = new EventHandler(this, looper);
    7. } else if ((looper = Looper.getMainLooper()) != null) {
    8. mEventHandler = new EventHandler(this, looper);
    9. } else {
    10. mEventHandler = null;
    11. }
    12. mTimeProvider = new TimeProvider(this);
    13. mOpenSubtitleSources = new Vector();
    14. AttributionSource attributionSource = AttributionSource.myAttributionSource();
    15. // set the package name to empty if it was null
    16. if (attributionSource.getPackageName() == null) {
    17. attributionSource = attributionSource.withPackageName("");
    18. }
    19. /* Native setup requires a weak reference to our object.
    20. * It's easier to create it here than in C++.
    21. */
    22. try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
    23. native_setup(new WeakReference(this), attributionSourceState.getParcel());
    24. }
    25. baseRegisterPlayer(sessionId);
    26. }

    看 Mediaplayer 也只是一些初始的行为。

    (2)setDataSource(MediaPlayer.java)->android_media_MediaPlayer_setDataSourceFD(android_media_MediaPlayer.cpp)->setDataSource(mediaplayer.cpp)-> setDataSource (IMediaPlayer.cpp), 如下是setDataSource的代码。看到如下代码应该就可以清楚为什么在mediaplayer后需要调用setDataSource,因为setDataSource 才是真正的开始创建播放器,这里也可以看到同mediaplayerservice的交互。

    1 const sp service(getMediaPlayerService()); 这一步其实是获取了BpMediaPlayerService 2 sp player(service->create(this, mAudioSessionId)); 这一步是通过BpMediaPlayerService 的create方法返回了BpMediaPlayer 3 attachNewPlayer 将player赋值给mPlayer

    1. status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
    2. {
    3. ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
    4. status_t err = UNKNOWN_ERROR;
    5. // 获取BpMediaPlayerService
    6. const sp service(getMediaPlayerService());
    7. if (service != 0) {
    8. //通过BpMediaPlayerService 的create方法返回了BpMediaPlayer
    9. sp player(service->create(this, mAudioSessionId, mAttributionSource));
    10. if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
    11. (NO_ERROR != player->setDataSource(fd, offset, length))) {
    12. player.clear();
    13. }
    14. //将player赋值给mPlayer
    15. err = attachNewPlayer(player);
    16. }
    17. return err;
    18. }
    1. IMediaDeathNotifier::getMediaPlayerService()
    2. {
    3. ALOGV("getMediaPlayerService");
    4. Mutex::Autolock _l(sServiceLock);
    5. if (sMediaPlayerService == 0) {
    6. sp sm = defaultServiceManager();
    7. sp binder;
    8. do {
    9. binder = sm->getService(String16("media.player"));
    10. if (binder != 0) {
    11. break;
    12. }
    13. ALOGW("Media player service not published, waiting...");
    14. usleep(500000); // 0.5 s
    15. } while (true);
    16. if (sDeathNotifier == NULL) {
    17. sDeathNotifier = new DeathNotifier();
    18. }
    19. binder->linkToDeath(sDeathNotifier);
    20. sMediaPlayerService = interface_cast(binder);
    21. }
    22. ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
    23. return sMediaPlayerService;
    24. }
    1. void MediaPlayerService::instantiate() {
    2. defaultServiceManager()->addService(
    3. String16("media.player"), new MediaPlayerService());
    4. }
    1. virtual sp create(
    2. const sp& client, audio_session_t audioSessionId,
    3. const AttributionSourceState& attributionSource) {
    4. Parcel data, reply;
    5. data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
    6. data.writeStrongBinder(IInterface::asBinder(client));
    7. data.writeInt32(audioSessionId);
    8. data.writeParcelable(attributionSource);
    9. remote()->transact(CREATE, data, &reply);
    10. return interface_cast(reply.readStrongBinder());
    11. }
    1. status_t BnMediaPlayerService::onTransact(
    2. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    3. {
    4. switch (code) {
    5. case CREATE: {
    6. CHECK_INTERFACE(IMediaPlayerService, data, reply);
    7. sp client =
    8. interface_cast(data.readStrongBinder());
    9. audio_session_t audioSessionId = (audio_session_t) data.readInt32();
    10. AttributionSourceState attributionSource;
    11. status_t status = data.readParcelable(&attributionSource);
    12. if (status != NO_ERROR) {
    13. return status;
    14. }
    15. sp player = create(client, audioSessionId, attributionSource);
    16. reply->writeStrongBinder(IInterface::asBinder(player));
    17. return NO_ERROR;
    18. } break;
    19. …………
    20. }
    21. }

    这一块也是C/S架构的核心,主要围绕C++层MediaPlayer通过BpMediaPlayerService这个proxy对象,经过IPC与远程服务端MediaPlayerService(BnMediaPlayerService)通信,完成C/S架构。(Bpxxx是一个代理外包,所有真正的工作是再Bnxxx里面做的,这里p指proxy,n指native, BpMediaPlayerService\BnMediaPlayerService都在IMediaPlayerService.cpp中实现)

    当Server端接受到Client端的请求,MediaPlayerService会为每一个Client进程创建一个会话,这里就是new一个MediaPlayer::Client对象与其交互,然后这个对象再根据Client端请求的资源类型去判断创建了什么类型的Player。在mediaplayerservice:create中,创建了一个MediaPlayerService::Client实例,也就是说,MediaPlayerService会为每个client应用程序创建一个相应的MediaPlayerServece::Client,来提供服务。也就是说,mediaplayer.cpp中执行的setDataSource函数,在MediaPlayerService.cpp中,实际上只是创建了一个client,并将两者对应起来,如果再次执行setDataSource函数,会创建第二个client。同时看这个函数的返回值类型,为sp,而在函数的最后,return c,这个c的类型是sp,从而从侧面也证明了两者几乎是等同的关系。

    1. sp MediaPlayerService::create(const sp& client,
    2. audio_session_t audioSessionId, const AttributionSourceState& attributionSource)
    3. {
    4. int32_t connId = android_atomic_inc(&mNextConnId);
    5. // TODO b/182392769: use attribution source util
    6. AttributionSourceState verifiedAttributionSource = attributionSource;
    7. verifiedAttributionSource.pid = VALUE_OR_FATAL(
    8. legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
    9. verifiedAttributionSource.uid = VALUE_OR_FATAL(
    10. legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
    11. sp c = new Client(
    12. this, verifiedAttributionSource, connId, client, audioSessionId);
    13. ALOGV("Create new client(%d) from %s, ", connId,
    14. verifiedAttributionSource.toString().c_str());
    15. wp w = c;
    16. {
    17. Mutex::Autolock lock(mLock);
    18. mClients.add(w);
    19. }
    20. return c;
    21. }

    再往回看mediaplayer.cpp的setDataSource,在service->create获取mediaplayerservice创建的

    client后执行player(即client)->setDataSource,这里才开始创建真正的player,在MediaPlayerFactory通过最高分数获取最匹配播放器类型,目前MediaPlayerFactory还保留的medialayer有NuPlayerFactory、TestPlayerFactory、IC厂商自己的播放器。

    1. status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
    2. {
    3. …………
    4. player_type playerType = MediaPlayerFactory::getPlayerType(this,
    5. fd,
    6. offset,
    7. length);
    8. sp p = setDataSource_pre(playerType);
    9. if (p == NULL) {
    10. return NO_INIT;
    11. }
    12. // now set data source
    13. return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
    14. }

    根据获取的播放器类型创建对应的播放器,安装原生的话是创建Nuplayer。

    1. sp MediaPlayerService::Client::setDataSource_pre(
    2. player_type playerType)
    3. {
    4. ALOGV("player type = %d", playerType);
    5. // create the right type of player
    6. sp p = createPlayer(playerType);
    7. …………
    8. if (!p->hardwareOutput()) {
    9. mAudioOutput = new AudioOutput(mAudioSessionId, mAttributionSource,
    10. mAudioAttributes, mAudioDeviceUpdatedListener);
    11. static_cast(p.get())->setAudioSink(mAudioOutput);
    12. }
    13. return p;
    14. }
    1. sp MediaPlayerService::Client::createPlayer(player_type playerType)
    2. {
    3. // determine if we have the right player type
    4. sp p = getPlayer();
    5. if ((p != NULL) && (p->playerType() != playerType)) {
    6. ALOGV("delete player");
    7. p.clear();
    8. }
    9. if (p == NULL) {
    10. p = MediaPlayerFactory::createPlayer(playerType, mListener,
    11. VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mAttributionSource.pid)));
    12. }
    13. if (p != NULL) {
    14. p->setUID(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mAttributionSource.uid)));
    15. }
    16. return p;
    17. }

    1. status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
    2. ALOGV("setDataSource(%p) file(%d)", this, fd);
    3. Mutex::Autolock autoLock(mLock);
    4. if (mState != STATE_IDLE) {
    5. return INVALID_OPERATION;
    6. }
    7. mState = STATE_SET_DATASOURCE_PENDING;
    8. mPlayer->setDataSourceAsync(fd, offset, length);
    9. while (mState == STATE_SET_DATASOURCE_PENDING) {
    10. mCondition.wait(mLock);
    11. }
    12. return mAsyncResult;
    13. }

    1. void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
    2. sp msg = new AMessage(kWhatSetDataSource, this);
    3. sp notify = new AMessage(kWhatSourceNotify, this);
    4. sp source =
    5. new GenericSource(notify, mUIDValid, mUID, mMediaClock);
    6. ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
    7. fd, (long long)offset, (long long)length, source.get());
    8. status_t err = source->setDataSource(fd, offset, length);
    9. if (err != OK) {
    10. ALOGE("Failed to set data source!");
    11. source = NULL;
    12. }
    13. msg->setObject("source", source);
    14. msg->post();
    15. mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
    16. }

    首先mediaplayer.cpp中发出setDataSource的函数 ---> 到达IMediaPlayer的Bp端 ---> 传到IMediaPlayer的Bn端 ---> 到达MediaPlayerService::Client端的MediaPlayerService::Client::setDataSource函数 ---> NuPlayerDriver::setDataSource ---> NuPlayer: setDataSourceAsync

    这里就基本将mediaplayer跟mediaplayerservice的交互理清了。

    mediaplayer跟mediaplayerservice 交互可以看如下的博客,写的极好:

    2. Android MultiMedia框架完全解析 - MediaPlayer的C/S架构与Binder机制实现_yanbixing123的博客-CSDN博客

  • 相关阅读:
    Java—基础知识测试总结1
    文件上传下载
    [附源码]计算机毕业设计JAVAjsp图书借阅系统
    PIL库的crop函数(图片裁剪操作)
    C语言每日一题(9):跳水比赛猜名次
    CSS实现背景网格线(background-image)
    Windows安装Node.js
    小程序jsencrypt不兼容处理一步步“调教“jsencrypt过程,调到服为止
    MySQL数据库之Java中如何使用数据库【JDBC编程】
    OC RSA加密解密
  • 原文地址:https://blog.csdn.net/mengxin00100/article/details/126167169