mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add large renderer position offset.
This helps to prevent issues where decoders can't handle negative timestamps. In particular it avoids issues when the media accidentally or intentionally starts with small negative timestamps. But it also helps to prevent other renderer resets at a later point, for example if a live stream with a large start offset is enqueued in the playlist. #minor-release PiperOrigin-RevId: 406786977
This commit is contained in:
parent
7115058ccd
commit
10dcdd1df5
@ -1274,7 +1274,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
queue.advancePlayingPeriod();
|
queue.advancePlayingPeriod();
|
||||||
}
|
}
|
||||||
queue.removeAfter(newPlayingPeriodHolder);
|
queue.removeAfter(newPlayingPeriodHolder);
|
||||||
newPlayingPeriodHolder.setRendererOffset(/* rendererPositionOffsetUs= */ 0);
|
newPlayingPeriodHolder.setRendererOffset(
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US);
|
||||||
enableRenderers();
|
enableRenderers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1307,7 +1308,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
MediaPeriodHolder playingMediaPeriod = queue.getPlayingPeriod();
|
MediaPeriodHolder playingMediaPeriod = queue.getPlayingPeriod();
|
||||||
rendererPositionUs =
|
rendererPositionUs =
|
||||||
playingMediaPeriod == null
|
playingMediaPeriod == null
|
||||||
? periodPositionUs
|
? MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US + periodPositionUs
|
||||||
: playingMediaPeriod.toRendererTime(periodPositionUs);
|
: playingMediaPeriod.toRendererTime(periodPositionUs);
|
||||||
mediaClock.resetPosition(rendererPositionUs);
|
mediaClock.resetPosition(rendererPositionUs);
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
@ -1383,7 +1384,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
pendingRecoverableRendererError = null;
|
pendingRecoverableRendererError = null;
|
||||||
isRebuffering = false;
|
isRebuffering = false;
|
||||||
mediaClock.stop();
|
mediaClock.stop();
|
||||||
rendererPositionUs = 0;
|
rendererPositionUs = MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US;
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
try {
|
try {
|
||||||
disableRenderer(renderer);
|
disableRenderer(renderer);
|
||||||
@ -1971,7 +1972,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
emptyTrackSelectorResult);
|
emptyTrackSelectorResult);
|
||||||
mediaPeriodHolder.mediaPeriod.prepare(this, info.startPositionUs);
|
mediaPeriodHolder.mediaPeriod.prepare(this, info.startPositionUs);
|
||||||
if (queue.getPlayingPeriod() == mediaPeriodHolder) {
|
if (queue.getPlayingPeriod() == mediaPeriodHolder) {
|
||||||
resetRendererPosition(mediaPeriodHolder.getStartPositionRendererTime());
|
resetRendererPosition(info.startPositionUs);
|
||||||
}
|
}
|
||||||
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);
|
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,26 @@ import com.google.common.collect.ImmutableList;
|
|||||||
*/
|
*/
|
||||||
/* package */ final class MediaPeriodQueue {
|
/* package */ final class MediaPeriodQueue {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial renderer position offset used for the first item in the queue, in microseconds.
|
||||||
|
*
|
||||||
|
* <p>Choosing a positive value, larger than any reasonable single media duration, ensures three
|
||||||
|
* things:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Media that accidentally or intentionally starts with small negative timestamps doesn't
|
||||||
|
* send samples with negative timestamps to decoders. This makes rendering more robust as
|
||||||
|
* many decoders are known to have problems with negative timestamps.
|
||||||
|
* <li>Enqueueing media after the initial item with a non-zero start offset (e.g. content after
|
||||||
|
* ad breaks or live streams) is virtually guaranteed to stay in the positive timestamp
|
||||||
|
* range even when seeking back. This prevents renderer resets that are required if the
|
||||||
|
* allowed timestamp range may become negative.
|
||||||
|
* <li>Choosing a large value with zeros at all relevant digits simplifies debugging as the
|
||||||
|
* original timestamp of the media is still visible.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static final long INITIAL_RENDERER_POSITION_OFFSET_US = 1_000_000_000_000L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Limits the maximum number of periods to buffer ahead of the current playing period. The
|
* Limits the maximum number of periods to buffer ahead of the current playing period. The
|
||||||
* buffering policy normally prevents buffering too far ahead, but the policy could allow too many
|
* buffering policy normally prevents buffering too far ahead, but the policy could allow too many
|
||||||
@ -165,9 +185,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
TrackSelectorResult emptyTrackSelectorResult) {
|
TrackSelectorResult emptyTrackSelectorResult) {
|
||||||
long rendererPositionOffsetUs =
|
long rendererPositionOffsetUs =
|
||||||
loading == null
|
loading == null
|
||||||
? (info.id.isAd() && info.requestedContentPositionUs != C.TIME_UNSET
|
? INITIAL_RENDERER_POSITION_OFFSET_US
|
||||||
? info.requestedContentPositionUs
|
|
||||||
: 0)
|
|
||||||
: (loading.getRendererOffset() + loading.info.durationUs - info.startPositionUs);
|
: (loading.getRendererOffset() + loading.info.durationUs - info.startPositionUs);
|
||||||
MediaPeriodHolder newPeriodHolder =
|
MediaPeriodHolder newPeriodHolder =
|
||||||
new MediaPeriodHolder(
|
new MediaPeriodHolder(
|
||||||
|
@ -499,10 +499,13 @@ public final class MediaPeriodQueueTest {
|
|||||||
// Change position of first ad (= change duration of playing content before first ad).
|
// Change position of first ad (= change duration of playing content before first ad).
|
||||||
updateAdPlaybackStateAndTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000);
|
updateAdPlaybackStateAndTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
||||||
long maxRendererReadPositionUs = FIRST_AD_START_TIME_US - 3000;
|
long maxRendererReadPositionUs =
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US + FIRST_AD_START_TIME_US - 3000;
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline, /* rendererPositionUs= */ 0, maxRendererReadPositionUs);
|
playbackInfo.timeline,
|
||||||
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
|
maxRendererReadPositionUs);
|
||||||
|
|
||||||
assertThat(changeHandled).isTrue();
|
assertThat(changeHandled).isTrue();
|
||||||
assertThat(getQueueLength()).isEqualTo(1);
|
assertThat(getQueueLength()).isEqualTo(1);
|
||||||
@ -524,10 +527,13 @@ public final class MediaPeriodQueueTest {
|
|||||||
// Change position of first ad (= change duration of playing content before first ad).
|
// Change position of first ad (= change duration of playing content before first ad).
|
||||||
updateAdPlaybackStateAndTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000);
|
updateAdPlaybackStateAndTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
||||||
long maxRendererReadPositionUs = FIRST_AD_START_TIME_US - 1000;
|
long maxRendererReadPositionUs =
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US + FIRST_AD_START_TIME_US - 1000;
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline, /* rendererPositionUs= */ 0, maxRendererReadPositionUs);
|
playbackInfo.timeline,
|
||||||
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
|
maxRendererReadPositionUs);
|
||||||
|
|
||||||
assertThat(changeHandled).isFalse();
|
assertThat(changeHandled).isFalse();
|
||||||
assertThat(getQueueLength()).isEqualTo(1);
|
assertThat(getQueueLength()).isEqualTo(1);
|
||||||
@ -558,10 +564,13 @@ public final class MediaPeriodQueueTest {
|
|||||||
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true);
|
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true);
|
||||||
updateTimeline();
|
updateTimeline();
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
||||||
long maxRendererReadPositionUs = FIRST_AD_START_TIME_US - 1000;
|
long maxRendererReadPositionUs =
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US + FIRST_AD_START_TIME_US - 1000;
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline, /* rendererPositionUs= */ 0, maxRendererReadPositionUs);
|
playbackInfo.timeline,
|
||||||
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
|
maxRendererReadPositionUs);
|
||||||
|
|
||||||
assertThat(changeHandled).isTrue();
|
assertThat(changeHandled).isTrue();
|
||||||
assertThat(getQueueLength()).isEqualTo(1);
|
assertThat(getQueueLength()).isEqualTo(1);
|
||||||
@ -589,7 +598,9 @@ public final class MediaPeriodQueueTest {
|
|||||||
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline, /* rendererPositionUs= */ 0, /* maxRendererReadPositionUs= */ 0);
|
playbackInfo.timeline,
|
||||||
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
|
/* maxRendererReadPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US);
|
||||||
|
|
||||||
assertThat(changeHandled).isTrue();
|
assertThat(changeHandled).isTrue();
|
||||||
assertThat(getQueueLength()).isEqualTo(3);
|
assertThat(getQueueLength()).isEqualTo(3);
|
||||||
@ -614,11 +625,13 @@ public final class MediaPeriodQueueTest {
|
|||||||
/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US - 1000);
|
/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US - 1000);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
||||||
|
long maxRendererReadPositionUs =
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US + FIRST_AD_START_TIME_US;
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline,
|
playbackInfo.timeline,
|
||||||
/* rendererPositionUs= */ 0,
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
/* maxRendererReadPositionUs= */ FIRST_AD_START_TIME_US);
|
maxRendererReadPositionUs);
|
||||||
|
|
||||||
assertThat(changeHandled).isFalse();
|
assertThat(changeHandled).isFalse();
|
||||||
assertThat(getQueueLength()).isEqualTo(3);
|
assertThat(getQueueLength()).isEqualTo(3);
|
||||||
@ -642,11 +655,14 @@ public final class MediaPeriodQueueTest {
|
|||||||
/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US - 1000);
|
/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US - 1000);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
||||||
long readingPositionAtStartOfContentBetweenAds = FIRST_AD_START_TIME_US + AD_DURATION_US;
|
long readingPositionAtStartOfContentBetweenAds =
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US
|
||||||
|
+ FIRST_AD_START_TIME_US
|
||||||
|
+ AD_DURATION_US;
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline,
|
playbackInfo.timeline,
|
||||||
/* rendererPositionUs= */ 0,
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
/* maxRendererReadPositionUs= */ readingPositionAtStartOfContentBetweenAds);
|
/* maxRendererReadPositionUs= */ readingPositionAtStartOfContentBetweenAds);
|
||||||
|
|
||||||
assertThat(changeHandled).isTrue();
|
assertThat(changeHandled).isTrue();
|
||||||
@ -671,11 +687,14 @@ public final class MediaPeriodQueueTest {
|
|||||||
/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US - 1000);
|
/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US - 1000);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
setAdGroupLoaded(/* adGroupIndex= */ 0);
|
||||||
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
setAdGroupLoaded(/* adGroupIndex= */ 1);
|
||||||
long readingPositionAtEndOfContentBetweenAds = SECOND_AD_START_TIME_US + AD_DURATION_US;
|
long readingPositionAtEndOfContentBetweenAds =
|
||||||
|
MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US
|
||||||
|
+ SECOND_AD_START_TIME_US
|
||||||
|
+ AD_DURATION_US;
|
||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline,
|
playbackInfo.timeline,
|
||||||
/* rendererPositionUs= */ 0,
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
/* maxRendererReadPositionUs= */ readingPositionAtEndOfContentBetweenAds);
|
/* maxRendererReadPositionUs= */ readingPositionAtEndOfContentBetweenAds);
|
||||||
|
|
||||||
assertThat(changeHandled).isFalse();
|
assertThat(changeHandled).isFalse();
|
||||||
@ -703,7 +722,7 @@ public final class MediaPeriodQueueTest {
|
|||||||
boolean changeHandled =
|
boolean changeHandled =
|
||||||
mediaPeriodQueue.updateQueuedPeriods(
|
mediaPeriodQueue.updateQueuedPeriods(
|
||||||
playbackInfo.timeline,
|
playbackInfo.timeline,
|
||||||
/* rendererPositionUs= */ 0,
|
/* rendererPositionUs= */ MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US,
|
||||||
/* maxRendererReadPositionUs= */ C.TIME_END_OF_SOURCE);
|
/* maxRendererReadPositionUs= */ C.TIME_END_OF_SOURCE);
|
||||||
|
|
||||||
assertThat(changeHandled).isFalse();
|
assertThat(changeHandled).isFalse();
|
||||||
|
@ -3,89 +3,89 @@ config:
|
|||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
buffer:
|
buffer:
|
||||||
time = 1000
|
time = 1000000001000
|
||||||
data = 1217833679
|
data = 1217833679
|
||||||
buffer:
|
buffer:
|
||||||
time = 97000
|
time = 1000000097000
|
||||||
data = 558614672
|
data = 558614672
|
||||||
buffer:
|
buffer:
|
||||||
time = 193000
|
time = 1000000193000
|
||||||
data = -709714787
|
data = -709714787
|
||||||
buffer:
|
buffer:
|
||||||
time = 289000
|
time = 1000000289000
|
||||||
data = 1367870571
|
data = 1367870571
|
||||||
buffer:
|
buffer:
|
||||||
time = 385000
|
time = 1000000385000
|
||||||
data = -141229457
|
data = -141229457
|
||||||
buffer:
|
buffer:
|
||||||
time = 481000
|
time = 1000000481000
|
||||||
data = 1287758361
|
data = 1287758361
|
||||||
buffer:
|
buffer:
|
||||||
time = 577000
|
time = 1000000577000
|
||||||
data = 1125289147
|
data = 1125289147
|
||||||
buffer:
|
buffer:
|
||||||
time = 673000
|
time = 1000000673000
|
||||||
data = -1677383475
|
data = -1677383475
|
||||||
buffer:
|
buffer:
|
||||||
time = 769000
|
time = 1000000769000
|
||||||
data = 2130742861
|
data = 2130742861
|
||||||
buffer:
|
buffer:
|
||||||
time = 865000
|
time = 1000000865000
|
||||||
data = -1292320253
|
data = -1292320253
|
||||||
buffer:
|
buffer:
|
||||||
time = 961000
|
time = 1000000961000
|
||||||
data = -456587163
|
data = -456587163
|
||||||
buffer:
|
buffer:
|
||||||
time = 1057000
|
time = 1000001057000
|
||||||
data = 748981534
|
data = 748981534
|
||||||
buffer:
|
buffer:
|
||||||
time = 1153000
|
time = 1000001153000
|
||||||
data = 1550456016
|
data = 1550456016
|
||||||
buffer:
|
buffer:
|
||||||
time = 1249000
|
time = 1000001249000
|
||||||
data = 1657906039
|
data = 1657906039
|
||||||
buffer:
|
buffer:
|
||||||
time = 1345000
|
time = 1000001345000
|
||||||
data = -762677083
|
data = -762677083
|
||||||
buffer:
|
buffer:
|
||||||
time = 1441000
|
time = 1000001441000
|
||||||
data = -1343810763
|
data = -1343810763
|
||||||
buffer:
|
buffer:
|
||||||
time = 1537000
|
time = 1000001537000
|
||||||
data = 1137318783
|
data = 1137318783
|
||||||
buffer:
|
buffer:
|
||||||
time = 1633000
|
time = 1000001633000
|
||||||
data = -1891318229
|
data = -1891318229
|
||||||
buffer:
|
buffer:
|
||||||
time = 1729000
|
time = 1000001729000
|
||||||
data = -472068495
|
data = -472068495
|
||||||
buffer:
|
buffer:
|
||||||
time = 1825000
|
time = 1000001825000
|
||||||
data = 832315001
|
data = 832315001
|
||||||
buffer:
|
buffer:
|
||||||
time = 1921000
|
time = 1000001921000
|
||||||
data = 2054935175
|
data = 2054935175
|
||||||
buffer:
|
buffer:
|
||||||
time = 2017000
|
time = 1000002017000
|
||||||
data = 57921641
|
data = 57921641
|
||||||
buffer:
|
buffer:
|
||||||
time = 2113000
|
time = 1000002113000
|
||||||
data = 2132759067
|
data = 2132759067
|
||||||
buffer:
|
buffer:
|
||||||
time = 2209000
|
time = 1000002209000
|
||||||
data = -1742540521
|
data = -1742540521
|
||||||
buffer:
|
buffer:
|
||||||
time = 2305000
|
time = 1000002305000
|
||||||
data = 1657024301
|
data = 1657024301
|
||||||
buffer:
|
buffer:
|
||||||
time = 2401000
|
time = 1000002401000
|
||||||
data = -585080145
|
data = -585080145
|
||||||
buffer:
|
buffer:
|
||||||
time = 2497000
|
time = 1000002497000
|
||||||
data = 427271397
|
data = 427271397
|
||||||
buffer:
|
buffer:
|
||||||
time = 2593000
|
time = 1000002593000
|
||||||
data = -364201340
|
data = -364201340
|
||||||
buffer:
|
buffer:
|
||||||
time = 2689000
|
time = 1000002689000
|
||||||
data = -627965287
|
data = -627965287
|
||||||
|
@ -3,89 +3,89 @@ config:
|
|||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
buffer:
|
buffer:
|
||||||
time = 0
|
time = 1000000000000
|
||||||
data = 225023649
|
data = 225023649
|
||||||
buffer:
|
buffer:
|
||||||
time = 96000
|
time = 1000000096000
|
||||||
data = 455106306
|
data = 455106306
|
||||||
buffer:
|
buffer:
|
||||||
time = 192000
|
time = 1000000192000
|
||||||
data = 2025727297
|
data = 2025727297
|
||||||
buffer:
|
buffer:
|
||||||
time = 288000
|
time = 1000000288000
|
||||||
data = 758514657
|
data = 758514657
|
||||||
buffer:
|
buffer:
|
||||||
time = 384000
|
time = 1000000384000
|
||||||
data = 1044986473
|
data = 1044986473
|
||||||
buffer:
|
buffer:
|
||||||
time = 480000
|
time = 1000000480000
|
||||||
data = -2030029695
|
data = -2030029695
|
||||||
buffer:
|
buffer:
|
||||||
time = 576000
|
time = 1000000576000
|
||||||
data = 1907053281
|
data = 1907053281
|
||||||
buffer:
|
buffer:
|
||||||
time = 672000
|
time = 1000000672000
|
||||||
data = -1974954431
|
data = -1974954431
|
||||||
buffer:
|
buffer:
|
||||||
time = 768000
|
time = 1000000768000
|
||||||
data = -206248383
|
data = -206248383
|
||||||
buffer:
|
buffer:
|
||||||
time = 864000
|
time = 1000000864000
|
||||||
data = 1484984417
|
data = 1484984417
|
||||||
buffer:
|
buffer:
|
||||||
time = 960000
|
time = 1000000960000
|
||||||
data = -1306117439
|
data = -1306117439
|
||||||
buffer:
|
buffer:
|
||||||
time = 1056000
|
time = 1000001056000
|
||||||
data = 692829792
|
data = 692829792
|
||||||
buffer:
|
buffer:
|
||||||
time = 1152000
|
time = 1000001152000
|
||||||
data = 1070563058
|
data = 1070563058
|
||||||
buffer:
|
buffer:
|
||||||
time = 1248000
|
time = 1000001248000
|
||||||
data = -1444096479
|
data = -1444096479
|
||||||
buffer:
|
buffer:
|
||||||
time = 1344000
|
time = 1000001344000
|
||||||
data = 1753016419
|
data = 1753016419
|
||||||
buffer:
|
buffer:
|
||||||
time = 1440000
|
time = 1000001440000
|
||||||
data = 1947797953
|
data = 1947797953
|
||||||
buffer:
|
buffer:
|
||||||
time = 1536000
|
time = 1000001536000
|
||||||
data = 266121411
|
data = 266121411
|
||||||
buffer:
|
buffer:
|
||||||
time = 1632000
|
time = 1000001632000
|
||||||
data = 1275494369
|
data = 1275494369
|
||||||
buffer:
|
buffer:
|
||||||
time = 1728000
|
time = 1000001728000
|
||||||
data = 372077825
|
data = 372077825
|
||||||
buffer:
|
buffer:
|
||||||
time = 1824000
|
time = 1000001824000
|
||||||
data = -993079679
|
data = -993079679
|
||||||
buffer:
|
buffer:
|
||||||
time = 1920000
|
time = 1000001920000
|
||||||
data = 177307937
|
data = 177307937
|
||||||
buffer:
|
buffer:
|
||||||
time = 2016000
|
time = 1000002016000
|
||||||
data = 2037083009
|
data = 2037083009
|
||||||
buffer:
|
buffer:
|
||||||
time = 2112000
|
time = 1000002112000
|
||||||
data = -435776287
|
data = -435776287
|
||||||
buffer:
|
buffer:
|
||||||
time = 2208000
|
time = 1000002208000
|
||||||
data = 1867447329
|
data = 1867447329
|
||||||
buffer:
|
buffer:
|
||||||
time = 2304000
|
time = 1000002304000
|
||||||
data = 1884495937
|
data = 1884495937
|
||||||
buffer:
|
buffer:
|
||||||
time = 2400000
|
time = 1000002400000
|
||||||
data = -804673375
|
data = -804673375
|
||||||
buffer:
|
buffer:
|
||||||
time = 2496000
|
time = 1000002496000
|
||||||
data = -588531007
|
data = -588531007
|
||||||
buffer:
|
buffer:
|
||||||
time = 2592000
|
time = 1000002592000
|
||||||
data = -1064642970
|
data = -1064642970
|
||||||
buffer:
|
buffer:
|
||||||
time = 2688000
|
time = 1000002688000
|
||||||
data = -1771406207
|
data = -1771406207
|
||||||
|
@ -279,6 +279,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
int result = readSource(getFormatHolder(), decoderInputBuffer, /* readFlags= */ 0);
|
int result = readSource(getFormatHolder(), decoderInputBuffer, /* readFlags= */ 0);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case C.RESULT_BUFFER_READ:
|
case C.RESULT_BUFFER_READ:
|
||||||
|
decoderInputBuffer.timeUs -= streamOffsetUs;
|
||||||
mediaClock.updateTimeForTrackType(getTrackType(), decoderInputBuffer.timeUs);
|
mediaClock.updateTimeForTrackType(getTrackType(), decoderInputBuffer.timeUs);
|
||||||
decoderInputBuffer.flip();
|
decoderInputBuffer.flip();
|
||||||
decoder.queueInputBuffer(decoderInputBuffer);
|
decoder.queueInputBuffer(decoderInputBuffer);
|
||||||
|
@ -34,6 +34,7 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
protected final Transformation transformation;
|
protected final Transformation transformation;
|
||||||
|
|
||||||
protected boolean isRendererStarted;
|
protected boolean isRendererStarted;
|
||||||
|
protected long streamOffsetUs;
|
||||||
|
|
||||||
public TransformerBaseRenderer(
|
public TransformerBaseRenderer(
|
||||||
int trackType,
|
int trackType,
|
||||||
@ -46,6 +47,12 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
this.transformation = transformation;
|
this.transformation = transformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs)
|
||||||
|
throws ExoPlaybackException {
|
||||||
|
this.streamOffsetUs = offsetUs;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@C.FormatSupport
|
@C.FormatSupport
|
||||||
public final int supportsFormat(Format format) {
|
public final int supportsFormat(Format format) {
|
||||||
|
@ -117,6 +117,7 @@ import java.nio.ByteBuffer;
|
|||||||
muxerWrapper.endTrack(getTrackType());
|
muxerWrapper.endTrack(getTrackType());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
buffer.timeUs -= streamOffsetUs;
|
||||||
mediaClock.updateTimeForTrackType(getTrackType(), buffer.timeUs);
|
mediaClock.updateTimeForTrackType(getTrackType(), buffer.timeUs);
|
||||||
ByteBuffer data = checkNotNull(buffer.data);
|
ByteBuffer data = checkNotNull(buffer.data);
|
||||||
data.flip();
|
data.flip();
|
||||||
|
@ -320,6 +320,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
case C.RESULT_FORMAT_READ:
|
case C.RESULT_FORMAT_READ:
|
||||||
throw new IllegalStateException("Format changes are not supported.");
|
throw new IllegalStateException("Format changes are not supported.");
|
||||||
case C.RESULT_BUFFER_READ:
|
case C.RESULT_BUFFER_READ:
|
||||||
|
decoderInputBuffer.timeUs -= streamOffsetUs;
|
||||||
mediaClock.updateTimeForTrackType(getTrackType(), decoderInputBuffer.timeUs);
|
mediaClock.updateTimeForTrackType(getTrackType(), decoderInputBuffer.timeUs);
|
||||||
ByteBuffer data = checkNotNull(decoderInputBuffer.data);
|
ByteBuffer data = checkNotNull(decoderInputBuffer.data);
|
||||||
data.flip();
|
data.flip();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user