Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
55e08ff7
authored
Apr 17, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Avoid time discontinuity when retrying a live stream.
Issue: #227 Issue: #389
parent
faf0e2c1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
38 additions
and
11 deletions
library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java
library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java
View file @
55e08ff7
...
...
@@ -80,6 +80,10 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
private
long
lastSeekPositionUs
;
private
long
pendingResetPositionUs
;
private
boolean
havePendingNextSampleUs
;
private
long
pendingNextSampleUs
;
private
long
sampleTimeOffsetUs
;
private
Loader
loader
;
private
ExtractingLoadable
loadable
;
private
IOException
currentLoadableException
;
...
...
@@ -235,6 +239,12 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
if
(
sampleQueue
.
getSample
(
sampleHolder
))
{
boolean
decodeOnly
=
frameAccurateSeeking
&&
sampleHolder
.
timeUs
<
lastSeekPositionUs
;
sampleHolder
.
flags
|=
decodeOnly
?
C
.
SAMPLE_FLAG_DECODE_ONLY
:
0
;
if
(
havePendingNextSampleUs
)
{
// Set the offset to make the timestamp of this sample equal to pendingNextSampleUs.
sampleTimeOffsetUs
=
pendingNextSampleUs
-
sampleHolder
.
timeUs
;
havePendingNextSampleUs
=
false
;
}
sampleHolder
.
timeUs
+=
sampleTimeOffsetUs
;
return
SAMPLE_READ
;
}
...
...
@@ -392,16 +402,27 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
long
elapsedMillis
=
SystemClock
.
elapsedRealtime
()
-
currentLoadableExceptionTimestamp
;
if
(
elapsedMillis
>=
getRetryDelayMillis
(
currentLoadableExceptionCount
))
{
currentLoadableException
=
null
;
if
(!
prepared
||
!
seekMap
.
isSeekable
())
{
// One of two cases applies:
// 1. We're not prepared. We don't know whether we're playing an on-demand or a live
// stream. Play it safe and start from scratch.
// 2. We're playing a non-seekable stream. Assume it's a live stream. In such cases it's
// best to discard the pending buffer and start from scratch.
if
(!
prepared
)
{
// We don't know whether we're playing an on-demand or a live stream. For a live stream
// we need to load from the start, as outlined below. Since we might be playing a live
// stream, play it safe and load from the start.
for
(
int
i
=
0
;
i
<
sampleQueues
.
size
();
i
++)
{
sampleQueues
.
valueAt
(
i
).
clear
();
}
loadable
=
createLoadableFromStart
();
}
else
if
(!
seekMap
.
isSeekable
())
{
// We're playing a non-seekable stream. Assume it's live, and therefore that the data at
// the uri is a continuously shifting window of the latest available media. For this case
// there's no way to continue loading from where a previous load finished, and hence it's
// necessary to load from the start whenever commencing a new load.
for
(
int
i
=
0
;
i
<
sampleQueues
.
size
();
i
++)
{
sampleQueues
.
valueAt
(
i
).
clear
();
}
loadable
=
createPreparationLoadable
();
loadable
=
createLoadableFromStart
();
// To avoid introducing a discontinuity, we shift the sample timestamps so that they will
// continue from the current downstream position.
pendingNextSampleUs
=
downstreamPositionUs
;
havePendingNextSampleUs
=
true
;
}
else
{
// We're playing a seekable on-demand stream. Resume the current loadable, which will
// request data starting from the point it left off.
...
...
@@ -411,11 +432,17 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
return
;
}
// We're not retrying, so we're either starting a playback or responding to an explicit seek.
// In both cases sampleTimeOffsetUs should be reset to zero, and any pending adjustment to
// sample timestamps should be discarded.
sampleTimeOffsetUs
=
0
;
havePendingNextSampleUs
=
false
;
if
(!
prepared
)
{
loadable
=
create
PreparationLoadable
();
loadable
=
create
LoadableFromStart
();
}
else
{
Assertions
.
checkState
(
isPendingReset
());
loadable
=
createLoadableF
orPosition
(
pendingResetPositionUs
);
loadable
=
createLoadableF
romPositionUs
(
pendingResetPositionUs
);
pendingResetPositionUs
=
NO_RESET_PENDING
;
}
loader
.
startLoading
(
loadable
,
this
);
...
...
@@ -441,11 +468,11 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
}
}
private
ExtractingLoadable
create
PreparationLoadable
()
{
private
ExtractingLoadable
create
LoadableFromStart
()
{
return
new
ExtractingLoadable
(
uri
,
dataSource
,
extractor
,
bufferPool
,
requestedBufferSize
,
0
);
}
private
ExtractingLoadable
createLoadableF
orPosition
(
long
positionUs
)
{
private
ExtractingLoadable
createLoadableF
romPositionUs
(
long
positionUs
)
{
return
new
ExtractingLoadable
(
uri
,
dataSource
,
extractor
,
bufferPool
,
requestedBufferSize
,
seekMap
.
getPosition
(
positionUs
));
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment