Skip to content

Commit

Permalink
Merge pull request #1 from google/dev
Browse files Browse the repository at this point in the history
Sync with google
  • Loading branch information
fougere-mike committed Jun 26, 2015
2 parents a8b975b + f03e1cd commit c1ada99
Show file tree
Hide file tree
Showing 30 changed files with 443 additions and 116 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* Support for extracting Matroska streams (implemented by WebmExtractor).
* Support for tx3g captions in MP4 streams.
* Support for H.265 in MPEG-TS streams on supported devices.
* HLS: Added support for MPEG audio (e.g. MP3).
* HLS: Improved robustness against missing chunks and variants.
* MP4: Added support for embedded MPEG audio (e.g. MP3).
* TTML: Improved handling of whitespace.
* DASH: Support Mpd.Location element.
* Add option to TsExtractor to allow non-IDR keyframes.
Expand Down
2 changes: 1 addition & 1 deletion extensions/vp9/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ NDK_PATH="<path to Android NDK>"
```
cd "${VP9_EXT_PATH}/jni" && \
git clone https://chromium.googlesource.com/webm/libvpx libvpx && \
git clone http://git.chromium.org/external/libyuv.git libyuv
git clone https://git.chromium.org/external/libyuv.git libyuv
```

* Run a script that generates necessary configuration files for libvpx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,8 +622,8 @@ private void setRendererEnabledInternal(int rendererIndex, boolean enabled)
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
} else {
if (renderer == rendererMediaClockSource) {
// We've been using timeSourceTrackRenderer to advance the current position, but it's
// being disabled. Sync mediaClock so that it can take over timing responsibilities.
// We've been using rendererMediaClockSource to advance the current position, but it's being
// disabled. Sync standaloneMediaClock so that it can take over timing responsibilities.
standaloneMediaClock.setPositionUs(rendererMediaClock.getPositionUs());
}
ensureStopped(renderer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public interface EventListener extends MediaCodecTrackRenderer.EventListener {
private static final String RAW_DECODER_NAME = "OMX.google.raw.decoder";

private final EventListener eventListener;
private final AudioTrack audioTrack;
protected final AudioTrack audioTrack;

private int audioSessionId;
private long currentPositionUs;
Expand Down Expand Up @@ -294,6 +294,7 @@ protected boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs, M

// If we are out of sync, allow currentPositionUs to jump backwards.
if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
handleDiscontinuity();
allowPositionDiscontinuity = true;
}

Expand All @@ -307,6 +308,10 @@ protected boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs, M
return false;
}

protected void handleDiscontinuity() {
// Do nothing
}

@Override
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
if (messageType == MSG_SET_VOLUME) {
Expand All @@ -318,7 +323,7 @@ public void handleMessage(int messageType, Object message) throws ExoPlaybackExc

private void notifyAudioTrackInitializationError(final AudioTrack.InitializationException e) {
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onAudioTrackInitializationError(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -835,23 +835,32 @@ private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs)
return false;
}

if ((outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (codecReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM) {
// We're waiting to re-initialize the codec, and have now received all final output buffers.
releaseCodec();
maybeInitCodec();
} else {
outputStreamEnded = true;
}
return false;
int decodeOnlyIndex = getDecodeOnlyIndex(outputBufferInfo.presentationTimeUs);
boolean isEndOfStream = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;

boolean processedOutputBuffer;
if (isEndOfStream && outputBufferInfo.size == 0) {
// Empty buffer indicating the end of the stream.
codec.releaseOutputBuffer(outputIndex, false);
processedOutputBuffer = true;
} else {
processedOutputBuffer = processOutputBuffer(positionUs, elapsedRealtimeUs, codec,
outputBuffers[outputIndex], outputBufferInfo, outputIndex, decodeOnlyIndex != -1);
}

int decodeOnlyIndex = getDecodeOnlyIndex(outputBufferInfo.presentationTimeUs);
if (processOutputBuffer(positionUs, elapsedRealtimeUs, codec, outputBuffers[outputIndex],
outputBufferInfo, outputIndex, decodeOnlyIndex != -1)) {
if (processedOutputBuffer) {
if (decodeOnlyIndex != -1) {
decodeOnlyPresentationTimestamps.remove(decodeOnlyIndex);
}
if (isEndOfStream) {
if (codecReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM) {
// We're waiting to re-initialize the codec, and have now processed all final buffers.
releaseCodec();
maybeInitCodec();
} else {
outputStreamEnded = true;
}
}
outputIndex = -1;
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public interface FrameReleaseTimeHelper {
private int currentWidth;
private int currentHeight;
private float currentPixelWidthHeightRatio;
private float pendingPixelWidthHeightRatio;
private int lastReportedWidth;
private int lastReportedHeight;
private float lastReportedPixelWidthHeightRatio;
Expand Down Expand Up @@ -248,6 +249,7 @@ public MediaCodecVideoTrackRenderer(SampleSource source, DrmSessionManager drmSe
currentWidth = -1;
currentHeight = -1;
currentPixelWidthHeightRatio = -1;
pendingPixelWidthHeightRatio = -1;
lastReportedWidth = -1;
lastReportedHeight = -1;
lastReportedPixelWidthHeightRatio = -1;
Expand Down Expand Up @@ -316,6 +318,7 @@ public void onDisabled() {
currentWidth = -1;
currentHeight = -1;
currentPixelWidthHeightRatio = -1;
pendingPixelWidthHeightRatio = -1;
lastReportedWidth = -1;
lastReportedHeight = -1;
lastReportedPixelWidthHeightRatio = -1;
Expand Down Expand Up @@ -367,9 +370,7 @@ protected void configureCodec(MediaCodec codec, String codecName,
@Override
protected void onInputFormatChanged(MediaFormatHolder holder) throws ExoPlaybackException {
super.onInputFormatChanged(holder);
// TODO: Ideally this would be read in onOutputFormatChanged, but there doesn't seem
// to be a way to pass a custom key/value pair value through to the output format.
currentPixelWidthHeightRatio = holder.format.pixelWidthHeightRatio == MediaFormat.NO_VALUE ? 1
pendingPixelWidthHeightRatio = holder.format.pixelWidthHeightRatio == MediaFormat.NO_VALUE ? 1
: holder.format.pixelWidthHeightRatio;
}

Expand All @@ -392,6 +393,7 @@ protected void onOutputFormatChanged(MediaFormat inputFormat,
currentHeight = hasCrop
? outputFormat.getInteger(KEY_CROP_BOTTOM) - outputFormat.getInteger(KEY_CROP_TOP) + 1
: outputFormat.getInteger(android.media.MediaFormat.KEY_HEIGHT);
currentPixelWidthHeightRatio = pendingPixelWidthHeightRatio;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ public InvalidAudioTrackTimestampException(String message) {
private static final int MIN_PLAYHEAD_OFFSET_SAMPLE_INTERVAL_US = 30000;
private static final int MIN_TIMESTAMP_SAMPLE_INTERVAL_US = 500000;

private static final int DEFAULT_TIMESCALE_PERCENT = 100;

/**
* Whether to enable a workaround for an issue where an audio effect does not keep its session
* active across releasing/initializing a new audio track, on platform API version < 21.
Expand Down Expand Up @@ -191,6 +193,7 @@ public InvalidAudioTrackTimestampException(String message) {
private long resumeSystemTimeUs;
private long latencyUs;
private float volume;
private int timeScalePercent;

private byte[] temporaryBuffer;
private int temporaryBufferOffset;
Expand Down Expand Up @@ -218,6 +221,7 @@ public AudioTrack() {
}
playheadOffsets = new long[MAX_PLAYHEAD_OFFSET_COUNT];
volume = 1.0f;
timeScalePercent = DEFAULT_TIMESCALE_PERCENT;
startMediaTimeState = START_NOT_SET;
}

Expand Down Expand Up @@ -477,7 +481,7 @@ public int handleBuffer(ByteBuffer buffer, int offset, int size, long presentati
} else {
// Sanity check that bufferStartTime is consistent with the expected value.
long expectedBufferStartTime = startMediaTimeUs
+ framesToDurationUs(bytesToFrames(submittedBytes));
+ (framesToDurationUs(bytesToFrames(submittedBytes)) * timeScalePercent) / 100;
if (startMediaTimeState == START_IN_SYNC
&& Math.abs(expectedBufferStartTime - bufferStartTime) > 200000) {
Log.e(TAG, "Discontinuity detected [expected " + expectedBufferStartTime + ", got "
Expand Down Expand Up @@ -586,6 +590,15 @@ public void pause() {
}
}

/**
* Updates the timescale percent for reporting current time
*
* @param timeScalePercent The new percent multiplier
*/
public void setTimeScalePercent(int timeScalePercent) {
this.timeScalePercent = timeScalePercent;
}

/**
* Releases the underlying audio track asynchronously. Calling {@link #initialize} will block
* until the audio track has been released, so it is safe to initialize immediately after
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,14 @@ public void enable(int track, long positionUs) {
downstreamMediaFormat = null;
downstreamPositionUs = positionUs;
lastSeekPositionUs = positionUs;
pendingDiscontinuity = false;
restartFrom(positionUs);
}

@Override
public void disable(int track) {
Assertions.checkState(state == STATE_ENABLED);
Assertions.checkState(track == 0);
pendingDiscontinuity = false;
state = STATE_PREPARED;
try {
chunkSource.disable(mediaChunks);
Expand Down Expand Up @@ -269,12 +269,14 @@ public int readData(int track, long positionUs, MediaFormatHolder formatHolder,
@Override
public void seekToUs(long positionUs) {
Assertions.checkState(state == STATE_ENABLED);

long currentPositionUs = isPendingReset() ? pendingResetPositionUs : downstreamPositionUs;
downstreamPositionUs = positionUs;
lastSeekPositionUs = positionUs;
if ((isPendingReset() ? pendingResetPositionUs : downstreamPositionUs) == positionUs) {
if (currentPositionUs == positionUs) {
return;
}

downstreamPositionUs = positionUs;
// If we're not pending a reset, see if we can seek within the sample queue.
boolean seekInsideBuffer = !isPendingReset() && sampleQueue.skipToKeyframeBefore(positionUs);
if (seekInsideBuffer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ public RandomEvaluator() {
this.random = new Random();
}

/**
* @param seed A seed for the underlying random number generator.
*/
public RandomEvaluator(int seed) {
this.random = new Random(seed);
}

@Override
public void enable() {
// Do nothing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,8 @@ public void onChunkLoadCompleted(Chunk chunk) {
if (initializationChunk.hasSeekMap()) {
representationHolder.segmentIndex = new DashWrappingSegmentIndex(
(ChunkIndex) initializationChunk.getSeekMap(),
initializationChunk.dataSpec.uri.toString());
initializationChunk.dataSpec.uri.toString(),
representationHolder.representation.periodStartMs * 1000);
}
// The null check avoids overwriting drmInitData obtained from the manifest with drmInitData
// obtained from the stream, as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
Expand Down Expand Up @@ -638,7 +639,8 @@ private Chunk newMediaChunk(RepresentationHolder representationHolder, DataSourc
DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
representation.getCacheKey());

long sampleOffsetUs = -1 * representation.presentationTimeOffsetUs;
long sampleOffsetUs = representation.periodStartMs * 1000
- representation.presentationTimeOffsetUs;
if (representation.format.mimeType.equals(MimeTypes.TEXT_VTT)) {
if (representationHolder.vttHeaderOffsetUs != sampleOffsetUs) {
// Update the VTT header.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@ public class DashWrappingSegmentIndex implements DashSegmentIndex {

private final ChunkIndex chunkIndex;
private final String uri;
private final long startTimeUs;

/**
* @param chunkIndex The {@link ChunkIndex} to wrap.
* @param uri The URI where the data is located.
* @param startTimeUs The start time of the index, in microseconds.
*/
public DashWrappingSegmentIndex(ChunkIndex chunkIndex, String uri) {
public DashWrappingSegmentIndex(ChunkIndex chunkIndex, String uri, long startTimeUs) {
this.chunkIndex = chunkIndex;
this.uri = uri;
this.startTimeUs = startTimeUs;
}

@Override
Expand All @@ -48,7 +51,7 @@ public int getLastSegmentNum() {

@Override
public long getTimeUs(int segmentNum) {
return chunkIndex.timesUs[segmentNum];
return chunkIndex.timesUs[segmentNum] + startTimeUs;
}

@Override
Expand All @@ -63,7 +66,7 @@ public RangedUri getSegmentUrl(int segmentNum) {

@Override
public int getSegmentNum(long timeUs) {
return chunkIndex.getChunkIndex(timeUs);
return chunkIndex.getChunkIndex(timeUs - startTimeUs);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
public class MediaPresentationDescriptionParser extends DefaultHandler
implements UriLoadable.Parser<MediaPresentationDescription> {

private static final Pattern FRAME_RATE_PATTERN = Pattern.compile("(\\d+)(?:/(\\d+))??");
private static final Pattern FRAME_RATE_PATTERN = Pattern.compile("(\\d+)(?:/(\\d+))?");

private final String contentId;
private final XmlPullParserFactory xmlParserFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,12 @@ public RangedUri getSegmentUrl(int segmentIndex) {

@Override
public int getSegmentNum(long timeUs) {
return segmentBase.getSegmentNum(timeUs);
return segmentBase.getSegmentNum(timeUs - periodStartMs * 1000);
}

@Override
public long getTimeUs(int segmentIndex) {
return segmentBase.getSegmentTimeUs(segmentIndex);
return segmentBase.getSegmentTimeUs(segmentIndex) + periodStartMs * 1000;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ public void enable(int track, long positionUs) {
if (enabledTrackCount == 1) {
seekToUs(positionUs);
}
pendingDiscontinuities[track] = false;
}

@Override
Expand All @@ -202,8 +203,8 @@ public void disable(int track) {
Assertions.checkState(trackEnabledStates[track]);
enabledTrackCount--;
trackEnabledStates[track] = false;
pendingDiscontinuities[track] = false;
if (enabledTrackCount == 0) {
downstreamPositionUs = Long.MIN_VALUE;
if (loader.isLoading()) {
loader.cancelLoading();
} else {
Expand Down Expand Up @@ -274,13 +275,13 @@ public void seekToUs(long positionUs) {
positionUs = 0;
}

long currentPositionUs = isPendingReset() ? pendingResetPositionUs : downstreamPositionUs;
downstreamPositionUs = positionUs;
lastSeekPositionUs = positionUs;
if ((isPendingReset() ? pendingResetPositionUs : downstreamPositionUs) == positionUs) {
if (currentPositionUs == positionUs) {
return;
}

downstreamPositionUs = positionUs;

// If we're not pending a reset, see if we can seek within the sample queues.
boolean seekInsideBuffer = !isPendingReset();
for (int i = 0; seekInsideBuffer && i < sampleQueues.size(); i++) {
Expand Down
Loading

0 comments on commit c1ada99

Please sign in to comment.