NuPlayer的解码引入了 NuPIayerDecoderBase,这是一个基类。真正的解码器逻辑在 NuPlayerDecoder.cpp文件中,它继承自NuPlayerDecoderBase类。下面先看看实例化解码器, 其位于
frameworksavmedialibmediaplayerservicenuplayerNuPlayer.cpp
中:
代码语言:javascript复制 status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) {
//音频解码器可以清除由tear down。如果仍然在关闭
//进程,不需要创建一个新的音频解码器。
if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) {
return OK;
}
sp<AMessage> format = mSource->getFormat(audio);
if (format == NULL) {
return -EWOULDBLOCK;
}
format->setInt32("priority", 0 /* realtime */);
if (!audio) {
AString mime;
CHECK(format->findString("mime", &mime));
sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, this);
if (mCCDecoder == NULL) {
mCCDecoder = new CCDecoder(ccNotify);
}
if (mSourceFlags & Source::FLAG_SECURE) {
format->setInt32("secure", true);
}
if (mSourceFlags & Source::FLAG_PROTECTED) {
format->setInt32("protected", true);
}
float rate = getFrameRate();
if (rate > 0) {
format->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed);
}
}
if (audio) {
sp<AMessage> notify = new AMessage(kWhatAudioNotify, this);
mAudioDecoderGeneration;
notify->setInt32("generation", mAudioDecoderGeneration);
determineAudioModeChange();
if (mOffloadAudio) {
const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL);
format->setInt32("has-video", hasVideo);
*decoder = new DecoderPassThrough(notify, mSource, mRenderer);
} else {
*decoder = new Decoder(notify, mSource, mPID, mRenderer);
}
} else {
sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
mVideoDecoderGeneration;
notify->setInt32("generation", mVideoDecoderGeneration);
*decoder = new Decoder(
notify, mSource, mPID, mRenderer, mSurface, mCCDecoder);
// enable FRC if high-quality AV sync is requested, even if not
// directly queuing to display, as this will even improve textureview
// playback.
{
char value[PROPERTY_VALUE_MAX];
if (property_get("persist.sys.media.avsync", value, NULL) &&
(!strcmp("1", value) || !strcasecmp("true", value))) {
format->setInt32("auto-frc", 1);
}
}
}
(*decoder)->init();
(*decoder)->configure(format);
// allocate buffers to decrypt widevine source buffers
Vector<sp<ABuffer> > inputBufs;
CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK);
Vector<MediaBuffer *> mediaBufs;
for (size_t i = 0; i < inputBufs.size(); i ) {
const sp<ABuffer> &buffer = inputBufs[i];
MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size());
mediaBufs.push(mbuf);
}
status_t err = mSource->setBuffers(audio, mediaBufs);
if (err != OK) {
for (size_t i = 0; i < mediaBufs.size(); i) {
mediaBufs[i]->release();
}
mediaBufs.clear();
ALOGE("Secure source didn't support secure mediaBufs.");
return err;
}
}
return OK;
}
上面的代码构造了 Decoder对象,且进行了初始化和构建解码器。 由于 NuPlayerDecoder 继承自 NuPlayerDecoderBase 类,所以 Configure 函数会执行 NuPlayerDecoder 的 Configure 函数,最终回调 onConfigure 函数,其位于 frameworksavmedia libmediaplayerservicenuplayerNuPIayerDecoder.cpp 中, 代码如下:
代码语言:javascript复制void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
CHECK(mCodec == NULL);
mFormatChangePending = false;
mTimeChangePending = false;
mBufferGeneration;
AString mime;
CHECK(format->findString("mime", &mime));
mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
mComponentName = mime;
mComponentName.append(" decoder");
ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
mCodec = MediaCodec::CreateByType(
mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid);
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);
}
}
if (mCodec == NULL) {
ALOGE("Failed to create %s%s decoder",
(secure ? "secure " : ""), mime.c_str());
handleError(UNKNOWN_ERROR);
return;
}
mIsSecure = secure;
mCodec->getName(&mComponentName);
status_t err;
if (mSurface != NULL) {
// MediaCodec将重新连接时断开与surface的连接
err = native_window_api_disconnect(
mSurface.get(), NATIVE_WINDOW_API_MEDIA);
//我们认为这是一个警告,因为这是一个准备步骤。
// Codec将尝试连接到表面
//任何错误信号都会发生。
ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
}
err = mCodec->configure(
format, mSurface, NULL /* crypto */, 0 /* flags */);
if (err != OK) {
ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
mCodec->release();
mCodec.clear();
handleError(err);
return;
}
rememberCodecSpecificData(format);
// the following should work in configured state
CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
mStats->setString("mime", mime.c_str());
mStats->setString("component-name", mComponentName.c_str());
if (!mIsAudio) {
int32_t width, height;
if (mOutputFormat->findInt32("width", &width)
&& mOutputFormat->findInt32("height", &height)) {
mStats->setInt32("width", width);
mStats->setInt32("height", height);
}
}
sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
mCodec->setCallback(reply);
err = mCodec->start();
if (err != OK) {
ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
mCodec->release();
mCodec.clear();
handleError(err);
return;
}
releaseAndResetMediaBuffers();
mPaused = false;
mResumePending = false;
}
从onConfigure函数可以看到,NuPlayerDecoder引入了 MediaCodec作为解码器。通过 CreateByType/CreateByComponentName 创建了 Codec 对象。