From aee15f6c70cc2d14c17c41502b7c1c4a79d96f46 Mon Sep 17 00:00:00 2001 From: Dustin Date: Thu, 3 Feb 2022 18:07:51 -0700 Subject: [PATCH] Simplify AviTrack --- .../extractor/avi/AviExtractor.java | 20 +++++----- .../exoplayer2/extractor/avi/AviTrack.java | 37 +++++++------------ .../extractor/avi/AviExtractorTest.java | 2 +- .../exoplayer2/extractor/avi/DataHelper.java | 10 ++--- 4 files changed, 30 insertions(+), 39 deletions(-) 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 ded38ab0a6..b0c65bd8ac 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 @@ -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()); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java index ac1cd66501..14812c265f 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java @@ -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; + } } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviExtractorTest.java index ead5808eaa..ea5df7e2e6 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviExtractorTest.java @@ -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 diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java index 5e74367243..e27e8f9700 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java @@ -76,7 +76,7 @@ public class DataHelper { final ArrayList 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