MediaPlayer(九)--reset()流程

frameworks/base/media/java/android/media/MediaPlayer.java

    /**
     * Resets the MediaPlayer to its uninitialized state. After calling
     * this method, you will have to initialize it again by setting the
     * data source and calling prepare().
     */
    public void reset() {
        mSelectedSubtitleTrackIndex = -1;
        synchronized(mOpenSubtitleSources) {
            for (final InputStream is: mOpenSubtitleSources) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            mOpenSubtitleSources.clear();
        }
        if (mSubtitleController != null) {
            mSubtitleController.reset();
        }
        if (mTimeProvider != null) {
            mTimeProvider.close();
            mTimeProvider = null;
        }

        stayAwake(false);
        _reset();
        // make sure none of the listeners get called anymore
        if (mEventHandler != null) {
            mEventHandler.removeCallbacksAndMessages(null);
        }

        synchronized (mIndexTrackPairs) {
            mIndexTrackPairs.clear();
            mInbandTrackIndices.clear();
        };

        resetDrmState();
    }

    private native void _reset();

主要步骤

  • 销毁 Subtitle相关处理
  • 销毁 mTimeProvider
  • stayAwake(false),不保持屏幕长开的的状态
  • _reset(),调用到jni层,下面分析
  • 销毁 mEventHandler所有消息,不再向播放器应用发送任何消息

frameworks/base/media/jni/android_media_MediaPlayer.cpp

static void
android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
{
    ALOGV("reset");
    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    if (mp == NULL ) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    }
    process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
}

frameworks/av/media/libmedia/mediaplayer.cpp

status_t MediaPlayer::reset_l()
{
    mLoop = false;
    if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
    mPrepareSync = false;
    if (mPlayer != 0) {
        status_t ret = mPlayer->reset();
        if (ret != NO_ERROR) {
            ALOGE("reset() failed with return code (%d)", ret);
            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
        } else {
            mPlayer->disconnect();
            mCurrentState = MEDIA_PLAYER_IDLE;
        }
        // setDataSource has to be called again to create a
        // new mediaplayer.
        mPlayer = 0;
        mCurrentBufferingSettings = BufferingSettings();
        return ret;
    }
    clear_l();
    return NO_ERROR;
}

主要步骤:

  • 调用MediaPlayerService 的reset方法
    这一步主要执行到NuPlayer的reset
  • 调用MediaPlayerService 的disconnect
    这一步会销毁MediaPlayerService 保存的服务端mediaplayer binder实例mClient
    和NuPlayer的实例
  • 将mPlayer销毁
    mPlayer是mediaplayer 同服务端MediaPlayerService

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

status_t MediaPlayerService::Client::reset()
{
    ALOGV("[%d] reset", mConnId);
    mMaybeVideoAlive = false;
    mRetransmitEndpointValid = false;
    sp<MediaPlayerBase> p = getPlayer();
    if (p == 0) return UNKNOWN_ERROR;
    return p->reset();
}

void MediaPlayerService::Client::disconnect()
{
    ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
    // grab local reference and clear main reference to prevent future
    // access to object
    sp<MediaPlayerBase> p;
    {
        Mutex::Autolock l(mLock);
       //使用了一个局部变量对mPlayer引用,即对底层播放器的引用。
       //会使强引用计数加1。在这个函数退出后,p的生命周期也结束,智能指针会自动销毁底层播放器实例
        p = mPlayer;

       //调用了智能指针的clear方法,将强引用计数减1,并m_ptr = 0 
       //mClient 为sp<IMediaPlayerClient>,即是对mediaplayer的引用
       //mPlayer 为sp<MediaPlayerBase>
       //mClient和mPlayer为全局的引用变量,使用clear后, mClient和mPlayer将无法再被使用
        mClient.clear();      
        mPlayer.clear();
    }

    // clear the notification to prevent callbacks to dead client
    // and reset the player. We assume the player will serialize
    // access to itself if necessary.
    if (p != 0) {
        p->setNotifyCallback(0, 0);
#if CALLBACK_ANTAGONIZER
        ALOGD("kill Antagonizer");
        mAntagonizer->kill();
#endif
        p->reset();
    }

    {
        Mutex::Autolock l(mLock);
        disconnectNativeWindow_l();
    }

    IPCThreadState::self()->flushCommands();
}

disconnect步骤稍微有点绕。先用一个局部变量p 指向了mPlayer,即增加了对NuPlayer的强引用计数,接着销毁了全局变量mClient和mPlayer引用。mClient计数应该会为0,所以对应的实例也会被销毁。而NuPlayer的引用计数由于局部变量p,引用计数不会为0。接着通过p 将NuPlayer的回调函数置为0,并调用到NuPlayer的reset方法,这里是重复调用了reset方法,因为release流程只会调用mediaplayer的disconnect方法,不会调用到reset方法。在函数执行完后,局部变量p会自动销毁,同时也会自动销毁NuPlayer实例
主要步骤:

  • 销毁mClient和mPlayer的引用
  • 设置NuPlayer的回调函数为0
  • 调用NuPlayer reset方法
  • disconnectNativeWindow_l(没详细研究,应该是涉及到显示的window,跟surface和wms相关)
  • flushCommands() 调用talkWithDriver(false)立即发送mOut缓存中的命令数据
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mediaplayer-viral.zip 是一个文件压缩包,其中包含了一个名为 "mediaplayer-viral" 的媒体播放器应用程序。 这个应用程序可能是一个用于播放音乐和视频的多媒体播放器。通过解压mediaplayer-viral.zip文件,可以将应用程序文件提取出来,并安装到适当的设备上进行使用。 该应用程序可能具有一些特殊的功能,使其能够迅速在社交媒体平台上传播开来。这可能意味着其具有与社交媒体平台的集成,可以方便地分享当前播放的音乐或视频到用户的社交媒体账户上。它可能还具有一些社交化的功能,比如用户之间可以相互关注、分享播放列表等等。这些功能对于即时分享和互动非常有用,可以帮助应用程序在社交媒体上迅速传播。 除了社交媒体功能,mediaplayer-viral.zip 中提供的媒体播放器应用程序可能还具有标准的播放控制功能,比如暂停、播放、切换曲目或视频等。它可能还支持设置播放列表、创建个人收藏夹、调整音量和亮度等常见的媒体播放器功能。此外,还可能具有一些额外的特性,比如可自定义的界面、歌曲识别功能或双重音频输出等等。这些功能将提供更好的用户体验和更多个性化的选项。 总的来说,mediaplayer-viral.zip 是一个包含了一个名为 "mediaplayer-viral" 的媒体播放器应用程序的文件压缩包。这个应用程序具有社交媒体集成和一系列常见的媒体播放器功能,旨在提供良好的用户体验和便捷的分享功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值