diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java index a19a4178df..33380cadd9 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java @@ -399,6 +399,14 @@ public class AviExtractor implements Extractor { w("No video track found"); return; } + if (remaining < 16) { + output.seekMap(new SeekMap.Unseekable(getDuration())); + w("Index too short"); + return; + } + final ByteBuffer firstEntry = AviExtractor.allocate(16); + input.peekFully(firstEntry.array(), 0, 16); + final int videoId = videoTrack.id; final ByteBuffer indexByteBuffer = allocate(Math.min(remaining, 64 * 1024)); final byte[] bytes = indexByteBuffer.array(); @@ -466,8 +474,10 @@ public class AviExtractor implements Extractor { videoTrack.setKeyFrames(seekIndexes[videoId].getArray()); } + //Work-around a bug where the offset is from the start of the file, not "movi" + final long seekOffset = firstEntry.getInt(8) > moviOffset ? 0L : moviOffset; final AviSeekMap seekMap = new AviSeekMap(videoId, videoTrack.clock.durationUs, videoTrack.chunks, - keyFrameOffsetsDiv2.getArray(), seekIndexes, moviOffset); + keyFrameOffsetsDiv2.getArray(), seekIndexes, seekOffset); i("Video chunks=" + videoTrack.chunks + " us=" + seekMap.getDurationUs()); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java index e5539039eb..717fd7f167 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java @@ -14,10 +14,13 @@ public class AviSeekMap implements SeekMap { final int[] keyFrameOffsetsDiv2; //Seek chunk indexes by streamId final int[][] seekIndexes; - final long moviOffset; + /** + * Usually the same as moviOffset, but sometimes 0 (muxer bug) + */ + final long seekOffset; public AviSeekMap(int videoId, long usDuration, int videoChunks, int[] keyFrameOffsetsDiv2, - UnboundedIntArray[] seekIndexes, long moviOffset) { + UnboundedIntArray[] seekIndexes, long seekOffset) { this.videoId = videoId; this.videoUsPerChunk = usDuration / videoChunks; this.duration = usDuration; @@ -26,7 +29,7 @@ public class AviSeekMap implements SeekMap { for (int i=0;i