mirror of
https://github.com/androidx/media.git
synced 2025-05-10 00:59:51 +08:00
Add work-around for muxer bug where idx1 offset is from 0, not "movi"
location
This commit is contained in:
parent
0ff238df99
commit
9bd93ad98e
@ -399,6 +399,14 @@ public class AviExtractor implements Extractor {
|
|||||||
w("No video track found");
|
w("No video track found");
|
||||||
return;
|
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 int videoId = videoTrack.id;
|
||||||
final ByteBuffer indexByteBuffer = allocate(Math.min(remaining, 64 * 1024));
|
final ByteBuffer indexByteBuffer = allocate(Math.min(remaining, 64 * 1024));
|
||||||
final byte[] bytes = indexByteBuffer.array();
|
final byte[] bytes = indexByteBuffer.array();
|
||||||
@ -466,8 +474,10 @@ public class AviExtractor implements Extractor {
|
|||||||
videoTrack.setKeyFrames(seekIndexes[videoId].getArray());
|
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,
|
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());
|
i("Video chunks=" + videoTrack.chunks + " us=" + seekMap.getDurationUs());
|
||||||
|
|
||||||
|
@ -14,10 +14,13 @@ public class AviSeekMap implements SeekMap {
|
|||||||
final int[] keyFrameOffsetsDiv2;
|
final int[] keyFrameOffsetsDiv2;
|
||||||
//Seek chunk indexes by streamId
|
//Seek chunk indexes by streamId
|
||||||
final int[][] seekIndexes;
|
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,
|
public AviSeekMap(int videoId, long usDuration, int videoChunks, int[] keyFrameOffsetsDiv2,
|
||||||
UnboundedIntArray[] seekIndexes, long moviOffset) {
|
UnboundedIntArray[] seekIndexes, long seekOffset) {
|
||||||
this.videoId = videoId;
|
this.videoId = videoId;
|
||||||
this.videoUsPerChunk = usDuration / videoChunks;
|
this.videoUsPerChunk = usDuration / videoChunks;
|
||||||
this.duration = usDuration;
|
this.duration = usDuration;
|
||||||
@ -26,7 +29,7 @@ public class AviSeekMap implements SeekMap {
|
|||||||
for (int i=0;i<seekIndexes.length;i++) {
|
for (int i=0;i<seekIndexes.length;i++) {
|
||||||
this.seekIndexes[i] = seekIndexes[i].getArray();
|
this.seekIndexes[i] = seekIndexes[i].getArray();
|
||||||
}
|
}
|
||||||
this.moviOffset = moviOffset;
|
this.seekOffset = seekOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -56,7 +59,7 @@ public class AviSeekMap implements SeekMap {
|
|||||||
private SeekPoint getSeekPoint(int index) {
|
private SeekPoint getSeekPoint(int index) {
|
||||||
long offset = keyFrameOffsetsDiv2[index] * 2L;
|
long offset = keyFrameOffsetsDiv2[index] * 2L;
|
||||||
final long outUs = seekIndexes[videoId][index] * videoUsPerChunk;
|
final long outUs = seekIndexes[videoId][index] * videoUsPerChunk;
|
||||||
final long position = offset + moviOffset;
|
final long position = offset + seekOffset;
|
||||||
return new SeekPoint(outUs, position);
|
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) {
|
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) {
|
if (index < 0) {
|
||||||
throw new IllegalArgumentException("Position: " + position);
|
throw new IllegalArgumentException("Position: " + position);
|
||||||
|
@ -9,7 +9,7 @@ public class AviSeekMapTest {
|
|||||||
@Test
|
@Test
|
||||||
public void setFrames_givenExactSeekPointMatch() {
|
public void setFrames_givenExactSeekPointMatch() {
|
||||||
final AviSeekMap aviSeekMap = DataHelper.getAviSeekMap();
|
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 int secs = 4;
|
||||||
final AviTrack[] aviTracks = new AviTrack[]{DataHelper.getVideoAviTrack(secs),
|
final AviTrack[] aviTracks = new AviTrack[]{DataHelper.getVideoAviTrack(secs),
|
||||||
DataHelper.getAudioAviTrack(secs)};
|
DataHelper.getAudioAviTrack(secs)};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user