涉及相关文件路径:
\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);
clearFlushComplete();
}
void NuPlayer::init(const wp<NuPlayerDriver> &driver) {
mDriver = driver;
sp<AMessage> notify = new AMessage(kWhatMediaClockNotify, this);
mM