use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.
the class XingSeekerTest method setUp.
@Override
public void setUp() throws Exception {
MpegAudioHeader xingFrameHeader = new MpegAudioHeader();
MpegAudioHeader.populateHeader(XING_FRAME_HEADER_DATA, xingFrameHeader);
seeker = XingSeeker.create(xingFrameHeader, new ParsableByteArray(XING_FRAME_PAYLOAD), XING_FRAME_POSITION, C.LENGTH_UNSET);
seekerWithInputLength = XingSeeker.create(xingFrameHeader, new ParsableByteArray(XING_FRAME_PAYLOAD), XING_FRAME_POSITION, INPUT_LENGTH);
xingFrameSize = xingFrameHeader.frameSize;
}
use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.
the class WavHeaderReader method skipToData.
/**
* Skips to the data in the given WAV input stream and returns its data size. After calling, the
* input stream's position will point to the start of sample data in the WAV.
* <p>
* If an exception is thrown, the input position will be left pointing to a chunk header.
*
* @param input Input stream to skip to the data chunk in. Its peek position must be pointing to
* a valid chunk header.
* @param wavHeader WAV header to populate with data bounds.
* @throws ParserException If an error occurs parsing chunks.
* @throws IOException If reading from the input fails.
* @throws InterruptedException If interrupted while reading from input.
*/
public static void skipToData(ExtractorInput input, WavHeader wavHeader) throws IOException, InterruptedException {
Assertions.checkNotNull(input);
Assertions.checkNotNull(wavHeader);
// Make sure the peek position is set to the read position before we peek the first header.
input.resetPeekPosition();
ParsableByteArray scratch = new ParsableByteArray(ChunkHeader.SIZE_IN_BYTES);
// Skip all chunks until we hit the data header.
ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
while (chunkHeader.id != Util.getIntegerCodeForString("data")) {
Log.w(TAG, "Ignoring unknown WAV chunk: " + chunkHeader.id);
long bytesToSkip = ChunkHeader.SIZE_IN_BYTES + chunkHeader.size;
// Override size of RIFF chunk, since it describes its size as the entire file.
if (chunkHeader.id == Util.getIntegerCodeForString("RIFF")) {
bytesToSkip = ChunkHeader.SIZE_IN_BYTES + 4;
}
if (bytesToSkip > Integer.MAX_VALUE) {
throw new ParserException("Chunk is too large (~2GB+) to skip; id: " + chunkHeader.id);
}
input.skipFully((int) bytesToSkip);
chunkHeader = ChunkHeader.peek(input, scratch);
}
// Skip past the "data" header.
input.skipFully(ChunkHeader.SIZE_IN_BYTES);
wavHeader.setDataBounds(input.getPosition(), chunkHeader.size);
}
use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.
the class WebvttExtractor method processSample.
private void processSample() throws ParserException {
ParsableByteArray webvttData = new ParsableByteArray(sampleData);
// Validate the first line of the header.
try {
WebvttParserUtil.validateWebvttHeaderLine(webvttData);
} catch (SubtitleDecoderException e) {
throw new ParserException(e);
}
// Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
long vttTimestampUs = 0;
long tsTimestampUs = 0;
// Parse the remainder of the header looking for X-TIMESTAMP-MAP.
String line;
while (!TextUtils.isEmpty(line = webvttData.readLine())) {
if (line.startsWith("X-TIMESTAMP-MAP")) {
Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
if (!localTimestampMatcher.find()) {
throw new ParserException("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line);
}
Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line);
if (!mediaTimestampMatcher.find()) {
throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
}
vttTimestampUs = WebvttParserUtil.parseTimestampUs(localTimestampMatcher.group(1));
tsTimestampUs = TimestampAdjuster.ptsToUs(Long.parseLong(mediaTimestampMatcher.group(1)));
}
}
// Find the first cue header and parse the start time.
Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
if (cueHeaderMatcher == null) {
// No cues found. Don't output a sample, but still output a corresponding track.
buildTrackOutput(0);
return;
}
long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(cueHeaderMatcher.group(1));
long sampleTimeUs = timestampAdjuster.adjustSampleTimestamp(firstCueTimeUs + tsTimestampUs - vttTimestampUs);
long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs;
// Output the track.
TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);
// Output the sample.
sampleDataWrapper.reset(sampleData, sampleSize);
trackOutput.sampleData(sampleDataWrapper, sampleSize);
trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.
the class Ac3Extractor method sniff.
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
// Skip any ID3 headers.
ParsableByteArray scratch = new ParsableByteArray(10);
int startPosition = 0;
while (true) {
input.peekFully(scratch.data, 0, 10);
scratch.setPosition(0);
if (scratch.readUnsignedInt24() != ID3_TAG) {
break;
}
scratch.skipBytes(3);
int length = scratch.readSynchSafeInt();
startPosition += 10 + length;
input.advancePeekPosition(length);
}
input.resetPeekPosition();
input.advancePeekPosition(startPosition);
int headerPosition = startPosition;
int validFramesCount = 0;
while (true) {
input.peekFully(scratch.data, 0, 5);
scratch.setPosition(0);
int syncBytes = scratch.readUnsignedShort();
if (syncBytes != AC3_SYNC_WORD) {
validFramesCount = 0;
input.resetPeekPosition();
if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
return false;
}
input.advancePeekPosition(headerPosition);
} else {
if (++validFramesCount >= 4) {
return true;
}
int frameSize = Ac3Util.parseAc3SyncframeSize(scratch.data);
if (frameSize == C.LENGTH_UNSET) {
return false;
}
input.advancePeekPosition(frameSize - 5);
}
}
}
use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.
the class AdtsExtractor method sniff.
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
// Skip any ID3 headers.
ParsableByteArray scratch = new ParsableByteArray(10);
ParsableBitArray scratchBits = new ParsableBitArray(scratch.data);
int startPosition = 0;
while (true) {
input.peekFully(scratch.data, 0, 10);
scratch.setPosition(0);
if (scratch.readUnsignedInt24() != ID3_TAG) {
break;
}
scratch.skipBytes(3);
int length = scratch.readSynchSafeInt();
startPosition += 10 + length;
input.advancePeekPosition(length);
}
input.resetPeekPosition();
input.advancePeekPosition(startPosition);
// Try to find four or more consecutive AAC audio frames, exceeding the MPEG TS packet size.
int headerPosition = startPosition;
int validFramesSize = 0;
int validFramesCount = 0;
while (true) {
input.peekFully(scratch.data, 0, 2);
scratch.setPosition(0);
int syncBytes = scratch.readUnsignedShort();
if ((syncBytes & 0xFFF6) != 0xFFF0) {
validFramesCount = 0;
validFramesSize = 0;
input.resetPeekPosition();
if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
return false;
}
input.advancePeekPosition(headerPosition);
} else {
if (++validFramesCount >= 4 && validFramesSize > 188) {
return true;
}
// Skip the frame.
input.peekFully(scratch.data, 0, 4);
scratchBits.setPosition(14);
int frameSize = scratchBits.readBits(13);
// Either the stream is malformed OR we're not parsing an ADTS stream.
if (frameSize <= 6) {
return false;
}
input.advancePeekPosition(frameSize - 6);
validFramesSize += frameSize;
}
}
}
Aggregations