stagefright框架下的awesomeplayer播放准备阶段
来源:互联网 发布:楼体亮化设计软件 编辑:程序博客网 时间:2024/05/17 23:08
前文分析了AwesomePlayer的setDataSource阶段,对于已经分离好的音视频数据,下一步就是为其设置解码器,这一阶段称为 prepare。
直接从AwesomePlayer::prepareAsync()
开始,
status_t AwesomePlayer::prepareAsync() { return prepareAsync_l();}status_t AwesomePlayer::prepareAsync_l() { if (!mQueueStarted) { mQueue.start(); mQueueStarted = true; } modifyFlags(PREPARING, SET); mAsyncPrepareEvent = new AwesomeEvent( this, &AwesomePlayer::onPrepareAsyncEvent); mQueue.postEvent(mAsyncPrepareEvent);}
播放器准备阶段主要由prepareAsync_l实施,_l代表lock。首先检查下时间队列是否正常工作,然后将mFlags设置为PREPARING。并将事件mAsyncPrepareEvent送到消息队列,于是onPrepareAsyncEvent将会执行。
void AwesomePlayer::onPrepareAsyncEvent() { Mutex::Autolock autoLock(mLock); beginPrepareAsync_l();}void AwesomePlayer::beginPrepareAsync_l() { if (mUri.size() > 0) { status_t err = finishSetDataSource_l(); if (err != OK) { abortPrepare(err); return; } } if (mVideoTrack != NULL && mVideoSource == NULL) { status_t err = initVideoDecoder(); } if (mAudioTrack != NULL && mAudioSource == NULL) { status_t err = initAudioDecoder(); } modifyFlags(PREPARING_CONNECTED, SET); if (isStreamingHTTP()) { postBufferingEvent_l(); } else { finishAsyncPrepare_l(); }}
beginPrepareAsync_l中会对http源做特殊处理,对于本地aaa.mp3则会初始化视频和音频解码器。
status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { mVideoSource = OMXCodec::Create( mClient.interface(), mVideoTrack->getFormat(), false, // createEncoder mVideoTrack, NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);#define USE_SURFACE_ALLOC 1
这里就大名鼎鼎的OpenMax编码解码框架,对于参数:
const sp &omx 为mClient.interface()
const sp &meta 为mVideoTrack->getFormat()
bool createEncoder 为false
const sp &source 为mVideoTrack
const char *matchComponentName 为NULL
uint32_t flags 为flags
const sp &nativeWindow 为mNativeWindow
将创建一个带解码的视频源mVideoSource,其实质是一个OMXCodec类型的codec。
Vector<CodecNameAndQuirks> matchingCodecs; findMatchingCodecs(mime, createEncoder, matchComponentName, flags, &matchingCodecs); sp<OMXCodec> codec = new OMXCodec( omx, node, quirks, flags, createEncoder, mime, componentName, source, nativeWindow); observer->setCodec(codec); return codec;enum CreationFlags { kPreferSoftwareCodecs = 1, // Request for software or hardware codecs. If request // can not be fullfilled, Create() returns NULL. kSoftwareCodecsOnly = 8, kHardwareCodecsOnly = 16, // Store meta data in video buffers kStoreMetaDataInVideoBuffers = 32, // Secure decoding mode kUseSecureInputBuffers = 256, };
在创建omx之前还会涉及到软解和硬解,先用一个matchingCodecs来装载匹配的解码器,根据解码内容和解码标志判断是需要硬解还是软解IsSoftwareCodec。如没指明用软解还是硬解,则将所有解码器装入matchingCodecs。
视频解码器设置完毕后,再设置音频解码器,
status_t AwesomePlayer::initAudioDecoder() { sp<MetaData> meta = mAudioTrack->getFormat(); CHECK(meta->findCString(kKeyMIMEType, &mime)); mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL),isStreamingHTTP(), streamType); 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; } }
音频解码器初始化首先检查是否为硬解码的音频流,如果是则不再对其解码,以免重复解码。然后检查下是否为已经解码过的音频流。如果音频流不为原始音频流MEDIA_MIMETYPE_AUDIO_RAW,则需要创建解码器,如果是正着解码的音频流,也需要创建解码器,但不启动它。
音频解码器和视频解码器的创建差不多,这块比较复杂,到OMX时再分析。
解码器创建好之后,修改播放标志位modifyFlags(PREPARING_CONNECTED, SET);并进入finishAsyncPrepare_l();
void AwesomePlayer::finishAsyncPrepare_l() { if (mIsAsyncPrepare) { if (mVideoSource == NULL) { notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); } else { notifyVideoSize_l(); } notifyListener_l(MEDIA_PREPARED); } mPrepareResult = OK; modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); modifyFlags(PREPARED, SET); mAsyncPrepareEvent = NULL; mPreparedCondition.broadcast();}
这里notifyVideoSize_l()开始准备视频播放时画面尺寸。主要参数有:
displayWidth、displayHeight、usableWidth、usableHeight、rotationDegrees。
然后发送通知播放器准备就绪,notifyListener_l(MEDIA_PREPARED);是时候播放媒体文件了。
- stagefright框架下的awesomeplayer播放准备阶段
- stagefright框架下的awesomeplayer设置数据源阶段
- Stagefright AwesomePlayer 播放流程的函数调用
- Android播放器框架分析之AwesomePlayer
- Android播放器框架分析之AwesomePlayer
- Android播放器框架分析之AwesomePlayer
- Android播放器框架分析之AwesomePlayer
- Android播放器框架分析之AwesomePlayer
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android-StageFright之数据流的封装和AwesomePlayer流程
- Android Multimedia框架总结(八)Stagefright框架之AwesomePlayer及数据解析器
- Android Multimedia框架总结(八)Stagefright框架之AwesomePlayer及数据解析器
- Android Multimedia框架总结(八)Stagefright框架之AwesomePlayer及数据解析器
- SIM卡运营商信息整理
- TabLayout和ViewPager以及Fragment实现超级简单导航栏
- 使用SparkSQL分析CSDN泄露的用户数据[top-n]
- Android中JNI使用详解(2)---Android Studio中NDK环境配置
- Android 2016的一些新东西
- stagefright框架下的awesomeplayer播放准备阶段
- 洛谷 P1330 封锁阳光大学
- u3d honey hex framework 代码解读记录(二)
- Spring05
- Spring学习笔记
- (15.1.18)为什么Android开发者应该使用FlatBuffers替代JSON?
- CentOS查看开启端口
- 205. Isomorphic Strings
- TexturePacker命令行使用(command line)