赞
踩
前文我们讲到了Exoplayer数据源打开过程, 媒体数据流链接建立好之后会对数据流解析媒体格式解析, 本文我们主要讲Extrator解析和读取数据的六层
ExtractingLoadable.load() ->
BundledExtractorsAdapter.read() →
Mp4Extractor.read() →
Mp4Extractor.readSample() →
TrackOutput.sampleData() →
SampleQueue.sampleData() ->
SampleDataQueue.sampleData() ->
public void load() throws IOException { int result = Extractor.RESULT_CONTINUE; while (result == Extractor.RESULT_CONTINUE && !loadCanceled) { try { //初始化Extractor progressiveMediaExtractor.init( extractorDataSource, uri, dataSource.getResponseHeaders(), position, length, extractorOutput); //如果result != Extractor.RESULT_CONTINUE 或者删除播放,退出读取数据 while (result == Extractor.RESULT_CONTINUE && !loadCanceled) { //Extractor 读取解析数据 result = progressiveMediaExtractor.read(positionHolder); } } }
public int read(PositionHolder positionHolder) throws IOException {
//extractor MP4Extractor实例 extractorInput DefaultExtractorInput实例
return Assertions.checkNotNull(extractor).read(Assertions.checkNotNull(extractorInput), positionHolder);
}
Mp4Extractor
// 这里我们只关心 STATE_READING_SAMPLE case, public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException { while (true) { switch (parserState) { case STATE_READING_ATOM_HEADER: if (!readAtomHeader(input)) { return RESULT_END_OF_INPUT; } break; case STATE_READING_ATOM_PAYLOAD: if (readAtomPayload(input, seekPosition)) { return RESULT_SEEK; } break; case STATE_READING_SAMPLE: // 读取数据 return readSample(input, seekPosition); case STATE_READING_SEF: return readSefData(input, seekPosition); default: throw new IllegalStateException(); } } } private int readSample(ExtractorInput input, PositionHolder positionHolder) throws IOException { //循环读取数据,并记录读取数据的长度 while (sampleBytesWritten < sampleSize) { int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false); sampleBytesRead += writtenBytes; sampleBytesWritten += writtenBytes; sampleCurrentNalBytesRemaining -= writtenBytes; } return RESULT_CONTINUE; }
default int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException {
return sampleData(input, length, allowEndOfInput, SAMPLE_DATA_PART_MAIN);
}
public final int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException {
//sampleDataQueue 是 SampleDataQueue实例
return sampleDataQueue.sampleData(input, length, allowEndOfInput);
}
SampleDataQueue
public int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException {
/* 将数据读取到writeAllocationNode.allocation.data 缓存中,
* writeAllocationNode.allocation.data 保存的是h264, pcm等压缩数据
* writeAllocationNode.allocation.data 后续会被渲染器读取, 解码渲染
*/
int bytesAppended =
input.read(
writeAllocationNode.allocation.data,
writeAllocationNode.translateOffset(totalBytesWritten),
length);
return bytesAppended;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。