video/audio playback:setDataSource

来源:互联网 发布:前端 后端 知乎 编辑:程序博客网 时间:2024/05/01 06:36

实现video/audio playerback,需要经过如下步骤:

MediaPlayer mp = new MediaPlayer();   

mp.setDataSource(String URL/FILE_PATH);   

mp.prepare();   

mp.start();

 

首先是setDataSource创建player,如果url是以content://形式的转换为FD,并提取出mAudioTrack/mVideoTrack保存起来,如果url是以http://之类的在线播放多媒体信息,需去下载SDP文件,找到url存储起来

1.framework/base/media/libmedia/ MediaPlayer.cpp

status_tMediaPlayer::setDataSource(

       const char *url, const KeyedVector<String8, String8> *headers) {

     (1)  const sp<IMediaPlayerService>& service(getMediaPlayerService()); ……首先获得mediaplayerService的服务

    if (service != 0) {

    2    sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));

    3 err = setDataSource(player);

    }

    return err;

}

2. framework/base/media/libmediaplayerservice/ MediaPlayerService.cpp

sp<IMediaPlayer> MediaPlayerService::create(

        pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,

        const KeyedVector<String8, String8> *headers, int audioSessionId)

{

….

    sp<Client> c = new Client(this, pid, connId, client, audioSessionId); …. 新建个mediaplayerservice client 的实例,即整个播放过程由这个实例控制

………

if (NO_ERROR != c->setDataSource(url, headers))…..create playersetDataSource

    {

        c.clear();

        return c;

    }

   

}

 

status_t MediaPlayerService::Client::setDataSource(

        const char *url, const KeyedVector<String8, String8> *headers)

{….

如果是url content://开头要转换为file descriptor

    if (strncmp(url, "content://", 10) == 0) {…

        int fd = android::openContentProviderFile(url16);

……….

        setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus

        close(fd);

        return mStatus;

    } else {

        player_type playerType = getPlayerType(url);…. createplayer前要判断是哪种类型

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

 

        // create the right type of player

        sp<MediaPlayerBase> p = createPlayer(playerType);

        mStatus = p->setDataSource(url, headers);

…       

return mStatus;

    }

}

 

player_type getPlayerType(const char* url) …………….根据url的后缀名判断属于哪种playerType,默认是stagefright

{

    if (TestPlayerStub::canBeUsed(url)) {

        return TEST_PLAYER;

    }

 

    // use MidiFile for MIDI extensions

    int lenURL = strlen(url);

    for (int i = 0; i < NELEM(FILE_EXTS); ++i) {

        int len = strlen(FILE_EXTS[i].extension);

        int start = lenURL - len;

        if (start > 0) {

            if (!strncasecmp(url + start,FILE_EXTS[i].extension, len)) {

                return FILE_EXTS[i].playertype;

            }

        }

    }

……………….

    return getDefaultPlayerType();

}

 

有如下类型的playerType

 

typedef struct {

    const char *extension;

    const player_type playertype;

} extmap;

extmap FILE_EXTS [] =  {

        {".mid", SONIVOX_PLAYER},

        {".midi", SONIVOX_PLAYER},

        {".smf", SONIVOX_PLAYER},

        {".xmf", SONIVOX_PLAYER},

        {".mxmf", SONIVOX_PLAYER},

        {".imy", SONIVOX_PLAYER},

        {".rtttl", SONIVOX_PLAYER},

        {".rtx", SONIVOX_PLAYER},

        {".ota", SONIVOX_PLAYER},

        {".mnv", SOLS_PLAYER},

        {".mnvtmp", SOLS_PLAYER},

#ifndef NO_OPENCORE

        {".wma", PV_PLAYER},

        {".wmv", PV_PLAYER},

        {".asf", PV_PLAYER},

#endif

};

 

 sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)

{…….  if (p == NULL) {

        p = android::createPlayer(playerType, this, notify);

    }

    return p;

}

 

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 STAGEFRIGHT_PLAYER:

            LOGV(" create StagefrightPlayer");

            p = new StagefrightPlayer;   

            break;

        case TEST_PLAYER:

            LOGV("Create Test Player stub");

            p = new TestPlayerStub();

            break;

        case SOLS_PLAYER:

            LOGV(" create SolsStagefrightPlayer");

            p = new SolsStagefrightPlayer;

            break;

    }….

    return p;

}

 

3, framework/base/media/libmediaplayerservice/StagefrightPlayer.cpp

创建stagefrightplayer实例也new了个AwesomePlayer(mPlayer)

StagefrightPlayer::StagefrightPlayer()

    : mPlayer(new AwesomePlayer) {

    LOGV("StagefrightPlayer");

 

    mPlayer->setListener(this);

}

4, framework/base/media/libStagefright/ AwesomePlayer.cpp

AwesomePlayer setDataSource 根据传过来的是 url(http://..),还是fd进行不同的处理

url:记录下url  http request header , mediaextract::finishSetDataSource_l中进行。

status_t AwesomePlayer::setDataSource_l(

        const char *uri, const KeyedVector<String8, String8> *headers) {

    LOGV("setDataSource '%s'", uri);

    // Check for sdp

    status_t err;

    if (headers) {

        mUriHeaders = *headers;

    }…….

    if (extension.length() == 4 && !strncasecmp(extension.string(), ".sdp", 4)) {

        //found sdp

        if (!strncasecmp("http://", tmpString8Uri.string(), 7)) {

            LOGV("found SDP file over http");

            String8 newUri;

            err = getUriFromSDP(uri, &newUri);…………..Download SDP, parse and return found URI                    SDP:Service Data Point业务数据点

            if (err == OK) {

                return setDataSource_l(newUri.string(), headers);

            } else {

..

            }

        }

    }

    reset_l();

    mUri = uri;

    return OK;

}

FD形式:根据FD生成filesource,后找到匹配的mediaextractor--->mVideoTrack/mAudioTrack

status_t AwesomePlayer::setDataSource(

       int fd, int64_t offset, int64_t length) {

    Mutex::Autolock autoLock(mLock);

    reset_l();

    sp<DataSource> dataSource = new FileSource(fd, offset, length);

…..

    return setDataSource_l(dataSource);

}

status_t AwesomePlayer::setDataSource_l(

       const sp<DataSource> &dataSource) {

    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);…….创建对应的extractor

…..

    return setDataSource_l(extractor);

}

status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {

        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {

            setVideoSource(extractor->getTrack(i)); ………>mVideoTrack

            haveVideo = true;

        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {

            setAudioSource(extractor->getTrack(i));……….>mAudioTrack

            haveAudio = true;

    return OK;

}

原创粉丝点击