资源预览内容
第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
第9页 / 共15页
第10页 / 共15页
亲,该文档总共15页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
Android视频播放数据读取的流程htt p:/blog.sina.com.cn/s/blog_645b74b90101aezn.h tml这里分析Android4.0.1本地视频数据读取的流程,其他过程类似当播放条件准备妥当之后,就要循环进行读取视频的原始数据放到 MediaBuffer,将MediaBuffer中的数据输送到解码器中解码,解码后的数据放 到MediaBuffer中,在将这MediaBuffer中的数据进行render显示。本文主要侧重读取原始数据的流程,主要是代码跟踪,不夹杂个人分析,有些 mpeg4的算法不懂。1: onVideoEvent中开始读取数据,具体代码如下:void AwesomePlayer:onVideoEvent() if (!mVideoBuffer) MediaSource:ReadOptions options;if (mSeeking != NO_SEEK) LOGV(seeking to %lld us (%.2f secs), mSeekTimeUs, mSeekTimeUs / 1E6);optio ns.se tSeekTo(mSeekTimeUs,mSeeking = SEEK_VIDE0_0NLY? MediaSource:ReadOptions:SEEK_NEXT_SYNCMediaSource:ReadOptions:SEEK_CLOSEST_SYNC);for (;) statuserr 二 mVideoSource-read(&mVideoBuffer, &optio ns);蓝色为核心代码,如果是正常读取,options为null,否则这个结构体中包含了 seek到的时间和seek的模式,用于具体从文件中哪里开始读取,传入的 mVideoBuffer引用用来装解码后的数据2:蓝色部分调用的是OMXCodec:read函数,这个函数中核心的代码如下:statusOMXCodec:read(MediaBuffer *buffer, const ReadOptions *options) status_t err = OK;*buffer = NULL;bool seeking = false;int64_t seekTimeUs;ReadOptions:SeekMode seekMode;if (options & optionsgetSeekTo(&seekTimeUs, &seekMode) seeking = true;if (seeking) CODEC_LOGV(seeking to %lld us (%.2f secs), seekTimeUs, seekTimeUs / 1E6);CHECK(seekTimeUs = 0);mSeekTimeUs = seekTimeUs;mSeekMode = seekMode;drainInp ut Buffers。;size_t index = *mFilledBuffers.begin(); / A list of indices into mPortStatuskPortlndexOutput filled with data.mFilledBuffers.erase(mFilledBuffers.begin();BufferInfo*info二&mPortBufferskPortlndexOutput .editltemAt(index);CHECK_EQ(int)info-mStatus, (int)OWNED_BY_US);info-mStatus = OWNED_BY_CLIENT;info-mMediaBuffer-add_ref();*buffer = info-mMediaBuffer;return OK;两点:a, drainInputBuffers开始了数据的读取;b , mFilledBuffers从这个队列中读取已经解码后的数据放入到传入的 MediaBuffer 中,mFilledBuffers 队 列 中 的 MediaBuffer 就 是drainlnputBuffers 中写进去的3: 跟到 drainlnputBuffer 中看看bool OMXCodec:drainInputBuffer(BufferInfo *info) CODEC_LOGV(calling emptyBuffer with codec specific data); statuserr = mOMX-emp ty Buffer(mNode, info-mBuffer, 0, size,OMX_BUFFERFLAG_ENDOFFRAMEOMX_BUFFERFLAG_CODECCONFIG,0);CHECK_EQ(err, (stat us_ t)0K);info-mStatus = 0WNED_BY_C0MP0NENT;status_t err;bool signalEOS = false;int64_t timestampUs = 0;size_t offset 二 0;int32_t n 二 0;for (;) MediaBuffer *srcBuffer;if (mSeekTimeUs = 0) MediaSource:ReadOptions options;options.setSeekTo(mSeekTimeUs, mSeekMode); mSeekTimeUs = T;mSeekMode = ReadOptions:SEEK_CLOSEST_SYNC;err = mSource-read(&srcBuffer, &options);if (err = OK) int64_t targetTimeUs;if (srcBuffer-meta_data()-findlnt64(kKeyTargetTime, &targetTimeUs)& targetTimeUs = 0) CODEC_LOGV(targetTimeUs = %lld us, targetTimeUs); mTargetTimeUs = targetTimeUs; else mTargetTimeUs = -1;CODEC_LOGV(Calling emptyBuffer on buffer %p (length %d),ti mes tamp %lld us (%.2f secs),info-mBuffer, offset,timestampUs, timestampUs / 1E6);err = mOMXemptyBuffer(mNode, infomBuffer, 0, offse t, flags, timestampUs);info-mStatus = 0WNED_BY_C0MP0NENT;return true;两点:a, 调用 err = mSource-read(&srcBuffer, &options);从原始文件中读取原始 数据,b, 往srcBuffer中读取数据前后,都调用omx转移已经读取到该info中的数据, 目的是解码,解码后的数据就房子了 mFilledBuffers这个队列中;4:针对mpeg4类型的视频,上面的read函数调用的是MPEG4Source的read函 数,核心代码如下:status_t MPEG4Source:read(MediaBuffer *out, const ReadOptions *options) *out = NULL;int64_t seekTimeUs;ReadOptions:SeekMode mode;if (options & optionsgetSeekTo(&seekTimeUs, &mode) if分支是用于有seek的流程1: 首先找到 seek time 附近的 samplelndex;2:然后找到samplelndex附近的关键帧的syncSamplelndex; 3:然后 syncSamplelndex 找到具体的 sampleTime,sampleTime 就是 目前需要播放到的位置;4 : mSampleTable-getMetaDataForSample 调用 这个函 数找到 sampleTime 时间的 offset 和 size;5 : 有了 offset 和 size 之后剩下就是调用 mDataSource-readAt(offset, (uint8_t *)mBuffer-data(), size);读取数据 放到buffer中去了;uint32_t findFlags = 0;switch (mode) case ReadOptions:SEEK_PREVIOUS_SYNC:findFlags = SampleTable:kFlagBefore;break;case ReadOptions:SEEK_NEXT_SYNC:findFlags = SampleTable:kFlagAfter;break;case ReadOptions:SEEK_CLOSEST_SYNC:case ReadOptions:SEEK_CLOSEST:findFlags = SampleTable:kFlagClosest;break;default:CHECK(!Should not be here.);break; uint32_t sampleIndex;status err = mSampleTable-findSampleAtTime(seekTimeUs * mTimescale / 1000000,&sampleindex, findFlags);uint32_t syncSamplelndex;if (err = OK) err = mSampleTable-findSyncSampleNear(sampleindex, &syncSamplelndex, findFlags);uint32_t sampleTime;if (err = OK) err = mSampleTable-getMetaDataForSample(sampleindex, NULL, NULL, &sampleTime);if (mode = ReadOptions:SEEK_CLOSEST) targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;mCurrentSamplelndex = syncSamplelndex;off64_t offset;size_t size;uint32_t cts;bool isSyncSample;bool newBuffer = false; if (mBuffer = NULL) newBuffer = true;statuserr =mSampleTable-getMeta
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号