Handle AVI containers with no keyframes in index
If there is no keyframe in the index assume that the first chunk has a keyframe. PiperOrigin-RevId: 650915467
This commit is contained in:
parent
b145a9b35e
commit
dcc3e439e2
@ -411,10 +411,8 @@ public final class AviExtractor implements Extractor {
|
|||||||
// We ignore unknown chunk IDs.
|
// We ignore unknown chunk IDs.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((flags & AVIIF_KEYFRAME) == AVIIF_KEYFRAME) {
|
chunkReader.appendIndexChunk(
|
||||||
chunkReader.appendKeyFrameToIndex(offset);
|
offset, /* isKeyFrame= */ (flags & AVIIF_KEYFRAME) == AVIIF_KEYFRAME);
|
||||||
}
|
|
||||||
chunkReader.incrementIndexChunkCount();
|
|
||||||
}
|
}
|
||||||
for (ChunkReader chunkReader : chunkReaders) {
|
for (ChunkReader chunkReader : chunkReaders) {
|
||||||
chunkReader.compactIndex();
|
chunkReader.compactIndex();
|
||||||
|
@ -70,17 +70,18 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
private int indexChunkCount;
|
private int indexChunkCount;
|
||||||
private int indexSize;
|
private int indexSize;
|
||||||
|
private long firstIndexChunkOffset;
|
||||||
private long[] keyFrameOffsets;
|
private long[] keyFrameOffsets;
|
||||||
private int[] keyFrameIndices;
|
private int[] keyFrameIndices;
|
||||||
|
|
||||||
public ChunkReader(
|
public ChunkReader(
|
||||||
int id,
|
int id,
|
||||||
@C.TrackType int trackType,
|
@C.TrackType int trackType,
|
||||||
long durationnUs,
|
long durationUs,
|
||||||
int streamHeaderChunkCount,
|
int streamHeaderChunkCount,
|
||||||
TrackOutput trackOutput) {
|
TrackOutput trackOutput) {
|
||||||
Assertions.checkArgument(trackType == C.TRACK_TYPE_AUDIO || trackType == C.TRACK_TYPE_VIDEO);
|
Assertions.checkArgument(trackType == C.TRACK_TYPE_AUDIO || trackType == C.TRACK_TYPE_VIDEO);
|
||||||
this.durationUs = durationnUs;
|
this.durationUs = durationUs;
|
||||||
this.streamHeaderChunkCount = streamHeaderChunkCount;
|
this.streamHeaderChunkCount = streamHeaderChunkCount;
|
||||||
this.trackOutput = trackOutput;
|
this.trackOutput = trackOutput;
|
||||||
@ChunkType
|
@ChunkType
|
||||||
@ -89,11 +90,16 @@ import java.util.Arrays;
|
|||||||
chunkId = getChunkIdFourCc(id, chunkType);
|
chunkId = getChunkIdFourCc(id, chunkType);
|
||||||
alternativeChunkId =
|
alternativeChunkId =
|
||||||
trackType == C.TRACK_TYPE_VIDEO ? getChunkIdFourCc(id, CHUNK_TYPE_VIDEO_UNCOMPRESSED) : -1;
|
trackType == C.TRACK_TYPE_VIDEO ? getChunkIdFourCc(id, CHUNK_TYPE_VIDEO_UNCOMPRESSED) : -1;
|
||||||
|
firstIndexChunkOffset = C.INDEX_UNSET;
|
||||||
keyFrameOffsets = new long[INITIAL_INDEX_SIZE];
|
keyFrameOffsets = new long[INITIAL_INDEX_SIZE];
|
||||||
keyFrameIndices = new int[INITIAL_INDEX_SIZE];
|
keyFrameIndices = new int[INITIAL_INDEX_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendKeyFrameToIndex(long offset) {
|
public void appendIndexChunk(long offset, boolean isKeyFrame) {
|
||||||
|
if (firstIndexChunkOffset == C.INDEX_UNSET) {
|
||||||
|
firstIndexChunkOffset = offset;
|
||||||
|
}
|
||||||
|
if (isKeyFrame) {
|
||||||
if (indexSize == keyFrameIndices.length) {
|
if (indexSize == keyFrameIndices.length) {
|
||||||
keyFrameOffsets = Arrays.copyOf(keyFrameOffsets, keyFrameOffsets.length * 3 / 2);
|
keyFrameOffsets = Arrays.copyOf(keyFrameOffsets, keyFrameOffsets.length * 3 / 2);
|
||||||
keyFrameIndices = Arrays.copyOf(keyFrameIndices, keyFrameIndices.length * 3 / 2);
|
keyFrameIndices = Arrays.copyOf(keyFrameIndices, keyFrameIndices.length * 3 / 2);
|
||||||
@ -102,6 +108,8 @@ import java.util.Arrays;
|
|||||||
keyFrameIndices[indexSize] = indexChunkCount;
|
keyFrameIndices[indexSize] = indexChunkCount;
|
||||||
indexSize++;
|
indexSize++;
|
||||||
}
|
}
|
||||||
|
indexChunkCount++;
|
||||||
|
}
|
||||||
|
|
||||||
public void advanceCurrentChunk() {
|
public void advanceCurrentChunk() {
|
||||||
currentChunkIndex++;
|
currentChunkIndex++;
|
||||||
@ -115,10 +123,6 @@ import java.util.Arrays;
|
|||||||
return getChunkTimestampUs(/* chunkIndex= */ 1);
|
return getChunkTimestampUs(/* chunkIndex= */ 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incrementIndexChunkCount() {
|
|
||||||
indexChunkCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compactIndex() {
|
public void compactIndex() {
|
||||||
keyFrameOffsets = Arrays.copyOf(keyFrameOffsets, indexSize);
|
keyFrameOffsets = Arrays.copyOf(keyFrameOffsets, indexSize);
|
||||||
keyFrameIndices = Arrays.copyOf(keyFrameIndices, indexSize);
|
keyFrameIndices = Arrays.copyOf(keyFrameIndices, indexSize);
|
||||||
@ -180,6 +184,11 @@ import java.util.Arrays;
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SeekMap.SeekPoints getSeekPoints(long timeUs) {
|
public SeekMap.SeekPoints getSeekPoints(long timeUs) {
|
||||||
|
if (indexSize == 0) {
|
||||||
|
// Return the offset of the first chunk as there are no keyframes in the index.
|
||||||
|
return new SeekMap.SeekPoints(
|
||||||
|
new SeekPoint(/* timeUs= */ 0, /* position= */ firstIndexChunkOffset));
|
||||||
|
}
|
||||||
int targetFrameIndex = (int) (timeUs / getFrameDurationUs());
|
int targetFrameIndex = (int) (timeUs / getFrameDurationUs());
|
||||||
int keyFrameIndex =
|
int keyFrameIndex =
|
||||||
Util.binarySearchFloor(
|
Util.binarySearchFloor(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user