nuplayer播放流程简略分析

涉及相关文件路径:\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.h\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDe...
摘要由CSDN通过智能技术生成

涉及相关文件路径:
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.h
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDecoder.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerRenderer.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\HTTPLiveSource.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDecoder.h
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerSource.h
\frameworks\av\media\libmediaplayerservice\nuplayer\HTTPLiveSource.h
\frameworks\av\media\libmediaplayerservice\nuplayer\HTTPLiveSource.cpp
\frameworks\av\media\libstagefright\httplive\LiveSession.h
\frameworks\av\media\libstagefright\httplive\LiveSession.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\RTSPSource.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\RTSPSource.h
\frameworks\av\media\libmediaplayerservice\nuplayer\GenericSource.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\GenericSource.h
\frameworks\av\media\libstagefright\MediaExtractorFactory.cpp
\frameworks\av\media\libmediaextractor\include\media\MediaSource.h
\frameworks\av\media\libmediaextractor\MediaExtractor.cpp
\frameworks\av\media\libmediaextractor\include\media\MediaExtractor.h
\frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp
\frameworks\av\media\libmediaplayerservice\MediaPlayerService.h
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDriver.cpp
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDriver.h
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerRenderer.h
\frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerRenderer.cpp
\frameworks\av\media\libstagefright\ACodecBufferChannel.cpp

nuplayer相关类结构如下图所示:

在这里插入图片描述

nuplayer流程如下图:

在这里插入图片描述

概述:

nuplayer是在7.0后android系统源码中使用的音视频播放类,负责控制音视频的播放相关的逻辑调度,主要流程概述如下:
1、在MediaPlayerService的内部类Client中初始化NuPlayerDriver,在NuPlayerDriver中初始化NuPlayer
2、在Client的setDataSource_pre中新建AudioOutput并将其赋给上一步已经创建的NuPlayer,AudioOutput继承自AudioSink,其头文件中的注释:音频输出的抽象层,之后会调用到NuPlayer中的setDataSourceAsync完成对source的初始化,source在如下几种类型中确定:HTTPLiveSource、RTSPSource、GenericSource。
3、在Client的prepareAsync中直接调用了NuPlayerDriver的prepareAsync,最终调用到source中的prepareAsync,在其中得到具体的IMediaSource信息
4、在Clietn中调用start方法,最终调用到Nuplayer中的onstart方法,在onstart方法中初始化mRenderer和mVideoDecoder、mAudioDecoder,在mVideoDecoder、mAudioDecoder中通过onConfigure进入到handleAnOutputBuffer从而将输出流渲染到mRenderer中,在mRenderer中通过queueBuffer接收输入数据,最终通过onDrainAudioQueue将音频数据写入到mAudioSink中,其中视频数据的渲染输出则要复杂的多,在mRenderer中通过onDrainVideoQueue将消息发回至Decoder中,在decoder中通过onRenderBuffer方法进入到MediaCodec中的renderOutputBufferAndRelease方法,通过mSoftRenderer->render执行视频渲染输出。

代码流程分析如下:
1、从MediaplayerService中的setDataSource开始,代码流程如下:
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
    ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
    struct stat sb;
    int ret = fstat(fd, &sb);
    if (ret != 0) {
        ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
        return UNKNOWN_ERROR;
    }
    //......省略部分代码
    //得到player类型,为NU_PLAYER
    player_type playerType = MediaPlayerFactory::getPlayerType(this,
                                                               fd,
                                                               offset,
                                                               length);
    //setDataSource前的环境准备包括AudioOutput的初始化                          
    sp<MediaPlayerBase> p = setDataSource_pre(playerType);
    if (p == NULL) {
        return NO_INIT;
    }
    //这里实际调用nuplayerdriver的setdatasource
    return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
}

sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
        player_type playerType)
{
    //这里得到的是NuPlayerDriver 
    sp<MediaPlayerBase> p = createPlayer(playerType);
    if (p == NULL) {
        return p;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.extractor"));
    //绑定提取器extractor死亡通知
    sp<ServiceDeathNotifier> extractorDeathListener =
            new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
    binder->linkToDeath(extractorDeathListener);

    sp<IOmx> omx = IOmx::getService();
    //绑定解码器死亡通知
    sp<ServiceDeathNotifier> codecDeathListener =
            new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
    omx->linkToDeath(codecDeathListener, 0);

    Mutex::Autolock lock(mLock);

    clearDeathNotifiers_l();
    mExtractorDeathListener = extractorDeathListener;
    mCodecDeathListener = codecDeathListener;
    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
    //初始化AudioOutput,并且将其设置给player
    if (!p->hardwareOutput()) {
        mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
                mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
        static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
    }

    return p;
}

MediaplayerService中的setDataSource在主要初始化了mplyer(NuPlayerDriver),然后初始化了一些通知监听,最重要的就是初始化了AudioOutput,并将其设置给了mplayer。
NuPlayerDriver中部分代码如下:

NuPlayerDriver::NuPlayerDriver(pid_t pid)
    : mState(STATE_IDLE),
      mIsAsyncPrepare(false),
      mAsyncResult(UNKNOWN_ERROR),
      mSetSurfaceInProgress(false),
      mDurationUs(-1),
      mPositionUs(-1),
      mSeekInProgress(false),
      mPlayingTimeUs(0),
      mRebufferingTimeUs(0),
      mRebufferingEvents(0),
      mRebufferingAtExit(false),
      mLooper(new ALooper),
      mMediaClock(new MediaClock),
      mPlayer(new NuPlayer(pid, mMediaClock)), //初始化nuplayer
      mPlayerFlags(0),
      mAnalyticsItem(NULL),
      mClientUid(-1),
      mAtEOS(false),
      mLooping(false),
      mAutoLoop(false) {
    //looper机制在nuplayer中大量运用,用来处理异步消息处理,跟framework中的looper一样,都是基于message发送异步消息到looper中去,looper维护一个队列,然后不断从队列中取出消息,交由handler去处理
    mLooper->setName("NuPlayerDriver Looper");

    mMediaClock->init();

    // set up an analytics record
    mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);

    mLooper->start(
            false, /* runOnCallingThread */
            true,  /* canCallJava */
            PRIORITY_AUDIO);

    mLooper->registerHandler(mPlayer);

    mPlayer->init(this);
}

//在pre_setdatasource中的设置audiosink如下
void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
    mPlayer->setAudioSink(audioSink);
    mAudioSink = audioSink;
}

Nuplayer中的初始化如下:

NuPlayer::NuPlayer(pid_t pid, const sp<MediaClock> &mediaClock)
    : mUIDValid(false),
      mPID(pid),
      mMediaClock(mediaClock),
      mSourceFlags(0),
      mOffloadAudio(false),
      mAudioDecoderGeneration(0),
      mVideoDecoderGeneration(0),
      mRendererGeneration(0),
      mLastStartedPlayingTimeNs(0),
      mLastStartedRebufferingTimeNs(0),
      mPreviousSeekTimeUs(0),
      mAudioEOS(false),
      mVideoEOS(false),
      mScanSourcesPending(false),
      mScanSourcesGeneration(0),
      mPollDurationGeneration(0),
      mTimedTextGeneration(0),
      mFlushingAudio(NONE),
      mFlushingVideo(NONE),
      mResumePending(false),
      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
      mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
      mVideoFpsHint(-1.f),
      mStarted(false),
      mPrepared(false),
      mResetting(false),
      mSourceStarted(false),
      mAudioDecoderError(false),
      mVideoDecoderError(false),
      mPaused(false),
      mPausedByClient(true),
      mPausedForBuffering(false),
      mIsDrmProtected(false),
      mDataSourceType(DATA_SOURCE_TYPE_NONE) {
    CHECK(mediaClock != NULL);
    clearF
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值