6. Android MultiMedia框架完全解析 - NuPlayerDriver与NuPlayer的通信
先解决NuPlayer与NuPlayerDriver的通信过程,在之前的文章中,都说了NuPlayerDriver是NuPlayer的一个Wrapper,上层的指令发送给NuPlayerDriver后,NuPlayer作为NuPlayerDriver的一个成员变量,NuPlayerDriver想调用NuPlayer的话,就相当简单。当NuPlayer完成一个指令后,如何通知NuPlayerDriver呢?下面我们就以setVideoSurfaceTexture为例来讲解一下(虽然这个函数的历程还没有追过,但是不影响这里的讨论):
当上层调用setVideoSurfaceTexture()时,根据之前的分析,最终会传递到NuPlayerDriver这里,来看看NuPlayerDriver是如何实现的:
status_t NuPlayerDriver::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer> &bufferProducer) {
......
mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
while (mSetSurfaceInProgress) {
mCondition.wait(mLock);
}
return OK;
}
在这里,sp<NuPlayer> mPlayer作为NuPlayerDriver中的一个成员变量,在NuPlayerDriver的构造函数中,就已经为他赋值,就是NuPlayer,所以,通过mPlayer->setVideoSurfaceTextureAsync(bufferProducer);这个命令,就可以跳转到NuPlayer中去执行它的setVideoSurfaceTextureAsync()函数,同时,NuPlayerDriver中会通过一个条件变量 mCondition 去等待这个函数的执行完毕。
我们再到NuPlayer中看看setVideoSurfaceTextureAsync这个函数:
void NuPlayer::setVideoSurfaceTextureAsync(
const sp<IGraphicBufferProducer> &bufferProducer) {
sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
if (bufferProducer == NULL) {
msg->setObject("surface", NULL);
} else {
msg->setObject("surface", new Surface(bufferProducer, true /* controlledByApp */));
}
msg->post();
}
它使用了AHanlder-ALooper-AMessage机制(NuPlayer中使用的一种机制,在7.中讲解),最终就会执行到NuPlayer::onMessageReceived函数的kWhatSetVideoSurface case中:
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
case kWhatSetVideoSurface:
{
......
if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) {
performSetSurface(surface);
break;
}
看看这个performSetSurface函数的过程:
void NuPlayer::performSetSurface(const sp<Surface> &surface) {
ALOGV("performSetSurface");
mSurface = surface;
// XXX - ignore error from setVideoScalingMode for now
setVideoScalingMode(mVideoScalingMode);
if (mDriver != NULL) {
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
driver->notifySetSurfaceComplete();
}
}
}
看到这里,应该就有点概念了,NuPlayer以mPlayer这个成员变量存在于NuPlayerDriver结构体中,同样的,NuPlayerDriver以 wp<NuPlayerDriver> mDriver; 的形式存在于NuPlayer中,它也是在NuPlayer的构造函数中赋值的。通过mDriver.promote()的方法就可以使弱指针升级成强指针sp<NuPlayerDriver> driver,这时候这个driver就是NuPlayerDriver了,下面的driver->notifySetSurfaceComplete()函数就是在NuPlayerDriver中实现的了:
void NuPlayerDriver::notifySetSurfaceComplete() {
ALOGV("notifySetSurfaceComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
CHECK(mSetSurfaceInProgress);
mSetSurfaceInProgress = false;
mCondition.broadcast();
}
通过发送广播,来通知NuPlayerDriver::setVideoSurfaceTexture()函数,NuPlayer执行完SetVideoSurfaceTexture了。