mirror of
https://github.com/androidx/media.git
synced 2025-05-11 01:31:40 +08:00
Simplify AviTrack
This commit is contained in:
parent
1528b8b5ee
commit
aee15f6c70
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user