mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Fix timestamp rollover issue for DASH live.
The timestamp scaling in SegmentBase.getSegmentTimeUs was overflowing for some streams. Apply a similar trick to that applied in the SmoothStreaming case to fix it.
This commit is contained in:
parent
c534263032
commit
2969bba60f
3 changed files with 62 additions and 34 deletions
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.google.android.exoplayer.dash.mpd;
|
||||
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -155,7 +157,7 @@ public abstract class SegmentBase {
|
|||
} else {
|
||||
unscaledSegmentTime = (sequenceNumber - startNumber) * duration;
|
||||
}
|
||||
return (unscaledSegmentTime * 1000000) / timescale;
|
||||
return Util.scaleLargeTimestamp(unscaledSegmentTime, 1000000, timescale);
|
||||
}
|
||||
|
||||
public abstract RangedUri getSegmentUrl(Representation representation, int index);
|
||||
|
|
|
|||
|
|
@ -53,19 +53,8 @@ public class SmoothStreamingManifest {
|
|||
this.isLive = isLive;
|
||||
this.protectionElement = protectionElement;
|
||||
this.streamElements = streamElements;
|
||||
if (timescale >= MICROS_PER_SECOND && (timescale % MICROS_PER_SECOND) == 0) {
|
||||
long divisionFactor = timescale / MICROS_PER_SECOND;
|
||||
dvrWindowLengthUs = dvrWindowLength / divisionFactor;
|
||||
durationUs = duration / divisionFactor;
|
||||
} else if (timescale < MICROS_PER_SECOND && (MICROS_PER_SECOND % timescale) == 0) {
|
||||
long multiplicationFactor = MICROS_PER_SECOND / timescale;
|
||||
dvrWindowLengthUs = dvrWindowLength * multiplicationFactor;
|
||||
durationUs = duration * multiplicationFactor;
|
||||
} else {
|
||||
double multiplicationFactor = (double) MICROS_PER_SECOND / timescale;
|
||||
dvrWindowLengthUs = (long) (dvrWindowLength * multiplicationFactor);
|
||||
durationUs = (long) (duration * multiplicationFactor);
|
||||
}
|
||||
dvrWindowLengthUs = Util.scaleLargeTimestamp(dvrWindowLength, MICROS_PER_SECOND, timescale);
|
||||
durationUs = Util.scaleLargeTimestamp(duration, MICROS_PER_SECOND, timescale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -186,26 +175,10 @@ public class SmoothStreamingManifest {
|
|||
this.tracks = tracks;
|
||||
this.chunkCount = chunkStartTimes.size();
|
||||
this.chunkStartTimes = chunkStartTimes;
|
||||
chunkStartTimesUs = new long[chunkStartTimes.size()];
|
||||
if (timescale >= MICROS_PER_SECOND && (timescale % MICROS_PER_SECOND) == 0) {
|
||||
long divisionFactor = timescale / MICROS_PER_SECOND;
|
||||
for (int i = 0; i < chunkStartTimesUs.length; i++) {
|
||||
chunkStartTimesUs[i] = chunkStartTimes.get(i) / divisionFactor;
|
||||
}
|
||||
lastChunkDurationUs = lastChunkDuration / divisionFactor;
|
||||
} else if (timescale < MICROS_PER_SECOND && (MICROS_PER_SECOND % timescale) == 0) {
|
||||
long multiplicationFactor = MICROS_PER_SECOND / timescale;
|
||||
for (int i = 0; i < chunkStartTimesUs.length; i++) {
|
||||
chunkStartTimesUs[i] = chunkStartTimes.get(i) * multiplicationFactor;
|
||||
}
|
||||
lastChunkDurationUs = lastChunkDuration * multiplicationFactor;
|
||||
} else {
|
||||
double multiplicationFactor = (double) MICROS_PER_SECOND / timescale;
|
||||
for (int i = 0; i < chunkStartTimesUs.length; i++) {
|
||||
chunkStartTimesUs[i] = (long) (chunkStartTimes.get(i) * multiplicationFactor);
|
||||
}
|
||||
lastChunkDurationUs = (long) (lastChunkDuration * multiplicationFactor);
|
||||
}
|
||||
lastChunkDurationUs =
|
||||
Util.scaleLargeTimestamp(lastChunkDuration, MICROS_PER_SECOND, timescale);
|
||||
chunkStartTimesUs =
|
||||
Util.scaleLargeTimestamps(chunkStartTimes, MICROS_PER_SECOND, timescale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -346,4 +346,57 @@ public final class Util {
|
|||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales a large timestamp.
|
||||
* <p>
|
||||
* Logically, scaling consists of a multiplication followed by a division. The actual operations
|
||||
* performed are designed to minimize the probability of overflow.
|
||||
*
|
||||
* @param timestamp The timestamp to scale.
|
||||
* @param multiplier The multiplier.
|
||||
* @param divisor The divisor.
|
||||
* @return The scaled timestamp.
|
||||
*/
|
||||
public static long scaleLargeTimestamp(long timestamp, long multiplier, long divisor) {
|
||||
if (divisor >= multiplier && (divisor % multiplier) == 0) {
|
||||
long divisionFactor = divisor / multiplier;
|
||||
return timestamp / divisionFactor;
|
||||
} else if (divisor < multiplier && (multiplier % divisor) == 0) {
|
||||
long multiplicationFactor = multiplier / divisor;
|
||||
return timestamp * multiplicationFactor;
|
||||
} else {
|
||||
double multiplicationFactor = (double) multiplier / divisor;
|
||||
return (long) (timestamp * multiplicationFactor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@link #scaleLargeTimestamp(long, long, long)} to a list of unscaled timestamps.
|
||||
*
|
||||
* @param timestamps The timestamps to scale.
|
||||
* @param multiplier The multiplier.
|
||||
* @param divisor The divisor.
|
||||
* @return The scaled timestamps.
|
||||
*/
|
||||
public static long[] scaleLargeTimestamps(List<Long> timestamps, long multiplier, long divisor) {
|
||||
long[] scaledTimestamps = new long[timestamps.size()];
|
||||
if (divisor >= multiplier && (divisor % multiplier) == 0) {
|
||||
long divisionFactor = divisor / multiplier;
|
||||
for (int i = 0; i < scaledTimestamps.length; i++) {
|
||||
scaledTimestamps[i] = timestamps.get(i) / divisionFactor;
|
||||
}
|
||||
} else if (divisor < multiplier && (multiplier % divisor) == 0) {
|
||||
long multiplicationFactor = multiplier / divisor;
|
||||
for (int i = 0; i < scaledTimestamps.length; i++) {
|
||||
scaledTimestamps[i] = timestamps.get(i) * multiplicationFactor;
|
||||
}
|
||||
} else {
|
||||
double multiplicationFactor = (double) multiplier / divisor;
|
||||
for (int i = 0; i < scaledTimestamps.length; i++) {
|
||||
scaledTimestamps[i] = (long) (timestamps.get(i) * multiplicationFactor);
|
||||
}
|
||||
}
|
||||
return scaledTimestamps;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue