framework层的MediaPlayer初始化未调用NuPlayer用关的函数。
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDriver.cpp
status_t NuPlayerDriver::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers) {
......
// 此处的mPlayer是指NuPlayer实例
mPlayer->setDataSourceAsync(httpService, url, headers);
......
}
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp
void NuPlayer::setDataSourceAsync(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
size_t len = strlen(url);
sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
sp<Source> source;
if (...) {
...... // 在线视频流的检测
} else {
ALOGV("setDataSourceAsync GenericSource %s", url);
sp<GenericSource> genericSource = new GenericSource(notify, mUIDValid, mUID, mMediaClock);
status_t err = genericSource->setDataSource(httpService, url, headers);
if (err == OK) {
source = genericSource;
} else {
ALOGE("Failed to set data source!");
}
// regardless of success/failure
mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
}
msg->setObject("source", source);
msg->post();
}
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetDataSource:
{
ALOGV("kWhatSetDataSource");
CHECK(mSource == NULL);
status_t err = OK;
sp<RefBase> obj;
CHECK(msg->findObject("source", &obj));
if (obj != NULL) {
Mutex::Autolock autoLock(mSourceLock);
mSource = static_cast<Source *>(obj.get());
} else {
err = UNKNOWN_ERROR;
}
CHECK(mDriver != NULL);
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
// 向NuPlayerDriver返回SetDataSourc的结果
driver->notifySetDataSourceCompleted(err);
}
break;
}
......
}
}
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp
void NuPlayer::prepareAsync() {
(new AMessage(kWhatPrepare, this))->post();
}
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
......
case kWhatPrepare:
{
mSource->prepareAsync();
break;
}
......
}
}
frameworks\av\media\libmediaplayerservice\nuplayer\GenericSource.cpp
void NuPlayer::GenericSource::prepareAsync() {
Mutex::Autolock _l(mLock);
ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
if (mLooper == NULL) {
mLooper = new ALooper;
mLooper->setName("generic");
mLooper->start();
mLooper->registerHandler(this);
}
sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
msg->post();
}
void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
Mutex::Autolock _l(mLock);
switch (msg->what()) {
case kWhatPrepareAsync:
{
onPrepareAsync();
break;
}
......
}
}
void NuPlayer::GenericSource::onPrepareAsync() {
mDisconnectLock.lock();
ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
// delayed data source creation
if (mDataSource == NULL) {
// set to false first, if the extractor
// comes back as secure, set it to true then.
mIsSecure = false;
if (!mUri.empty()) {
const char* uri = mUri.c_str();
String8 contentType;
if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
sp<DataSource> httpSource;
mDisconnectLock.unlock();
httpSource = PlayerServiceDataSourceFactory::getInstance()
->CreateMediaHTTP(mHTTPService);
if (httpSource == NULL) {
ALOGE("Failed to create http source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
mDisconnectLock.lock();
if (!mDisconnected) {
mHttpSource = httpSource;
}
}
mLock.unlock();
mDisconnectLock.unlock();
// This might take long time if connection has some issue.
sp<DataSource> dataSource = PlayerServiceDataSourceFactory::getInstance()
->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType,
static_cast<HTTPBase *>(mHttpSource.get()));
mDisconnectLock.lock();
mLock.lock();
if (!mDisconnected) {
mDataSource = dataSource;
}
} else {
if (property_get_bool("media.stagefright.extractremote", true) &&
!PlayerServiceFileSource::requiresDrm(
mFd.get(), mOffset, mLength, nullptr /* mime */)) {
sp<IBinder> binder =
defaultServiceManager()->getService(String16("media.extractor"));
if (binder != nullptr) {
ALOGD("FileSource remote");
sp<IMediaExtractorService> mediaExService(
interface_cast<IMediaExtractorService>(binder));
sp<IDataSource> source;
mediaExService->makeIDataSource(base::unique_fd(dup(mFd.get())), mOffset, mLength, &source);
ALOGV("IDataSource(FileSource): %p %d %lld %lld",
source.get(), mFd.get(), (long long)mOffset, (long long)mLength);
if (source.get() != nullptr) {
mDataSource = CreateDataSourceFromIDataSource(source);
} else {
ALOGW("extractor service cannot make data source");
}
} else {
ALOGW("extractor service not running");
}
}
if (mDataSource == nullptr) {
ALOGD("FileSource local");
mDataSource = new PlayerServiceFileSource(dup(mFd.get()), mOffset, mLength);
}
}
if (mDataSource == NULL) {
ALOGE("Failed to create data source!");
mDisconnectLock.unlock();
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
}
if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
mDisconnectLock.unlock();
// For cached streaming cases, we need to wait for enough
// buffering before reporting prepared.
mIsStreaming = (mCachedSource != NULL);
// init extractor from data source
status_t err = initFromDataSource();
if (err != OK) {
ALOGE("Failed to init from data source!");
notifyPreparedAndCleanup(err);
return;
}
if (mVideoTrack.mSource != NULL) {
sp<MetaData> meta = getFormatMeta_l(false /* audio */);
sp<AMessage> msg = new AMessage;
err = convertMetaDataToMessage(meta, &msg);
if(err != OK) {
notifyPreparedAndCleanup(err);
return;
}
notifyVideoSizeChanged(msg);
}
notifyFlagsChanged(
// FLAG_SECURE will be known if/when prepareDrm is called by the app
// FLAG_PROTECTED will be known if/when prepareDrm is called by the app
FLAG_CAN_PAUSE |
FLAG_CAN_SEEK_BACKWARD |
FLAG_CAN_SEEK_FORWARD |
FLAG_CAN_SEEK);
finishPrepareAsync();
ALOGV("onPrepareAsync: Done");
}
NuPlayer::onStart
中调用postScanSources()
,postScanSources()
中发送kWhatScanSources
消息,在消息处理中分别初始化mVideoDecoder
和mAudioDecoder
。
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp
void NuPlayer::onStart(int64_t startPositionUs, MediaPlayerSeekMode mode) {
......
postScanSources();
}
void NuPlayer::postScanSources() {
......
sp<AMessage> msg = new AMessage(kWhatScanSources, this);
msg->setInt32("generation", mScanSourcesGeneration);
msg->post();
mScanSourcesPending = true;
}
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
......
case kWhatScanSources:
{
......
// initialize video before audio because successful initialization of
// video may change deep buffer mode of audio.
if (mSurface != NULL) {
if (instantiateDecoder(false, &mVideoDecoder) == -EWOULDBLOCK) {
rescan = true;
}
}
// Don't try to re-open audio sink if there's an existing decoder.
if (mAudioSink != NULL && mAudioDecoder == NULL) {
if (instantiateDecoder(true, &mAudioDecoder) == -EWOULDBLOCK) {
rescan = true;
}
}
......
break;
}
......
}
status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder, bool checkAudioModeChange) {
// The audio decoder could be cleared by tear down. If still in shut down
// process, no need to create a new audio decoder.
if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) {
return OK;
}
......
Mutex::Autolock autoLock(mDecoderLock);
if (audio) {
sp<AMessage> notify = new AMessage(kWhatAudioNotify, this);
++mAudioDecoderGeneration;
notify->setInt32("generation", mAudioDecoderGeneration);
if (checkAudioModeChange) {
determineAudioModeChange(format);
}
if (mOffloadAudio) {
mSource->setOffloadAudio(true /* offload */);
const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL);
format->setInt32("has-video", hasVideo);
*decoder = new DecoderPassThrough(notify, mSource, mRenderer);
ALOGV("instantiateDecoder audio DecoderPassThrough hasVideo: %d", hasVideo);
} else {
mSource->setOffloadAudio(false /* offload */);
// new NuPlayer::Decoder
*decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer);
ALOGV("instantiateDecoder audio Decoder");
}
mAudioDecoderError = false;
} else {
sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
++mVideoDecoderGeneration;
notify->setInt32("generation", mVideoDecoderGeneration);
// new NuPlayer::Decoder
*decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer, mSurface, mCCDecoder);
mVideoDecoderError = false;
// enable FRC if high-quality AV sync is requested, even if not
// directly queuing to display, as this will even improve textureview
// playback.
{
if (property_get_bool("persist.sys.media.avsync", false)) {
format->setInt32("auto-frc", 1);
}
}
}
(*decoder)->init(); // 调用 NuPlayer::DecoderBase::init
......
/* 调用NuPlayer::DecoderBase::configure,其内部发送一个kWhatConfigure消息,在消息处理中调用NuPlayer::Decoder::onConfigure */
(*decoder)->configure(format); // 调用NuPlayer::Decoder::onConfigure
......
}
在NuPlayer::Decoder::onConfigure(const sp
中,创建了native层的MediaCodec的实例对象。
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDecoder.cpp
void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
......
mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid, mUid);
int32_t secure = 0;
if (format->findInt32("secure", &secure) && secure != 0) {
if (mCodec != NULL) {
mCodec->getName(&mComponentName);
mComponentName.append(".secure");
mCodec->release();
ALOGI("[%s] creating", mComponentName.c_str());
mCodec = MediaCodec::CreateByComponentName(mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid, mUid);
}
}
......
err = mCodec->configure(format, mSurface, crypto, 0 /* flags */);
......
err = mCodec->start();
......
}
TODO
TODO
TODO
TODO