资源预览内容
第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
第9页 / 共15页
第10页 / 共15页
亲,该文档总共15页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
Android视频播放数据读取的流程http:/blog.sina.com.cn/s/blog_645b74b90101aezn.html这里分析 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);options.setSeekTo(mSeekTimeUs,mSeeking = SEEK_VIDEO_ONLY? MediaSource:ReadOptions:SEEK_NEXT_SYNC: MediaSource:ReadOptions:SEEK_CLOSEST_SYNC); for (;) status_t err = mVideoSource-read(&mVideoBuffer, 蓝色为核心代码,如果是正常读取,options 为 null,否则这个结构体中包含了 seek到的时间和 seek的模式,用于具体从文件中哪里开始读取,传入的mVideoBuffer引用用来装解码后的数据2:蓝色部分调用的是 OMXCodec:read函数,这个函数中核心的代码如下:status_t OMXCodec:read(MediaBuffer *buffer, const ReadOptions *options) status_t err = OK;*buffer = NULL;bool seeking = false;int64_t seekTimeUs;ReadOptions:SeekMode seekMode;if (options & options-getSeekTo(&seekTimeUs, &seekMode) seeking = true;if (seeking) CODEC_LOGV(seeking to %lld us (%.2f secs), seekTimeUs, seekTimeUs / 1E6);CHECK(seekTimeUs = 0);mSeekTimeUs = seekTimeUs;mSeekMode = seekMode;drainInputBuffers();size_t index = *mFilledBuffers.begin(); / A list of indices into mPortStatuskPortIndexOutput filled with data.mFilledBuffers.erase(mFilledBuffers.begin();BufferInfo *info = 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就是drainInputBuffers中写进去的3:跟到 drainInputBuffer中看看bool OMXCodec:drainInputBuffer(BufferInfo *info) CODEC_LOGV(calling emptyBuffer with codec specific data);status_t err = mOMX-emptyBuffer(mNode, info-mBuffer, 0, size,OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,0);CHECK_EQ(err, (status_t)OK);info-mStatus = OWNED_BY_COMPONENT;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 = -1;mSeekMode = ReadOptions:SEEK_CLOSEST_SYNC;err = mSource-read(if (err = OK) int64_t targetTimeUs;if (srcBuffer-meta_data()-findInt64(kKeyTargetTime, &targetTimeUs)& targetTimeUs = 0) CODEC_LOGV(targetTimeUs = %lld us, targetTimeUs);mTargetTimeUs = targetTimeUs; else mTargetTimeUs = -1;CODEC_LOGV(Calling emptyBuffer on buffer %p (length %d), timestamp %lld us (%.2f secs),info-mBuffer, offset, timestampUs, timestampUs / 1E6);err = mOMX-emptyBuffer(mNode, info-mBuffer, 0, offset,flags, timestampUs);info-mStatus = OWNED_BY_COMPONENT;return true;两点:a,调用 err = mSource-read(从原始文件中读取原始数据,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 & options-getSeekTo(&seekTimeUs, &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_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_t err = mSampleTable-findSampleAtTime(seekTimeUs * mTimescale / 1000000,uint32_t syncSampleIndex;if (err = OK) err = mSampleTable-findSyncSampleNear(sampleIndex, uint32_t sampleTime;if (err = OK) err = mSampleTable-getMetaDataForSample(sampleIndex, NULL, NULL, if (mode = ReadOptions:SEEK_CLOSEST) targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;mCurrentSampleIndex = syncSampleIndex; off64_t offset;size_t size;uint32_t cts;bool isSyncSample;bool newBuffer = false;if (mBuffer = NULL) newBuffer = true;status_t err =mSampleTable-getMetaDataForSample(mCurrentSampleIndex, &offset, &size, &cts, if (err != OK) return err;err = mGroup-acquire_buffer(if (err != OK) CHECK(mBuffer = NULL);return err; if (!mIsAVC | mWantsNALFragments) if (newBuffer) ssize_t num_bytes_read =mDataSource-readAt(offset, (uint8_t *)mBuffer-data(), size);CHECK(mBuffer != NULL);mBuffer-set_range(0, size);mBuffer-meta_data()-clear
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号