文中序列图用
websequencediagrams
在线工具画的
framework层的MediaPlayer初始化未调用NuPlayer用关的函数,进而未调用MediaCodec。
NuPlayer的setDataSource
直接返回结果给NuPlayerDriver,没有调用到MediaCodec。
NuPlayer的prepare
设置了一些参数,没有调用到MediaCodec。
mCodec = MediaCodec::CreateByComponentName(mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid, mUid);
frameworks\av\media\libstagefright\MediaCodec.cpp
sp<MediaCodec> MediaCodec::CreateByType(const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid, uid_t uid) {
Vector<AString> matchingCodecs;
MediaCodecList::findMatchingCodecs(
mime.c_str(),
encoder,
0,
&matchingCodecs);
if (err != NULL) {
*err = NAME_NOT_FOUND;
}
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
// 创建MediaCodec实例对象
sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
AString componentName = matchingCodecs[i];
// 调用MediaCodec::init进行初始化
status_t ret = codec->init(componentName);
if (err != NULL) {
*err = ret;
}
if (ret == OK) {
return codec;
}
ALOGD("Allocating component '%s' failed (%d), try next one.", componentName.c_str(), ret);
}
return NULL;
}
status_t MediaCodec::init(const AString &name) {
......
// 实例化ACodec,此处的mCodec未ACodec实例
mCodec = GetCodecBase(localname, owner);
......
// 注册hanlder用于消息处理
mLooper->registerHandler(this);
......
// 发送kWhatInit消息
sp<AMessage> msg = new AMessage(kWhatInit, this);
......
status_t err;
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo));
for (int i = 0; i <= kMaxRetry; ++i) {
if (i > 0) {
// Don't try to reclaim resource for the first time.
if (!mResourceManagerProxy->reclaimResource(resources)) {
break;
}
}
sp<AMessage> response;
err = PostAndAwaitResponse(msg, &response);
if (!isResourceError(err)) {
break;
}
}
return err;
}
sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, const char *owner) {
if (owner) {
if (strcmp(owner, "default") == 0) {
return new ACodec;
} else if (strncmp(owner, "codec2", 6) == 0) {
return CreateCCodec();
}
}
if (name.startsWithIgnoreCase("c2.")) {
return CreateCCodec();
} else if (name.startsWithIgnoreCase("omx.")) {
// at this time only ACodec specifies a mime type.
return new ACodec;
} else if (name.startsWithIgnoreCase("android.filter.")) {
return new MediaFilter;
} else {
return NULL;
}
}
void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
......
case kWhatInit:
{
......
// 调用ACodec::initiateAllocateComponent
mCodec->initiateAllocateComponent(format);
break;
}
......
}
}
frameworks\av\media\libstagefright\ACodec.cpp
void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
msg->setWhat(kWhatAllocateComponent);
msg->setTarget(this);
msg->post();
}
bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
bool handled = false;
switch (msg->what()) {
......
case ACodec::kWhatAllocateComponent:
{
onAllocateComponent(msg);
handled = true;
break;
}
......
}
}
bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
......
sp<CodecObserver> observer = new CodecObserver(notify);
sp<IOMX> omx;
sp<IOMXNode> omxNode;
status_t err = NAME_NOT_FOUND;
// 获取OMX的binder对象
OMXClient client;
if (client.connect(owner.c_str()) != OK) {
mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
return false;
}
omx = client.interface();
pid_t tid = gettid();
int prevPriority = androidGetThreadPriority(tid);
androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
// 申请omx组件
err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
androidSetThreadPriority(tid, prevPriority);
if (err != OK) {
ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
return false;
}
......
// 保存OMX相关对象,此时就和OMX关联起来了
mCodec->mOMX = omx;
mCodec->mOMXNode = omxNode;
// 回调通知MediaCodec
mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str());
mCodec->changeState(mCodec->mLoadedState);
return true;
}
err = mCodec->configure(format, mSurface, crypto, 0 /* flags */);
frameworks\av\media\libstagefright\MediaCodec.cpp
status_t MediaCodec::configure(
const sp<AMessage> &format,
const sp<Surface> &surface,
const sp<ICrypto> &crypto,
const sp<IDescrambler> &descrambler,
uint32_t flags) {
sp<AMessage> msg = new AMessage(kWhatConfigure, this);
......
}
void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
......
case kWhatConfigure:
{
......
setState(CONFIGURING);
......
mCodec->initiateConfigureComponent(format);
break;
}
......
}
}
frameworks\av\media\libstagefright\ACodec.cpp
void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
msg->setWhat(kWhatConfigureComponent);
msg->setTarget(this);
msg->post();
}
bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
bool handled = false;
switch (msg->what()) {
case ACodec::kWhatConfigureComponent:
{
onConfigureComponent(msg);
handled = true;
break;
}
......
}
}
bool ACodec::LoadedState::onConfigureComponent(
const sp<AMessage> &msg) {
ALOGV("onConfigureComponent");
CHECK(mCodec->mOMXNode != NULL);
status_t err = OK;
AString mime;
if (!msg->findString("mime", &mime)) {
err = BAD_VALUE;
} else {
err = mCodec->configureCodec(mime.c_str(), msg);
}
if (err != OK) {
ALOGE("[%s] configureCodec returning error %d", mCodec->mComponentName.c_str(), err);
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
return false;
}
mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat);
return true;
}
status_t ACodec::configureCodec(const char *mime, const sp<AMessage> &msg) {
// 内容很多,主要是通过mCodec->mOMXNode对OMX进行参数配置
......
}
err = mCodec->start();
frameworks\av\media\libstagefright\MediaCodec.cpp
status_t MediaCodec::start() {
sp<AMessage> msg = new AMessage(kWhatStart, this);
......
}
void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
......
case kWhatStart:
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
if (mState == FLUSHED) {
setState(STARTED);
if (mHavePendingInputBuffers) {
onInputBufferAvailable();
mHavePendingInputBuffers = false;
}
mCodec->signalResume();
PostReplyWithError(replyID, OK);
break;
} else if (mState != CONFIGURED) {
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
mReplyID = replyID;
setState(STARTING);
mCodec->initiateStart();
break;
}
......
}
}
frameworks\av\media\libstagefright\ACodec.cpp
void ACodec::initiateStart() {
(new AMessage(kWhatStart, this))->post();
}
bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
bool handled = false;
switch (msg->what()) {
......
case ACodec::kWhatStart:
{
onStart();
handled = true;
break;
}
......
}
}
void ACodec::LoadedState::onStart() {
ALOGV("onStart");
status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
} else {
mCodec->changeState(mCodec->mLoadedToIdleState);
}
}
TODO
TODO
TODO
TODO