Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix DASH VOD and Live manifest and segment pacing #21

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class VideoStreamingSamplerFactory {
VideoStreamingHttpClient httpClient,
TimeMachine timeMachine, SampleResultProcessor sampleResultProcessor) {
//HLS Master Playlist must contain this .m3u8 extension in their URLs
if (url.contains(".m3u8")) {
if (url.contains(".m3u8")||url.contains("format=m3u8")) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space between OR

Suggested change
if (url.contains(".m3u8")||url.contains("format=m3u8")) {
if (url.contains(".m3u8") || url.contains("format=m3u8")) {

return createHlsSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor);
} else {
return createDashSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ public MediaRepresentation findMatchingVariant(List<MediaRepresentation> variant
boolean initialLoop = true;
while (!mediaPlayback.hasEnded()) {
if (mediaPlayback.needsManifestUpdate() && !initialLoop) {
long awaitMillis = manifest.getReloadTimeMillis(timeMachine.now());
long segmentDurationMillis = (long) mediaPlayback.getLastSegment().getDurationSeconds() * 1000;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is too long, does not fit with code style

Suggested change
long segmentDurationMillis = (long) mediaPlayback.getLastSegment().getDurationSeconds() * 1000;
long segmentDurationMillis =
(long) mediaPlayback.getLastSegment().getDurationSeconds() * 1000;

long awaitMillis = manifest.getReloadTimeMillis(segmentDurationMillis);

if (awaitMillis > 0) {
timeMachine.awaitMillis(awaitMillis);
}
Expand Down Expand Up @@ -187,7 +189,7 @@ private void awaitSegmentAvailable(DashMediaSegment segment) throws InterruptedE
Instant availabilityTime = segment.getStartAvailabilityTime();
Instant now = timeMachine.now();
if (availabilityTime.isAfter(now)) {
timeMachine.awaitMillis(Duration.between(availabilityTime, now).toMillis());
timeMachine.awaitMillis(Duration.between(now, availabilityTime).toMillis());
}
}

Expand Down Expand Up @@ -219,11 +221,9 @@ private boolean hasContents() {
return segmentBuilder != null;
}

// dynamic manifests (live) or empty segment list require manifest get (timing determined elsewhere)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again this line is too long

Suggested change
// dynamic manifests (live) or empty segment list require manifest get (timing determined elsewhere)
// dynamic manifests (live) or empty segment list require manifest get (timing determined
// elsewhere)

private boolean needsManifestUpdate() {
return manifest.isDynamic()
&& manifest.getMinimumUpdatePeriod() != null
&& (manifest.getReloadTimeMillis(timeMachine.now()) <= 0
|| !segmentBuilder.hasNext() && !periods.hasNext());
return manifest.isDynamic() || !segmentBuilder.hasNext() && !periods.hasNext();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import io.lindstrom.mpd.data.MPD;
import io.lindstrom.mpd.data.Period;
import io.lindstrom.mpd.data.PresentationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to the project code style, the imports should be in alphabetical order


import java.net.URI;
import java.time.Duration;
import java.time.Instant;
Expand All @@ -17,13 +20,15 @@ public class Manifest {

private final URI uri;
private final MPD mpd;
private final Instant downloadTime;
private final Instant lastDownLoadTime;
private final List<MediaPeriod> periods;
private Instant playbackStartTime;
private static final Logger LOG = LoggerFactory.getLogger(Manifest.class);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static variables should be defined at the beginning of variables definition


private Manifest(URI uri, MPD mpd, Instant timestamp) {
this.uri = uri;
this.mpd = mpd;
this.downloadTime = timestamp;
this.lastDownLoadTime = timestamp;
this.periods = buildPeriods(mpd);
}

Expand Down Expand Up @@ -81,9 +86,13 @@ public Duration getMinimumUpdatePeriod() {
return mpd.getMinimumUpdatePeriod();
}

public long getReloadTimeMillis(Instant now) {
return Math
.max(mpd.getMinimumUpdatePeriod().minus(Duration.between(downloadTime, now)).toMillis(), 0);
public long getReloadTimeMillis(long segmentDurationMillis) {
Duration minUpdatePeriod = mpd.getMinimumUpdatePeriod();
// wait at least segment duration if minUpdatePeriod is 0 (or very small)
long maxIntervalTime = Math.max(minUpdatePeriod.toMillis(), segmentDurationMillis);
Instant now = Instant.now();

return Math.max(maxIntervalTime - Duration.between(lastDownLoadTime, now).toMillis(), 0);
Comment on lines +89 to +95

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both minUpdatePeriod & now could be inlined, due to them are only used once.

Suggested change
public long getReloadTimeMillis(long segmentDurationMillis) {
Duration minUpdatePeriod = mpd.getMinimumUpdatePeriod();
// wait at least segment duration if minUpdatePeriod is 0 (or very small)
long maxIntervalTime = Math.max(minUpdatePeriod.toMillis(), segmentDurationMillis);
Instant now = Instant.now();
return Math.max(maxIntervalTime - Duration.between(lastDownLoadTime, now).toMillis(), 0);
public long getReloadTimeMillis(long segmentDurationMillis) {
// wait at least segment duration if minUpdatePeriod is 0 (or very small)
long maxIntervalTime = Math.max(mpd.getMinimumUpdatePeriod().toMillis(), segmentDurationMillis);
return Math
.max(maxIntervalTime - Duration.between(lastDownLoadTime, Instant.now()).toMillis(), 0);
}

}

public Duration getBufferStartTime() {
Expand All @@ -97,7 +106,12 @@ public Duration getBufferStartTime() {

public Instant getAvailabilityStartTime() {
OffsetDateTime time = mpd.getAvailabilityStartTime();
return time != null ? time.toInstant() : Instant.MIN;
// simulating availabilityStartTime for VOD enables pacing of segment GETs according to segment duration

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long

Suggested change
// simulating availabilityStartTime for VOD enables pacing of segment GETs according to segment duration
// simulating availabilityStartTime for VOD enables pacing of segment GETs according to
// segment duration

if (time == null && playbackStartTime == null) {
LOG.info("setting playbackStartTime to now()");
playbackStartTime = Instant.now();
}
return time != null ? time.toInstant() : playbackStartTime;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private Playlist tryDownloadPlaylist(URI uri, Function<Playlist, String> namer)
}
try {
HTTPSampleResult playlistResult = httpClient.downloadUri(uri);
if (!uri.toString().contains(".m3u8")) {
if (!uri.toString().contains(".m3u8") && !uri.toString().contains("format=m3u8")) {
String playlistName = namer.apply(null);
sampleResultProcessor.accept(playlistName, playlistResult);
return null;
Expand Down