Skip to content

Commit

Permalink
Merge pull request #2 from google/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
drhill committed Mar 29, 2016
2 parents ec4bea5 + 41dbb34 commit ab10949
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 44 deletions.
4 changes: 2 additions & 2 deletions demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
</activity>

<activity android:name="com.google.android.exoplayer.demo.PlayerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:launchMode="singleInstance"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:launchMode="singleTop"
android:label="@string/application_name"
android:theme="@style/PlayerTheme">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,23 @@ public void onNewIntent(Intent intent) {
setIntent(intent);
}

@Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
onShown();
}
}

@Override
public void onResume() {
super.onResume();
if (Util.SDK_INT <= 23 || player == null) {
onShown();
}
}

private void onShown() {
Intent intent = getIntent();
contentUri = intent.getData();
contentType = intent.getIntExtra(CONTENT_TYPE_EXTRA,
Expand All @@ -216,6 +230,20 @@ public void onResume() {
@Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
onHidden();
}
}

@Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
onHidden();
}
}

private void onHidden() {
if (!enableBackgroundAudio) {
releasePlayer();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ public void testParseMediaPlaylist() {
+ "\n"
+ "#EXT-X-KEY:METHOD=AES-128,URI=\"https://priv.example.com/key.php?r=2680\",IV=0x1566B\n"
+ "#EXTINF:7.975,\n"
+ "#EXT-X-BYTERANGE:51501@51370\n"
+ "#EXT-X-BYTERANGE:51501@2147483648\n"
+ "https://priv.example.com/fileSequence2680.ts\n"
+ "\n"
+ "#EXT-X-KEY:METHOD=NONE\n"
+ "#EXTINF:7.941,\n"
+ "#EXT-X-BYTERANGE:51501\n" // @102871
+ "#EXT-X-BYTERANGE:51501\n" // @2147535149
+ "https://priv.example.com/fileSequence2681.ts\n"
+ "\n"
+ "#EXT-X-DISCONTINUITY\n"
+ "#EXT-X-KEY:METHOD=AES-128,URI=\"https://priv.example.com/key.php?r=2682\"\n"
+ "#EXTINF:7.975,\n"
+ "#EXT-X-BYTERANGE:51740\n" // @154372
+ "#EXT-X-BYTERANGE:51740\n" // @2147586650
+ "https://priv.example.com/fileSequence2682.ts\n"
+ "\n"
+ "#EXTINF:7.975,\n"
Expand Down Expand Up @@ -95,7 +95,7 @@ public void testParseMediaPlaylist() {
assertEquals("https://priv.example.com/key.php?r=2680", segments.get(1).encryptionKeyUri);
assertEquals("0x1566B", segments.get(1).encryptionIV);
assertEquals(51501, segments.get(1).byterangeLength);
assertEquals(51370, segments.get(1).byterangeOffset);
assertEquals(2147483648L, segments.get(1).byterangeOffset);
assertEquals("https://priv.example.com/fileSequence2680.ts", segments.get(1).url);

assertEquals(4, segments.get(2).discontinuitySequenceNumber);
Expand All @@ -104,7 +104,7 @@ public void testParseMediaPlaylist() {
assertEquals(null, segments.get(2).encryptionKeyUri);
assertEquals(null, segments.get(2).encryptionIV);
assertEquals(51501, segments.get(2).byterangeLength);
assertEquals(102871, segments.get(2).byterangeOffset);
assertEquals(2147535149L, segments.get(2).byterangeOffset);
assertEquals("https://priv.example.com/fileSequence2681.ts", segments.get(2).url);

assertEquals(5, segments.get(3).discontinuitySequenceNumber);
Expand All @@ -115,7 +115,7 @@ public void testParseMediaPlaylist() {
assertNotNull(segments.get(3).encryptionIV);
assertEquals("A7A", segments.get(3).encryptionIV.toUpperCase(Locale.getDefault()));
assertEquals(51740, segments.get(3).byterangeLength);
assertEquals(154372, segments.get(3).byterangeOffset);
assertEquals(2147586650L, segments.get(3).byterangeOffset);
assertEquals("https://priv.example.com/fileSequence2682.ts", segments.get(3).url);

assertEquals(5, segments.get(4).discontinuitySequenceNumber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@
* <p>
* Warning - This class is marked as deprecated because there are known device specific issues
* associated with its use, including playbacks not starting, playbacks stuttering and other
* miscellaneous failures. For mp4, m4a, mp3, webm, mkv, mpeg-ts and aac playbacks it is strongly
* recommended to use {@link ExtractorSampleSource} instead. Where this is not possible this class
* can still be used, but please be aware of the associated risks. Playing container formats for
* which an ExoPlayer extractor does not yet exist (e.g. ogg) is a valid use case of this class.
* miscellaneous failures. For mp4, m4a, mp3, webm, mkv, mpeg-ts, ogg, wav and aac playbacks it is
* strongly recommended to use {@link ExtractorSampleSource} instead. Where this is not possible
* this class can still be used, but please be aware of the associated risks. Playing container
* formats for which an ExoPlayer extractor does not yet exist (e.g. avi) is a valid use case of
* this class.
* <p>
* Over time we hope to enhance {@link ExtractorSampleSource} to support more formats, and hence
* make use of this class unnecessary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,9 @@ private boolean feedInputBuffer(long positionUs, boolean firstFeed) throws ExoPl
if (sampleHolder.isDecodeOnly()) {
decodeOnlyPresentationTimestamps.add(presentationTimeUs);
}

onQueuedInputBuffer(presentationTimeUs, sampleHolder.data, bufferSize, sampleEncrypted);

if (sampleEncrypted) {
MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(sampleHolder,
adaptiveReconfigurationBytes);
Expand All @@ -696,7 +699,6 @@ private boolean feedInputBuffer(long positionUs, boolean firstFeed) throws ExoPl
codecReceivedBuffers = true;
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
codecCounters.inputBufferCount++;
onQueuedInputBuffer(presentationTimeUs);
} catch (CryptoException e) {
notifyCryptoError(e);
throw new ExoPlaybackException(e);
Expand Down Expand Up @@ -793,13 +795,17 @@ protected void onOutputStreamEnded() {
}

/**
* Invoked when an input buffer is queued into the codec.
* Invoked immediately before an input buffer is queued into the codec.
* <p>
* The default implementation is a no-op.
*
* @param presentationTimeUs The timestamp associated with the input buffer.
* @param buffer The buffer to be queued.
* @param bufferSize the size of the sample data stored in the buffer.
* @param sampleEncrypted Whether the sample data is encrypted.
*/
protected void onQueuedInputBuffer(long presentationTimeUs) {
protected void onQueuedInputBuffer(
long presentationTimeUs, ByteBuffer buffer, int bufferSize, boolean sampleEncrypted) {
// Do nothing.
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
public interface ExtractorInput {

/**
* Reads up to {@code length} bytes from the input.
* Reads up to {@code length} bytes from the input and resets the peek position.
* <p>
* This method blocks until at least one byte of data can be read, the end of the input is
* detected, or an exception is thrown.
Expand Down Expand Up @@ -153,7 +153,7 @@ boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput
* {@code offset}. The current read position is left unchanged.
* <p>
* Calling {@link #resetPeekPosition()} resets the peek position to equal the current read
* position, so the caller can peek the same data again. Reading and skipping also reset the peek
* position, so the caller can peek the same data again. Reading or skipping also resets the peek
* position.
*
* @param target A target array into which data should be written.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -877,8 +877,9 @@ public Extractor selectExtractor(ExtractorInput input)
}
} catch (EOFException e) {
// Do nothing.
} finally {
input.resetPeekPosition();
}
input.resetPeekPosition();
}
if (extractor == null) {
throw new UnrecognizedInputFormatException(extractors);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public boolean sniff(ExtractorInput input) throws IOException, InterruptedExcept
} catch (ParserException e) {
// does not happen
} finally {
input.resetPeekPosition();
scratch.reset();
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public final class WavExtractor implements Extractor, SeekMap {
private ExtractorOutput extractorOutput;
private TrackOutput trackOutput;
private WavHeader wavHeader;
private int bytesPerFrame;
private int pendingBytes;

@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
Expand All @@ -53,7 +55,7 @@ public void init(ExtractorOutput output) {

@Override
public void seek() {
// Do nothing.
pendingBytes = 0;
}

@Override
Expand All @@ -66,6 +68,7 @@ public int read(ExtractorInput input, PositionHolder seekPosition)
// Someone tried to read a non-WAV or unsupported WAV without sniffing first.
throw new ParserException("Error initializing WavHeader. Did you sniff first?");
}
bytesPerFrame = wavHeader.getBytesPerFrame();
}

// If we haven't read in the data start and size, read and store them.
Expand All @@ -86,14 +89,28 @@ public int read(ExtractorInput input, PositionHolder seekPosition)
extractorOutput.seekMap(this);
}

long inputPosition = input.getPosition();
int bytesAppended = trackOutput.sampleData(input, MAX_INPUT_SIZE - pendingBytes, true);

int bytesRead = trackOutput.sampleData(input, MAX_INPUT_SIZE, true);
if (bytesRead == RESULT_END_OF_INPUT) {
if (bytesAppended != RESULT_END_OF_INPUT) {
pendingBytes += bytesAppended;
}

// Round down the pending number of bytes to the nearest frame.
int frameBytes = pendingBytes / bytesPerFrame * bytesPerFrame;
if (frameBytes > 0) {
long sampleStartPosition = input.getPosition() - pendingBytes;
pendingBytes -= frameBytes;
trackOutput.sampleMetadata(
wavHeader.getTimeUs(sampleStartPosition),
C.SAMPLE_FLAG_SYNC,
frameBytes,
pendingBytes,
null);
}

if (bytesAppended == RESULT_END_OF_INPUT) {
return RESULT_END_OF_INPUT;
}
trackOutput.sampleMetadata(
wavHeader.getTimeUs(inputPosition), C.SAMPLE_FLAG_SYNC, bytesRead, 0, null);

return RESULT_CONTINUE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ public int getBytesPerSample() {
return blockAlignment / numChannels;
}

/** Returns the bytes per frame of this WAV. */
public int getBytesPerFrame() {
return blockAlignment;
}

/** Returns the bitrate of this WAV. */
public int getBitrate() {
return sampleRateHz * bitsPerSample * numChannels;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public static WavHeader peek(ExtractorInput input)
throw new ParserException(
"Second chunk in RIFF WAV should be format; got: " + formatChunkHeader.id);
}
Assertions.checkState(formatChunkHeader.size >= 16);

input.peekFully(scratch.data, 0, 16);
scratch.setPosition(0);
Expand All @@ -95,18 +96,14 @@ public static WavHeader peek(ExtractorInput input)
return null;
}

if (type == TYPE_PCM) {
Assertions.checkState(formatChunkHeader.size == 16);
// No more data to read.
} else if (type == TYPE_WAVE_FORMAT_EXTENSIBLE) {
Assertions.checkState(formatChunkHeader.size == 40);
// Skip extensionSize, validBitsPerSample, channelMask, subFormatGuid.
input.advancePeekPosition(2 + 2 + 4 + 16);
} else {
if (type != TYPE_PCM && type != TYPE_WAVE_FORMAT_EXTENSIBLE) {
Log.e(TAG, "Unsupported WAV format type: " + type);
return null;
}

// If present, skip extensionSize, validBitsPerSample, channelMask, subFormatGuid, ...
input.advancePeekPosition((int) formatChunkHeader.size - 16);

return new WavHeader(
numChannels, sampleRateHz, averageBytesPerSecond, blockAlignment, bitsPerSample);
}
Expand All @@ -118,7 +115,7 @@ public static WavHeader peek(ExtractorInput input)
* 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 that is not the RIFF chunk.
* a valid chunk header.
* @param wavHeader WAV header to populate with data bounds.
* @throws IOException If reading from the input fails.
* @throws InterruptedException If interrupted while reading from input.
Expand All @@ -135,6 +132,10 @@ public static void skipToData(ExtractorInput input, WavHeader wavHeader)
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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,14 @@ public boolean read(ExtractorInput input) throws IOException, InterruptedExcepti
*/
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws EOFException,
IOException, InterruptedException {
input.resetPeekPosition();
while (true) {
input.resetPeekPosition();
input.peekFully(scratch, 0, MAX_ID_BYTES);
int varintLength = VarintReader.parseUnsignedVarintLength(scratch[0]);
if (varintLength != -1 && varintLength <= MAX_ID_BYTES) {
int potentialId = (int) VarintReader.assembleVarint(scratch, varintLength, false);
if (output.isLevel1Element(potentialId)) {
input.skipFully(varintLength);
input.resetPeekPosition();
return potentialId;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ public static final class Segment implements Comparable<Long> {
public final boolean isEncrypted;
public final String encryptionKeyUri;
public final String encryptionIV;
public final int byterangeOffset;
public final int byterangeLength;
public final long byterangeOffset;
public final long byterangeLength;

public Segment(String uri, double durationSecs, int discontinuitySequenceNumber,
long startTimeUs, boolean isEncrypted, String encryptionKeyUri, String encryptionIV,
int byterangeOffset, int byterangeLength) {
long byterangeOffset, long byterangeLength) {
this.url = uri;
this.durationSecs = durationSecs;
this.discontinuitySequenceNumber = discontinuitySequenceNumber;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String
double segmentDurationSecs = 0.0;
int discontinuitySequenceNumber = 0;
long segmentStartTimeUs = 0;
int segmentByterangeOffset = 0;
int segmentByterangeLength = C.LENGTH_UNBOUNDED;
long segmentByterangeOffset = 0;
long segmentByterangeLength = C.LENGTH_UNBOUNDED;
int segmentMediaSequence = 0;

boolean isEncrypted = false;
Expand Down Expand Up @@ -274,9 +274,9 @@ private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String
} else if (line.startsWith(BYTERANGE_TAG)) {
String byteRange = HlsParserUtil.parseStringAttr(line, BYTERANGE_REGEX, BYTERANGE_TAG);
String[] splitByteRange = byteRange.split("@");
segmentByterangeLength = Integer.parseInt(splitByteRange[0]);
segmentByterangeLength = Long.parseLong(splitByteRange[0]);
if (splitByteRange.length > 1) {
segmentByterangeOffset = Integer.parseInt(splitByteRange[1]);
segmentByterangeOffset = Long.parseLong(splitByteRange[1]);
}
} else if (line.startsWith(DISCONTINUITY_SEQUENCE_TAG)) {
discontinuitySequenceNumber = Integer.parseInt(line.substring(line.indexOf(':') + 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import android.content.Context;
import android.os.Handler;

import java.nio.ByteBuffer;

/**
* Decodes and renders video using {@link MediaCodecVideoTrackRenderer}. Provides buffer timestamp
* assertions.
Expand Down Expand Up @@ -51,7 +53,8 @@ public DebugMediaCodecVideoTrackRenderer(Context context, SampleSource source,
}

@Override
protected void onQueuedInputBuffer(long presentationTimeUs) {
protected void onQueuedInputBuffer(
long presentationTimeUs, ByteBuffer buffer, int bufferSize, boolean sampleEncrypted) {
if (enableBufferTimestampAssertions) {
insertTimestamp(presentationTimeUs);
maybeShiftTimestampsList();
Expand Down

0 comments on commit ab10949

Please sign in to comment.