admin管理员组

文章数量:1609986

1.Video Playback的流程
在Android上,预设的多媒体框架(multimedia framework)是OpenCORE。OpenCORE的优点是兼顾了跨平台的移植性,而且已经过多方验证,所以相对来说较為稳定;但是其缺点是过於庞大复杂,需要耗费相当多的时间去维护。从Android 2.0开始,Google引进了架构稍為简洁的Stagefright,并且有逐渐取代OpenCORE的趋势 (註1)。

[图1] Stagefright在Android多媒体架构中的位置。

[图2] Stagefright所涵盖的模组 (註2)。
以下我们就先来看看Stagefright是如何播放一个影片档。
Stagefright在Android中是以shared library的形式存在(libstagefright.so),其中的module – AwesomePlayer可用来播放video/audio (註3)。AwesomePlayer提供许多API,可以让上层的应用程式(Java/JNI)来呼叫,我们以一个简单的程式来说明video playback的流程。
在Java中,若要播放一个影片档,我们会这样写:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE); … (1)
mp.prepare(); … (2)、(3)
mp.start(); … (4)
在Stagefright中,则会看到相对应的处理;
(1) 将档案的绝对路径指定给mUri

status_t AwesomePlayer::setDataSource(const char* uri, …)
{
return setDataSource_l(uri, …);
}
status_t AwesomePlayer::setDataSource_l(const char* uri, …)
{
mUri = uri;
}

(2)启动mQueue,作为event handler

status_t AwesomePlayer::prepare()
{
return prepare_l();
}
status_t AwesomePlayer::prepare_l()
{
prepareAsync_l();
while (mFlags & PREPARING)
{
mPreparedCondition.wait(mLock);
}
}
status_t AwesomePlayer::prepareAsync_l()
{
mQueue.start();
mFlags |= PREPARING;
mAsyncPrepareEvent = new AwesomeEvent(this&AwesomePlayer::onPrepareAsyncEvent);
mQueue.postEvent(mAsyncPrepareEvent);
}

(3) onPrepareAsyncEvent被触发

void AwesomePlayer::onPrepareAsyncEvent()
{
finishSetDataSource_l();
initVideoDecoder(); … (3.3)
initAudioDecoder();
}
status_t AwesomePlayer::finishSetDataSource_l()
{
dataSource = DataSource::CreateFromURI(mUri.string(), …);
sp extractor =MediaExtractor::Create(dataSource); … (3.1)
return setDataSource_l(extractor); … (3.2)
}

(3.1) 解析mUri所指定的档案,并且根据其header来选择对应的extractor

sp MediaExtractor::Create(const sp &source, …)
{
source->sniff(&tmp, …);
mime = tmp.string();
if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
{
return new MPEG4Extractor(source);
}
else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG))
{
return new MP3Extractor(source);
}
else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
{
return new AMRExtractor(source);
}
}

(3.2) 使用extractor对档案做A/V(Audio/Video)的分离 (mVideoTrack/mAudioTrack)

status_t AwesomePlayer::setDataSource_l(const sp &extractor)
{
for (size_t i = 0; i < extractor->countTracks(); ++i)
{
sp meta = extractor->getTrackMetaData(i);
CHECK(meta->findCString(kKeyMIMEType, &mime));
if(!haveVideo && !strncasecmp(mime, “video/”, 6))
{
setVideoSource(extractor->getTrack(i));
haveVideo = true;
}
else if (!haveAudi

本文标签: 流程Videoplayback