mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
More AviExtractor tests
This commit is contained in:
parent
66c240f1bd
commit
432ff5ea70
5 changed files with 191 additions and 6 deletions
|
|
@ -351,7 +351,8 @@ public class AviExtractor implements Extractor {
|
||||||
return RESULT_SEEK;
|
return RESULT_SEEK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AviTrack getVideoTrack() {
|
@VisibleForTesting
|
||||||
|
AviTrack getVideoTrack() {
|
||||||
for (@Nullable AviTrack aviTrack : aviTracks) {
|
for (@Nullable AviTrack aviTrack : aviTracks) {
|
||||||
if (aviTrack != null && aviTrack.isVideo()) {
|
if (aviTrack != null && aviTrack.isVideo()) {
|
||||||
return aviTrack;
|
return aviTrack;
|
||||||
|
|
@ -510,7 +511,7 @@ public class AviExtractor implements Extractor {
|
||||||
final AviTrack aviTrack = getAviTrack(chunkId);
|
final AviTrack aviTrack = getAviTrack(chunkId);
|
||||||
if (aviTrack == null) {
|
if (aviTrack == null) {
|
||||||
seekPosition.position = alignPosition(input.getPosition() + size);
|
seekPosition.position = alignPosition(input.getPosition() + size);
|
||||||
Log.w(TAG, "Unknown tag=" + toString(chunkId) + " pos=" + (input.getPosition() - 8)
|
w("Unknown tag=" + toString(chunkId) + " pos=" + (input.getPosition() - 8)
|
||||||
+ " size=" + size + " moviEnd=" + moviEnd);
|
+ " size=" + size + " moviEnd=" + moviEnd);
|
||||||
return RESULT_SEEK;
|
return RESULT_SEEK;
|
||||||
}
|
}
|
||||||
|
|
@ -590,6 +591,27 @@ public class AviExtractor implements Extractor {
|
||||||
this.aviTracks = aviTracks;
|
this.aviTracks = aviTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
void setAviHeader(final AviHeaderBox aviHeaderBox) {
|
||||||
|
aviHeader = aviHeaderBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
void setMovi(final int offset, final int end) {
|
||||||
|
moviOffset = offset;
|
||||||
|
moviEnd = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
AviTrack getChunkHandler() {
|
||||||
|
return chunkHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
void setChunkHandler(final AviTrack aviTrack) {
|
||||||
|
chunkHandler = aviTrack;
|
||||||
|
}
|
||||||
|
|
||||||
private static void w(String message) {
|
private static void w(String message) {
|
||||||
try {
|
try {
|
||||||
Log.w(TAG, message);
|
Log.w(TAG, message);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.google.android.exoplayer2.extractor.avi;
|
package com.google.android.exoplayer2.extractor.avi;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public class AviHeaderBox extends ResidentBox {
|
public class AviHeaderBox extends ResidentBox {
|
||||||
|
|
@ -49,4 +50,9 @@ public class AviHeaderBox extends ResidentBox {
|
||||||
// 28 - dwSuggestedBufferSize
|
// 28 - dwSuggestedBufferSize
|
||||||
// 32 - dwWidth
|
// 32 - dwWidth
|
||||||
// 36 - dwHeight
|
// 36 - dwHeight
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
void setFlags(int flags) {
|
||||||
|
byteBuffer.putInt(12, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
package com.google.android.exoplayer2.extractor.avi;
|
package com.google.android.exoplayer2.extractor.avi;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
|
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer2.testutil.FakeExtractorInput;
|
import com.google.android.exoplayer2.testutil.FakeExtractorInput;
|
||||||
import com.google.android.exoplayer2.testutil.FakeExtractorOutput;
|
import com.google.android.exoplayer2.testutil.FakeExtractorOutput;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeTrackOutput;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
@ -296,4 +300,153 @@ public class AviExtractorTest {
|
||||||
|
|
||||||
Assert.assertTrue(listBox.getChildren().get(0) instanceof AviHeaderBox);
|
Assert.assertTrue(listBox.getChildren().get(0) instanceof AviHeaderBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findMovi_givenMoviListAndIndex() throws IOException {
|
||||||
|
final AviExtractor aviExtractor = new AviExtractor();
|
||||||
|
aviExtractor.setAviHeader(DataHelper.createAviHeaderBox());
|
||||||
|
final FakeExtractorOutput fakeExtractorOutput = new FakeExtractorOutput();
|
||||||
|
aviExtractor.init(fakeExtractorOutput);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = AviExtractor.allocate(12);
|
||||||
|
byteBuffer.putInt(ListBox.LIST);
|
||||||
|
byteBuffer.putInt(64*1024);
|
||||||
|
byteBuffer.putInt(AviExtractor.MOVI);
|
||||||
|
final ExtractorInput input = new FakeExtractorInput.Builder().setData(byteBuffer.array()).build();
|
||||||
|
aviExtractor.findMovi(input, new PositionHolder());
|
||||||
|
Assert.assertEquals(aviExtractor.state, AviExtractor.STATE_READ_IDX1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findMovi_givenMoviListAndNoIndex() throws IOException {
|
||||||
|
final AviExtractor aviExtractor = new AviExtractor();
|
||||||
|
final AviHeaderBox aviHeaderBox = DataHelper.createAviHeaderBox();
|
||||||
|
aviHeaderBox.setFlags(0);
|
||||||
|
aviExtractor.setAviHeader(aviHeaderBox);
|
||||||
|
final FakeExtractorOutput fakeExtractorOutput = new FakeExtractorOutput();
|
||||||
|
aviExtractor.init(fakeExtractorOutput);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = AviExtractor.allocate(12);
|
||||||
|
byteBuffer.putInt(ListBox.LIST);
|
||||||
|
byteBuffer.putInt(64*1024);
|
||||||
|
byteBuffer.putInt(AviExtractor.MOVI);
|
||||||
|
final ExtractorInput input = new FakeExtractorInput.Builder().setData(byteBuffer.array()).build();
|
||||||
|
aviExtractor.state = AviExtractor.STATE_FIND_MOVI;
|
||||||
|
aviExtractor.read(input, new PositionHolder());
|
||||||
|
Assert.assertEquals(aviExtractor.state, AviExtractor.STATE_READ_TRACKS);
|
||||||
|
Assert.assertTrue(fakeExtractorOutput.seekMap instanceof SeekMap.Unseekable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findMovi_givenJunk() throws IOException {
|
||||||
|
final AviExtractor aviExtractor = new AviExtractor();
|
||||||
|
aviExtractor.setAviHeader(DataHelper.createAviHeaderBox());
|
||||||
|
final FakeExtractorOutput fakeExtractorOutput = new FakeExtractorOutput();
|
||||||
|
aviExtractor.init(fakeExtractorOutput);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = AviExtractor.allocate(12);
|
||||||
|
byteBuffer.putInt(AviExtractor.JUNK);
|
||||||
|
byteBuffer.putInt(64*1024);
|
||||||
|
final ExtractorInput input = new FakeExtractorInput.Builder().setData(byteBuffer.array()).build();
|
||||||
|
final PositionHolder positionHolder = new PositionHolder();
|
||||||
|
aviExtractor.findMovi(input, positionHolder);
|
||||||
|
Assert.assertEquals(64 * 1024 + 8, positionHolder.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AviExtractor setupReadSamples() {
|
||||||
|
final AviExtractor aviExtractor = new AviExtractor();
|
||||||
|
aviExtractor.setAviHeader(DataHelper.createAviHeaderBox());
|
||||||
|
final FakeExtractorOutput fakeExtractorOutput = new FakeExtractorOutput();
|
||||||
|
aviExtractor.init(fakeExtractorOutput);
|
||||||
|
|
||||||
|
final AviTrack aviTrack = DataHelper.getVideoAviTrack(9);
|
||||||
|
aviExtractor.setAviTracks(new AviTrack[]{aviTrack});
|
||||||
|
final Format format = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_MP4V).build();
|
||||||
|
aviTrack.trackOutput.format(format);
|
||||||
|
|
||||||
|
aviExtractor.state = AviExtractor.STATE_READ_SAMPLES;
|
||||||
|
aviExtractor.setMovi(DataHelper.MOVI_OFFSET, 128*1024);
|
||||||
|
return aviExtractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readSamples_givenAtEndOfInput() throws IOException {
|
||||||
|
AviExtractor aviExtractor = setupReadSamples();
|
||||||
|
aviExtractor.setMovi(0, 0);
|
||||||
|
final AviTrack aviTrack = aviExtractor.getVideoTrack();
|
||||||
|
final ByteBuffer byteBuffer = AviExtractor.allocate(32);
|
||||||
|
byteBuffer.putInt(aviTrack.chunkId);
|
||||||
|
byteBuffer.putInt(24);
|
||||||
|
|
||||||
|
final ExtractorInput input = new FakeExtractorInput.Builder().setData(byteBuffer.array()).build();
|
||||||
|
Assert.assertEquals(Extractor.RESULT_END_OF_INPUT, aviExtractor.read(input, new PositionHolder()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readSamples_completeChunk() throws IOException {
|
||||||
|
AviExtractor aviExtractor = setupReadSamples();
|
||||||
|
final AviTrack aviTrack = aviExtractor.getVideoTrack();
|
||||||
|
final ByteBuffer byteBuffer = AviExtractor.allocate(32);
|
||||||
|
byteBuffer.putInt(aviTrack.chunkId);
|
||||||
|
byteBuffer.putInt(24);
|
||||||
|
|
||||||
|
final ExtractorInput input = new FakeExtractorInput.Builder().setData(byteBuffer.array())
|
||||||
|
.build();
|
||||||
|
Assert.assertEquals(Extractor.RESULT_CONTINUE, aviExtractor.read(input, new PositionHolder()));
|
||||||
|
|
||||||
|
final FakeTrackOutput fakeTrackOutput = (FakeTrackOutput) aviTrack.trackOutput;
|
||||||
|
Assert.assertEquals(24, fakeTrackOutput.getSampleData(0).length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readSamples_fragmentedChunk() throws IOException {
|
||||||
|
AviExtractor aviExtractor = setupReadSamples();
|
||||||
|
final AviTrack aviTrack = aviExtractor.getVideoTrack();
|
||||||
|
final int size = 24 + 16;
|
||||||
|
final ByteBuffer byteBuffer = AviExtractor.allocate(32);
|
||||||
|
byteBuffer.putInt(aviTrack.chunkId);
|
||||||
|
byteBuffer.putInt(size);
|
||||||
|
|
||||||
|
final ExtractorInput chunk0 = new FakeExtractorInput.Builder().setData(byteBuffer.array())
|
||||||
|
.build();
|
||||||
|
Assert.assertEquals(Extractor.RESULT_CONTINUE, aviExtractor.read(chunk0, new PositionHolder()));
|
||||||
|
|
||||||
|
final ExtractorInput chunk1 = new FakeExtractorInput.Builder().setData(new byte[16])
|
||||||
|
.build();
|
||||||
|
Assert.assertEquals(Extractor.RESULT_CONTINUE, aviExtractor.read(chunk1, new PositionHolder()));
|
||||||
|
|
||||||
|
final FakeTrackOutput fakeTrackOutput = (FakeTrackOutput) aviTrack.trackOutput;
|
||||||
|
Assert.assertEquals(size, fakeTrackOutput.getSampleData(0).length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void seek_givenPosition0() throws IOException {
|
||||||
|
final AviExtractor aviExtractor = setupReadSamples();
|
||||||
|
final AviTrack aviTrack = aviExtractor.getVideoTrack();
|
||||||
|
aviExtractor.setChunkHandler(aviTrack);
|
||||||
|
aviTrack.getClock().setIndex(10);
|
||||||
|
|
||||||
|
aviExtractor.seek(0L, 0L);
|
||||||
|
|
||||||
|
Assert.assertNull(aviExtractor.getChunkHandler());
|
||||||
|
Assert.assertEquals(0, aviTrack.getClock().getIndex());
|
||||||
|
Assert.assertEquals(aviExtractor.state, AviExtractor.STATE_SEEK_START);
|
||||||
|
|
||||||
|
|
||||||
|
final ExtractorInput input = new FakeExtractorInput.Builder().setData(new byte[0]).build();
|
||||||
|
final PositionHolder positionHolder = new PositionHolder();
|
||||||
|
Assert.assertEquals(Extractor.RESULT_SEEK, aviExtractor.read(input, positionHolder));
|
||||||
|
Assert.assertEquals(DataHelper.MOVI_OFFSET + 4, positionHolder.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void seek_givenKeyFrame() throws IOException {
|
||||||
|
final AviExtractor aviExtractor = setupReadSamples();
|
||||||
|
final AviSeekMap aviSeekMap = DataHelper.getAviSeekMap();
|
||||||
|
aviExtractor.aviSeekMap = aviSeekMap;
|
||||||
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,9 +8,7 @@ public class AviHeaderBoxTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getters() {
|
public void getters() {
|
||||||
final ByteBuffer byteBuffer = DataHelper.createAviHeader();
|
final AviHeaderBox aviHeaderBox = DataHelper.createAviHeaderBox();
|
||||||
final AviHeaderBox aviHeaderBox = new AviHeaderBox(AviHeaderBox.AVIH,
|
|
||||||
byteBuffer.capacity(), byteBuffer);
|
|
||||||
Assert.assertEquals(DataHelper.VIDEO_US, aviHeaderBox.getMicroSecPerFrame());
|
Assert.assertEquals(DataHelper.VIDEO_US, aviHeaderBox.getMicroSecPerFrame());
|
||||||
Assert.assertTrue(aviHeaderBox.hasIndex());
|
Assert.assertTrue(aviHeaderBox.hasIndex());
|
||||||
Assert.assertFalse(aviHeaderBox.mustUseIndex());
|
Assert.assertFalse(aviHeaderBox.mustUseIndex());
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ public class DataHelper {
|
||||||
static final int VIDEO_SIZE = 4096;
|
static final int VIDEO_SIZE = 4096;
|
||||||
static final int AUDIO_SIZE = 256;
|
static final int AUDIO_SIZE = 256;
|
||||||
static final int AUDIO_ID = 1;
|
static final int AUDIO_ID = 1;
|
||||||
|
static final int MOVI_OFFSET = 4096;
|
||||||
private static final long AUDIO_US = VIDEO_US / AUDIO_PER_VIDEO;
|
private static final long AUDIO_US = VIDEO_US / AUDIO_PER_VIDEO;
|
||||||
|
|
||||||
//Base path "\ExoPlayer\library\extractor\."
|
//Base path "\ExoPlayer\library\extractor\."
|
||||||
|
|
@ -124,7 +125,7 @@ public class DataHelper {
|
||||||
audioArray.add(0);
|
audioArray.add(0);
|
||||||
audioArray.add(128);
|
audioArray.add(128);
|
||||||
return new AviSeekMap(0, 100L, 8, keyFrameOffsetsDiv2,
|
return new AviSeekMap(0, 100L, 8, keyFrameOffsetsDiv2,
|
||||||
new UnboundedIntArray[]{videoArray, audioArray}, 4096);
|
new UnboundedIntArray[]{videoArray, audioArray}, MOVI_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void putIndex(final ByteBuffer byteBuffer, int chunkId, int flags, int offset,
|
private static void putIndex(final ByteBuffer byteBuffer, int chunkId, int flags, int offset,
|
||||||
|
|
@ -186,4 +187,9 @@ public class DataHelper {
|
||||||
byteBuffer.clear();
|
byteBuffer.clear();
|
||||||
return byteBuffer;
|
return byteBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AviHeaderBox createAviHeaderBox() {
|
||||||
|
final ByteBuffer byteBuffer = createAviHeader();
|
||||||
|
return new AviHeaderBox(AviHeaderBox.AVIH, byteBuffer.capacity(), byteBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue