系列文章目录
ExoPlayer架构详解与源码分析(1)——前言
ExoPlayer架构详解与源码分析(2)——Player
ExoPlayer架构详解与源码分析(3)——Timeline
ExoPlayer架构详解与源码分析(4)——整体架构
ExoPlayer架构详解与源码分析(5)——MediaSource
ExoPlayer架构详解与源码分析(6)——MediaPeriod
ExoPlayer架构详解与源码分析(7)——SampleQueue
ExoPlayer架构详解与源码分析(8)——Loader
ExoPlayer架构详解与源码分析(9)——TsExtractor
ExoPlayer架构详解与源码分析(10)——H264Reader
ExoPlayer架构详解与源码分析(11)——DataSource
ExoPlayer架构详解与源码分析(12)——Cache
ExoPlayer架构详解与源码分析(13)——TeeDataSource和CacheDataSource
ExoPlayer架构详解与源码分析(14)——ProgressiveMediaPeriod
文章目录
前言
中途间隔了一段时间,之前写了那么多铺垫,终于看到ProgressiveMediaPeriod实现部分了
ProgressiveMediaPeriod
有了之前的那些铺垫,这里直接看源码了
@Override
public void prepare(Callback callback, long positionUs) {
this.callback = callback;
loadCondition.open();//保证继续加载的开关打开,Loader不阻塞
startLoading();
}
private void startLoading() {
ExtractingLoadable loadable =//创建loadable 共Loader加载
new ExtractingLoadable(//extractorOutput监听,也就是Loader加载过程中会回调ProgressiveMediaPeriod的track,endTracks
uri, dataSource, progressiveMediaExtractor, /* extractorOutput= */ this, loadCondition);
if (prepared) {
//如果已经准备完成
Assertions.checkState(isPendingReset());
if (durationUs != C.TIME_UNSET && pendingResetPositionUs > durationUs) {
//当前定位位置已经超过总时长,直接加载结束
loadingFinished = true;
pendingResetPositionUs = C.TIME_UNSET;
return;
}
//通过seekMap查找出当前时间对于的数据位置
loadable.setLoadPosition(
checkNotNull(seekMap).getSeekPoints(pendingResetPositionUs).first.position,
pendingResetPositionUs);
for (SampleQueue sampleQueue : sampleQueues) {
//将所有的轨道开始时间同步
sampleQueue.setStartTimeUs(pendingResetPositionUs);
}
pendingResetPositionUs = C.TIME_UNSET;
}
//获取开始加载时所有轨道已经提前的数据块总数,后面通过当前的数据块总数和开始的数量对比,可以判断出是否加载了新的数据
extractedSamplesCountAtStartOfLoad = getExtractedSamplesCount();
long elapsedRealtimeMs =
loader.startLoading(//Loader开始加载,具体过程参照Loader部分的文章,此时加载状态的回调this,也就是加载完成后会调用ProgressiveMediaPeriod onLoadCompleted,seekMap
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(dataType));
DataSpec dataSpec = loadable.dataSpec;
//触发监听
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, dataSpec, elapsedRealtimeMs),
C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN,
/* trackFormat= */ null,
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ loadable.seekTimeUs,
durationUs);
}
@Override
//Loader加载时如果解析器需要输出Sample数据会先回调track,获取TrackOutput
public TrackOutput