牛骨文教育服务平台(让学习变的简单)

3 mediaplayer的核心库libmedia.so

libs/media/mediaplayer.cpp文件用于实现mediaplayer.h提供的接口,其中一个重要的片段如下所示:

const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
{
    Mutex::Autolock _l(mServiceLock);
    if (mMediaPlayerService.get() == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
    do {
        binder = sm->getService(String16("media.player"));
        if (binder != 0)
        break;
        LOGW("MediaPlayerService not published, waiting...");
        usleep(500000); // 0.5 s
        } while(true);
        if (mDeathNotifier == NULL) {
        mDeathNotifier = new DeathNotifier();
    }
        binder->linkToDeath(mDeathNotifier);
        mMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    }
    LOGE_IF(mMediaPlayerService==0, "no MediaPlayerService!?");
    return mMediaPlayerService;
}

其中最重要的一点是binder = sm->getService(String16("media.player"));这个调用用来得到一个名称为"media.player"的服务,这个调用返回值的类型为IBinder,根据实现将其转换成类型IMediaPlayerService使用。

status_t MediaPlayer::setDataSource(const char *url)
{
    LOGV("setDataSource(%s)", url);
    status_t err = UNKNOWN_ERROR;
    if (url != NULL) {
        const sp<IMediaPlayerService>& service(getMediaPlayerService());
        if (service != 0) {
            sp<IMediaPlayer> player(service->create(getpid(), this, url));
            err = setDataSource(player);
        }
    }
    return err;
}

在函数setDataSource函数中,调用getMediaPlayerService得到了一个IMediaPlayerService,又从IMediaPlayerService中得到了IMediaPlayer类型的指针,通过这个指针进行着具体的操作。
其他一些函数的实现也与setDataSource类似。

为了实现Binder的具体功能,在这些类中还需要实现一个BpXXX的类,例如IMediaPlayerClient.cpp的实现如下所示:l

class BpMediaPlayerClient: public BpInterface<IMediaPlayerClient>
{
public:
    BpMediaPlayerClient(const sp<IBinder>& impl)
    : BpInterface<IMediaPlayerClient>(impl){}
    virtual void notify(int msg, int ext1, int ext2)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor());
        data.writeInt32(msg);
        data.writeInt32(ext1);
        data.writeInt32(ext2);
        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
    }
};

以上的实现都是基于Binder框架的实现方式,只需要按照模版实现即可。其中BpXXX的类为代理类(proxy),BnXXX的类为本地类(native)。代理类的transact函数和本地类的onTransact函数实现对应的通讯。

4 media服务libmediaservice.so

多媒体服务的守护进程的代码:frameworks/base/media/mediaserver/其中只有一个源文件main_mediaserver.cpp,将被编译成为一个可执行程序mediaserver。它负责启
动了多媒体服务、照相机服务,音频服务这三个服务

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

frameworks/base/medialibmediaplayerservice目录中的MediaPlayerService.h和MediaPlayerService.cpp用于实现一个
servers/media/的服务,MediaPlayerService是继承BnMediaPlayerService的实现,在这个类的内部又定义了类Client,MediaPlayerService::Client继承了BnMediaPlayer。

class MediaPlayerService : public BnMediaPlayerService
{
    class Client : public BnMediaPlayer
}

   在MediaPlayerService中具有如下一个静态函数instantiate:

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
    String16("media.player"), new MediaPlayerService());
}

在instantiate函数中,调用IServiceManager的一个函数addService,向其中增加了一个名为"media.player"的服务。
这个名为"media.player"的服务和mediaplayer.cpp中调用getService中得到的使用一样名称。因此,在这里调用addService增加服务在mediaplayer.cpp中可以按照名称"media.player"来使用。这就是使用Binder实现进程间通讯的(IPC)的作用,事实上这个MediaPlayerService类是在服务中运行的,而mediaplayer.cpp调用的功能在应用中运行,二者并不是一个进程。但是在mediaplayer.cpp却像一个进程的调用一样调用MediaPlayerService的功能。

 在MediaPlayerService.cpp中的createPlayer函数如下所示:

static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
        notify_callback_f notifyFunc)
{
    sp<MediaPlayerBase> p;
    switch (playerType) {
#ifndef NO_OPENCORE
        case PV_PLAYER:
            LOGV(" create PVPlayer");
            p = new PVPlayer();
            break;
#endif
        case SONIVOX_PLAYER:
            LOGV(" create MidiFile");
            p = new MidiFile();
            break;
        case VORBIS_PLAYER:
            LOGV(" create VorbisPlayer");
            p = new VorbisPlayer();
            break;
#if BUILD_WITH_FULL_STAGEFRIGHT
        case STAGEFRIGHT_PLAYER:
            LOGV(" create StagefrightPlayer");
            p = new StagefrightPlayer;
            break;
#endif
        case TEST_PLAYER:
            LOGV("Create Test Player stub");
            p = new TestPlayerStub();
            break;
    }
    if (p != NULL) {
        if (p->initCheck() == NO_ERROR) {
            p->setNotifyCallback(cookie, notifyFunc);
        } else {
            p.clear();
        }
    }
    if (p == NULL) {
        LOGE("Failed to create player object");
    }
    return p;
}

在这里根据playerType的类型建立不同的播放器:对于大多数情况,类型将是PV_PLAYER,这时会调用了new PVPlayer()建立一个PVPlayer,然后将其指针转换成MediaPlayerBase来使用;对于Mini文件的情况,类型为SONIVOX_PLAYER,将会建立一个MidiFile;对于Ogg Vorbis格式的情况,将会建立一个VorbisPlayer。
(OGG Vobis是一种音频压缩格式,与MP3等的音乐格式类似,它具有完全免费、开放和没有专利限制的特点。)
值得注意的是PVPlayer、MidiFile和VorbisPlayer三个类都是继承MediaPlayerInterface得到的,而MediaPlayerInterface又是继承MediaPlayerBase得到的,因此三者具有相同接口类型。只有建立的时候会调用各自的构造函数,在建立之后,将只通过MediaPlayerBase接口来MediaPlayerBase控制它们。
   在frameworks/base/media/libmediaplayerservice目录中,MidiFile.h和MidiFile.cpp的实现MidiFile,VorbisPlayer.h和VorbisPlayer.cpp实现一个VorbisPlayer。