1.setAudioStreamType的过程
frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp
status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
{
ALOGE("[%d] setAudioStreamType(%d)", mConnId, type);
// TODO: for hardware output, call player instead
Mutex::Autolock l(mLock);
if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
return NO_ERROR;
}
这里的mAudioOutput是在Audio播放流程(二)—MediaPlayerService流程之setDataSource中创建的。
setDataSource_pre
mAudioOutput = new AudioOutput(...)
将AudioOutput设置为NuPlayer的Sink端
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
继续
void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
{
Mutex::Autolock lock(mLock);
// do not allow direct stream type modification if attributes have been set
if (mAttributes == NULL) {
mStreamType = streamType;
// No attributes are set, for mediaPlayer playback, force populate attributes
// This is done to ensure that we qualify for a direct output
mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
if (mAttributes != NULL) {
stream_type_to_audio_attributes(mStreamType, mAttributes);
}
}
}
...
static void stream_type_to_audio_attributes(audio_stream_type_t streamType,
audio_attributes_t *attr) {
memset(attr, 0, sizeof(audio_attributes_t));
switch (streamType) {
case AUDIO_STREAM_DEFAULT:
case AUDIO_STREAM_MUSIC:
attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
attr->usage = AUDIO_USAGE_MEDIA;
break;
case AUDIO_STREAM_VOICE_CALL:
attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
break;
case AUDIO_STREAM_ENFORCED_AUDIBLE:
attr->flags |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
// intended fall through, attributes in common with STREAM_SYSTEM
case AUDIO_STREAM_SYSTEM:
attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
attr->usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
break;
case AUDIO_STREAM_RING:
attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
attr->usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
break;
case AUDIO_STREAM_ALARM:
attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
attr->usage = AUDIO_USAGE_ALARM;
break;
case AUDIO_STREAM_NOTIFICATION:
attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
attr->usage = AUDIO_USAGE_NOTIFICATION;
break;
case AUDIO_STREAM_BLUETOOTH_SCO:
attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
attr->flags |= AUDIO_FLAG_SCO;
break;
case AUDIO_STREAM_DTMF:
attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
break;
case AUDIO_STREAM_TTS:
attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
attr->usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
break;
default:
ALOGE("invalid stream type %d when converting to attributes", streamType);
}
}
这个API还是很简单的,就是设置音频的属性,例如:
case AUDIO_STREAM_MUSIC:
attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
attr->usage = AUDIO_USAGE_MEDIA;
2.prepareAsync的调用流程
frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp
status_t MediaPlayerService::Client::prepareAsync()
{
ALOGE("[%d] prepareAsync", mConnId);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
status_t ret = p->prepareAsync();
#if CALLBACK_ANTAGONIZER
ALOGD("start Antagonizer");
if (ret == NO_ERROR) mAntagonizer->start();
#endif
return ret;
}
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDriver.cpp
status_t NuPlayerDriver::prepareAsync() {
ALOGV("prepareAsync(%p)", this);
Mutex::Autolock autoLock(mLock);
switch (mState) {
case STATE_UNPREPARED:
mState = STATE_PREPARING;
mIsAsyncPrepare = true;
mPlayer->prepareAsync();
return OK;
case STATE_STOPPED:
// this is really just paused. handle as seek to start
mAtEOS = false;
mState = STATE_STOPPED_AND_PREPARING;
mIsAsyncPrepare = true;
mPlayer->seekToAsync(0, true /* needNotify */);
return OK;
default:
return INVALID_OPERATION;
};
}
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp
void NuPlayer::prepareAsync() {
(new AMessage(kWhatPrepare, this))->post();
}
这里使用了Native的Handle机制,这个机制原理上和JAVA端的是一致的。
先看处理这个handle的线程是在什么地方创建的,如下
frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDriver.cpp
NuPlayerDriver::NuPlayerDriver(pid_t pid)
: mState(STATE_IDLE),
mIsAsyncPrepare(false),
mAsyncResult(UNKNOWN_ERROR),
mSetSurfaceInProgress(false),
mDurationUs(-1),
mPositionUs(-1),
mSeekInProgress(false),
mLooper(new ALooper),
mPlayerFlags(0),
mAtEOS(false),
mLooping(false),
mAutoLoop(false) {
ALOGV("NuPlayerDriver(%p)", this);
mLooper->setName("NuPlayerDriver Looper");
//开启线程
mLooper->start(
false, /* runOnCallingThread */
true, /* canCallJava */
PRIORITY_AUDIO);
mPlayer = AVNuFactory::get()->createNuPlayer(pid);
mLooper->registerHandler(mPlayer);
mPlayer->setDriver(this);
}
如上,Looper会创建一个名为"NuPlayerDriver Looper"的线程,随后调用mLooper->start开启这个线程,之后循环等待是否有事件需要处理;
mLooper->registerHandler(mPlayer);
上面是为Looper设置handle(mPlayer继承自AHandler),之后AMessage将消息发送到Looper线程,随后线程回调AHandler的onMessageReceived方法去处理。这里需要注意的是onMessageReceived有可能会被AHandler的派生类重载。
AHandler的理论讲完了,回到NuPlayer::prepareAsync()
,这里面通过AMessage将消息kWhatPrepare发送到了NuPlayer的onMessageReceived
方法:
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
...
case kWhatPrepare:
{
mSource->prepareAsync();
break;
}
...
}
这里的mSource在上一步kWhatSetDataSource
消息的处理中已经完成赋值了
这里的mSource指向的是GenericSource对象,因此prepareAsync会走向
frameworks\av\media\libmediaplayerservice\nuplayer\GenericSource.cpp
void NuPlayer::GenericSource::prepareAsync() {
if (mLooper == NULL) {
mLooper = new ALooper;
mLooper->setName("generic");
mLooper->start();
mLooper->registerHandler(this);
}
sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
msg->post();
}
如上GenericSource内部又开启了一个线程(“generic”),这个线程处理来自GenericSource的消息,因此,这条消息会继续发往GenericSource的onMessageReceived
void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatPrepareAsync:
{
onPrepareAsync();
break;
}
...
}
...
void NuPlayer::GenericSource::onPrepareAsync() {
...
创建DataSource
mDataSource = new FileSource(mFd, mOffset, mLength);
...
//进行多媒体文件的格式探测和解析
status_t err = initFromDataSource();
// 上报流状态
notifyFlagsChanged(
(mIsSecure ? FLAG_SECURE : 0)
| (mDecryptHandle != NULL ? FLAG_PROTECTED : 0)
| FLAG_CAN_PAUSE
| FLAG_CAN_SEEK_BACKWARD
| FLAG_CAN_SEEK_FORWARD
| FLAG_CAN_SEEK);
...
//上报调用完成
finishPrepareAsync();
...
}
我们重点关注initFromDataSource中的多媒体文件探测和解析
status_t NuPlayer::GenericSource::initFromDataSource() {
...
//创建多媒体探测器,这里会通过binder调度到MediaExtractor获取对应的解析器,例如MP3会使用MP3Extractor
extractor = MediaExtractor::Create(mDataSource,
mimeType.isEmpty() ? NULL : mimeType.string(),
mIsStreaming ? 0 : AVNuUtils::get()->getFlags());
//获取多媒体文件的元数据
mFileMeta = extractor->getMetaData();
//获取多媒体文件总共有多少个track
size_t numtracks = extractor->countTracks();
for (size_t i = 0; i < numtracks; ++i) {
//获取每一个track
sp<IMediaSource> track = extractor->getTrack(i);
//获取当前track的meta数据
sp<MetaData> meta = extractor->getTrackMetaData(i);
const char *mime;
//从当前track的meta信息中得到,多媒体是audio还是video
CHECK(meta->findCString(kKeyMIMEType, &mime));
if (!strncasecmp(mime, "audio/", 6)) {
if (mAudioTrack.mSource == NULL) {
mAudioTrack.mIndex = i;
mAudioTrack.mSource = track;
mAudioTrack.mPackets =
new AnotherPacketSource(mAudioTrack.mSource->getFormat());
if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
mAudioIsVorbis = true;
} else {
mAudioIsVorbis = false;
}
if (AVNuUtils::get()->isByteStreamModeEnabled(meta)) {
mIsByteMode = true;
}
}
} else if (!strncasecmp(mime, "video/", 6)) {
....
}
}
//获取时长
if (meta->findInt64(kKeyDuration, &durationUs)) {
if (durationUs > mDurationUs) {
mDurationUs = durationUs;
}
}
...
一般对于音频的文件而言,track只有一个,如下:
size_t MP3Extractor::countTracks() {
return mInitCheck != OK ? 0 : 1;
}