美文网首页源码原理知识点
MediaPlayer 播放器全面剖析(一)

MediaPlayer 播放器全面剖析(一)

作者: 码上就说 | 来源:发表于2020-02-01 21:11 被阅读0次

    一、MediaPlayer状态

    Android官网上赫然挂着这张MediaPlayer状态图,熟悉这张图,对了解MediaPlayer的工作原理有很大的帮助;
    下图中,单箭头表示同步调用,双箭头表示异步调用;


    mediaplayer_state_diagram.gif
    • MediaPlayer 创建实例或者在调用reset方法之后,播放器处于Idle状态;
    • MediaPlayer 有prepare 和 prepareAysnc两种方法,prepare 针对本地音视频,是同步的;prepareAsync针对网络音视频,异步的;
    • MediaPlayer在播放中调用pause函数,Started ---> Paused 状态切换是瞬间的;但是再次调用 MediaPlayer.start函数,Paused ---> Started 状态切换需要一些耗时;即时是本地音视频,也是需要一些耗时的;
    • MediaPlayer 进入onPrepared状态,才可以设置一些属性,例如 音量、 screenOnWhilePlaying looping;第一次调start函数有效,后续调用无效;
    • MediaPlayer.stop ---> 播放器进入Stopped状态,这事想要重新激活,可以重新调用prepare / prepareAsync 函数

    二、MediaPlayer 调用流程剖析

    MediaPlayer 从启动,初始化,setDataSource,到 setSurface 步骤的操作过程;


    MediaPlayer.png MediaPlayer 类关系

    本章讲解涉及到的源码路径:
    /frameworks/base/media/java/android/media/MediaPlayer.java

    /frameworks/base/media/jni/android_media_MediaPlayer.cpp

    /frameworks/av/media/libmedia/mediaplayer.cpp

    /frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

    /frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

    /frameworks/av/include/media/MediaPlayerInterface.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp

    /frameworks/av/media/libmedia/mediaplayer.cpp




    下面从源码的角度分析一下重要的执行流程:
    /frameworks/av/media/libmedia/mediaplayer.cpp

    175status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
    176{
    177    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
    178    status_t err = UNKNOWN_ERROR;
    179    const sp<IMediaPlayerService> service(getMediaPlayerService());
    180    if (service != 0) {
    181        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
    182        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
    183            (NO_ERROR != player->setDataSource(fd, offset, length))) {
    184            player.clear();
    185        }
    186        err = attachNewPlayer(player);
    187    }
    188    return err;
    189}
    

    执行了:
    sp<IMediaPlayer> player(service->create(this, mAudioSessionId));

    313sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
    314        audio_session_t audioSessionId)
    315{
    316    pid_t pid = IPCThreadState::self()->getCallingPid();
    317    int32_t connId = android_atomic_inc(&mNextConnId);
    318
    319    sp<Client> c = new Client(
    320            this, pid, connId, client, audioSessionId,
    321            IPCThreadState::self()->getCallingUid());
    322
    323    ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
    324         IPCThreadState::self()->getCallingUid());
    325
    326    wp<Client> w = c;
    327    {
    328        Mutex::Autolock lock(mLock);
    329        mClients.add(w);
    330    }
    331    return c;
    332}
    

    调用到MediaPlayerService::Client 类中:

    795status_t MediaPlayerService::Client::setDataSource(
    796        const sp<IMediaHTTPService> &httpService,
    797        const char *url,
    798        const KeyedVector<String8, String8> *headers)
    799{
    800    ALOGV("setDataSource(%s)", url);
    801    if (url == NULL)
    802        return UNKNOWN_ERROR;
    803
    804    if ((strncmp(url, "http://", 7) == 0) ||
    805        (strncmp(url, "https://", 8) == 0) ||
    806        (strncmp(url, "rtsp://", 7) == 0)) {
    807        if (!checkPermission("android.permission.INTERNET")) {
    808            return PERMISSION_DENIED;
    809        }
    810    }
    811
    812    if (strncmp(url, "content://", 10) == 0) {
    813        // get a filedescriptor for the content Uri and
    814        // pass it to the setDataSource(fd) method
    815
    816        String16 url16(url);
    817        int fd = android::openContentProviderFile(url16);
    818        if (fd < 0)
    819        {
    820            ALOGE("Couldn't open fd for %s", url);
    821            return UNKNOWN_ERROR;
    822        }
    823        status_t status = setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
    824        close(fd);
    825        return mStatus = status;
    826    } else {
    827        player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
    828        sp<MediaPlayerBase> p = setDataSource_pre(playerType);
    829        if (p == NULL) {
    830            return NO_INIT;
    831        }
    832
    833        return mStatus =
    834                setDataSource_post(
    835                p, p->setDataSource(httpService, url, headers));
    836    }
    837}
    

    重点关注这个代码片段的执行流程:

    827        player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
    828        sp<MediaPlayerBase> p = setDataSource_pre(playerType);
    829        if (p == NULL) {
    830            return NO_INIT;
    831        }
    832
    833        return mStatus =
    834                setDataSource_post(
    835                p, p->setDataSource(httpService, url, headers));
    

    这儿会执行两个函数:
    setDataSource_pre
    setDataSource_post

    从字面上可以理解,一个是setDataSource 执行前,一个是setDataSource执行后;

    724sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
    725        player_type playerType)
    726{
    727    ALOGV("player type = %d", playerType);
    728
    729    // create the right type of player
    730    sp<MediaPlayerBase> p = createPlayer(playerType);
    731    if (p == NULL) {
    732        return p;
    733    }
    734
    735    sp<IServiceManager> sm = defaultServiceManager();
    736    sp<IBinder> binder = sm->getService(String16("media.extractor"));
    737    if (binder == NULL) {
    738        ALOGE("extractor service not available");
    739        return NULL;
    740    }
    741    sp<ServiceDeathNotifier> extractorDeathListener =
    742            new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
    743    binder->linkToDeath(extractorDeathListener);
    744
    745    sp<IOmx> omx = IOmx::getService();
    746    if (omx == nullptr) {
    747        ALOGE("IOmx service is not available");
    748        return NULL;
    749    }
    750    sp<ServiceDeathNotifier> codecDeathListener =
    751            new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
    752    omx->linkToDeath(codecDeathListener, 0);
    753
    754    Mutex::Autolock lock(mLock);
    755
    756    clearDeathNotifiers_l();
    757    mExtractorDeathListener = extractorDeathListener;
    758    mCodecDeathListener = codecDeathListener;
    759    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
    760
    761    if (!p->hardwareOutput()) {
    762        mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
    763                mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
    764        static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
    765    }
    766
    767    return p;
    768}
    
    • 获取 media.extractor 服务;
    • 获取omx服务;

    这两个服务在视频解析和解码的流程中非常重要;

    其中在mediaplayer.cpp 中有调用 getMediaPlayerService()函数,具体是在
    /frameworks/av/media/libmedia/IMediaDeathNotifier.cpp

    // establish binder interface to MediaPlayerService
    /*static*/const sp<IMediaPlayerService>
    IMediaDeathNotifier::getMediaPlayerService()
    {
        ALOGV("getMediaPlayerService");
        Mutex::Autolock _l(sServiceLock);
        if (sMediaPlayerService == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16("media.player"));
                if (binder != 0) {
                    break;
                }
                ALOGW("Media player service not published, waiting...");
                usleep(500000); // 0.5 s
            } while (true);
    
            if (sDeathNotifier == NULL) {
                sDeathNotifier = new DeathNotifier();
            }
            binder->linkToDeath(sDeathNotifier);
            sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
        }
        ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
        return sMediaPlayerService;
    }
    

    调用的是初始化定义的media.player服务,就实现从Client到Server端之间的调用;

    /frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

    241void MediaPlayerFactory::registerBuiltinFactories() {
    242    Mutex::Autolock lock_(&sLock);
    243
    244    if (sInitComplete)
    245        return;
    246
    247    IFactory* factory = new NuPlayerFactory();
    248    if (registerFactory_l(factory, NU_PLAYER) != OK)
    249        delete factory;
    250    factory = new TestPlayerFactory();
    251    if (registerFactory_l(factory, TEST_PLAYER) != OK)
    252        delete factory;
    253
    254    sInitComplete = true;
    255}
    

    MediaPlayerFactory.cpp是管理播放器的一个工厂类,从源码中可以看出来,目前只有一个NuPlayerFactory 管理类了,TestPlayerFactory 是测试使用的,可以忽略;
    NuPlayerFactory工厂类源码如下:

    164/*****************************************************************************
    165 *                                                                           *
    166 *                     Built-In Factory Implementations                      *
    167 *                                                                           *
    168 *****************************************************************************/
    169
    170class NuPlayerFactory : public MediaPlayerFactory::IFactory {
    171  public:
    172    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    173                               const char* url,
    174                               float curScore) {
    175        static const float kOurScore = 0.8;
    176
    177        if (kOurScore <= curScore)
    178            return 0.0;
    179
    180        if (!strncasecmp("http://", url, 7)
    181                || !strncasecmp("https://", url, 8)
    182                || !strncasecmp("file://", url, 7)) {
    183            size_t len = strlen(url);
    184            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
    185                return kOurScore;
    186            }
    187
    188            if (strstr(url,"m3u8")) {
    189                return kOurScore;
    190            }
    191
    192            if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
    193                return kOurScore;
    194            }
    195        }
    196
    197        if (!strncasecmp("rtsp://", url, 7)) {
    198            return kOurScore;
    199        }
    200
    201        return 0.0;
    202    }
    203
    204    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    205                               const sp<IStreamSource>& /*source*/,
    206                               float /*curScore*/) {
    207        return 1.0;
    208    }
    209
    210    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    211                               const sp<DataSource>& /*source*/,
    212                               float /*curScore*/) {
    213        // Only NuPlayer supports setting a DataSource source directly.
    214        return 1.0;
    215    }
    216
    217    virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
    218        ALOGV(" create NuPlayer");
    219        return new NuPlayerDriver(pid);
    220    }
    221};
    

    最终createPlayer中是实例化一个NuPlayerDriver对象;
    这儿判断是否是m3u8视频类型简直是简单粗暴啊;

    • url的后缀名是不是.m3u8;
    • url中是否包含 m3u8 字符串;
    184            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
    185                return kOurScore;
    186            }
    187
    188            if (strstr(url,"m3u8")) {
    189                return kOurScore;
    190            }
    

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp

    71NuPlayerDriver::NuPlayerDriver(pid_t pid)
    72    : mState(STATE_IDLE),
    73      mIsAsyncPrepare(false),
    74      mAsyncResult(UNKNOWN_ERROR),
    75      mSetSurfaceInProgress(false),
    76      mDurationUs(-1),
    77      mPositionUs(-1),
    78      mSeekInProgress(false),
    79      mPlayingTimeUs(0),
    80      mRebufferingTimeUs(0),
    81      mRebufferingEvents(0),
    82      mRebufferingAtExit(false),
    83      mLooper(new ALooper),
    84      mMediaClock(new MediaClock),
    85      mPlayer(new NuPlayer(pid, mMediaClock)),
    86      mPlayerFlags(0),
    87      mAnalyticsItem(NULL),
    88      mClientUid(-1),
    89      mAtEOS(false),
    90      mLooping(false),
    91      mAutoLoop(false) {
    92    ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
    93    mLooper->setName("NuPlayerDriver Looper");
    94
    95    mMediaClock->init();
    96
    97    // set up an analytics record
    98    mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
    99
    100    mLooper->start(
    101            false, /* runOnCallingThread */
    102            true,  /* canCallJava */
    103            PRIORITY_AUDIO);
    104
    105    mLooper->registerHandler(mPlayer);
    106
    107    mPlayer->init(this);
    108}
    
    mPlayer(new NuPlayer(pid, mMediaClock)),
    

    setDataSource 会执行到NuPlayer.cpp 中:

    257void NuPlayer::setDataSourceAsync(
    258        const sp<IMediaHTTPService> &httpService,
    259        const char *url,
    260        const KeyedVector<String8, String8> *headers) {
    261
    262    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
    263    size_t len = strlen(url);
    264
    265    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
    266
    267    sp<Source> source;
    268    if (IsHTTPLiveURL(url)) {
    269        source = new HTTPLiveSource(notify, httpService, url, headers);
    270        ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
    271        mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
    272    } else if (!strncasecmp(url, "rtsp://", 7)) {
    273        source = new RTSPSource(
    274                notify, httpService, url, headers, mUIDValid, mUID);
    275        ALOGV("setDataSourceAsync RTSPSource %s", url);
    276        mDataSourceType = DATA_SOURCE_TYPE_RTSP;
    277    } else if ((!strncasecmp(url, "http://", 7)
    278                || !strncasecmp(url, "https://", 8))
    279                    && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
    280                    || strstr(url, ".sdp?"))) {
    281        source = new RTSPSource(
    282                notify, httpService, url, headers, mUIDValid, mUID, true);
    283        ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
    284        mDataSourceType = DATA_SOURCE_TYPE_RTSP;
    285    } else {
    286        ALOGV("setDataSourceAsync GenericSource %s", url);
    287
    288        sp<GenericSource> genericSource =
    289                new GenericSource(notify, mUIDValid, mUID, mMediaClock);
    290
    291        status_t err = genericSource->setDataSource(httpService, url, headers);
    292
    293        if (err == OK) {
    294            source = genericSource;
    295        } else {
    296            ALOGE("Failed to set data source!");
    297        }
    298
    299        // regardless of success/failure
    300        mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
    301    }
    302    msg->setObject("source", source);
    303    msg->post();
    304}
    

    通过NuPlayer.cpp 内部定义的AMessage 消息来控制:

    548void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
    549    switch (msg->what()) {
    550        case kWhatSetDataSource:
    551        {
    552            ALOGV("kWhatSetDataSource");
    553
    554            CHECK(mSource == NULL);
    555
    556            status_t err = OK;
    557            sp<RefBase> obj;
    558            CHECK(msg->findObject("source", &obj));
    559            if (obj != NULL) {
    560                Mutex::Autolock autoLock(mSourceLock);
    561                mSource = static_cast<Source *>(obj.get());
    562            } else {
    563                err = UNKNOWN_ERROR;
    564            }
    565
    566            CHECK(mDriver != NULL);
    567            sp<NuPlayerDriver> driver = mDriver.promote();
    568            if (driver != NULL) {
    569                driver->notifySetDataSourceCompleted(err);
    570            }
    571            break;
    572        }
    

    接收到消息,将传入的source赋给mSource对象;
    根据url来封装source:

    267    sp<Source> source;
    268    if (IsHTTPLiveURL(url)) {
    269        source = new HTTPLiveSource(notify, httpService, url, headers);
    270        ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
    271        mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
    272    } else if (!strncasecmp(url, "rtsp://", 7)) {
    273        source = new RTSPSource(
    274                notify, httpService, url, headers, mUIDValid, mUID);
    275        ALOGV("setDataSourceAsync RTSPSource %s", url);
    276        mDataSourceType = DATA_SOURCE_TYPE_RTSP;
    277    } else if ((!strncasecmp(url, "http://", 7)
    278                || !strncasecmp(url, "https://", 8))
    279                    && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
    280                    || strstr(url, ".sdp?"))) {
    281        source = new RTSPSource(
    282                notify, httpService, url, headers, mUIDValid, mUID, true);
    283        ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
    284        mDataSourceType = DATA_SOURCE_TYPE_RTSP;
    285    } else {
    286        ALOGV("setDataSourceAsync GenericSource %s", url);
    287
    288        sp<GenericSource> genericSource =
    289                new GenericSource(notify, mUIDValid, mUID, mMediaClock);
    290
    291        status_t err = genericSource->setDataSource(httpService, url, headers);
    292
    293        if (err == OK) {
    294            source = genericSource;
    295        } else {
    296            ALOGE("Failed to set data source!");
    297        }
    298
    299        // regardless of success/failure
    300        mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
    301    }
    

    /frameworks/av/include/media/stagefright/foundation/AHandler.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerSource.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/StreamingSource.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/RTSPSource.h

    MediaPlayer Source 类关系

    HTTPLiveSource:针对m3u8 视频,实际上直播不止m3u8一种类型,MediaPlayer 支持有限;
    RTSPSource:这是针对RTSP的流,MediaPlayer专门针对RTSP的流做了优化;
    GenericSource:通用的source,一些http https file:///协议的url都是走这儿的;

    240static bool IsHTTPLiveURL(const char *url) {
    241    if (!strncasecmp("http://", url, 7)
    242            || !strncasecmp("https://", url, 8)
    243            || !strncasecmp("file://", url, 7)) {
    244        size_t len = strlen(url);
    245        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
    246            return true;
    247        }
    248
    249        if (strstr(url,"m3u8")) {
    250            return true;
    251        }
    252    }
    253
    254    return false;
    255}
    

    setVideoSurfaceTexture 执行到 MediaPlayerService.cpp:

    916status_t MediaPlayerService::Client::setVideoSurfaceTexture(
    917        const sp<IGraphicBufferProducer>& bufferProducer)
    918{
    919    ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
    920    sp<MediaPlayerBase> p = getPlayer();
    921    if (p == 0) return UNKNOWN_ERROR;
    922
    923    sp<IBinder> binder(IInterface::asBinder(bufferProducer));
    924    if (mConnectedWindowBinder == binder) {
    925        return OK;
    926    }
    927
    928    sp<ANativeWindow> anw;
    929    if (bufferProducer != NULL) {
    930        anw = new Surface(bufferProducer, true /* controlledByApp */);
    931        status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
    932
    933        if (err != OK) {
    934            ALOGE("setVideoSurfaceTexture failed: %d", err);
    935            // Note that we must do the reset before disconnecting from the ANW.
    936            // Otherwise queue/dequeue calls could be made on the disconnected
    937            // ANW, which may result in errors.
    938            reset();
    939
    940            Mutex::Autolock lock(mLock);
    941            disconnectNativeWindow_l();
    942
    943            return err;
    944        }
    945    }
    946
    947    // Note that we must set the player's new GraphicBufferProducer before
    948    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
    949    // on the disconnected ANW, which may result in errors.
    950    status_t err = p->setVideoSurfaceTexture(bufferProducer);
    951
    952    mLock.lock();
    953    disconnectNativeWindow_l();
    954
    955    if (err == OK) {
    956        mConnectedWindow = anw;
    957        mConnectedWindowBinder = binder;
    958        mLock.unlock();
    959    } else {
    960        mLock.unlock();
    961        status_t err = nativeWindowDisconnect(
    962                anw.get(), "disconnectNativeWindow");
    963
    964        if (err != OK) {
    965            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
    966                    strerror(-err), err);
    967        }
    968    }
    969
    970    return err;
    971}
    

    创建一个Surface对象:

    930        anw = new Surface(bufferProducer, true /* controlledByApp */);
    931        status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
    
    950    status_t err = p->setVideoSurfaceTexture(bufferProducer);
    

    这个p 对象就是 MediaPlayerFactory 中定义的 NuPlayer对象;
    上面也说过了NuPlayer 是在NuPlayerDriver中定义的;
    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp

    377void NuPlayer::setVideoSurfaceTextureAsync(
    378        const sp<IGraphicBufferProducer> &bufferProducer) {
    379    sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
    380
    381    if (bufferProducer == NULL) {
    382        msg->setObject("surface", NULL);
    383    } else {
    384        msg->setObject("surface", new Surface(bufferProducer, true /* controlledByApp */));
    385    }
    386
    387    msg->post();
    388}
    

    发送一个异步消息通知设置Surface成功了;

    Surface设置成功了,setDataSource 也设置成功了,接下来开始发起请求了,MediaPlayer发起请求的函数是prepare 或者 prepareAsync 函数,一个是同步请求,一个是异步请求,建议还是使用异步请求,毕竟网络请求有时候比较慢;

    下面主要分析MediaPlayer->prepareAsync 执行流程:


    MediaPlayer->prepareAsync调用流程

    /frameworks/av/media/libmedia/mediaplayer.cpp
    中持有的mPlayer 对象就是 MediaPlayerService::Client 对象;

    273status_t MediaPlayer::prepareAsync_l()
    274{
    275    if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
    276        if (mAudioAttributesParcel != NULL) {
    277            mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
    278        } else {
    279            mPlayer->setAudioStreamType(mStreamType);
    280        }
    281        mCurrentState = MEDIA_PLAYER_PREPARING;
    282        return mPlayer->prepareAsync();
    283    }
    284    ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
    285    return INVALID_OPERATION;
    286}
    

    上面两个都是设置一些播放过程中的基本参数,主要是mPlayer->prepareAsync()

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp

    306status_t NuPlayerDriver::prepareAsync() {
    307    ALOGV("prepareAsync(%p)", this);
    308    Mutex::Autolock autoLock(mLock);
    309
    310    switch (mState) {
    311        case STATE_UNPREPARED:
    312            mState = STATE_PREPARING;
    313            mIsAsyncPrepare = true;
    314            mPlayer->prepareAsync();
    315            return OK;
    316        case STATE_STOPPED:
    317            // this is really just paused. handle as seek to start
    318            mAtEOS = false;
    319            mState = STATE_STOPPED_AND_PREPARING;
    320            mIsAsyncPrepare = true;
    321            mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
    322                    true /* needNotify */);
    323            return OK;
    324        default:
    325            return INVALID_OPERATION;
    326    };
    327}
    

    源码中看出这儿执行prepareAsync 也是需要看播放器当前的播放状态的,STATE_UNPREPARED 的时候说明播放器之前从没有执行过prepare ;STATE_STOPPED 说明播放器执行了 stop 函数;
    其他状态的情况下prepareAsync 可以直接忽略;

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp

    371void NuPlayer::prepareAsync() {
    372    ALOGV("prepareAsync");
    373
    374    (new AMessage(kWhatPrepare, this))->post();
    375}
    

    NuPlayer 中定义了一个 Handler message处理机制:

    548void NuPlayer::onMessageReceived(const sp<AMessage> &msg)
    

    执行到NuPlayer-->prepareAsync(...)中的函数,需要发送一个 :
    (new AMessage(kWhatPrepare, this))->post()
    消息;

    616        case kWhatPrepare:
    617        {
    618            ALOGV("onMessageReceived kWhatPrepare");
    619
    620            mSource->prepareAsync();
    621            break;
    622        }
    

    从上面源码可以看出,这个mSource是 执行setDataSource的时候设置进去的,有3种Source,我们以GenericSource 为例;
    /frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.cpp

    342void NuPlayer::GenericSource::prepareAsync() {
    343    Mutex::Autolock _l(mLock);
    344    ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
    345
    346    if (mLooper == NULL) {
    347        mLooper = new ALooper;
    348        mLooper->setName("generic");
    349        mLooper->start();
    350
    351        mLooper->registerHandler(this);
    352    }
    353
    354    sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
    355    msg->post();
    356}
    
    583void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
    584    Mutex::Autolock _l(mLock);
    585    switch (msg->what()) {
    586      case kWhatPrepareAsync:
    587      {
    588          onPrepareAsync();
    589          break;
    590      }
    

    这个函数中是执行视频资源网络请求的核心函数;

    358void NuPlayer::GenericSource::onPrepareAsync() {
    359    ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
    360
    361    // delayed data source creation
    362    if (mDataSource == NULL) {
    363        // set to false first, if the extractor
    364        // comes back as secure, set it to true then.
    365        mIsSecure = false;
    366
    367        if (!mUri.empty()) {
    368            const char* uri = mUri.c_str();
    369            String8 contentType;
    370
    371            if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
    372                mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
    373                if (mHttpSource == NULL) {
    374                    ALOGE("Failed to create http source!");
    375                    notifyPreparedAndCleanup(UNKNOWN_ERROR);
    376                    return;
    377                }
    378            }
    379
    380            mLock.unlock();
    381            // This might take long time if connection has some issue.
    382            sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
    383                   mHTTPService, uri, &mUriHeaders, &contentType,
    384                   static_cast<HTTPBase *>(mHttpSource.get()));
    385            mLock.lock();
    386            if (!mDisconnected) {
    387                mDataSource = dataSource;
    388            }
    389        } else {
    390            if (property_get_bool("media.stagefright.extractremote", true) &&
    391                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
    392                sp<IBinder> binder =
    393                        defaultServiceManager()->getService(String16("media.extractor"));
    394                if (binder != nullptr) {
    395                    ALOGD("FileSource remote");
    396                    sp<IMediaExtractorService> mediaExService(
    397                            interface_cast<IMediaExtractorService>(binder));
    398                    sp<IDataSource> source =
    399                            mediaExService->makeIDataSource(mFd, mOffset, mLength);
    400                    ALOGV("IDataSource(FileSource): %p %d %lld %lld",
    401                            source.get(), mFd, (long long)mOffset, (long long)mLength);
    402                    if (source.get() != nullptr) {
    403                        mDataSource = CreateDataSourceFromIDataSource(source);
    404                        if (mDataSource != nullptr) {
    405                            // Close the local file descriptor as it is not needed anymore.
    406                            close(mFd);
    407                            mFd = -1;
    408                        }
    409                    } else {
    410                        ALOGW("extractor service cannot make data source");
    411                    }
    412                } else {
    413                    ALOGW("extractor service not running");
    414                }
    415            }
    416            if (mDataSource == nullptr) {
    417                ALOGD("FileSource local");
    418                mDataSource = new FileSource(mFd, mOffset, mLength);
    419            }
    420            // TODO: close should always be done on mFd, see the lines following
    421            // CreateDataSourceFromIDataSource above,
    422            // and the FileSource constructor should dup the mFd argument as needed.
    423            mFd = -1;
    424        }
    425
    426        if (mDataSource == NULL) {
    427            ALOGE("Failed to create data source!");
    428            notifyPreparedAndCleanup(UNKNOWN_ERROR);
    429            return;
    430        }
    431    }
    432
    433    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
    434        mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
    435    }
    436
    437    // For cached streaming cases, we need to wait for enough
    438    // buffering before reporting prepared.
    439    mIsStreaming = (mCachedSource != NULL);
    440
    441    // init extractor from data source
    442    status_t err = initFromDataSource();
    443
    444    if (err != OK) {
    445        ALOGE("Failed to init from data source!");
    446        notifyPreparedAndCleanup(err);
    447        return;
    448    }
    449
    450    if (mVideoTrack.mSource != NULL) {
    451        sp<MetaData> meta = getFormatMeta_l(false /* audio */);
    452        sp<AMessage> msg = new AMessage;
    453        err = convertMetaDataToMessage(meta, &msg);
    454        if(err != OK) {
    455            notifyPreparedAndCleanup(err);
    456            return;
    457        }
    458        notifyVideoSizeChanged(msg);
    459    }
    460
    461    notifyFlagsChanged(
    462            // FLAG_SECURE will be known if/when prepareDrm is called by the app
    463            // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
    464            FLAG_CAN_PAUSE |
    465            FLAG_CAN_SEEK_BACKWARD |
    466            FLAG_CAN_SEEK_FORWARD |
    467            FLAG_CAN_SEEK);
    468
    469    finishPrepareAsync();
    470
    471    ALOGV("onPrepareAsync: Done");
    472}
    

    关键的执行片段是:

    371            if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
    372                mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
    373                if (mHttpSource == NULL) {
    374                    ALOGE("Failed to create http source!");
    375                    notifyPreparedAndCleanup(UNKNOWN_ERROR);
    376                    return;
    377                }
    378            }
    379
    380            mLock.unlock();
    381            // This might take long time if connection has some issue.
    382            sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
    383                   mHTTPService, uri, &mUriHeaders, &contentType,
    384                   static_cast<HTTPBase *>(mHttpSource.get()));
    385            mLock.lock();
    386            if (!mDisconnected) {
    387                mDataSource = dataSource;
    388            }
    

    开始onPrepared 和 onVideoSizeChanged 回调:

    450    if (mVideoTrack.mSource != NULL) {
    451        sp<MetaData> meta = getFormatMeta_l(false /* audio */);
    452        sp<AMessage> msg = new AMessage;
    453        err = convertMetaDataToMessage(meta, &msg);
    454        if(err != OK) {
    455            notifyPreparedAndCleanup(err);
    456            return;
    457        }
    458        notifyVideoSizeChanged(msg);
    459    }
    

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerSource.h

    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp

    2487        case Source::kWhatPrepared:
    2488        {
    2489            ALOGV("NuPlayer::onSourceNotify Source::kWhatPrepared source: %p", mSource.get());
    2490            if (mSource == NULL) {
    2491                // This is a stale notification from a source that was
    2492                // asynchronously preparing when the client called reset().
    2493                // We handled the reset, the source is gone.
    2494                break;
    2495            }
    2496
    2497            int32_t err;
    2498            CHECK(msg->findInt32("err", &err));
    2499
    2500            if (err != OK) {
    2501                // shut down potential secure codecs in case client never calls reset
    2502                mDeferredActions.push_back(
    2503                        new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */,
    2504                                               FLUSH_CMD_SHUTDOWN /* video */));
    2505                processDeferredActions();
    2506            } else {
    2507                mPrepared = true;
    2508            }
    2509
    2510            sp<NuPlayerDriver> driver = mDriver.promote();
    2511            if (driver != NULL) {
    2512                // notify duration first, so that it's definitely set when
    2513                // the app received the "prepare complete" callback.
    2514                int64_t durationUs;
    2515                if (mSource->getDuration(&durationUs) == OK) {
    2516                    driver->notifyDuration(durationUs);
    2517                }
    2518                driver->notifyPrepareCompleted(err);
    2519            }
    2520
    2521            break;
    2522        }
    
    2510            sp<NuPlayerDriver> driver = mDriver.promote();
    2511            if (driver != NULL) {
    2512                // notify duration first, so that it's definitely set when
    2513                // the app received the "prepare complete" callback.
    2514                int64_t durationUs;
    2515                if (mSource->getDuration(&durationUs) == OK) {
    2516                    driver->notifyDuration(durationUs);
    2517                }
    2518                driver->notifyPrepareCompleted(err);
    2519            }
    

    回调了notifyPrepareCompleted 和 notifyDuration

    其中/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
    继承了
    /frameworks/av/media/libmediaplayerservice/include/MediaPlayerInterface.h
    所有底层NuPlayer的回调会通过NuPlayerDriver.h 中的sendEvent 到MediaPlayerInterface.h:

    282    void        sendEvent(int msg, int ext1=0, int ext2=0,
    283                          const Parcel *obj=NULL) {
    284        sp<Listener> listener;
    285        {
    286            Mutex::Autolock autoLock(mNotifyLock);
    287            listener = mListener;
    288        }
    289
    290        if (listener != NULL) {
    291            listener->notify(msg, ext1, ext2, obj);
    292        }
    293    }
    

    这个listener 是MediaPlayerService.cpp中设置进来的,所有还会回调到MediaPlayerService.cpp

    1424void MediaPlayerService::Client::notify(
    1425        int msg, int ext1, int ext2, const Parcel *obj)
    1426{
    1427    sp<IMediaPlayerClient> c;
    1428    sp<Client> nextClient;
    1429    status_t errStartNext = NO_ERROR;
    1430    {
    1431        Mutex::Autolock l(mLock);
    1432        c = mClient;
    1433        if (msg == MEDIA_PLAYBACK_COMPLETE && mNextClient != NULL) {
    1434            nextClient = mNextClient;
    1435
    1436            if (mAudioOutput != NULL)
    1437                mAudioOutput->switchToNextOutput();
    1438
    1439            errStartNext = nextClient->start();
    1440        }
    1441    }
    1442
    1443    if (nextClient != NULL) {
    1444        sp<IMediaPlayerClient> nc;
    1445        {
    1446            Mutex::Autolock l(nextClient->mLock);
    1447            nc = nextClient->mClient;
    1448        }
    1449        if (nc != NULL) {
    1450            if (errStartNext == NO_ERROR) {
    1451                nc->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
    1452            } else {
    1453                nc->notify(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN , 0, obj);
    1454                ALOGE("gapless:start playback for next track failed, err(%d)", errStartNext);
    1455            }
    1456        }
    1457    }
    1458
    1459    if (MEDIA_INFO == msg &&
    1460        MEDIA_INFO_METADATA_UPDATE == ext1) {
    1461        const media::Metadata::Type metadata_type = ext2;
    1462
    1463        if(shouldDropMetadata(metadata_type)) {
    1464            return;
    1465        }
    1466
    1467        // Update the list of metadata that have changed. getMetadata
    1468        // also access mMetadataUpdated and clears it.
    1469        addNewMetadataUpdate(metadata_type);
    1470    }
    1471
    1472    if (c != NULL) {
    1473        ALOGV("[%d] notify (%d, %d, %d)", mConnId, msg, ext1, ext2);
    1474        c->notify(msg, ext1, ext2, obj);
    1475    }
    1476}
    

    /frameworks/av/media/libmedia/mediaplayer.cpp
    继承
    /frameworks/av/media/libmedia/IMediaPlayerClient.cpp

    上层MediaPlayer 所有的回调都会集中在
    /frameworks/av/media/libmedia/mediaplayer.cpp
    中的notify 函数回调:

    848void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
    849{
    850    ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
    851    bool send = true;
    852    bool locked = false;
    853
    854    // TODO: In the future, we might be on the same thread if the app is
    855    // running in the same process as the media server. In that case,
    856    // this will deadlock.
    857    //
    858    // The threadId hack below works around this for the care of prepare,
    859    // seekTo, start, and reset within the same process.
    860    // FIXME: Remember, this is a hack, it's not even a hack that is applied
    861    // consistently for all use-cases, this needs to be revisited.
    862    if (mLockThreadId != getThreadId()) {
    863        mLock.lock();
    864        locked = true;
    865    }
    866
    867    // Allows calls from JNI in idle state to notify errors
    868    if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
    869        ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
    870        if (locked) mLock.unlock();   // release the lock when done.
    871        return;
    872    }
    873
    874    switch (msg) {
    875    case MEDIA_NOP: // interface test message
    876        break;
    877    case MEDIA_PREPARED:
    878        ALOGV("MediaPlayer::notify() prepared");
    879        mCurrentState = MEDIA_PLAYER_PREPARED;
    880        if (mPrepareSync) {
    881            ALOGV("signal application thread");
    882            mPrepareSync = false;
    883            mPrepareStatus = NO_ERROR;
    884            mSignal.signal();
    885        }
    886        break;
    887    case MEDIA_DRM_INFO:
    888        ALOGV("MediaPlayer::notify() MEDIA_DRM_INFO(%d, %d, %d, %p)", msg, ext1, ext2, obj);
    889        break;
    890    case MEDIA_PLAYBACK_COMPLETE:
    891        ALOGV("playback complete");
    892        if (mCurrentState == MEDIA_PLAYER_IDLE) {
    893            ALOGE("playback complete in idle state");
    894        }
    895        if (!mLoop) {
    896            mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
    897        }
    898        break;
    899    case MEDIA_ERROR:
    900        // Always log errors.
    901        // ext1: Media framework error code.
    902        // ext2: Implementation dependant error code.
    903        ALOGE("error (%d, %d)", ext1, ext2);
    904        mCurrentState = MEDIA_PLAYER_STATE_ERROR;
    905        if (mPrepareSync)
    906        {
    907            ALOGV("signal application thread");
    908            mPrepareSync = false;
    909            mPrepareStatus = ext1;
    910            mSignal.signal();
    911            send = false;
    912        }
    913        break;
    914    case MEDIA_INFO:
    915        // ext1: Media framework error code.
    916        // ext2: Implementation dependant error code.
    917        if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
    918            ALOGW("info/warning (%d, %d)", ext1, ext2);
    919        }
    920        break;
    921    case MEDIA_SEEK_COMPLETE:
    922        ALOGV("Received seek complete");
    923        if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
    924            ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekMode);
    925            mSeekPosition = -1;
    926            mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
    927            seekTo_l(mCurrentPosition, mCurrentSeekMode);
    928        }
    929        else {
    930            ALOGV("All seeks complete - return to regularly scheduled program");
    931            mCurrentPosition = mSeekPosition = -1;
    932            mCurrentSeekMode = mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
    933        }
    934        break;
    935    case MEDIA_BUFFERING_UPDATE:
    936        ALOGV("buffering %d", ext1);
    937        break;
    938    case MEDIA_SET_VIDEO_SIZE:
    939        ALOGV("New video size %d x %d", ext1, ext2);
    940        mVideoWidth = ext1;
    941        mVideoHeight = ext2;
    942        break;
    943    case MEDIA_NOTIFY_TIME:
    944        ALOGV("Received notify time message");
    945        break;
    946    case MEDIA_TIMED_TEXT:
    947        ALOGV("Received timed text message");
    948        break;
    949    case MEDIA_SUBTITLE_DATA:
    950        ALOGV("Received subtitle data message");
    951        break;
    952    case MEDIA_META_DATA:
    953        ALOGV("Received timed metadata message");
    954        break;
    955    default:
    956        ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
    957        break;
    958    }
    959
    960    sp<MediaPlayerListener> listener = mListener;
    961    if (locked) mLock.unlock();
    962
    963    // this prevents re-entrant calls into client code
    964    if ((listener != 0) && send) {
    965        Mutex::Autolock _l(mNotifyLock);
    966        ALOGV("callback application");
    967        listener->notify(msg, ext1, ext2, obj);
    968        ALOGV("back from callback");
    969    }
    970}
    

    以onPrepared 回调为例:

    877    case MEDIA_PREPARED:
    878        ALOGV("MediaPlayer::notify() prepared");
    879        mCurrentState = MEDIA_PLAYER_PREPARED;
    880        if (mPrepareSync) {
    881            ALOGV("signal application thread");
    882            mPrepareSync = false;
    883            mPrepareStatus = NO_ERROR;
    884            mSignal.signal();
    885        }
    886        break;
    ......
    ......
    ......
    960    sp<MediaPlayerListener> listener = mListener;
    961    if (locked) mLock.unlock();
    962
    963    // this prevents re-entrant calls into client code
    964    if ((listener != 0) && send) {
    965        Mutex::Autolock _l(mNotifyLock);
    966        ALOGV("callback application");
    967        listener->notify(msg, ext1, ext2, obj);
    968        ALOGV("back from callback");
    969    }
    

    从上面分析MediaPlayer->setDataSource 和 MediaPlayer->prepareAsync 两个调用流程来看,我们简单总结一下主要调用的类;
    /frameworks/base/media/java/android/media/MediaPlayer.java
    /frameworks/base/media/jni/android_media_MediaPlayer.cpp
    /frameworks/av/media/libmedia/mediaplayer.cpp
    /frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
    /frameworks/av/media/libmediaplayerservice/include/MediaPlayerInterface.h
    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
    /frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp

    将上面的类图再完善一下:


    MediaPlayer 类关系

    相关文章

      网友评论

        本文标题:MediaPlayer 播放器全面剖析(一)

        本文链接:https://www.haomeiwen.com/subject/nxyyactx.html