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
b7be7bc0
authored
Jan 27, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Fix handling of PTS wraparound.
parent
ee834680
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
34 additions
and
14 deletions
library/src/main/java/com/google/android/exoplayer/hls/TsExtractor.java
library/src/main/java/com/google/android/exoplayer/hls/TsExtractor.java
View file @
b7be7bc0
...
@@ -53,19 +53,21 @@ public final class TsExtractor {
...
@@ -53,19 +53,21 @@ public final class TsExtractor {
private
static
final
int
TS_STREAM_TYPE_ID3
=
0x15
;
private
static
final
int
TS_STREAM_TYPE_ID3
=
0x15
;
private
static
final
int
TS_STREAM_TYPE_EIA608
=
0x100
;
// 0xFF + 1
private
static
final
int
TS_STREAM_TYPE_EIA608
=
0x100
;
// 0xFF + 1
private
static
final
long
MAX_PTS
=
0x1FFFFFFFF
L
;
private
final
BitArray
tsPacketBuffer
;
private
final
BitArray
tsPacketBuffer
;
private
final
SparseArray
<
SampleQueue
>
sampleQueues
;
// Indexed by streamType
private
final
SparseArray
<
SampleQueue
>
sampleQueues
;
// Indexed by streamType
private
final
SparseArray
<
TsPayloadReader
>
tsPayloadReaders
;
// Indexed by pid
private
final
SparseArray
<
TsPayloadReader
>
tsPayloadReaders
;
// Indexed by pid
private
final
SamplePool
samplePool
;
private
final
SamplePool
samplePool
;
private
final
boolean
shouldSpliceIn
;
private
final
boolean
shouldSpliceIn
;
/* package */
final
long
firstSampleTimestamp
;
private
final
long
firstSampleTimestamp
;
// Accessed only by the consuming thread.
// Accessed only by the consuming thread.
private
boolean
spliceConfigured
;
private
boolean
spliceConfigured
;
// Accessed only by the loading thread.
// Accessed only by the loading thread.
/* package */
boolean
pendingFirstSampleTimestampAdjustment
;
private
long
timestampOffsetUs
;
/* package */
long
sampleTimestampOffsetU
s
;
private
long
lastPt
s
;
// Accessed by both the loading and consuming threads.
// Accessed by both the loading and consuming threads.
private
volatile
boolean
prepared
;
private
volatile
boolean
prepared
;
...
@@ -75,12 +77,12 @@ public final class TsExtractor {
...
@@ -75,12 +77,12 @@ public final class TsExtractor {
this
.
firstSampleTimestamp
=
firstSampleTimestamp
;
this
.
firstSampleTimestamp
=
firstSampleTimestamp
;
this
.
samplePool
=
samplePool
;
this
.
samplePool
=
samplePool
;
this
.
shouldSpliceIn
=
shouldSpliceIn
;
this
.
shouldSpliceIn
=
shouldSpliceIn
;
pendingFirstSampleTimestampAdjustment
=
true
;
tsPacketBuffer
=
new
BitArray
();
tsPacketBuffer
=
new
BitArray
();
sampleQueues
=
new
SparseArray
<
SampleQueue
>();
sampleQueues
=
new
SparseArray
<
SampleQueue
>();
tsPayloadReaders
=
new
SparseArray
<
TsPayloadReader
>();
tsPayloadReaders
=
new
SparseArray
<
TsPayloadReader
>();
tsPayloadReaders
.
put
(
TS_PAT_PID
,
new
PatReader
());
tsPayloadReaders
.
put
(
TS_PAT_PID
,
new
PatReader
());
largestParsedTimestampUs
=
Long
.
MIN_VALUE
;
largestParsedTimestampUs
=
Long
.
MIN_VALUE
;
lastPts
=
Long
.
MIN_VALUE
;
}
}
/**
/**
...
@@ -295,6 +297,33 @@ public final class TsExtractor {
...
@@ -295,6 +297,33 @@ public final class TsExtractor {
}
}
/**
/**
* Adjusts a PTS value to the corresponding time in microseconds, accounting for PTS wraparound.
*
* @param pts The raw PTS value.
* @return The corresponding time in microseconds.
*/
/* package */
long
ptsToTimeUs
(
long
pts
)
{
if
(
lastPts
!=
Long
.
MIN_VALUE
)
{
// The wrap count for the current PTS may be closestWrapCount or (closestWrapCount - 1),
// and we need to snap to the one closest to lastPts.
long
closestWrapCount
=
(
lastPts
+
(
MAX_PTS
/
2
))
/
MAX_PTS
;
long
ptsWrapBelow
=
pts
+
(
MAX_PTS
*
(
closestWrapCount
-
1
));
long
ptsWrapAbove
=
pts
+
(
MAX_PTS
*
closestWrapCount
);
pts
=
Math
.
abs
(
ptsWrapBelow
-
lastPts
)
<
Math
.
abs
(
ptsWrapAbove
-
lastPts
)
?
ptsWrapBelow
:
ptsWrapAbove
;
}
// Calculate the corresponding timestamp.
long
timeUs
=
(
pts
*
C
.
MICROS_PER_SECOND
)
/
90000
;
// If we haven't done the initial timestamp adjustment, do it now.
if
(
lastPts
==
Long
.
MIN_VALUE
)
{
timestampOffsetUs
=
firstSampleTimestamp
-
timeUs
;
}
// Record the adjusted PTS to adjust for wraparound next time.
lastPts
=
pts
;
return
timeUs
+
timestampOffsetUs
;
}
/**
* Parses payload data.
* Parses payload data.
*/
*/
private
abstract
static
class
TsPayloadReader
{
private
abstract
static
class
TsPayloadReader
{
...
@@ -482,7 +511,7 @@ public final class TsExtractor {
...
@@ -482,7 +511,7 @@ public final class TsExtractor {
pesBuffer
.
skipBits
(
1
);
pesBuffer
.
skipBits
(
1
);
pts
|=
pesBuffer
.
readBitsLong
(
15
);
pts
|=
pesBuffer
.
readBitsLong
(
15
);
pesBuffer
.
skipBits
(
1
);
pesBuffer
.
skipBits
(
1
);
timeUs
=
(
pts
*
C
.
MICROS_PER_SECOND
)
/
90000
;
timeUs
=
ptsToTimeUs
(
pts
)
;
// Skip the rest of the header.
// Skip the rest of the header.
pesBuffer
.
skipBytes
(
headerDataLength
-
5
);
pesBuffer
.
skipBytes
(
headerDataLength
-
5
);
}
else
{
}
else
{
...
@@ -690,7 +719,6 @@ public final class TsExtractor {
...
@@ -690,7 +719,6 @@ public final class TsExtractor {
}
}
protected
void
addSample
(
Sample
sample
)
{
protected
void
addSample
(
Sample
sample
)
{
adjustTimestamp
(
sample
);
largestParsedTimestampUs
=
Math
.
max
(
largestParsedTimestampUs
,
sample
.
timeUs
);
largestParsedTimestampUs
=
Math
.
max
(
largestParsedTimestampUs
,
sample
.
timeUs
);
internalQueue
.
add
(
sample
);
internalQueue
.
add
(
sample
);
}
}
...
@@ -703,14 +731,6 @@ public final class TsExtractor {
...
@@ -703,14 +731,6 @@ public final class TsExtractor {
sample
.
size
+=
size
;
sample
.
size
+=
size
;
}
}
private
void
adjustTimestamp
(
Sample
sample
)
{
if
(
pendingFirstSampleTimestampAdjustment
)
{
sampleTimestampOffsetUs
=
firstSampleTimestamp
-
sample
.
timeUs
;
pendingFirstSampleTimestampAdjustment
=
false
;
}
sample
.
timeUs
+=
sampleTimestampOffsetUs
;
}
}
}
/**
/**
...
...
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