android stagefright基本流程总结
数据流的封装
一、
由数据源DataSource生成MediaExtractor。
通过MediaExtractor::Create(dataSource)来实现。Create方法通过两步来生成相应的MediaExtractor:
1、通过dataSource->sniff来探测数据类型
2、生成相应的Extractor:
1 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4) 2 3 || !strcasecmp(mime, "audio/mp4")) { 4 5 return new MPEG4Extractor(source); 6 7 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 8 9 return new MP3Extractor(source, meta); 10 11 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB) 12 13 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 14 15 return new AMRExtractor(source); 16 17 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) { 18 19 return new WAVExtractor(source); 20 21 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) { 22 23 return new OggExtractor(source); 24 25 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) { 26 27 return new MatroskaExtractor(source); 28 29 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) { 30 31 return new MPEG2TSExtractor(source); 32 33 }
二、
接下来,通过以下代码把音视频轨道分离:
1 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 2 3 setVideoSource(extractor->getTrack(i)); 4 5 haveVideo = true; 6 7 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 8 9 setAudioSource(extractor->getTrack(i)); 10 11 haveAudio = true;
生成mVideoTrack和mAudioTrack两个MediaSource。
三、
到目前为止我们得到的这两个MediaSource只具有parser功能,没有decode功能。还需要对这两个MediaSource做进一步的包装:
1 mVideoSource = OMXCodec::Create( 2 3 mClient.interface(), mVideoTrack->getFormat(), 4 5 false, // createEncoder 6 7 mVideoTrack, 8 9 NULL, flags); 10 11 mAudioSource = OMXCodec::Create( 12 13 mClient.interface(), mAudioTrack->getFormat(), 14 15 false, // createEncoder 16 17 mAudioTrack);
这回又获取了两个MediaSource。它们具有parse和decode功能。当调用MediaSource.start()方法后,它的内部 就会开始从数据源获取数据并解析,等到缓冲区满后便停止。在AwesomePlayer里就可以调用MediaSource的read方法读取解码后的数 据。
对于mVideoSource来说:
读取的数据。
1 mVideoSource->read(&mVideoBuffer, &options)
交给显示模块进行渲染。
1 mVideoRenderer->render(mVideoBuffer);
对mAudioSource来说:
用mAudioPlayer对mAudioSource进行封装,然后由mAudioPlayer负责读取数据和播放控制。
AwesomePlayer流程
URI,FD
|
DataSource
|
|
mVideoTrack mAudioTrack//音视频数据流
|
mVideoSource mAudioSource//音视频解码器
| |
mVideoBuffer mAudioPlayer
上面示意了数据由源到最终解码后的流程。
1、设置DataSource,数据源可以两种URI和FD。URI可以http://,rtsp://等。FD是一个本地文件描述符,能过FD,可以找到对应的文件。
2、由DataSource生成MediaExtractor。通过sp extractor = MediaExtractor::Create(dataSource);来实现。 MediaExtractor::Create(dataSource)会根据不同的数据内容创建不同的数据读取对象。
3、通过调用setVideoSource由MediaExtractor分解生成音频数据流(mAudioTrack)和视频数据流(mVideoTrack)。
4、 onPrepareAsyncEvent()
如果DataSource是URL的话,根据地址获取数据,并开始缓冲,直到获取到mVideoTrack和mAudioTrack。
mVideoTrack和mAudioTrack通过调用initVideoDecoder()和initAudioDecoder()来生成mVideoSource和mAudioSource这两个音视频解码器。
然后调用postBufferingEvent_l()提交事件开启缓冲。数据缓冲的执行函数是onBufferingUpdate()。
缓冲区有足够的数据可以播放时,调用play_l()开始播放。play_l()中关键是调用了postVideoEvent_l(),提交了 mVideoEvent。这个事件执行时会调用函数onVideoEvent()。这个函数通过调用 mVideoSource->read(&mVideoBuffer, &options)进行视频解码。音频解码通过mAudioPlayer实现。
视频解码器解码后通过mVideoSource->read读取一帧帧的数据,放到mVideoBuffer中,最后通过mVideoRenderer->render(mVideoBuffer)把视频数据发送到显示模块。
当需要暂停或停止时,调用cancelPlayerEvents来提交事件用来停止解码,还可以选择是否继续缓冲数据。