Simplify AviTrack

This commit is contained in:
Dustin 2022-02-03 18:07:51 -07:00
parent 1528b8b5ee
commit aee15f6c70
4 changed files with 30 additions and 39 deletions

View File

@ -258,7 +258,7 @@ public class AviExtractor implements Extractor {
builder.setSampleMimeType(mimeType);
final LinearClock clock = new LinearClock(durationUs, length);
aviTrack = new AviTrack(streamId, C.TRACK_TYPE_VIDEO, clock, trackOutput);
aviTrack = new AviTrack(streamId, AviTrack.CHUNK_TYPE_VIDEO, clock, trackOutput);
if (MimeTypes.VIDEO_H264.equals(mimeType)) {
final AvcChunkPeeker avcChunkPeeker = new AvcChunkPeeker(builder, trackOutput, clock);
@ -294,7 +294,7 @@ public class AviExtractor implements Extractor {
builder.setInitializationData(Collections.singletonList(audioFormat.getCodecData()));
}
trackOutput.format(builder.build());
aviTrack = new AviTrack(streamId, C.TRACK_TYPE_AUDIO,
aviTrack = new AviTrack(streamId, AviTrack.CHUNK_TYPE_AUDIO,
new LinearClock(durationUs, length), trackOutput);
aviTrack.setKeyFrames(AviTrack.ALL_KEY_FRAMES);
}else {
@ -370,18 +370,18 @@ public class AviExtractor implements Extractor {
if (aviTrack != null) {
if (aviTrack.isAudio()) {
final long durationUs = aviTrack.getClock().durationUs;
i("Audio #" + aviTrack.id + " chunks: " + aviTrack.chunks + " us=" + durationUs +
i("Audio #" + aviTrack.getId() + " chunks: " + aviTrack.chunks + " us=" + durationUs +
" size=" + aviTrack.size);
final LinearClock linearClock = aviTrack.getClock();
//If the audio track duration is off from the video by >5 % recalc using video
if ((durationUs - videoDuration) / (float)videoDuration > .05f) {
w("Audio #" + aviTrack.id + " duration is off using videoDuration");
w("Audio #" + aviTrack.getId() + " duration is off using videoDuration");
linearClock.setDuration(videoDuration);
}
linearClock.setLength(aviTrack.chunks);
if (aviTrack.chunks != keyFrameCounts[aviTrack.id]) {
if (aviTrack.chunks != keyFrameCounts[aviTrack.getId()]) {
w("Audio is not all key frames chunks=" + aviTrack.chunks + " keyFrames=" +
keyFrameCounts[aviTrack.id]);
keyFrameCounts[aviTrack.getId()]);
}
}
}
@ -406,7 +406,7 @@ public class AviExtractor implements Extractor {
final ByteBuffer firstEntry = AviExtractor.allocate(16);
input.peekFully(firstEntry.array(), 0, 16);
final int videoId = videoTrack.id;
final int videoId = videoTrack.getId();
final ByteBuffer indexByteBuffer = allocate(Math.min(remaining, 64 * 1024));
final byte[] bytes = indexByteBuffer.array();
@ -453,19 +453,19 @@ public class AviExtractor implements Extractor {
keyFrameOffsetsDiv2.add(offset / 2);
for (AviTrack seekTrack : aviTracks) {
if (seekTrack != null) {
seekIndexes[seekTrack.id].add(seekTrack.chunks);
seekIndexes[seekTrack.getId()].add(seekTrack.chunks);
}
}
}
}
keyFrameCounts[aviTrack.id]++;
keyFrameCounts[aviTrack.getId()]++;
}
aviTrack.chunks++;
aviTrack.size+=size;
}
indexByteBuffer.compact();
}
if (videoTrack.chunks == keyFrameCounts[videoTrack.id]) {
if (videoTrack.chunks == keyFrameCounts[videoTrack.getId()]) {
videoTrack.setKeyFrames(AviTrack.ALL_KEY_FRAMES);
} else {
videoTrack.setKeyFrames(seekIndexes[videoId].getArray());

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.avi;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.TrackOutput;
@ -29,10 +30,8 @@ import java.util.Arrays;
*/
public class AviTrack {
public static final int[] ALL_KEY_FRAMES = new int[0];
final int id;
final @C.TrackType int trackType;
public static int CHUNK_TYPE_VIDEO = ('d' << 16) | ('c' << 24);
public static int CHUNK_TYPE_AUDIO = ('w' << 16) | ('b' << 24);
@NonNull
LinearClock clock;
@ -57,34 +56,22 @@ public class AviTrack {
transient int chunkSize;
transient int chunkRemaining;
private static int getChunkIdLower(int id) {
@VisibleForTesting
static int getChunkIdLower(int id) {
int tens = id / 10;
int ones = id % 10;
return ('0' + tens) | (('0' + ones) << 8);
}
public static int getVideoChunkId(int id) {
return getChunkIdLower(id) | ('d' << 16) | ('c' << 24);
}
public static int getAudioChunkId(int id) {
return getChunkIdLower(id) | ('w' << 16) | ('b' << 24);
}
AviTrack(int id, @C.TrackType int trackType, @NonNull LinearClock clock,
AviTrack(int id, int chunkType, @NonNull LinearClock clock,
@NonNull TrackOutput trackOutput) {
this.id = id;
this.chunkId = getChunkIdLower(id) | chunkType;
this.clock = clock;
this.trackType = trackType;
this.trackOutput = trackOutput;
if (isVideo()) {
chunkId = getVideoChunkId(id);
chunkIdAlt = getChunkIdLower(id) | ('d' << 16) | ('b' << 24);
} else if (isAudio()) {
chunkId = getAudioChunkId(id);
chunkIdAlt = 0xffff;
} else {
throw new IllegalArgumentException("Unknown Track Type: " + trackType);
chunkIdAlt = -1;
}
}
@ -118,11 +105,11 @@ public class AviTrack {
}
public boolean isVideo() {
return trackType == C.TRACK_TYPE_VIDEO;
return (chunkId & CHUNK_TYPE_VIDEO) == CHUNK_TYPE_VIDEO;
}
public boolean isAudio() {
return trackType == C.TRACK_TYPE_AUDIO;
return (chunkId & CHUNK_TYPE_AUDIO) == CHUNK_TYPE_AUDIO;
}
public boolean newChunk(int tag, int size, ExtractorInput input) throws IOException {
@ -169,4 +156,8 @@ public class AviTrack {
//Log.d(AviExtractor.TAG, "Frame: " + (isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " size=" + size + " frame=" + clock.getIndex() + " key=" + isKeyFrame());
clock.advance();
}
public int getId() {
return ((chunkId >> 8) & 0xf) + ( chunkId & 0xf) * 10;
}
}

View File

@ -473,7 +473,7 @@ public class AviExtractorTest {
final AviTrack aviTrack = aviExtractor.getVideoTrack();
final long position = DataHelper.MOVI_OFFSET + aviSeekMap.keyFrameOffsetsDiv2[1] * 2L;
aviExtractor.seek(position, 0L);
Assert.assertEquals(aviSeekMap.seekIndexes[aviTrack.id][1], aviTrack.getClock().getIndex());
Assert.assertEquals(aviSeekMap.seekIndexes[aviTrack.getId()][1], aviTrack.getClock().getIndex());
}
@Test

View File

@ -76,7 +76,7 @@ public class DataHelper {
final ArrayList<Box> list = new ArrayList<>(2);
list.add(streamHeaderBox);
list.add(streamFormatBox);
return new ListBox((int)(streamHeaderBox.getSize() + streamFormatBox.getSize()),
return new ListBox(streamHeaderBox.getSize() + streamFormatBox.getSize(),
ListBox.TYPE_STRL, list);
}
@ -106,14 +106,14 @@ public class DataHelper {
public static AviTrack getVideoAviTrack(int sec) {
final FakeTrackOutput fakeTrackOutput = new FakeTrackOutput(false);
return new AviTrack(0, C.TRACK_TYPE_VIDEO,
return new AviTrack(0, AviTrack.CHUNK_TYPE_VIDEO,
new LinearClock(sec * 1_000_000L, sec * FPS),
fakeTrackOutput);
}
public static AviTrack getAudioAviTrack(int sec) {
final FakeTrackOutput fakeTrackOutput = new FakeTrackOutput(false);
return new AviTrack(AUDIO_ID, C.TRACK_TYPE_AUDIO,
return new AviTrack(AUDIO_ID, AviTrack.CHUNK_TYPE_AUDIO,
new LinearClock(sec * 1_000_000L, sec * FPS * AUDIO_PER_VIDEO),
fakeTrackOutput);
}
@ -153,8 +153,8 @@ public class DataHelper {
*/
public static ByteBuffer getIndex(final int secs, final int keyFrameRate, int offset) {
final int videoFrames = secs * FPS;
final int videoChunkId = AviTrack.getVideoChunkId(0);
final int audioChunkId = AviTrack.getAudioChunkId(1);
final int videoChunkId = AviTrack.CHUNK_TYPE_VIDEO | AviTrack.getChunkIdLower(0);
final int audioChunkId = AviTrack.CHUNK_TYPE_AUDIO | AviTrack.getChunkIdLower(1);
final ByteBuffer byteBuffer = AviExtractor.allocate((videoFrames + videoFrames*AUDIO_PER_VIDEO) * 16);
for (int v=0;v<videoFrames;v++) {