Add work-around for muxer bug where idx1 offset is from 0, not "movi"

location
This commit is contained in:
Dustin 2022-01-31 04:48:57 -07:00
parent 0ff238df99
commit 9bd93ad98e
3 changed files with 20 additions and 7 deletions

View File

@ -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());

View File

@ -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<seekIndexes.length;i++) {
this.seekIndexes[i] = seekIndexes[i].getArray();
}
this.moviOffset = moviOffset;
this.seekOffset = seekOffset;
}
@Override
@ -56,7 +59,7 @@ public class AviSeekMap implements SeekMap {
private SeekPoint getSeekPoint(int index) {
long offset = keyFrameOffsetsDiv2[index] * 2L;
final long outUs = seekIndexes[videoId][index] * videoUsPerChunk;
final long position = offset + moviOffset;
final long position = offset + seekOffset;
return new SeekPoint(outUs, position);
}
@ -78,7 +81,7 @@ public class AviSeekMap implements SeekMap {
}
public void setFrames(final long position, final long timeUs, final AviTrack[] aviTracks) {
final int index = Arrays.binarySearch(keyFrameOffsetsDiv2, (int)((position - moviOffset) / 2));
final int index = Arrays.binarySearch(keyFrameOffsetsDiv2, (int)((position - seekOffset) / 2));
if (index < 0) {
throw new IllegalArgumentException("Position: " + position);

View File

@ -9,7 +9,7 @@ public class AviSeekMapTest {
@Test
public void setFrames_givenExactSeekPointMatch() {
final AviSeekMap aviSeekMap = DataHelper.getAviSeekMap();
final long position = aviSeekMap.keyFrameOffsetsDiv2[1] * 2L + aviSeekMap.moviOffset;
final long position = aviSeekMap.keyFrameOffsetsDiv2[1] * 2L + aviSeekMap.seekOffset;
final int secs = 4;
final AviTrack[] aviTracks = new AviTrack[]{DataHelper.getVideoAviTrack(secs),
DataHelper.getAudioAviTrack(secs)};