android mediaplayer 分析

http://hi.baidu.com/dean_wang/blog/item/c45aec3a96b30ed5d4622515.html

剖析android的MediaPlay.java的JNI实现;【封装太深】

 

MediaPlay.java在源码frameworks\base\media\java\android\media文件夹位置;

所有的JNI接口实现在frameworks\base\media\jni下android_media_MediaPlayer.cpp文件;

从初始化开始;

MediaPlay.java:

static {

        System.loadLibrary("media_jni");

        native_init();

    }

调用了native_init;映射到android_media_MediaPlayer.cpp的android_media_MediaPlayer_native_init函数,主要进行该cpp内struct 变量field的初始化;

 

MediaPlayer.java的构造函数调用native_setup函数映射到android_media_MediaPlayer_native_setup函数,主要操作是:

sp mp = new MediaPlayer();

setMediaPlayer(env, thiz, mp);

构造了一个MediaPlayer类并将指针赋值给上层MediaPlayer.java的mNativeContext变量;

 

JNI层 的MediaPlayer是一个C++类,头文件在frameworks\base\include\media\mediaplayer.h,实现在frameworks\base\media\libmedia\mediaplayer.cpp;

 

来看mediaplayer.h函数的setDataSource实现;两个不同参数的setDataSource函数都调用了

const sp& service(getMediaPlayerService());

sp player(service->create(getpid(), this, url, headers));

setDataSource(player);

上述代码有两步:1、getMediaPlayerService,并调用service->create;2、调用另一个内部的函数setDataSource(player);

第二步做的主要事情就是将第一步创建出来的player设置为mPlayer;

分析第一步:

getMediaPlayerService()函数是底层MediaPlayer的父类IMediaDeathNotifier的一个成员函数:

IMediaDeathNotifier::getMediaPlayerService()

{

    LOGV("getMediaPlayerService");

    Mutex::Autolock _l(sServiceLock);

    if (sMediaPlayerService.get() == 0) {

        sp sm = defaultServiceManager();

        sp binder;

        do {

            binder = sm->getService(String16("media.player"));

            if (binder != 0) {

                break;

             }

             LOGW("Media player service not published, waiting...");

             usleep(500000); // 0.5 s

        } while(true);

 

        if (sDeathNotifier == NULL) {

        sDeathNotifier = new DeathNotifier();

    }

    binder->linkToDeath(sDeathNotifier);

    sMediaPlayerService = interface_cast(binder);

    }

    LOGE_IF(sMediaPlayerService == 0, "no media player service!?");

    return sMediaPlayerService;

}

defaultServiceManager函数是frameworks/base/libs/utils/IServiceManager.cpp下实现,头文件是frameworks\base\include\binder\IServiceManager.h;

基本上到这一步就是系统服务管理的东西了。打止。

 

回到MediaService;查看frameworks\base\media\libmediaplayerservice\MediaPlayerService.h和MediaPlayerService.cpp文件;找create函数;

sp MediaPlayerService::create(pid_t pid, const sp& client,

        int fd, int64_t offset, int64_t length)

{

    int32_t connId = android_atomic_inc(&mNextConnId);

    sp c = new Client(this, pid, connId, client);

    LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",

            connId, pid, fd, offset, length);

    if (NO_ERROR != c->setDataSource(fd, offset, length)) {

        c.clear();

    } else {

        wp w = c;

        Mutex::Autolock lock(mLock);

        mClients.add(w);

    }

    ::close(fd);

    return c;

}

另外一个函数大致流程也一样,只不过接收参数是URL;都是先创建一个Client然后调用Client的setDataSource方法;

Client是MediaPlayerService的一个内部类;在MediaPlayerService.cpp文件内找到Client里面的setDataSource方法实现:

status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)

{

    LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);

    struct stat sb;

    int ret = fstat(fd, &sb);

    if (ret != 0) {

        LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));

        return UNKNOWN_ERROR;

    }

 

    LOGV("st_dev  = %llu", sb.st_dev);

    LOGV("st_mode = %u", sb.st_mode);

    LOGV("st_uid  = %lu", sb.st_uid);

    LOGV("st_gid  = %lu", sb.st_gid);

    LOGV("st_size = %llu", sb.st_size);

 

    if (offset >= sb.st_size) {

        LOGE("offset error");

        ::close(fd);

        return UNKNOWN_ERROR;

    }

    if (offset + length > sb.st_size) {

        length = sb.st_size - offset;

        LOGV("calculated length = %lld", length);

    }

 

    player_type playerType = getPlayerType(fd, offset, length);

    LOGV("player type = %d", playerType);

 

    // create the right type of player

    sp p = createPlayer(playerType);

    if (p == NULL) return NO_INIT;

 

    if (!p->hardwareOutput()) {

        mAudioOutput = new AudioOutput();

        static_cast(p.get())->setAudioSink(mAudioOutput);

    }

 

    // now set data source

    mStatus = p->setDataSource(fd, offset, length);

    if (mStatus == NO_ERROR) mPlayer = p;

    return mStatus;

}

Client做的主要事情:

1、调用getPlayerType

2、调用createPlayer创建一个MediaPlayerBase并调用其setDataSource方法


你可能感兴趣的:(android,frameworks,jni,service,include,struct)