原址
Platform: RK3288 OS: Android 6.0 Kernel: 3.10.92 以Gallery播放视频为例(只关注MediaPlayer相关部分): rk用的是ffplayer,但是没有开源,所以这里就以stagefright为例了解解码流程. 创建: onCreate -> MovieActivity.java mPlayer = new MoviePlayer -> MoviePlayer.java mVideoView = (VideoView) rootView.findViewById -> VideoView -> VideoView.java initVideoView mVideoView.setVideoURI(mUri) setVideoURI -> //VideoView.java openVideo -> mMediaPlayer = new MediaPlayer -> MediaPlayer -> MediaPlayer.java native_setup -> android_media_MediaPlayer_native_setup -> android_media_MediaPlayer.cpp new MediaPlayer -> MediaPlayer::MediaPlayer mediaplayer.cpp AudioSystem::acquireAudioSessionId //获取AudioFlinger. mMediaPlayer.setDataSource -> _setDataSource -> android_media_MediaPlayer_setDataSourceFD -> android_media_MediaPlayer.cpp getMediaPlayer mp->setDataSource -> MediaPlayer::setDataSource -> service->create MediaPlayerService::create -> new Client player->setDataSource -> MediaPlayerService::Client::setDataSource -> MediaPlayerFactory::getPlayerType //根据当前的文件格式类型来确定应该使用哪个player setDataSource_pre -> //返回对应的player. createPlayer -> MediaPlayerFactory::createPlayer -> factory = sFactoryMap.valueFor //根据之前在MediaPlayerService中注册的player来选择一个对应type. factory->createPlayer //对应player的调用,假设这里是stagefrightplayer. new StagefrightPlayer -> new AwesomePlayer //真正实现的是AwesomePlayer new AudioOutput //创建audio输出 attachNewPlayer mMediaPlayer.setDisplay -> //设置对应surface. _setVideoSurface updateSurfaceScreenOn mMediaPlayer.setAudioStreamType //tpye是STREAM_MUSIC 点击屏幕播放: onKeyDown -> MovieActivity.java mPlayer.onKeyDown onKeyDown -> MoviePlayer.java playVideo -> mVideoView.start -> start -> VideoView.java mMediaPlayer.start -> _start -> MediaPlayer.java android_media_MediaPlayer_start -> android_media_MediaPlayer.cpp mp->start MediaPlayer::start -> mediaplayer.cpp mPlayer->setVolume mPlayer->start -> MediaPlayerService::Client::start -> p->start -> //当前对应的是StagefrightPlayer StagefrightPlayer::start -> StagefrightPlayer.cpp mPlayer->play -> //AwesomePlayer去实现 AwesomePlayer::play -> AwesomePlayer.cpp AwesomePlayer::play_l -> prepare_l -> prepareAsync_l -> mQueue.postEvent -> //event: mAsyncPrepareEvent AwesomePlayer::onPrepareAsyncEvent -> beginPrepareAsync_l -> finishSetDataSource_l -> DataSource::CreateFromURI -> new FileSource MediaExtractor::Create -> //根据播放type来选择相应的Extractor,用来将视频和音频分离. new MPEG4Extractor setDataSource_l -> //设定上面的extractor为track. setVideoSource setAudioSource initVideoDecoder -> mVideoSource = OMXCodec::Create -> //得到video source. findMatchingCodecs -> OMXCodec.cpp,codecs在mediaplayerservice初始化,比如获得的codec名是OMX.rk.video_encoder.avc MediaCodecList::getInstance -> service->getCodecList -> MediaPlayerService::getCodecList -> MediaCodecList::getLocalInstance -> new MediaCodecList -> parseTopLevelXMLFile // /etc/media_codecs.xml parseTopLevelXMLFile // /etc/media_codecs_performance.xml info->getCodecName //获取codec name matchingCodecs->add //有可能有多个,比如hw/sw都支持解码,依次添加进去. 这里有个函数IsSoftwareCodec(),通过实现可以知道是否是hw codec可以通过前缀来区分. InstantiateSoftwareCodec //目前只支持匹配RkAudioDecoder或者FLACDecoder,不匹配就继续往下走 omx->allocateNode -> //omx是OMXClient::connect中初始化的,指向的是mps里的OMX OMX::allocateNode -> OMX.cpp mMaster->makeComponentInstance //mMaster在OMX初始化的时候new的,指向OMXMaster OMXMaster::makeComponentInstance -> OMXMaster.cpp plugin->makeComponentInstance //plugin在OMXMaster初始化是new的,是SoftOMXPlugin SoftOMXPlugin::makeComponentInstance -> //看看sw的codec有没有符合的,支持的codec全部在kComponents数组中 new OMXCodec codec->configureCodec -> OMXCodec::configureCodec -> setVideoOutputFormat initNativeWindow //关联window mVideoSource->start -> OMXCodec::start -> mSource->start -> //mSource是mVideoTrack,最终指向MPEG4Source MPEG4Source::start -> new MediaBufferGroup //分配buffer mGroup->add_buffer //new MediaBuffer initAudioDecoder //获取audio decoder,流程和上面的initVideoDecoder基本上一样,只是因为mime不同因此得到的decoder不同. finishAsyncPrepare_l -> mPreparedCondition.broadcast //AwesomePlayer的prepare_l()等待返回准备执行start() createAudioPlayer_l -> new AudioPlayer mAudioPlayer->setSource postVideoEvent_l -> mQueue.postEventWithDelay -> AwesomePlayer::onVideoEvent -> initRenderer_l //初始化 mVideoRenderer为new AwesomeNativeWindowRenderer mVideoSource->read -> //取原始的压缩数据 OMXCodec::read -> drainInputBuffers -> drainInputBuffer -> mSource->read -> MPEG4Source::read -> mDataSource->readAt //从之前解析出来的datasoure中读取 fillOutputBuffers -> OMXCodec::fillOutputBuffer -> mOMX->fillBuffer -> OMX::fillBuffer -> OMXNodeInstance::fillBuffer -> OMX_FillThisBuffer -> //参数handle和node关联,在OMX::allocateNode()赋值,指向了当前使用的decoder,所以硬件解码器相关的库了. waitForBufferFilled_l mVideoRenderer->render -> //mVideoRenderer指向AwesomeNativeWindowRenderer render -> AwesomePlayer.cpp mNativeWindow->queueBuffer //其实就是显示了!