MediaPlayer补充
一般播放器模式:三个线程
1.解码线程:audiotrack将数据解码出来往共享缓存写
2.播放线程:AudioFlinger中的播放线程从共享缓存读取数据,然后往bsp写
3.控制线程:控制视频和音频的播放,从而保持一致。
status_t AwesomePlayer::prepareAsync_l() { if (!mQueueStarted) { mQueue.start(); //开启一个事件队列,不停的处理各种事件 mQueueStarted = true; } modifyFlags(PREPARING, SET); mAsyncPrepareEvent = new AwesomeEvent(this, &AwesomePlayer::onPrepareAsyncEvent); mQueue.postEvent(mAsyncPrepareEvent); //发送第一个事件:PrepareAsyncEvent,做些初始化的事件。当处理这个事情的时候回调AwesomePlayer::onPrepareAsyncEvent return OK; }
//做一些初始化的操作:初始化AudioDecoder和VideoDecoder
void AwesomePlayer::onPrepareAsyncEvent() { finishSetDataSource_l(); initVideoDecoder(); initAudioDecoder(); } status_t AwesomePlayer::finishSetDataSource_l() { dataSource = DataSource::CreateFromURI(mUri.string(),...); sp<</span>MediaExtractor> extractor= MediaExtractor::Create(dataSource); //依据mime类型来创建对应的解码器
return setDataSource_l(extractor); //然后依据extractor做A/V分离 }
视频文件存储数据方式:一段一段的存储,每一段都有个头标识这一段是视频部分还是音频部分。
http://blog.csdn.net/mci2004/article/details/7629146
awesomeplayer中主要有如下几个事件
sp<TimedEventQueue::Event> mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); --- 显示一帧画面,并负责同步处理
sp<TimedEventQueue::Event> mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); -- 播放结束的处理
sp<TimedEventQueue::Event> mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); -- cache数据
sp<TimedEventQueue::Event> mCheckAudioStatusEvent = new AwesomeEvent(this, &AwesomePlayer::onCheckAudioStatus); -- 监测audio 状态:seek以及播放结束
sp<TimedEventQueue::Event> mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate); -- 监测video 解码性能
sp<TimedEventQueue::Event> mAsyncPrepareEvent = new AwesomeEvent(this, &AwesomePlayer::onPrepareAsyncEvent); -- 完成prepareAsync工作
----------------------------------------------------------------------------------------------------------------------
把音视频轨道分离,生成mVideoTrack和mAudioTrack两个MediaSource。代码如下(AwesomePlayer.cpp):
if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
setVideoSource(extractor->getTrack(i));
haveVideo = true;
} else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
setAudioSource(extractor->getTrack(i));
haveAudio = true;
}
得到的这两个MediaSource,只具有parser功能,没有decode功能。还需要对这两个MediaSource做进一步的包装,获取了两个MediaSource(具有parse和decode功能):
initVideoDecoder()
mVideoSource = OMXCodec::Create(
mClient.interface(), mVideoTrack->getFormat(),
false, // createEncoder
mVideoTrack,
NULL, flags);
initAudioDecoder()
mAudioSource = OMXCodec::Create(
mClient.interface(), mAudioTrack->getFormat(),
false, // createEncoder
mAudioTrack);
当调用MediaSource.start()方法后,它的内部就会开始从数据源获取数据并解析,等到缓冲区满后便停止。在AwesomePlayer里就可以调用MediaSource的read方法读取解码后的数据。
对于mVideoSource来说,读取的数据:mVideoSource->read(&mVideoBuffer, &options)交给显示模块进行渲染,mVideoRenderer->render(mVideoBuffer);
对mAudioSource来说,用mAudioPlayer对mAudioSource进行封装,然后由mAudioPlayer负责读取数据和播放控制。
-----------------------------------------------------------------------------------------------------------------------------
//MediaPlayer.cpp
new MediaPlayer() {
mStreamType = AUDIO_STREAM_MUSIC;//给的默认流类型是MUSIC
}
status_t MediaPlayer::prepare()
{
status_t ret = prepareAsync_l();
}
status_t MediaPlayer::prepareAsync_l()
{
mPlayer->setAudioStreamType(mStreamType);
mCurrentState = MEDIA_PLAYER_PREPARING;
return mPlayer->prepareAsync();
}
-----------------------------------------------------------------------------------------------
static player_type getDefaultPlayerType() {
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.use-awesome", value, NULL)
&& (!strcmp("1", value) || !strcasecmp("true", value))) {
return STAGEFRIGHT_PLAYER;
}
// TODO: remove this EXPERIMENTAL developer settings property
if (property_get("persist.sys.media.use-awesome", value, NULL)
&& !strcasecmp("true", value)) {
return STAGEFRIGHT_PLAYER;
}
return NU_PLAYER;
}
enum player_type {
PV_PLAYER = 1,
SONIVOX_PLAYER = 2,
STAGEFRIGHT_PLAYER = 3,
NU_PLAYER = 4,
TEST_PLAYER = 5,
DLNA_PLAYER = 1001,
DTCPIP_PLAYER = 1002,
};
sony播放器优先使用NuPlayer来播放
~/log$ adb shell getprop |grep stagefright
[media.stagefright.enable-aac]: [true]
[media.stagefright.enable-fma2dp]: [true]
[media.stagefright.enable-http]: [true]
[media.stagefright.enable-player]: [true]
[media.stagefright.enable-qcp]: [true]
[media.stagefright.enable-scan]: [true]
daichenghui@daichenghui-OptiPlex-3020:~/log$
为了使用stagefrightplayer来播放,可以设置属性来达到目的
adb root && adb remount
adb shell setprop media.stagefright.use-awesome 1 //这里也可以设置成true
~/log$ adb shell getprop |grep stagefright
[media.stagefright.enable-aac]: [true]
[media.stagefright.enable-fma2dp]: [true]
[media.stagefright.enable-http]: [true]
[media.stagefright.enable-player]: [true]
[media.stagefright.enable-qcp]: [true]
[media.stagefright.enable-scan]: [true]
[media.stagefright.use-awesome]: [1]
daichenghui@daichenghui-OptiPlex-3020:~/log$
---------------------------------------------------------------------------
stagefright框架播放时,都会不停的调用size_t AudioPlayer::fillBuffer(void *data, size_t size)
而且AudioPlayer: mAudioSink.get() != NULL 也就是说回调函数是AudioSinkCallback
1.如果播放mp3数据 offload模式播放
2.如果播放raw AudioPlayer: buffer->size() = 32766, mPositionTimeMediaUs=0.00 mPositionTimeRealUs=0.00
size_t AudioPlayer::AudioSinkCallback( MediaPlayerBase::AudioSink * /* audioSink */, void *buffer, size_t size, void *cookie, MediaPlayerBase::AudioSink::cb_event_t event) { AudioPlayer *me = (AudioPlayer *)cookie; switch(event) { case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER: return me->fillBuffer(buffer, size); case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END: ALOGV("AudioSinkCallback: stream end"); me->mReachedEOS = true; me->notifyAudioEOS(); break; case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN: ALOGV("AudioSinkCallback: Tear down event"); me->mObserver->postAudioTearDown(); break; } return 0; }
--------------------------------------------------------------------------------
AudioSystem是AudioPolicyService和AudioFlinger对外提供接口类。
[11:06:09] 刘思云: mmm external/tinyalsa/
[11:06:18] 刘思云: 生成alsa工具
[11:06:28] 刘思云: tinyplay/tinymix/tinycap
-------------------------------------------------------------------
播放线程之间的关系:
线程1:UI线程prepare()的时候会在AudioPlayer中起一个线程mQueue来控制音频和视频的同步等控制
线程2:每创建一个track时,cbf!=null 都会创建这个track对应的工作线程AudioTrack::AudioTrackThread来调用回调函数,从而调用fillbuffer
AwesomePlayer {
sp<MediaSource> mAudioTrack; //offload和raw模式下一般选择这个
sp<MediaSource> mOmxSource;//一般不选这个
sp<MediaSource> mAudioSource = mAudioTrack; //最终使用的MediaSource,这个是音频轨
AudioPlayer *mAudioPlayer = new AudioPlayer(mAudioSink, flags, this);
mAudioPlayer->setSource(mAudioSource);
status_t AwesomePlayer::initAudioDecoder() {
mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), isStreamingHTTP(), streamType);
//canOffloadStream()=> AudioSystem::isOffloadSupported(info)=>aps->isOffloadSupported(info)
if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
ALOGV("createAudioPlayer: bypass OMX (raw)");
mAudioSource = mAudioTrack;
} else {
// If offloading we still create a OMX decoder as a fall-back
// but we don't start it
mOmxSource = OMXCodec::Create(
mClient.interface(), mAudioTrack->getFormat(),
false, // createEncoder
mAudioTrack);
if (mOffloadAudio) {
ALOGV("createAudioPlayer: bypass OMX (offload)");
mAudioSource = mAudioTrack;
} else {
mAudioSource = mOmxSource;
}
}
status_t err = mAudioSource->start();
}
}
class AudioPlayer{
void AudioPlayer::setSource(const sp<MediaSource> &source) {
mSource = source;
}
fillBuffer() {
mSource->read(&mInputBuffer, &options);
}
}
线程3:AudioFlinger中创建一个track的同时可能会创建一个播放线程PlayBackThread(如果该播放线程不存在)。
线程4:创建client的线程,这个线程始终只有一个。而且随着MediaPlayerService的启动而创建。来提供给外部MediaPlayer调用的。
也就是说UI只是通过MediaPlayerService::client发送一些简单命令。UI线程跟读写数据的线程是没有直接关系的。它只是负责一些简单的控制如start() stop()等
AudioFlinger中存在3个线程来协同工作:
一个是回调AudioPlayer::fillbuffer()=>track::write()写数据的线程
第二个是PlayerBackThread读数据往dsp写数据
第三个是创建client的线程,这个线程始终只有一个。而且随着MediaPlayerService的启动而创建。来提供给外部MediaPlayer调用的。
-------------------------------------------------------------------------------
status_t MediaPlayerService::AudioCache::open()这个是流媒体用的,将数据存在cache中
status_t MediaPlayerService::AudioOutput::start()一般是用来播放本地媒体的
status_t MediaPlayerService::AudioOutput::start() { ALOGV("start"); if (mCallbackData != NULL) { mCallbackData->endTrackSwitch(); } if (mTrack != 0) { mTrack->setVolume(mLeftVolume, mRightVolume); mTrack->setAuxEffectSendLevel(mSendLevel); return mTrack->start(); } return NO_INIT; }
-----------------------------------------------------
class AudioPlayer : public TimeSource {}
//offload 模式下 fillBuffer(){ if (mInputBuffer == NULL) { ALOGD("mInputBuffer == NULL"); status_t err; if (mIsFirstBuffer) { ALOGD("mIsFirstBuffer == true"); mInputBuffer = mFirstBuffer; mFirstBuffer = NULL; err = mFirstBufferResult; mIsFirstBuffer = false; } else { ALOGD("mIsFirstBuffer == false mSource->read()"); err = mSource->read(&mInputBuffer, &options); if (err == OK && mInputBuffer == NULL && mSourcePaused) { ALOGV("mSourcePaused, return 0 from fillBuffer"); return 0; } } }
92:04-16 05:17:57.255 347 2082 E AudioPlayer: mAudioSink.get() ?
93:04-16 05:17:57.255 347 2082 E AudioPlayer: mAudioSink.get() != NULL
94:04-16 05:17:57.255 347 2082 V AudioPlayer: start, mBitsPerSample 16, mSampleRate 44100, channelMask 0, audioFormat 16777216
208:04-16 05:17:57.288 347 7212 V AudioPlayer: AudioCallback fillBuffer()
209:04-16 05:17:57.288 347 7212 V AudioPlayer: AudioCallback
210:04-16 05:17:57.288 347 7212 D AudioPlayer: mInputBuffer == NULL
211:04-16 05:17:57.288 347 7212 D AudioPlayer: mIsFirstBuffer == true
212:04-16 05:17:57.288 347 7212 D AudioPlayer: mInputBuffer == NULL
213:04-16 05:17:57.288 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
214:04-16 05:17:57.288 347 7212 D AudioPlayer: mInputBuffer == NULL
215:04-16 05:17:57.288 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
216:04-16 05:17:57.288 347 7212 D AudioPlayer: mInputBuffer == NULL
217:04-16 05:17:57.288 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
......................
570:04-16 05:17:57.316 347 7212 V AudioPlayer: AudioCallback fillBuffer()
571:04-16 05:17:57.316 347 7212 D AudioPlayer: mInputBuffer == NULL
572:04-16 05:17:57.316 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
573:04-16 05:17:57.316 347 7212 D AudioPlayer: mInputBuffer == NULL
574:04-16 05:17:57.316 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
........................
570:04-16 05:17:57.316 347 7212 V AudioPlayer: AudioCallback fillBuffer()
571:04-16 05:17:57.316 347 7212 D AudioPlayer: mInputBuffer == NULL
572:04-16 05:17:57.316 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
573:04-16 05:17:57.316 347 7212 D AudioPlayer: mInputBuffer == NULL
574:04-16 05:17:57.316 347 7212 D AudioPlayer: mIsFirstBuffer == false mSource->read()
非offload模式
116:04-16 05:17:25.440 347 1054 E AudioPlayer: mAudioSink.get() ?
117:04-16 05:17:25.440 347 1054 E AudioPlayer: mAudioSink.get() != NULL
118:04-16 05:17:25.440 347 1054 V AudioPlayer: start, mBitsPerSample 24, mSampleRate 32000, channelMask 3, audioFormat 6
185:04-16 05:17:25.449 347 7188 V AudioPlayer: AudioCallback fillBuffer()
186:04-16 05:17:25.450 347 7188 V AudioPlayer: AudioCallback
187:04-16 05:17:25.450 347 7188 D AudioPlayer: mInputBuffer == NULL
188:04-16 05:17:25.450 347 7188 D AudioPlayer: mIsFirstBuffer == true
189:04-16 05:17:25.450 347 7188 V AudioPlayer: buffer->size() = 32766, mPositionTimeMediaUs=0.00 mPositionTimeRealUs=0.00
191:04-16 05:17:25.450 347 7188 V AudioPlayer: AudioCallback fillBuffer()
193:04-16 05:17:25.450 347 7188 V AudioPlayer: AudioCallback fillBuffer()
198:04-16 05:17:25.454 347 347 V AudioPlayer: getRealTimeUsLocked -196401
251:04-16 05:17:25.747 347 7188 V AudioPlayer: AudioCallback fillBuffer()
255:04-16 05:17:25.772 347 7188 V AudioPlayer: AudioCallback fillBuffer()
257:04-16 05:17:25.772 347 7188 V AudioPlayer: AudioCallback fillBuffer()
258:04-16 05:17:25.772 347 7188 D AudioPlayer: mInputBuffer == NULL
259:04-16 05:17:25.772 347 7188 D AudioPlayer: mIsFirstBuffer == false mSource->read()
260:04-16 05:17:25.773 347 7188 V AudioPlayer: buffer->size() = 32766, mPositionTimeMediaUs=0.17 mPositionTimeRealUs=0.17
284:04-16 05:17:25.871 347 7188 V AudioPlayer: AudioCallback fillBuffer()
287:04-16 05:17:25.901 347 7188 V AudioPlayer: AudioCallback fillBuffer()
288:04-16 05:17:25.901 347 7188 D AudioPlayer: mInputBuffer == NULL
289:04-16 05:17:25.901 347 7188 D AudioPlayer: mIsFirstBuffer == false mSource->read()
290:04-16 05:17:25.901 347 7188 V AudioPlayer: buffer->size() = 32766, mPositionTimeMediaUs=0.34 mPositionTimeRealUs=0.34
------------------------------------------------------------------------------------
daichenghui@daichenghui-OptiPlex-3020:~/log/log$ grep -n AwesomePlayer raw.log
74:04-16 05:17:25.347 347 347 V AwesomePlayer: AwesomePlayer running on behalf of uid 10247
80:04-16 05:17:25.431 347 347 V AwesomePlayer: track of type 'audio/raw' does not publish bitrate
81:04-16 05:17:25.431 347 347 V AwesomePlayer: mBitrate = -1 bits/sec
87:04-16 05:17:25.434 347 7187 D AwesomePlayer: AwesomePlayer::initAudioDecoder()
91:04-16 05:17:25.434 347 7187 V AwesomePlayer: createAudioPlayer: bypass OMX (raw) mAudioSource = mAudioTrack
93:04-16 05:17:25.434 347 7187 I AwesomePlayer: Could not offload audio decode, try pcm offload
112:04-16 05:17:25.440 347 1054 V AwesomePlayer: createAudioPlayer_l()
04-27 13:37:27.357 344 964 D AudioFlinger: mNormalSink != 0
04-27 13:37:27.357 344 964 D AudioFlinger: mNormalSink != 0 mNormalSink->write()
04-27 13:37:27.357 344 964 D audio_hw_primary: out_write()
04-27 13:37:27.377 344 964 D AudioFlinger: mNormalSink != 0
04-27 13:37:27.377 344 964 D AudioFlinger: mNormalSink != 0 mNormalSink->write()
04-27 13:37:27.377 344 964 D audio_hw_primary: out_write()
------------------------------
daichenghui@daichenghui-OptiPlex-3020:~/log/log$ grep -n AwesomePlayer offload.log
47:04-16 05:17:57.222 347 1054 V AwesomePlayer: AwesomePlayer running on behalf of uid 10247
53:04-16 05:17:57.246 347 1054 V AwesomePlayer: mBitrate = 128000 bits/sec
59:04-16 05:17:57.248 347 7209 D AwesomePlayer: AwesomePlayer::initAudioDecoder()
74:04-16 05:17:57.252 347 7209 V AwesomePlayer: createAudioPlayer: bypass OMX (offload) mAudioSource = mAudioTrack;
89:04-16 05:17:57.255 347 2082 V AwesomePlayer: createAudioPlayer_l()
04-27 13:35:45.626 344 8004 D AudioFlinger: mNormalSink == 0
04-27 13:35:45.626 344 8004 D audio_hw_primary: out_write()
04-27 13:35:45.628 344 8004 V AudioFlinger: OffloadThread::prepareTracks_l active tracks 1
04-27 13:35:45.629 344 8004 D AudioFlinger: mNormalSink == 0
04-27 13:35:45.629 344 8004 D audio_hw_primary: out_write()
---------------------------------------------------------------------------------------

浙公网安备 33010602011771号