video/audio playback:setDataSource

原创 2012年03月27日 11:21:23

实现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_t MediaPlayer::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 player setDataSource

    {

        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;

}

stagefright框架(六)-Audio Playback的流程

到目前為止,我們都只著重在video處理的部分,對於audio卻隻字未提。這篇文章將會開始audio處理的流程。Stagefright中關於audio的部分是交由AudioPlayer來處理,它是在A...
  • zjc0888
  • zjc0888
  • 2011年03月26日 11:40
  • 2428

Android中MediaPlayer的setDataSource方法的使用

MediaPlayer.java文件路径:frameworks/base/media/java/android/media/MediaPlayer.javaMediaPlayer的setDataSou...
  • yanlinembed
  • yanlinembed
  • 2016年09月23日 20:39
  • 9472

Android MediaPlayer使用方法简单介绍---(setdatasource)

1)如何获得MediaPlayer实例: 可以使用直接new的方式: MediaPlayer mp = new MediaPlayer(); 也可以使用create的方式,如: ...
  • u013366022
  • u013366022
  • 2014年05月21日 10:12
  • 4687

Android Multimedia框架总结(三)MediaPlayer中创建到setDataSource过程

前言:前一篇的mediaPlayer框架,对于各个模块的关系,得先从核心类MediaPlayer铺开,同样看下今天的Agenda: - MediaPlayer从create到setDisplay时序图...
  • hejjunlin
  • hejjunlin
  • 2016年09月01日 01:32
  • 8322

Android N Audio播放二:setDataSource窥探

在上一篇Android如何播放一首音乐中介绍了如何使用MediaPlayer来播放音乐文件。可以看到,步骤非常简单。player.setDataSource(path); player.prepare...
  • Liu1314you
  • Liu1314you
  • 2017年02月13日 14:33
  • 976

关于音频播放使用setDataSource(String path)遇到的问题

遇到的一个问题是要播放data/data/package/files/o.mp3 是一直说prepare失败,当放到sd卡下面却没有问题,后来发现当把setDataSource(String path...
  • Mr_Tony
  • Mr_Tony
  • 2015年12月24日 15:01
  • 768

Java中使用SQL标签库<sql:setDataSource />设置数据源

setDataSource标签用于生成一个数据源,需要制定JDBC驱动、数据库连接URL、数据库用户名密码等,例如: setDataSource.jsp ...
  • wuruiaoxue
  • wuruiaoxue
  • 2016年02月15日 05:25
  • 1399

MediaPlayer中设定数据源的几种方法

作者:孔祥辉 前言          MediaPlayer类是android的sdk中实现多媒体支持的非常重要的一部分。内嵌了 ,支持等几种格式。对其的应用是我们通常情况下实现多媒体播放的必经之...
  • pku_android
  • pku_android
  • 2012年04月14日 10:53
  • 3509

【Android笔记】MediaPlayer基本使用方式

Android MediaPlayer基本使用方式 使用MediaPlayer播放音频或者视频的最简单例子:JAVA代码部分:public class MediaPlayerStudy extends...
  • ddna
  • ddna
  • 2010年01月11日 17:21
  • 175772

Java中使用SQL标签库<sql:setDataSource />设置数据源

setDataSource标签用于生成一个数据源,需要制定JDBC驱动、数据库连接URL、数据库用户名密码等,例如: setDataSource.jsp ...
  • wuruiaoxue
  • wuruiaoxue
  • 2016年02月15日 05:25
  • 1399
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:video/audio playback:setDataSource
举报原因:
原因补充:

(最多只允许输入30个字)