Supports extracting from AMR container format.

Supports extracting data from AMR container format for both narrow and wide
band formats. Also added AmrExtractor as one of the default extractor to be
used in DefaultExtractorsFactory.

GitHub: #2527.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=194407507
This commit is contained in:
hoangtc 2018-04-26 09:29:01 -07:00 committed by Oliver Woodman
parent 59f01ec333
commit fe32401792
10 changed files with 2244 additions and 14 deletions

View File

@ -35,6 +35,8 @@
* IMA: Allow setting the ad media load timeout * IMA: Allow setting the ad media load timeout
([#3691](https://github.com/google/ExoPlayer/issues/3691)). ([#3691](https://github.com/google/ExoPlayer/issues/3691)).
* Audio: * Audio:
* Support extracting data from AMR container formats, including both narrow
and wide band ([#2527](https://github.com/google/ExoPlayer/issues/2527)).
* FLAC: * FLAC:
* Sniff FLAC files correctly if they have ID3 headers * Sniff FLAC files correctly if they have ID3 headers
([#4055](https://github.com/google/ExoPlayer/issues/4055)). ([#4055](https://github.com/google/ExoPlayer/issues/4055)).

View File

@ -34,6 +34,7 @@ dependencies {
implementation 'com.android.support:support-annotations:' + supportLibraryVersion implementation 'com.android.support:support-annotations:' + supportLibraryVersion
implementation project(modulePrefix + 'library-core') implementation project(modulePrefix + 'library-core')
androidTestImplementation project(modulePrefix + 'testutils') androidTestImplementation project(modulePrefix + 'testutils')
testImplementation project(modulePrefix + 'testutils-robolectric')
} }
ext { ext {

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.extractor; package com.google.android.exoplayer2.extractor;
import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
import com.google.android.exoplayer2.extractor.flv.FlvExtractor; import com.google.android.exoplayer2.extractor.flv.FlvExtractor;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor; import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
@ -35,18 +36,19 @@ import java.lang.reflect.Constructor;
* An {@link ExtractorsFactory} that provides an array of extractors for the following formats: * An {@link ExtractorsFactory} that provides an array of extractors for the following formats:
* *
* <ul> * <ul>
* <li>MP4, including M4A ({@link Mp4Extractor})</li> * <li>MP4, including M4A ({@link Mp4Extractor})
* <li>fMP4 ({@link FragmentedMp4Extractor})</li> * <li>fMP4 ({@link FragmentedMp4Extractor})
* <li>Matroska and WebM ({@link MatroskaExtractor})</li> * <li>Matroska and WebM ({@link MatroskaExtractor})
* <li>Ogg Vorbis/FLAC ({@link OggExtractor}</li> * <li>Ogg Vorbis/FLAC ({@link OggExtractor}
* <li>MP3 ({@link Mp3Extractor})</li> * <li>MP3 ({@link Mp3Extractor})
* <li>AAC ({@link AdtsExtractor})</li> * <li>AAC ({@link AdtsExtractor})
* <li>MPEG TS ({@link TsExtractor})</li> * <li>MPEG TS ({@link TsExtractor})
* <li>MPEG PS ({@link PsExtractor})</li> * <li>MPEG PS ({@link PsExtractor})
* <li>FLV ({@link FlvExtractor})</li> * <li>FLV ({@link FlvExtractor})
* <li>WAV ({@link WavExtractor})</li> * <li>WAV ({@link WavExtractor})
* <li>AC3 ({@link Ac3Extractor})</li> * <li>AC3 ({@link Ac3Extractor})
* <li>FLAC (only available if the FLAC extension is built and included)</li> * <li>AMR ({@link AmrExtractor})
* <li>FLAC (only available if the FLAC extension is built and included)
* </ul> * </ul>
*/ */
public final class DefaultExtractorsFactory implements ExtractorsFactory { public final class DefaultExtractorsFactory implements ExtractorsFactory {
@ -159,7 +161,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
@Override @Override
public synchronized Extractor[] createExtractors() { public synchronized Extractor[] createExtractors() {
Extractor[] extractors = new Extractor[FLAC_EXTRACTOR_CONSTRUCTOR == null ? 11 : 12]; Extractor[] extractors = new Extractor[FLAC_EXTRACTOR_CONSTRUCTOR == null ? 12 : 13];
extractors[0] = new MatroskaExtractor(matroskaFlags); extractors[0] = new MatroskaExtractor(matroskaFlags);
extractors[1] = new FragmentedMp4Extractor(fragmentedMp4Flags); extractors[1] = new FragmentedMp4Extractor(fragmentedMp4Flags);
extractors[2] = new Mp4Extractor(mp4Flags); extractors[2] = new Mp4Extractor(mp4Flags);
@ -171,9 +173,10 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
extractors[8] = new OggExtractor(); extractors[8] = new OggExtractor();
extractors[9] = new PsExtractor(); extractors[9] = new PsExtractor();
extractors[10] = new WavExtractor(); extractors[10] = new WavExtractor();
extractors[11] = new AmrExtractor();
if (FLAC_EXTRACTOR_CONSTRUCTOR != null) { if (FLAC_EXTRACTOR_CONSTRUCTOR != null) {
try { try {
extractors[11] = FLAC_EXTRACTOR_CONSTRUCTOR.newInstance(); extractors[12] = FLAC_EXTRACTOR_CONSTRUCTOR.newInstance();
} catch (Exception e) { } catch (Exception e) {
// Should never happen. // Should never happen.
throw new IllegalStateException("Unexpected error creating FLAC extractor", e); throw new IllegalStateException("Unexpected error creating FLAC extractor", e);

View File

@ -0,0 +1,299 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.extractor.amr;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import java.io.EOFException;
import java.io.IOException;
import java.util.Arrays;
/**
* Extracts data from the AMR containers format (either AMR or AMR-WB). This follows RFC-4867,
* section 5.
*
* <p>This extractor only supports single-channel AMR container formats.
*/
public final class AmrExtractor implements Extractor {
/** Factory for {@link AmrExtractor} instances. */
public static final ExtractorsFactory FACTORY =
new ExtractorsFactory() {
@Override
public Extractor[] createExtractors() {
return new Extractor[] {new AmrExtractor()};
}
};
/**
* The frame size in bytes, including header (1 byte), for each of the 16 frame types for AMR
* narrow band.
*/
private static final int[] frameSizeBytesByTypeNb = {
13,
14,
16,
18,
20,
21,
27,
32,
6, // AMR SID
7, // GSM-EFR SID
6, // TDMA-EFR SID
6, // PDC-EFR SID
1, // Future use
1, // Future use
1, // Future use
1 // No data
};
/**
* The frame size in bytes, including header (1 byte), for each of the 16 frame types for AMR wide
* band.
*/
private static final int[] frameSizeBytesByTypeWb = {
18,
24,
33,
37,
41,
47,
51,
59,
61,
6, // AMR-WB SID
1, // Future use
1, // Future use
1, // Future use
1, // Future use
1, // speech lost
1 // No data
};
private static final byte[] amrSignatureNb = Util.getUtf8Bytes("#!AMR\n");
private static final byte[] amrSignatureWb = Util.getUtf8Bytes("#!AMR-WB\n");
/** Theoretical maximum frame size for a AMR frame. */
private static final int MAX_FRAME_SIZE_BYTES = frameSizeBytesByTypeWb[8];
private static final int SAMPLE_RATE_WB = 16_000;
private static final int SAMPLE_RATE_NB = 8_000;
private static final int SAMPLE_TIME_PER_FRAME_US = 20_000;
private final byte[] scratch;
private boolean isWideBand;
private long currentSampleTimeUs;
private int currentSampleTotalBytes;
private int currentSampleBytesRemaining;
private TrackOutput trackOutput;
private boolean hasOutputFormat;
public AmrExtractor() {
scratch = new byte[1];
}
// Extractor implementation.
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
return readAmrHeader(input);
}
@Override
public void init(ExtractorOutput output) {
output.seekMap(new SeekMap.Unseekable(C.TIME_UNSET));
trackOutput = output.track(/* id= */ 0, C.TRACK_TYPE_AUDIO);
output.endTracks();
}
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
throws IOException, InterruptedException {
if (input.getPosition() == 0) {
if (!readAmrHeader(input)) {
throw new ParserException("Could not find AMR header.");
}
}
maybeOutputFormat();
return readSample(input);
}
@Override
public void seek(long position, long timeUs) {
currentSampleTimeUs = 0;
currentSampleTotalBytes = 0;
currentSampleBytesRemaining = 0;
}
@Override
public void release() {
// Do nothing
}
/* package */ static int frameSizeBytesByTypeNb(int frameType) {
return frameSizeBytesByTypeNb[frameType];
}
/* package */ static int frameSizeBytesByTypeWb(int frameType) {
return frameSizeBytesByTypeWb[frameType];
}
/* package */ static byte[] amrSignatureNb() {
return Arrays.copyOf(amrSignatureNb, amrSignatureNb.length);
}
/* package */ static byte[] amrSignatureWb() {
return Arrays.copyOf(amrSignatureWb, amrSignatureWb.length);
}
// Internal methods.
/**
* Peeks the AMR header from the beginning of the input, and consumes it if it exists.
*
* @param input The {@link ExtractorInput} from which data should be peeked/read.
* @return Whether the AMR header has been read.
*/
private boolean readAmrHeader(ExtractorInput input) throws IOException, InterruptedException {
if (peekAmrSignature(input, amrSignatureNb)) {
isWideBand = false;
input.skipFully(amrSignatureNb.length);
return true;
} else if (peekAmrSignature(input, amrSignatureWb)) {
isWideBand = true;
input.skipFully(amrSignatureWb.length);
return true;
}
return false;
}
/** Peeks from the beginning of the input to see if the given AMR signature exists. */
private boolean peekAmrSignature(ExtractorInput input, byte[] amrSignature)
throws IOException, InterruptedException {
input.resetPeekPosition();
byte[] header = new byte[amrSignature.length];
input.peekFully(header, 0, amrSignature.length);
return Arrays.equals(header, amrSignature);
}
private void maybeOutputFormat() {
if (!hasOutputFormat) {
hasOutputFormat = true;
String mimeType = isWideBand ? MimeTypes.AUDIO_AMR_WB : MimeTypes.AUDIO_AMR_NB;
int sampleRate = isWideBand ? SAMPLE_RATE_WB : SAMPLE_RATE_NB;
trackOutput.format(
Format.createAudioSampleFormat(
/* id= */ null,
mimeType,
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
MAX_FRAME_SIZE_BYTES,
/* channelCount= */ 1,
sampleRate,
/* pcmEncoding= */ Format.NO_VALUE,
/* initializationData= */ null,
/* drmInitData= */ null,
/* selectionFlags= */ 0,
/* language= */ null));
}
}
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
if (currentSampleBytesRemaining == 0) {
try {
currentSampleTotalBytes = readNextSampleSize(extractorInput);
} catch (EOFException e) {
return RESULT_END_OF_INPUT;
}
currentSampleBytesRemaining = currentSampleTotalBytes;
}
int bytesAppended =
trackOutput.sampleData(
extractorInput, currentSampleBytesRemaining, /* allowEndOfInput= */ true);
if (bytesAppended == C.RESULT_END_OF_INPUT) {
return RESULT_END_OF_INPUT;
}
currentSampleBytesRemaining -= bytesAppended;
if (currentSampleBytesRemaining > 0) {
return RESULT_CONTINUE;
}
trackOutput.sampleMetadata(
currentSampleTimeUs,
C.BUFFER_FLAG_KEY_FRAME,
currentSampleTotalBytes,
/* offset= */ 0,
/* encryptionData= */ null);
currentSampleTimeUs += SAMPLE_TIME_PER_FRAME_US;
return RESULT_CONTINUE;
}
private int readNextSampleSize(ExtractorInput extractorInput)
throws IOException, InterruptedException {
extractorInput.resetPeekPosition();
extractorInput.peekFully(scratch, /* offset= */ 0, /* length= */ 1);
byte frameHeader = scratch[0];
if ((frameHeader & 0x83) > 0) {
// The padding bits are at bit-1 positions in the following pattern: 1000 0011
// Padding bits must be 0.
throw new ParserException("Invalid padding bits for frame header " + frameHeader);
}
int frameType = (frameHeader >> 3) & 0x0f;
return getFrameSizeInBytes(frameType);
}
private int getFrameSizeInBytes(int frameType) throws ParserException {
if (!isValidFrameType(frameType)) {
throw new ParserException(
"Illegal AMR " + (isWideBand ? "WB" : "NB") + " frame type " + frameType);
}
return isWideBand ? frameSizeBytesByTypeWb[frameType] : frameSizeBytesByTypeNb[frameType];
}
private boolean isValidFrameType(int frameType) {
return frameType >= 0
&& frameType <= 15
&& (isWideBandValidFrameType(frameType) || isNarrowBandValidFrameType(frameType));
}
private boolean isWideBandValidFrameType(int frameType) {
// For wide band, type 10-13 are for future use.
return isWideBand && (frameType < 10 || frameType > 13);
}
private boolean isNarrowBandValidFrameType(int frameType) {
// For narrow band, type 12-14 are for future use.
return !isWideBand && (frameType < 12 || frameType > 14);
}
}

Binary file not shown.

View File

@ -0,0 +1,902 @@
seekMap:
isSeekable = false
duration = UNSET TIME
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/3gpp
maxInputSize = 61
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 8000
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 2834
sample count = 218
sample 0:
time = 0
flags = 1
data = length 13, hash 371B046C
sample 1:
time = 20000
flags = 1
data = length 13, hash CE30BF5B
sample 2:
time = 40000
flags = 1
data = length 13, hash 19A59975
sample 3:
time = 60000
flags = 1
data = length 13, hash 4879773C
sample 4:
time = 80000
flags = 1
data = length 13, hash E8F83019
sample 5:
time = 100000
flags = 1
data = length 13, hash D265CDC9
sample 6:
time = 120000
flags = 1
data = length 13, hash 91653DAA
sample 7:
time = 140000
flags = 1
data = length 13, hash C79456F6
sample 8:
time = 160000
flags = 1
data = length 13, hash CDDC4422
sample 9:
time = 180000
flags = 1
data = length 13, hash D9ED3AF1
sample 10:
time = 200000
flags = 1
data = length 13, hash BAB75A33
sample 11:
time = 220000
flags = 1
data = length 13, hash 2221B4FF
sample 12:
time = 240000
flags = 1
data = length 13, hash 96400A0B
sample 13:
time = 260000
flags = 1
data = length 13, hash 582E6FB
sample 14:
time = 280000
flags = 1
data = length 13, hash C4E878E5
sample 15:
time = 300000
flags = 1
data = length 13, hash C849A1BD
sample 16:
time = 320000
flags = 1
data = length 13, hash CFA8A9ED
sample 17:
time = 340000
flags = 1
data = length 13, hash 70CA4907
sample 18:
time = 360000
flags = 1
data = length 13, hash B47D4454
sample 19:
time = 380000
flags = 1
data = length 13, hash 282998C1
sample 20:
time = 400000
flags = 1
data = length 13, hash 3F3F7A65
sample 21:
time = 420000
flags = 1
data = length 13, hash CC2EAB58
sample 22:
time = 440000
flags = 1
data = length 13, hash 279EF712
sample 23:
time = 460000
flags = 1
data = length 13, hash AA2F4B29
sample 24:
time = 480000
flags = 1
data = length 13, hash F6F658C4
sample 25:
time = 500000
flags = 1
data = length 13, hash D7DEBD17
sample 26:
time = 520000
flags = 1
data = length 13, hash 6DAB9A17
sample 27:
time = 540000
flags = 1
data = length 13, hash 6ECE1571
sample 28:
time = 560000
flags = 1
data = length 13, hash B3D0507F
sample 29:
time = 580000
flags = 1
data = length 13, hash 21E356B9
sample 30:
time = 600000
flags = 1
data = length 13, hash 410EA12
sample 31:
time = 620000
flags = 1
data = length 13, hash 533895A8
sample 32:
time = 640000
flags = 1
data = length 13, hash C61B3E5A
sample 33:
time = 660000
flags = 1
data = length 13, hash 982170E6
sample 34:
time = 680000
flags = 1
data = length 13, hash 7A0468C5
sample 35:
time = 700000
flags = 1
data = length 13, hash 9C85EAA7
sample 36:
time = 720000
flags = 1
data = length 13, hash B6B341B6
sample 37:
time = 740000
flags = 1
data = length 13, hash 6937532E
sample 38:
time = 760000
flags = 1
data = length 13, hash 8CF2A3A0
sample 39:
time = 780000
flags = 1
data = length 13, hash D2682AC6
sample 40:
time = 800000
flags = 1
data = length 13, hash BBC5710F
sample 41:
time = 820000
flags = 1
data = length 13, hash 59080B6C
sample 42:
time = 840000
flags = 1
data = length 13, hash E4118291
sample 43:
time = 860000
flags = 1
data = length 13, hash A1E5B296
sample 44:
time = 880000
flags = 1
data = length 13, hash D7B8F95B
sample 45:
time = 900000
flags = 1
data = length 13, hash CC839BE1
sample 46:
time = 920000
flags = 1
data = length 13, hash D459DFCE
sample 47:
time = 940000
flags = 1
data = length 13, hash D6AD19EC
sample 48:
time = 960000
flags = 1
data = length 13, hash D05E373D
sample 49:
time = 980000
flags = 1
data = length 13, hash 6A4460C7
sample 50:
time = 1000000
flags = 1
data = length 13, hash C9A0D93F
sample 51:
time = 1020000
flags = 1
data = length 13, hash 3FA819E7
sample 52:
time = 1040000
flags = 1
data = length 13, hash 1D3CBDFC
sample 53:
time = 1060000
flags = 1
data = length 13, hash 8BBBB403
sample 54:
time = 1080000
flags = 1
data = length 13, hash 21B4A0F9
sample 55:
time = 1100000
flags = 1
data = length 13, hash C0F921D1
sample 56:
time = 1120000
flags = 1
data = length 13, hash 5D812AAB
sample 57:
time = 1140000
flags = 1
data = length 13, hash 50C9F3F8
sample 58:
time = 1160000
flags = 1
data = length 13, hash 5C2BB5D1
sample 59:
time = 1180000
flags = 1
data = length 13, hash 6BF9BEA5
sample 60:
time = 1200000
flags = 1
data = length 13, hash 2738C1E6
sample 61:
time = 1220000
flags = 1
data = length 13, hash 5FC288A6
sample 62:
time = 1240000
flags = 1
data = length 13, hash 7E8E442A
sample 63:
time = 1260000
flags = 1
data = length 13, hash AEAA2BBA
sample 64:
time = 1280000
flags = 1
data = length 13, hash 4E2ACD2F
sample 65:
time = 1300000
flags = 1
data = length 13, hash D6C90ACF
sample 66:
time = 1320000
flags = 1
data = length 13, hash 6FD8A944
sample 67:
time = 1340000
flags = 1
data = length 13, hash A835BBF9
sample 68:
time = 1360000
flags = 1
data = length 13, hash F7713830
sample 69:
time = 1380000
flags = 1
data = length 13, hash 3AA966E5
sample 70:
time = 1400000
flags = 1
data = length 13, hash F939E829
sample 71:
time = 1420000
flags = 1
data = length 13, hash 7676DE49
sample 72:
time = 1440000
flags = 1
data = length 13, hash 93BB890A
sample 73:
time = 1460000
flags = 1
data = length 13, hash B57DBEC8
sample 74:
time = 1480000
flags = 1
data = length 13, hash 66B0A5B6
sample 75:
time = 1500000
flags = 1
data = length 13, hash D733E0D
sample 76:
time = 1520000
flags = 1
data = length 13, hash 80941726
sample 77:
time = 1540000
flags = 1
data = length 13, hash 556ED633
sample 78:
time = 1560000
flags = 1
data = length 13, hash C5EDF4E1
sample 79:
time = 1580000
flags = 1
data = length 13, hash 6B287445
sample 80:
time = 1600000
flags = 1
data = length 13, hash DC97C4A7
sample 81:
time = 1620000
flags = 1
data = length 13, hash DA8CBDF4
sample 82:
time = 1640000
flags = 1
data = length 13, hash 6F60FF77
sample 83:
time = 1660000
flags = 1
data = length 13, hash 3EB22B96
sample 84:
time = 1680000
flags = 1
data = length 13, hash B3C31AF5
sample 85:
time = 1700000
flags = 1
data = length 13, hash 1854AA92
sample 86:
time = 1720000
flags = 1
data = length 13, hash 6488264B
sample 87:
time = 1740000
flags = 1
data = length 13, hash 4CC8C5C1
sample 88:
time = 1760000
flags = 1
data = length 13, hash 19CC7523
sample 89:
time = 1780000
flags = 1
data = length 13, hash 9BE7B928
sample 90:
time = 1800000
flags = 1
data = length 13, hash 47EC7CFD
sample 91:
time = 1820000
flags = 1
data = length 13, hash EC940120
sample 92:
time = 1840000
flags = 1
data = length 13, hash 73BDA6D0
sample 93:
time = 1860000
flags = 1
data = length 13, hash FACB3314
sample 94:
time = 1880000
flags = 1
data = length 13, hash EC61D13B
sample 95:
time = 1900000
flags = 1
data = length 13, hash B28C7B6C
sample 96:
time = 1920000
flags = 1
data = length 13, hash B1A4CECD
sample 97:
time = 1940000
flags = 1
data = length 13, hash 56D41BA6
sample 98:
time = 1960000
flags = 1
data = length 13, hash 90499F4
sample 99:
time = 1980000
flags = 1
data = length 13, hash 65D9A9D3
sample 100:
time = 2000000
flags = 1
data = length 13, hash D9004CC
sample 101:
time = 2020000
flags = 1
data = length 13, hash 4139C6ED
sample 102:
time = 2040000
flags = 1
data = length 13, hash C4F8097C
sample 103:
time = 2060000
flags = 1
data = length 13, hash 94D424FA
sample 104:
time = 2080000
flags = 1
data = length 13, hash C2C6F5FD
sample 105:
time = 2100000
flags = 1
data = length 13, hash 15719008
sample 106:
time = 2120000
flags = 1
data = length 13, hash 4F64F524
sample 107:
time = 2140000
flags = 1
data = length 13, hash F9E01C1E
sample 108:
time = 2160000
flags = 1
data = length 13, hash 74C4EE74
sample 109:
time = 2180000
flags = 1
data = length 13, hash 7EE7553D
sample 110:
time = 2200000
flags = 1
data = length 13, hash 62DE6539
sample 111:
time = 2220000
flags = 1
data = length 13, hash 7F5EC222
sample 112:
time = 2240000
flags = 1
data = length 13, hash 644067F
sample 113:
time = 2260000
flags = 1
data = length 13, hash CDF6C9DC
sample 114:
time = 2280000
flags = 1
data = length 13, hash 8B5DBC80
sample 115:
time = 2300000
flags = 1
data = length 13, hash AD4BBA03
sample 116:
time = 2320000
flags = 1
data = length 13, hash 7A76340
sample 117:
time = 2340000
flags = 1
data = length 13, hash 3610F5B0
sample 118:
time = 2360000
flags = 1
data = length 13, hash 430BC60B
sample 119:
time = 2380000
flags = 1
data = length 13, hash 99CF1CA6
sample 120:
time = 2400000
flags = 1
data = length 13, hash 1331C70B
sample 121:
time = 2420000
flags = 1
data = length 13, hash BD76E69D
sample 122:
time = 2440000
flags = 1
data = length 13, hash 5DA652AC
sample 123:
time = 2460000
flags = 1
data = length 13, hash 3B7BF6CE
sample 124:
time = 2480000
flags = 1
data = length 13, hash ABBFD143
sample 125:
time = 2500000
flags = 1
data = length 13, hash E9447166
sample 126:
time = 2520000
flags = 1
data = length 13, hash EC40068C
sample 127:
time = 2540000
flags = 1
data = length 13, hash A2869400
sample 128:
time = 2560000
flags = 1
data = length 13, hash C7E0746B
sample 129:
time = 2580000
flags = 1
data = length 13, hash 60601BB1
sample 130:
time = 2600000
flags = 1
data = length 13, hash 975AAE9B
sample 131:
time = 2620000
flags = 1
data = length 13, hash 8BBC0EB2
sample 132:
time = 2640000
flags = 1
data = length 13, hash 57FB39E5
sample 133:
time = 2660000
flags = 1
data = length 13, hash 4CDCEEDB
sample 134:
time = 2680000
flags = 1
data = length 13, hash EA16E256
sample 135:
time = 2700000
flags = 1
data = length 13, hash 287E7D9E
sample 136:
time = 2720000
flags = 1
data = length 13, hash 55AB8FB9
sample 137:
time = 2740000
flags = 1
data = length 13, hash 129890EF
sample 138:
time = 2760000
flags = 1
data = length 13, hash 90834F57
sample 139:
time = 2780000
flags = 1
data = length 13, hash 5B3228E0
sample 140:
time = 2800000
flags = 1
data = length 13, hash DD19E175
sample 141:
time = 2820000
flags = 1
data = length 13, hash EE7EA342
sample 142:
time = 2840000
flags = 1
data = length 13, hash DB3AF473
sample 143:
time = 2860000
flags = 1
data = length 13, hash 25AEC43F
sample 144:
time = 2880000
flags = 1
data = length 13, hash EE9BF97F
sample 145:
time = 2900000
flags = 1
data = length 13, hash FFFBE047
sample 146:
time = 2920000
flags = 1
data = length 13, hash BEACFCB0
sample 147:
time = 2940000
flags = 1
data = length 13, hash AEB5096C
sample 148:
time = 2960000
flags = 1
data = length 13, hash B0D381B
sample 149:
time = 2980000
flags = 1
data = length 13, hash 3D9D5122
sample 150:
time = 3000000
flags = 1
data = length 13, hash 6C1DDB95
sample 151:
time = 3020000
flags = 1
data = length 13, hash ADACADCF
sample 152:
time = 3040000
flags = 1
data = length 13, hash 159E321E
sample 153:
time = 3060000
flags = 1
data = length 13, hash B1466264
sample 154:
time = 3080000
flags = 1
data = length 13, hash 4DDF7223
sample 155:
time = 3100000
flags = 1
data = length 13, hash C9BDB82A
sample 156:
time = 3120000
flags = 1
data = length 13, hash A49B2D9D
sample 157:
time = 3140000
flags = 1
data = length 13, hash D645E7E5
sample 158:
time = 3160000
flags = 1
data = length 13, hash 1C4232DC
sample 159:
time = 3180000
flags = 1
data = length 13, hash 83078219
sample 160:
time = 3200000
flags = 1
data = length 13, hash D6D8B072
sample 161:
time = 3220000
flags = 1
data = length 13, hash 975DB40
sample 162:
time = 3240000
flags = 1
data = length 13, hash A15FDD05
sample 163:
time = 3260000
flags = 1
data = length 13, hash 4B839E41
sample 164:
time = 3280000
flags = 1
data = length 13, hash 7418F499
sample 165:
time = 3300000
flags = 1
data = length 13, hash 7A4945E4
sample 166:
time = 3320000
flags = 1
data = length 13, hash 6249558C
sample 167:
time = 3340000
flags = 1
data = length 13, hash BD4C5BE3
sample 168:
time = 3360000
flags = 1
data = length 13, hash BAB30F1D
sample 169:
time = 3380000
flags = 1
data = length 13, hash 1E1C7012
sample 170:
time = 3400000
flags = 1
data = length 13, hash 9A3F8A89
sample 171:
time = 3420000
flags = 1
data = length 13, hash 20BE6D7B
sample 172:
time = 3440000
flags = 1
data = length 13, hash CAA0591D
sample 173:
time = 3460000
flags = 1
data = length 13, hash 6D554D17
sample 174:
time = 3480000
flags = 1
data = length 13, hash D97C3B31
sample 175:
time = 3500000
flags = 1
data = length 13, hash 75BC5C3
sample 176:
time = 3520000
flags = 1
data = length 13, hash 7BA1784B
sample 177:
time = 3540000
flags = 1
data = length 13, hash 1D175D92
sample 178:
time = 3560000
flags = 1
data = length 13, hash ADCA60FD
sample 179:
time = 3580000
flags = 1
data = length 13, hash 37018693
sample 180:
time = 3600000
flags = 1
data = length 13, hash 4553606F
sample 181:
time = 3620000
flags = 1
data = length 13, hash CF434565
sample 182:
time = 3640000
flags = 1
data = length 13, hash D264D757
sample 183:
time = 3660000
flags = 1
data = length 13, hash 4FB493EF
sample 184:
time = 3680000
flags = 1
data = length 13, hash 919F53A
sample 185:
time = 3700000
flags = 1
data = length 13, hash C22B009B
sample 186:
time = 3720000
flags = 1
data = length 13, hash 5981470
sample 187:
time = 3740000
flags = 1
data = length 13, hash A5D3937C
sample 188:
time = 3760000
flags = 1
data = length 13, hash A2504429
sample 189:
time = 3780000
flags = 1
data = length 13, hash AD1B70BE
sample 190:
time = 3800000
flags = 1
data = length 13, hash 2E39ED5E
sample 191:
time = 3820000
flags = 1
data = length 13, hash 13A8BE8E
sample 192:
time = 3840000
flags = 1
data = length 13, hash 1ACD740B
sample 193:
time = 3860000
flags = 1
data = length 13, hash 80F38B3
sample 194:
time = 3880000
flags = 1
data = length 13, hash DA9DA79F
sample 195:
time = 3900000
flags = 1
data = length 13, hash 21B95B7E
sample 196:
time = 3920000
flags = 1
data = length 13, hash CD22497B
sample 197:
time = 3940000
flags = 1
data = length 13, hash 718BB35D
sample 198:
time = 3960000
flags = 1
data = length 13, hash 69ABA6AD
sample 199:
time = 3980000
flags = 1
data = length 13, hash BAE19549
sample 200:
time = 4000000
flags = 1
data = length 13, hash 2A792FB3
sample 201:
time = 4020000
flags = 1
data = length 13, hash 71FCD8
sample 202:
time = 4040000
flags = 1
data = length 13, hash 44D2B5B3
sample 203:
time = 4060000
flags = 1
data = length 13, hash 1E87B11B
sample 204:
time = 4080000
flags = 1
data = length 13, hash 78CD2C11
sample 205:
time = 4100000
flags = 1
data = length 13, hash 9F198DF0
sample 206:
time = 4120000
flags = 1
data = length 13, hash B291F16A
sample 207:
time = 4140000
flags = 1
data = length 13, hash CF820EE0
sample 208:
time = 4160000
flags = 1
data = length 13, hash 4E24F683
sample 209:
time = 4180000
flags = 1
data = length 13, hash 52BCD68F
sample 210:
time = 4200000
flags = 1
data = length 13, hash 42588CB0
sample 211:
time = 4220000
flags = 1
data = length 13, hash EBBFECA2
sample 212:
time = 4240000
flags = 1
data = length 13, hash C11050CF
sample 213:
time = 4260000
flags = 1
data = length 13, hash 6F738603
sample 214:
time = 4280000
flags = 1
data = length 13, hash DAD06E5
sample 215:
time = 4300000
flags = 1
data = length 13, hash 5B036C64
sample 216:
time = 4320000
flags = 1
data = length 13, hash A58DC12E
sample 217:
time = 4340000
flags = 1
data = length 13, hash AC59BA7C
tracksEnded = true

Binary file not shown.

View File

@ -0,0 +1,706 @@
seekMap:
isSeekable = false
duration = UNSET TIME
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/amr-wb
maxInputSize = 61
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 16000
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 4056
sample count = 169
sample 0:
time = 0
flags = 1
data = length 24, hash C3025798
sample 1:
time = 20000
flags = 1
data = length 24, hash 39CABAE9
sample 2:
time = 40000
flags = 1
data = length 24, hash 2752F470
sample 3:
time = 60000
flags = 1
data = length 24, hash 394F76F6
sample 4:
time = 80000
flags = 1
data = length 24, hash FF9EEF
sample 5:
time = 100000
flags = 1
data = length 24, hash 54ECB1B4
sample 6:
time = 120000
flags = 1
data = length 24, hash 6D7A3A5F
sample 7:
time = 140000
flags = 1
data = length 24, hash 684CD144
sample 8:
time = 160000
flags = 1
data = length 24, hash 87B7D176
sample 9:
time = 180000
flags = 1
data = length 24, hash 4C02F9A5
sample 10:
time = 200000
flags = 1
data = length 24, hash B4154108
sample 11:
time = 220000
flags = 1
data = length 24, hash 4448F477
sample 12:
time = 240000
flags = 1
data = length 24, hash 755A4939
sample 13:
time = 260000
flags = 1
data = length 24, hash 8C8BC6C3
sample 14:
time = 280000
flags = 1
data = length 24, hash BC37F63F
sample 15:
time = 300000
flags = 1
data = length 24, hash 3352C43C
sample 16:
time = 320000
flags = 1
data = length 24, hash 7998E1F2
sample 17:
time = 340000
flags = 1
data = length 24, hash A8ECBEFC
sample 18:
time = 360000
flags = 1
data = length 24, hash 944AC118
sample 19:
time = 380000
flags = 1
data = length 24, hash FD2C8E1F
sample 20:
time = 400000
flags = 1
data = length 24, hash B3D867AF
sample 21:
time = 420000
flags = 1
data = length 24, hash 3DC6E592
sample 22:
time = 440000
flags = 1
data = length 24, hash 32B276CD
sample 23:
time = 460000
flags = 1
data = length 24, hash 5488AEF3
sample 24:
time = 480000
flags = 1
data = length 24, hash 7A4D516
sample 25:
time = 500000
flags = 1
data = length 24, hash 570AE83F
sample 26:
time = 520000
flags = 1
data = length 24, hash E5CB3477
sample 27:
time = 540000
flags = 1
data = length 24, hash E04C00E4
sample 28:
time = 560000
flags = 1
data = length 24, hash 21B7C97
sample 29:
time = 580000
flags = 1
data = length 24, hash 1633F470
sample 30:
time = 600000
flags = 1
data = length 24, hash 28D65CA6
sample 31:
time = 620000
flags = 1
data = length 24, hash CC6A675C
sample 32:
time = 640000
flags = 1
data = length 24, hash 4C91080A
sample 33:
time = 660000
flags = 1
data = length 24, hash F6482FB5
sample 34:
time = 680000
flags = 1
data = length 24, hash 2C76F48C
sample 35:
time = 700000
flags = 1
data = length 24, hash 6E3B0D72
sample 36:
time = 720000
flags = 1
data = length 24, hash 799AA003
sample 37:
time = 740000
flags = 1
data = length 24, hash DFC0BA81
sample 38:
time = 760000
flags = 1
data = length 24, hash CBDF3826
sample 39:
time = 780000
flags = 1
data = length 24, hash 16862B75
sample 40:
time = 800000
flags = 1
data = length 24, hash 865A828E
sample 41:
time = 820000
flags = 1
data = length 24, hash 336BBDC9
sample 42:
time = 840000
flags = 1
data = length 24, hash 6CFC6C34
sample 43:
time = 860000
flags = 1
data = length 24, hash 32C8CD46
sample 44:
time = 880000
flags = 1
data = length 24, hash 9FE11C4C
sample 45:
time = 900000
flags = 1
data = length 24, hash AA5A12B7
sample 46:
time = 920000
flags = 1
data = length 24, hash AA0F4A4D
sample 47:
time = 940000
flags = 1
data = length 24, hash 34415484
sample 48:
time = 960000
flags = 1
data = length 24, hash 5018928E
sample 49:
time = 980000
flags = 1
data = length 24, hash 4A04D162
sample 50:
time = 1000000
flags = 1
data = length 24, hash 4C70F9F0
sample 51:
time = 1020000
flags = 1
data = length 24, hash 99EF3168
sample 52:
time = 1040000
flags = 1
data = length 24, hash C600DAF
sample 53:
time = 1060000
flags = 1
data = length 24, hash FDBB192E
sample 54:
time = 1080000
flags = 1
data = length 24, hash 99096A48
sample 55:
time = 1100000
flags = 1
data = length 24, hash D793F88B
sample 56:
time = 1120000
flags = 1
data = length 24, hash EEB921BD
sample 57:
time = 1140000
flags = 1
data = length 24, hash 8B941A4C
sample 58:
time = 1160000
flags = 1
data = length 24, hash ED5F5FEE
sample 59:
time = 1180000
flags = 1
data = length 24, hash A588E0BB
sample 60:
time = 1200000
flags = 1
data = length 24, hash 588CBC01
sample 61:
time = 1220000
flags = 1
data = length 24, hash DE22266C
sample 62:
time = 1240000
flags = 1
data = length 24, hash 921B6E5C
sample 63:
time = 1260000
flags = 1
data = length 24, hash EC11F041
sample 64:
time = 1280000
flags = 1
data = length 24, hash 5BA9E0A3
sample 65:
time = 1300000
flags = 1
data = length 24, hash DB6D52F3
sample 66:
time = 1320000
flags = 1
data = length 24, hash 8EEBE525
sample 67:
time = 1340000
flags = 1
data = length 24, hash 47A742AE
sample 68:
time = 1360000
flags = 1
data = length 24, hash E93F1E03
sample 69:
time = 1380000
flags = 1
data = length 24, hash 3251F57C
sample 70:
time = 1400000
flags = 1
data = length 24, hash 3EDBBBDD
sample 71:
time = 1420000
flags = 1
data = length 24, hash 2E98465A
sample 72:
time = 1440000
flags = 1
data = length 24, hash A09EA52E
sample 73:
time = 1460000
flags = 1
data = length 24, hash A2A86FA6
sample 74:
time = 1480000
flags = 1
data = length 24, hash 71DCD51C
sample 75:
time = 1500000
flags = 1
data = length 24, hash 2B02DEE1
sample 76:
time = 1520000
flags = 1
data = length 24, hash 7A725192
sample 77:
time = 1540000
flags = 1
data = length 24, hash 929AD483
sample 78:
time = 1560000
flags = 1
data = length 24, hash 68440BF5
sample 79:
time = 1580000
flags = 1
data = length 24, hash 5BD41AD6
sample 80:
time = 1600000
flags = 1
data = length 24, hash 91A381
sample 81:
time = 1620000
flags = 1
data = length 24, hash 8010C408
sample 82:
time = 1640000
flags = 1
data = length 24, hash 482274BE
sample 83:
time = 1660000
flags = 1
data = length 24, hash D7DB8BCC
sample 84:
time = 1680000
flags = 1
data = length 24, hash 680BD9DD
sample 85:
time = 1700000
flags = 1
data = length 24, hash E313577C
sample 86:
time = 1720000
flags = 1
data = length 24, hash 9C10B0CD
sample 87:
time = 1740000
flags = 1
data = length 24, hash 2D90AC02
sample 88:
time = 1760000
flags = 1
data = length 24, hash 64E8C245
sample 89:
time = 1780000
flags = 1
data = length 24, hash 3954AC1B
sample 90:
time = 1800000
flags = 1
data = length 24, hash ACB8999F
sample 91:
time = 1820000
flags = 1
data = length 24, hash 43AE3957
sample 92:
time = 1840000
flags = 1
data = length 24, hash 3C664DB7
sample 93:
time = 1860000
flags = 1
data = length 24, hash 9354B576
sample 94:
time = 1880000
flags = 1
data = length 24, hash B5B9C14E
sample 95:
time = 1900000
flags = 1
data = length 24, hash 7DA9C98F
sample 96:
time = 1920000
flags = 1
data = length 24, hash EFEE54C6
sample 97:
time = 1940000
flags = 1
data = length 24, hash 79DC8CBD
sample 98:
time = 1960000
flags = 1
data = length 24, hash A71A475C
sample 99:
time = 1980000
flags = 1
data = length 24, hash CA1CBB94
sample 100:
time = 2000000
flags = 1
data = length 24, hash 91922226
sample 101:
time = 2020000
flags = 1
data = length 24, hash C90278BC
sample 102:
time = 2040000
flags = 1
data = length 24, hash BD51986F
sample 103:
time = 2060000
flags = 1
data = length 24, hash 90AEF368
sample 104:
time = 2080000
flags = 1
data = length 24, hash 1D83C955
sample 105:
time = 2100000
flags = 1
data = length 24, hash 8FA9A915
sample 106:
time = 2120000
flags = 1
data = length 24, hash C6C753E0
sample 107:
time = 2140000
flags = 1
data = length 24, hash 85FA27A7
sample 108:
time = 2160000
flags = 1
data = length 24, hash A0277324
sample 109:
time = 2180000
flags = 1
data = length 24, hash B7696535
sample 110:
time = 2200000
flags = 1
data = length 24, hash D69D668C
sample 111:
time = 2220000
flags = 1
data = length 24, hash 34C057CD
sample 112:
time = 2240000
flags = 1
data = length 24, hash 4EC5E974
sample 113:
time = 2260000
flags = 1
data = length 24, hash 1C1CD40D
sample 114:
time = 2280000
flags = 1
data = length 24, hash 76CC54BC
sample 115:
time = 2300000
flags = 1
data = length 24, hash D497ACF5
sample 116:
time = 2320000
flags = 1
data = length 24, hash A1386080
sample 117:
time = 2340000
flags = 1
data = length 24, hash 7ED36954
sample 118:
time = 2360000
flags = 1
data = length 24, hash C11A3BF9
sample 119:
time = 2380000
flags = 1
data = length 24, hash 8FB69488
sample 120:
time = 2400000
flags = 1
data = length 24, hash C6225F59
sample 121:
time = 2420000
flags = 1
data = length 24, hash 122AB6D2
sample 122:
time = 2440000
flags = 1
data = length 24, hash 1E195E7D
sample 123:
time = 2460000
flags = 1
data = length 24, hash BD3DF418
sample 124:
time = 2480000
flags = 1
data = length 24, hash D8AE4A5
sample 125:
time = 2500000
flags = 1
data = length 24, hash 977BD182
sample 126:
time = 2520000
flags = 1
data = length 24, hash F361F060
sample 127:
time = 2540000
flags = 1
data = length 24, hash 11EC8CD0
sample 128:
time = 2560000
flags = 1
data = length 24, hash 3798F3D2
sample 129:
time = 2580000
flags = 1
data = length 24, hash B2C2517C
sample 130:
time = 2600000
flags = 1
data = length 24, hash FBE0D0D8
sample 131:
time = 2620000
flags = 1
data = length 24, hash 7033172F
sample 132:
time = 2640000
flags = 1
data = length 24, hash BE760029
sample 133:
time = 2660000
flags = 1
data = length 24, hash 590AF28C
sample 134:
time = 2680000
flags = 1
data = length 24, hash AD28C48F
sample 135:
time = 2700000
flags = 1
data = length 24, hash 640AA61B
sample 136:
time = 2720000
flags = 1
data = length 24, hash ABE659B
sample 137:
time = 2740000
flags = 1
data = length 24, hash ED2691D2
sample 138:
time = 2760000
flags = 1
data = length 24, hash D998C80E
sample 139:
time = 2780000
flags = 1
data = length 24, hash 8DC0DF5C
sample 140:
time = 2800000
flags = 1
data = length 24, hash 7692247B
sample 141:
time = 2820000
flags = 1
data = length 24, hash C1D1CCB9
sample 142:
time = 2840000
flags = 1
data = length 24, hash 362CE78E
sample 143:
time = 2860000
flags = 1
data = length 24, hash 54FA84A
sample 144:
time = 2880000
flags = 1
data = length 24, hash 29E88C84
sample 145:
time = 2900000
flags = 1
data = length 24, hash 1CD848AC
sample 146:
time = 2920000
flags = 1
data = length 24, hash 5C3D4A79
sample 147:
time = 2940000
flags = 1
data = length 24, hash 1AA8E604
sample 148:
time = 2960000
flags = 1
data = length 24, hash 186A4316
sample 149:
time = 2980000
flags = 1
data = length 24, hash 61ACE481
sample 150:
time = 3000000
flags = 1
data = length 24, hash D0C42780
sample 151:
time = 3020000
flags = 1
data = length 24, hash FAD51BA1
sample 152:
time = 3040000
flags = 1
data = length 24, hash F1A9AC71
sample 153:
time = 3060000
flags = 1
data = length 24, hash 24425449
sample 154:
time = 3080000
flags = 1
data = length 24, hash 37AAC3E6
sample 155:
time = 3100000
flags = 1
data = length 24, hash 91F68CB4
sample 156:
time = 3120000
flags = 1
data = length 24, hash F8C92820
sample 157:
time = 3140000
flags = 1
data = length 24, hash ECD39C3E
sample 158:
time = 3160000
flags = 1
data = length 24, hash B27D8F78
sample 159:
time = 3180000
flags = 1
data = length 24, hash C9EB3DFB
sample 160:
time = 3200000
flags = 1
data = length 24, hash 88DC54A2
sample 161:
time = 3220000
flags = 1
data = length 24, hash 7FC4C5BE
sample 162:
time = 3240000
flags = 1
data = length 24, hash E4F684EF
sample 163:
time = 3260000
flags = 1
data = length 24, hash 55C08B56
sample 164:
time = 3280000
flags = 1
data = length 24, hash E5A0F006
sample 165:
time = 3300000
flags = 1
data = length 24, hash DE3F3AA7
sample 166:
time = 3320000
flags = 1
data = length 24, hash 3F28AE7F
sample 167:
time = 3340000
flags = 1
data = length 24, hash 3949CAFF
sample 168:
time = 3360000
flags = 1
data = length 24, hash 772665A0
tracksEnded = true

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.extractor;
import static com.google.common.truth.Truth.assertThat;
import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
import com.google.android.exoplayer2.extractor.flv.FlvExtractor;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
import com.google.android.exoplayer2.extractor.ogg.OggExtractor;
import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
import com.google.android.exoplayer2.extractor.ts.PsExtractor;
import com.google.android.exoplayer2.extractor.ts.TsExtractor;
import com.google.android.exoplayer2.extractor.wav.WavExtractor;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Unit test for {@link DefaultExtractorsFactory}. */
@RunWith(RobolectricTestRunner.class)
public final class DefaultExtractorsFactoryTest {
@Test
public void testCreateExtractors_returnExpectedClasses() {
DefaultExtractorsFactory defaultExtractorsFactory = new DefaultExtractorsFactory();
Extractor[] extractors = defaultExtractorsFactory.createExtractors();
List<Class> listCreatedExtractorClasses = new ArrayList<>();
for (Extractor extractor : extractors) {
listCreatedExtractorClasses.add(extractor.getClass());
}
Class[] expectedExtractorClassses =
new Class[] {
MatroskaExtractor.class,
FragmentedMp4Extractor.class,
Mp4Extractor.class,
Mp3Extractor.class,
AdtsExtractor.class,
Ac3Extractor.class,
TsExtractor.class,
FlvExtractor.class,
OggExtractor.class,
PsExtractor.class,
WavExtractor.class,
AmrExtractor.class
};
assertThat(listCreatedExtractorClasses).containsNoDuplicates();
assertThat(listCreatedExtractorClasses).containsExactlyElementsIn(expectedExtractorClassses);
}
}

View File

@ -0,0 +1,246 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.extractor.amr;
import static com.google.android.exoplayer2.extractor.amr.AmrExtractor.amrSignatureNb;
import static com.google.android.exoplayer2.extractor.amr.AmrExtractor.amrSignatureWb;
import static com.google.android.exoplayer2.extractor.amr.AmrExtractor.frameSizeBytesByTypeNb;
import static com.google.android.exoplayer2.extractor.amr.AmrExtractor.frameSizeBytesByTypeWb;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.fail;
import android.support.annotation.NonNull;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.testutil.ExtractorAsserts;
import com.google.android.exoplayer2.testutil.FakeExtractorInput;
import com.google.android.exoplayer2.testutil.FakeExtractorOutput;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Unit test for {@link AmrExtractor}. */
@RunWith(RobolectricTestRunner.class)
public final class AmrExtractorTest {
private static final Random RANDOM = new Random(1234);
@Test
public void testSniff_nonAmrSignature_returnFalse() throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
FakeExtractorInput input = fakeExtractorInputWithData(Util.getUtf8Bytes("0#!AMR\n123"));
boolean result = amrExtractor.sniff(input);
assertThat(result).isFalse();
}
@Test
public void testRead_nonAmrSignature_throwParserException()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
FakeExtractorInput input = fakeExtractorInputWithData(Util.getUtf8Bytes("0#!AMR-WB\n"));
try {
amrExtractor.read(input, new PositionHolder());
fail();
} catch (ParserException e) {
// expected
}
}
@Test
public void testRead_amrNb_returnParserException_forInvalidFrameType()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
// Frame type 12-14 for narrow band is reserved for future usage.
byte[] amrFrame = newNarrowBandAmrFrameWithType(12);
byte[] data = joinData(amrSignatureNb(), amrFrame);
FakeExtractorInput input = fakeExtractorInputWithData(data);
try {
amrExtractor.read(input, new PositionHolder());
fail();
} catch (ParserException e) {
// expected
}
}
@Test
public void testRead_amrWb_returnParserException_forInvalidFrameType()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
// Frame type 10-13 for wide band is reserved for future usage.
byte[] amrFrame = newWideBandAmrFrameWithType(13);
byte[] data = joinData(amrSignatureWb(), amrFrame);
FakeExtractorInput input = fakeExtractorInputWithData(data);
try {
amrExtractor.read(input, new PositionHolder());
fail();
} catch (ParserException e) {
// expected
}
}
@Test
public void testRead_amrNb_returnEndOfInput_ifInputEncountersEoF()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
byte[] amrFrame = newNarrowBandAmrFrameWithType(3);
byte[] data = joinData(amrSignatureNb(), amrFrame);
FakeExtractorInput input = fakeExtractorInputWithData(data);
// Read 1st frame, which will put the input at EoF.
amrExtractor.read(input, new PositionHolder());
int result = amrExtractor.read(input, new PositionHolder());
assertThat(result).isEqualTo(Extractor.RESULT_END_OF_INPUT);
}
@Test
public void testRead_amrWb_returnEndOfInput_ifInputEncountersEoF()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
byte[] amrFrame = newWideBandAmrFrameWithType(5);
byte[] data = joinData(amrSignatureWb(), amrFrame);
FakeExtractorInput input = fakeExtractorInputWithData(data);
// Read 1st frame, which will put the input at EoF.
amrExtractor.read(input, new PositionHolder());
int result = amrExtractor.read(input, new PositionHolder());
assertThat(result).isEqualTo(Extractor.RESULT_END_OF_INPUT);
}
@Test
public void testRead_amrNb_returnParserException_forInvalidFrameHeader()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
byte[] invalidHeaderFrame = newNarrowBandAmrFrameWithType(4);
// The padding bits are at bit-1 positions in the following pattern: 1000 0011
// Padding bits must be 0.
invalidHeaderFrame[0] = (byte) (invalidHeaderFrame[0] | 0b01111101);
byte[] data = joinData(amrSignatureNb(), invalidHeaderFrame);
FakeExtractorInput input = fakeExtractorInputWithData(data);
try {
amrExtractor.read(input, new PositionHolder());
fail();
} catch (ParserException e) {
// expected
}
}
@Test
public void testRead_amrWb_returnParserException_forInvalidFrameHeader()
throws IOException, InterruptedException {
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
byte[] invalidHeaderFrame = newWideBandAmrFrameWithType(6);
// The padding bits are at bit-1 positions in the following pattern: 1000 0011
// Padding bits must be 0.
invalidHeaderFrame[0] = (byte) (invalidHeaderFrame[0] | 0b01111110);
byte[] data = joinData(amrSignatureWb(), invalidHeaderFrame);
FakeExtractorInput input = fakeExtractorInputWithData(data);
try {
amrExtractor.read(input, new PositionHolder());
fail();
} catch (ParserException e) {
// expected
}
}
@Test
public void testExtractingNarrowBandSamples() throws Exception {
ExtractorAsserts.assertBehavior(createAmrExtractorFactory(), "amr/sample_nb.amr");
}
@Test
public void testExtractingWideBandSamples() throws Exception {
ExtractorAsserts.assertBehavior(createAmrExtractorFactory(), "amr/sample_wb.amr");
}
private byte[] newWideBandAmrFrameWithType(int frameType) {
byte frameHeader = (byte) ((frameType << 3) & (0b01111100));
int frameContentInBytes = frameSizeBytesByTypeWb(frameType) - 1;
return joinData(new byte[] {frameHeader}, randomBytesArrayWithLength(frameContentInBytes));
}
private byte[] newNarrowBandAmrFrameWithType(int frameType) {
byte frameHeader = (byte) ((frameType << 3) & (0b01111100));
int frameContentInBytes = frameSizeBytesByTypeNb(frameType) - 1;
return joinData(new byte[] {frameHeader}, randomBytesArrayWithLength(frameContentInBytes));
}
private static byte[] randomBytesArrayWithLength(int length) {
byte[] result = new byte[length];
RANDOM.nextBytes(result);
return result;
}
private static byte[] joinData(byte[]... byteArrays) {
int totalLength = 0;
for (byte[] byteArray : byteArrays) {
totalLength += byteArray.length;
}
byte[] result = new byte[totalLength];
int offset = 0;
for (byte[] byteArray : byteArrays) {
System.arraycopy(byteArray, /* srcPos= */ 0, result, offset, byteArray.length);
offset += byteArray.length;
}
return result;
}
@NonNull
private static AmrExtractor setupAmrExtractorWithOutput() {
AmrExtractor amrExtractor = new AmrExtractor();
FakeExtractorOutput output = new FakeExtractorOutput();
amrExtractor.init(output);
return amrExtractor;
}
@NonNull
private static FakeExtractorInput fakeExtractorInputWithData(byte[] data) {
return new FakeExtractorInput.Builder().setData(data).build();
}
@NonNull
private static ExtractorAsserts.ExtractorFactory createAmrExtractorFactory() {
return new ExtractorAsserts.ExtractorFactory() {
@Override
public Extractor create() {
return new AmrExtractor();
}
};
}
}