实现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;
}
来自:video-audio playback:setDataSource - 太妃糖的专栏 - 博客频道 - CSDN_NET.mht