Android视频播放数据读取的流程Word格式文档下载.docx
- 文档编号:16151979
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:10
- 大小:17.60KB
Android视频播放数据读取的流程Word格式文档下载.docx
《Android视频播放数据读取的流程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Android视频播放数据读取的流程Word格式文档下载.docx(10页珍藏版)》请在冰豆网上搜索。
read(&
mVideoBuffer,&
options);
}
蓝色为核心代码,如果是正常读取,options为null,否则这个结构体中包含了seek到的时间和seek的模式,用于具体从文件中哪里开始读取,传入的mVideoBuffer引用用来装解码后的数据
2:
蓝色部分调用的是OMXCodec:
read函数,这个函数中核心的代码如下:
status_tOMXCodec:
read(
MediaBuffer**buffer,constReadOptions*options){
status_terr=OK;
*buffer=NULL;
boolseeking=false;
int64_tseekTimeUs;
ReadOptions:
SeekModeseekMode;
if(options&
&
options->
getSeekTo(&
seekTimeUs,&
seekMode)){
seeking=true;
if(seeking){
CODEC_LOGV("
seekTimeUs,seekTimeUs/1E6);
CHECK(seekTimeUs>
=0);
mSeekTimeUs=seekTimeUs;
mSeekMode=seekMode;
drainInputBuffers();
size_tindex=*mFilledBuffers.begin();
//AlistofindicesintomPortStatus[kPortIndexOutput]filledwithdata.
mFilledBuffers.erase(mFilledBuffers.begin());
BufferInfo*info=&
mPortBuffers[kPortIndexOutput].editItemAt(index);
CHECK_EQ((int)info->
mStatus,(int)OWNED_BY_US);
info->
mStatus=OWNED_BY_CLIENT;
mMediaBuffer->
add_ref();
*buffer=info->
mMediaBuffer;
returnOK;
两点:
a,drainInputBuffers开始了数据的读取;
b,mFilledBuffers从这个队列中读取已经解码后的数据放入到传入的MediaBuffer中,mFilledBuffers队列中的MediaBuffer就是drainInputBuffers中写进去的
3:
跟到drainInputBuffer中看看
boolOMXCodec:
drainInputBuffer(BufferInfo*info){
callingemptyBufferwithcodecspecificdata"
);
status_terr=mOMX->
emptyBuffer(
mNode,info->
mBuffer,0,size,
OMX_BUFFERFLAG_ENDOFFRAME|OMX_BUFFERFLAG_CODECCONFIG,
0);
CHECK_EQ(err,(status_t)OK);
mStatus=OWNED_BY_COMPONENT;
status_terr;
boolsignalEOS=false;
int64_ttimestampUs=0;
size_toffset=0;
int32_tn=0;
MediaBuffer*srcBuffer;
if(mSeekTimeUs>
=0){
options.setSeekTo(mSeekTimeUs,mSeekMode);
mSeekTimeUs=-1;
mSeekMode=ReadOptions:
SEEK_CLOSEST_SYNC;
err=mSource->
srcBuffer,&
if(err==OK){
int64_ttargetTimeUs;
if(srcBuffer->
meta_data()->
findInt64(
kKeyTargetTime,&
targetTimeUs)
&
targetTimeUs>
targetTimeUs=%lldus"
targetTimeUs);
mTargetTimeUs=targetTimeUs;
}else{
mTargetTimeUs=-1;
CallingemptyBufferonbuffer%p(length%d),"
"
timestamp%lldus(%.2fsecs)"
mBuffer,offset,
timestampUs,timestampUs/1E6);
err=mOMX->
mBuffer,0,offset,
flags,timestampUs);
returntrue;
a,调用err=mSource->
从原始文件中读取原始数据,
b,往srcBuffer中读取数据前后,都调用omx转移已经读取到该info中的数据,目的是解码,解码后的数据就房子了mFilledBuffers这个队列中;
4:
针对mpeg4类型的视频,上面的read函数调用的是MPEG4Source的read函数,核心代码如下:
status_tMPEG4Source:
MediaBuffer**out,constReadOptions*options){
*out=NULL;
SeekModemode;
mode)){
if分支是用于有seek的流程
1:
首先找到seektime附近的sampleIndex;
2:
然后找到sampleIndex附近的关键帧的syncSampleIndex;
3:
然后syncSampleIndex找到具体的sampleTime,sampleTime就是目前需要播放到的位置;
4:
mSampleTable->
getMetaDataForSample调用这个函数找到sampleTime时间的offset和size;
5:
有了offset和size之后剩下就是调用mDataSource->
readAt(offset,(uint8_t*)mBuffer->
data(),size);
读取数据放到buffer中去了;
uint32_tfindFlags=0;
switch(mode){
caseReadOptions:
SEEK_PREVIOUS_SYNC:
findFlags=SampleTable:
kFlagBefore;
break;
SEEK_NEXT_SYNC:
kFlagAfter;
SEEK_CLOSEST_SYNC:
SEEK_CLOSEST:
kFlagClosest;
default:
CHECK(!
"
Shouldnotbehere."
uint32_tsampleIndex;
status_terr=mSampleTable->
findSampleAtTime(
seekTimeUs*mTimescale/1000000,
sampleIndex,findFlags);
uint32_tsyncSampleIndex;
err=mSampleTable->
findSyncSampleNear(
sampleIndex,&
syncSampleIndex,findFlags);
uint32_tsampleTime;
getMetaDataForSample(
sampleIndex,NULL,NULL,&
sampleTime);
if(mode==ReadOptions:
SEEK_CLOSEST){
targetSampleTimeUs=(sampleTime*1000000ll)/mTimescale;
mCurrentSampleIndex=syncSampleIndex;
off64_toffset;
size_tsize;
uint32_tcts;
boolisSyncSample;
boolnewBuffer=false;
if(mBuffer==NULL){
newBuffer=true;
status_terr=
mSampleTable->
mCurrentSampleIndex,&
offset,&
size,&
cts,&
isSyncSample);
if(err!
=OK){
returnerr;
err=mGroup->
acquire_buffer(&
mBuffer);
CHECK(mBuffer==NULL);
mIsAVC||mWantsNALFragments){
if(newBuffer){
ssize_tnum_bytes_read=
mDataSource->
CHECK(mBuffer!
=NULL);
mBuffer->
set_range(0,size);
clear();
setInt64(
kKeyTime,((int64_t)cts*1000000)/mTimescale);
if(isSyncSample){
setInt32(kKeyIsSyncFrame,1);
++mCurrentSampleIndex;
mIsAVC){
*out=mBuffer;
mBuffer=NULL;
//EachNALunitissplitupintoitsconstituentfragmentsand
//eachoneofthemreturnedinitsownbuffer.
CHECK(mBuffer->
range_length()>
=mNALLengthSize);
constuint8_t*src=
(constuint8_t*)mBuffer->
data()+mBuffer->
range_offset();
size_tnal_size=parseNALSize(src);
MediaBuffer*clone=mBuffer->
clone();
CHECK(clone!
clone->
set_range(mBuffer->
range_offset()+mNALLengthSize,nal_size);
set_range(
range_offset()+mNALLengthSize+nal_size,
range_length()-mNALLengthSize-nal_size);
if(mBuffer->
range_length()==0){
release();
*out=clone;
蓝色部分为主要的流程
5:
后续就是开始调用SampleTable.cpp和SampleIterator.cpp这两个类的相关函数解析文件和读取数据,最主要的函数时通过sampleIndex获取offset和size信息了,代码如下:
status_tSampleTable:
uint32_tsampleIndex,
off64_t*offset,
size_t*size,
uint32_t*compositionTime,
bool*isSyncSample){
Mutex:
AutolockautoLock(mLock);
if((err=mSampleIterator->
seekTo(sampleIndex))!
if(offset){
*offset=mSampleIterator->
getSampleOffset();
if(size){
*size=mSampleIterator->
getSampleSize();
if(compositionTime){
*compositionTime=mSampleIterator->
getSampleTime();
*isSyncSample=false;
if(mSyncSampleOffset<
0){
//Everysampleisasyncsample.
*isSyncSample=true;
size_ti=(mLastSyncSampleIndex<
mNumSyncSamples)
(mSyncSamples[mLastSyncSampleIndex]<
=sampleIndex)
mLastSyncSampleIndex:
0;
while(i<
mNumSyncSamples&
mSyncSamples[i]<
sampleIndex){
++i;
if(i<
mSyncSamples[i]==sampleIndex){
mLastSyncSampleIndex=i;
下面这个函数没有看懂,对具体的mpeg4压缩协议没有进行深入了解
status_tSampleIterator:
findSampleTime(
uint32_tsampleIndex,uint32_t*time){
if(sampleIndex>
=mTable->
mNumSampleSizes){
returnERROR_OUT_OF_RANGE;
while(sampleIndex>
=mTTSSampleIndex+mTTSCount){
if(mTimeToSampleIndex==mTable->
mTimeToSampleCount){
mTTSSampleIndex+=mTTSCount;
mTTSSampleTime+=mTTSCount*mTTSDuration;
mTTSCount=mTable->
mTimeToSample[2*mTimeToSampleIndex];
mTTSDuration=mTable->
mTimeToSample[2*mTimeToSampleIndex+1];
++mTimeToSampleIndex;
*time=mTTSSampleTime+mTTSDuration*(sampleIndex-mTTSSampleIndex);
*time+=mTable->
getCompositionTimeOffset(sampleIndex);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 视频 播放 数据 读取 流程