Simplify DashMediaSource and simulate manifest refreshes
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=130507478
This commit is contained in:
parent
5296d5b198
commit
317a8ef19b
@ -87,7 +87,8 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
private final ManifestCallback manifestCallback;
|
private final ManifestCallback manifestCallback;
|
||||||
private final Object manifestUriLock;
|
private final Object manifestUriLock;
|
||||||
private final SparseArray<DashMediaPeriod> periodsById;
|
private final SparseArray<DashMediaPeriod> periodsById;
|
||||||
private final Runnable refreshSourceInfoRunnable;
|
private final Runnable refreshManifestRunnable;
|
||||||
|
private final Runnable simulateManifestRefreshRunnable;
|
||||||
|
|
||||||
private MediaSource.Listener sourceListener;
|
private MediaSource.Listener sourceListener;
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
@ -124,10 +125,16 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
manifestCallback = new ManifestCallback();
|
manifestCallback = new ManifestCallback();
|
||||||
manifestUriLock = new Object();
|
manifestUriLock = new Object();
|
||||||
periodsById = new SparseArray<>();
|
periodsById = new SparseArray<>();
|
||||||
refreshSourceInfoRunnable = new Runnable() {
|
refreshManifestRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
refreshSourceInfo();
|
startLoadingManifest();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
simulateManifestRefreshRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
processManifest();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -236,18 +243,18 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
DashManifest newManifest = loadable.getResult();
|
DashManifest newManifest = loadable.getResult();
|
||||||
|
|
||||||
int periodCount = manifest == null ? 0 : manifest.getPeriodCount();
|
int periodCount = manifest == null ? 0 : manifest.getPeriodCount();
|
||||||
int periodsToRemoveCount = 0;
|
int removedPeriodCount = 0;
|
||||||
long newFirstPeriodStartTimeMs = newManifest.getPeriod(0).startMs;
|
long newFirstPeriodStartTimeMs = newManifest.getPeriod(0).startMs;
|
||||||
while (periodsToRemoveCount < periodCount
|
while (removedPeriodCount < periodCount
|
||||||
&& manifest.getPeriod(periodsToRemoveCount).startMs < newFirstPeriodStartTimeMs) {
|
&& manifest.getPeriod(removedPeriodCount).startMs < newFirstPeriodStartTimeMs) {
|
||||||
periodsToRemoveCount++;
|
removedPeriodCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// After discarding old periods, we should never have more periods than listed in the new
|
// After discarding old periods, we should never have more periods than listed in the new
|
||||||
// manifest. That would mean that a previously announced period is no longer advertised. If
|
// manifest. That would mean that a previously announced period is no longer advertised. If
|
||||||
// this condition occurs, assume that we are hitting a manifest server that is out of sync and
|
// this condition occurs, assume that we are hitting a manifest server that is out of sync and
|
||||||
// behind, discard this manifest, and try again later.
|
// behind, discard this manifest, and try again later.
|
||||||
if (periodCount - periodsToRemoveCount > newManifest.getPeriodCount()) {
|
if (periodCount - removedPeriodCount > newManifest.getPeriodCount()) {
|
||||||
Log.w(TAG, "Out of sync manifest");
|
Log.w(TAG, "Out of sync manifest");
|
||||||
scheduleManifestRefresh();
|
scheduleManifestRefresh();
|
||||||
return;
|
return;
|
||||||
@ -270,31 +277,11 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
if (manifest.utcTiming != null) {
|
if (manifest.utcTiming != null) {
|
||||||
resolveUtcTimingElement(manifest.utcTiming);
|
resolveUtcTimingElement(manifest.utcTiming);
|
||||||
} else {
|
} else {
|
||||||
finishManifestProcessing();
|
processManifestAndScheduleRefresh();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Remove old periods.
|
firstPeriodId += removedPeriodCount;
|
||||||
while (periodsToRemoveCount-- > 0) {
|
processManifestAndScheduleRefresh();
|
||||||
firstPeriodId++;
|
|
||||||
periodCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update existing periods. Only the first and the last periods can change.
|
|
||||||
if (periodCount > 0) {
|
|
||||||
updatePeriod(0);
|
|
||||||
if (periodCount > 1) {
|
|
||||||
updatePeriod(periodCount - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finishManifestProcessing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePeriod(int index) {
|
|
||||||
DashMediaPeriod period = periodsById.get(firstPeriodId + index);
|
|
||||||
if (period != null) {
|
|
||||||
period.updateManifest(manifest, index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,22 +357,27 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
|
|
||||||
private void onUtcTimestampResolved(long elapsedRealtimeOffsetMs) {
|
private void onUtcTimestampResolved(long elapsedRealtimeOffsetMs) {
|
||||||
this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
|
this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
|
||||||
finishManifestProcessing();
|
processManifestAndScheduleRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUtcTimestampResolutionError(IOException error) {
|
private void onUtcTimestampResolutionError(IOException error) {
|
||||||
Log.e(TAG, "Failed to resolve UtcTiming element.", error);
|
Log.e(TAG, "Failed to resolve UtcTiming element.", error);
|
||||||
// Be optimistic and continue in the hope that the device clock is correct.
|
// Be optimistic and continue in the hope that the device clock is correct.
|
||||||
finishManifestProcessing();
|
processManifestAndScheduleRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishManifestProcessing() {
|
private void processManifestAndScheduleRefresh() {
|
||||||
handler.removeCallbacks(refreshSourceInfoRunnable);
|
processManifest();
|
||||||
refreshSourceInfo();
|
|
||||||
scheduleManifestRefresh();
|
scheduleManifestRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshSourceInfo() {
|
private void processManifest() {
|
||||||
|
// Update any periods.
|
||||||
|
for (int i = 0; i < periodsById.size(); i++) {
|
||||||
|
periodsById.valueAt(i).updateManifest(manifest, firstPeriodId + periodsById.keyAt(i));
|
||||||
|
}
|
||||||
|
// Remove any pending simulated updates.
|
||||||
|
handler.removeCallbacks(simulateManifestRefreshRunnable);
|
||||||
// Update the window.
|
// Update the window.
|
||||||
int lastPeriodIndex = manifest.getPeriodCount() - 1;
|
int lastPeriodIndex = manifest.getPeriodCount() - 1;
|
||||||
PeriodSeekInfo firstPeriodSeekInfo = PeriodSeekInfo.createPeriodSeekInfo(manifest.getPeriod(0),
|
PeriodSeekInfo firstPeriodSeekInfo = PeriodSeekInfo.createPeriodSeekInfo(manifest.getPeriod(0),
|
||||||
@ -395,9 +387,6 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
long currentStartTimeUs;
|
long currentStartTimeUs;
|
||||||
long currentEndTimeUs;
|
long currentEndTimeUs;
|
||||||
if (manifest.dynamic && !lastPeriodSeekInfo.isIndexExplicit) {
|
if (manifest.dynamic && !lastPeriodSeekInfo.isIndexExplicit) {
|
||||||
// The window is changing so post a Runnable to update it.
|
|
||||||
handler.postDelayed(refreshSourceInfoRunnable, NOTIFY_MANIFEST_INTERVAL_MS);
|
|
||||||
|
|
||||||
long minStartPositionUs = firstPeriodSeekInfo.availableStartTimeUs;
|
long minStartPositionUs = firstPeriodSeekInfo.availableStartTimeUs;
|
||||||
long maxEndPositionUs = lastPeriodSeekInfo.availableEndTimeUs;
|
long maxEndPositionUs = lastPeriodSeekInfo.availableEndTimeUs;
|
||||||
long timeShiftBufferDepthUs = manifest.timeShiftBufferDepth == -1 ? -1
|
long timeShiftBufferDepthUs = manifest.timeShiftBufferDepth == -1 ? -1
|
||||||
@ -406,8 +395,9 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
getNowUnixTimeUs() - manifest.availabilityStartTime * 1000);
|
getNowUnixTimeUs() - manifest.availabilityStartTime * 1000);
|
||||||
currentStartTimeUs = timeShiftBufferDepthUs == -1 ? minStartPositionUs
|
currentStartTimeUs = timeShiftBufferDepthUs == -1 ? minStartPositionUs
|
||||||
: Math.max(minStartPositionUs, currentEndTimeUs - timeShiftBufferDepthUs);
|
: Math.max(minStartPositionUs, currentEndTimeUs - timeShiftBufferDepthUs);
|
||||||
|
// The window is changing implicitly. Post a simulated manifest refresh to update it.
|
||||||
|
handler.postDelayed(simulateManifestRefreshRunnable, NOTIFY_MANIFEST_INTERVAL_MS);
|
||||||
} else {
|
} else {
|
||||||
handler.removeCallbacks(refreshSourceInfoRunnable);
|
|
||||||
currentStartTimeUs = firstPeriodSeekInfo.availableStartTimeUs;
|
currentStartTimeUs = firstPeriodSeekInfo.availableStartTimeUs;
|
||||||
currentEndTimeUs = lastPeriodSeekInfo.availableEndTimeUs;
|
currentEndTimeUs = lastPeriodSeekInfo.availableEndTimeUs;
|
||||||
}
|
}
|
||||||
@ -435,12 +425,7 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
}
|
}
|
||||||
long nextLoadTimestamp = manifestLoadStartTimestamp + minUpdatePeriod;
|
long nextLoadTimestamp = manifestLoadStartTimestamp + minUpdatePeriod;
|
||||||
long delayUntilNextLoad = Math.max(0, nextLoadTimestamp - SystemClock.elapsedRealtime());
|
long delayUntilNextLoad = Math.max(0, nextLoadTimestamp - SystemClock.elapsedRealtime());
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(refreshManifestRunnable, delayUntilNextLoad);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
startLoadingManifest();
|
|
||||||
}
|
|
||||||
}, delayUntilNextLoad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void startLoading(ParsingLoadable<T> loadable,
|
private <T> void startLoading(ParsingLoadable<T> loadable,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user