Skip to content

Commit

Permalink
Ensure only timestamp adjustment masters set first sample timestamps
Browse files Browse the repository at this point in the history
Without this, it is possible that a non timestamp master instances
the adjuster with its own chunk start time. When chunks are not
aligned, this breaks adjustment.

Issue:#2424

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=149764488
  • Loading branch information
AquilesCanta authored and ojw28 committed Mar 13, 2017
1 parent 15aad26 commit 952bde7
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,8 @@ public void consume(ParsableByteArray sectionData) {
if (mode == MODE_SINGLE_PMT || mode == MODE_HLS || remainingPmts == 1) {
timestampAdjuster = timestampAdjusters.get(0);
} else {
timestampAdjuster = new TimestampAdjuster(timestampAdjusters.get(0).firstSampleTimestampUs);
timestampAdjuster = new TimestampAdjuster(
timestampAdjusters.get(0).getFirstSampleTimestampUs());
timestampAdjusters.add(timestampAdjuster);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public Metadata decode(MetadataInputBuffer inputBuffer) throws MetadataDecoderEx
case TYPE_PRIVATE_COMMAND:
command = PrivateCommand.parseFromSection(sectionData, spliceCommandLength, ptsAdjustment);
break;
default:
// Do nothing.
break;
}
return command == null ? new Metadata() : new Metadata(command);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ public void getNextChunk(HlsMediaChunk previous, long playbackPositionUs, HlsChu
int discontinuitySequence = mediaPlaylist.discontinuitySequence
+ segment.relativeDiscontinuitySequence;
TimestampAdjuster timestampAdjuster = timestampAdjusterProvider.getAdjuster(
discontinuitySequence, startTimeUs);
discontinuitySequence);

// Configure the data source and spec for the chunk.
Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ private void loadMedia() throws IOException, InterruptedException {
}
if (!isMasterTimestampSource) {
timestampAdjuster.waitUntilInitialized();
} else if (timestampAdjuster.getFirstSampleTimestampUs() == TimestampAdjuster.DO_NOT_OFFSET) {
// We're the master and we haven't set the desired first sample timestamp yet.
timestampAdjuster.setFirstSampleTimestampUs(startTimeUs);
}
try {
ExtractorInput input = new DefaultExtractorInput(dataSource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,12 @@ public TimestampAdjusterProvider() {
* a chunk with a given discontinuity sequence.
*
* @param discontinuitySequence The chunk's discontinuity sequence.
* @param startTimeUs The chunk's start time.
* @return A {@link TimestampAdjuster}.
*/
public TimestampAdjuster getAdjuster(int discontinuitySequence, long startTimeUs) {
public TimestampAdjuster getAdjuster(int discontinuitySequence) {
TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence);
if (adjuster == null) {
adjuster = new TimestampAdjuster(startTimeUs);
adjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET);
timestampAdjusters.put(discontinuitySequence, adjuster);
}
return adjuster;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,39 @@ public final class TimestampAdjuster {
*/
private static final long MAX_PTS_PLUS_ONE = 0x200000000L;

public final long firstSampleTimestampUs;

private long firstSampleTimestampUs;
private long timestampOffsetUs;

// Volatile to allow isInitialized to be called on a different thread to adjustSampleTimestamp.
private volatile long lastSampleTimestamp;

/**
* @param firstSampleTimestampUs The desired result of the first call to
* {@link #adjustSampleTimestamp(long)}, or {@link #DO_NOT_OFFSET} if presentation timestamps
* should not be offset.
* @param firstSampleTimestampUs See {@link #setFirstSampleTimestampUs(long)}.
*/
public TimestampAdjuster(long firstSampleTimestampUs) {
this.firstSampleTimestampUs = firstSampleTimestampUs;
lastSampleTimestamp = C.TIME_UNSET;
setFirstSampleTimestampUs(firstSampleTimestampUs);
}

/**
* Sets the desired result of the first call to {@link #adjustSampleTimestamp(long)}. Can only be
* called before any timestamps have been adjusted.
*
* @param firstSampleTimestampUs The first adjusted sample timestamp in microseconds, or
* {@link #DO_NOT_OFFSET} if presentation timestamps should not be offset.
*/
public synchronized void setFirstSampleTimestampUs(long firstSampleTimestampUs) {
Assertions.checkState(lastSampleTimestamp == C.TIME_UNSET);
this.firstSampleTimestampUs = firstSampleTimestampUs;
}

/**
* Returns the first adjusted sample timestamp in microseconds.
*
* @return The first adjusted sample timestamp in microseconds.
*/
public long getFirstSampleTimestampUs() {
return firstSampleTimestampUs;
}

/**
Expand Down

0 comments on commit 952bde7

Please sign in to comment.