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
cbffc14f
authored
Jul 19, 2017
by
ojw28
Committed by
GitHub
Jul 19, 2017
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #3083 from google/dev-v2-r2.4.4
r2.4.4
parents
2bebd526
46ba81c4
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
364 additions
and
347 deletions
RELEASENOTES.md
build.gradle
demo/src/main/AndroidManifest.xml
demo/src/main/java/com/google/android/exoplayer2/demo/TrackSelectionHelper.java
demo/src/main/res/values/strings.xml
library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/VorbisBitArrayTest.java
library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableBitArrayTest.java
library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArrayTest.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisBitArray.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamInfo.java
library/core/src/main/java/com/google/android/exoplayer2/util/NalUnitUtil.java
library/core/src/main/java/com/google/android/exoplayer2/util/ParsableBitArray.java
library/core/src/main/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArray.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
RELEASENOTES.md
View file @
cbffc14f
# Release notes #
# Release notes #
### r2.4.4 ###
*
HLS/MPEG-TS: Some initial optimizations of MPEG-TS extractor performance
(
[
#3040
](
https://github.com/google/ExoPlayer/issues/3040
)
).
*
HLS: Fix propagation of format identifier for CEA-608
(
[
#3033
](
https://github.com/google/ExoPlayer/issues/3033
)
).
*
HLS: Detect playlist stuck and reset conditions
(
[
#2872
](
https://github.com/google/ExoPlayer/issues/2872
)
).
*
Video: Fix video dimension reporting on some devices
(
[
#3007
](
https://github.com/google/ExoPlayer/issues/3007
)
).
### r2.4.3 ###
### r2.4.3 ###
*
Audio: Workaround custom audio decoders misreporting their maximum supported
*
Audio: Workaround custom audio decoders misreporting their maximum supported
...
...
build.gradle
View file @
cbffc14f
...
@@ -48,7 +48,7 @@ allprojects {
...
@@ -48,7 +48,7 @@ allprojects {
releaseRepoName
=
getBintrayRepo
()
releaseRepoName
=
getBintrayRepo
()
releaseUserOrg
=
'google'
releaseUserOrg
=
'google'
releaseGroupId
=
'com.google.android.exoplayer'
releaseGroupId
=
'com.google.android.exoplayer'
releaseVersion
=
'r2.4.
3
'
releaseVersion
=
'r2.4.
4
'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
}
}
if
(
it
.
hasProperty
(
'externalBuildDir'
))
{
if
(
it
.
hasProperty
(
'externalBuildDir'
))
{
...
...
demo/src/main/AndroidManifest.xml
View file @
cbffc14f
...
@@ -16,8 +16,8 @@
...
@@ -16,8 +16,8 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.google.android.exoplayer2.demo"
package=
"com.google.android.exoplayer2.demo"
android:versionCode=
"240
3
"
android:versionCode=
"240
4
"
android:versionName=
"2.4.
3
"
>
android:versionName=
"2.4.
4
"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
...
...
demo/src/main/java/com/google/android/exoplayer2/demo/TrackSelectionHelper.java
View file @
cbffc14f
...
@@ -136,7 +136,6 @@ import java.util.Arrays;
...
@@ -136,7 +136,6 @@ import java.util.Arrays;
root
.
addView
(
defaultView
);
root
.
addView
(
defaultView
);
// Per-track views.
// Per-track views.
boolean
haveSupportedTracks
=
false
;
boolean
haveAdaptiveTracks
=
false
;
boolean
haveAdaptiveTracks
=
false
;
trackViews
=
new
CheckedTextView
[
trackGroups
.
length
][];
trackViews
=
new
CheckedTextView
[
trackGroups
.
length
][];
for
(
int
groupIndex
=
0
;
groupIndex
<
trackGroups
.
length
;
groupIndex
++)
{
for
(
int
groupIndex
=
0
;
groupIndex
<
trackGroups
.
length
;
groupIndex
++)
{
...
@@ -159,7 +158,6 @@ import java.util.Arrays;
...
@@ -159,7 +158,6 @@ import java.util.Arrays;
trackView
.
setFocusable
(
true
);
trackView
.
setFocusable
(
true
);
trackView
.
setTag
(
Pair
.
create
(
groupIndex
,
trackIndex
));
trackView
.
setTag
(
Pair
.
create
(
groupIndex
,
trackIndex
));
trackView
.
setOnClickListener
(
this
);
trackView
.
setOnClickListener
(
this
);
haveSupportedTracks
=
true
;
}
else
{
}
else
{
trackView
.
setFocusable
(
false
);
trackView
.
setFocusable
(
false
);
trackView
.
setEnabled
(
false
);
trackView
.
setEnabled
(
false
);
...
@@ -169,10 +167,7 @@ import java.util.Arrays;
...
@@ -169,10 +167,7 @@ import java.util.Arrays;
}
}
}
}
if
(!
haveSupportedTracks
)
{
if
(
haveAdaptiveTracks
)
{
// Indicate that the default selection will be nothing.
defaultView
.
setText
(
R
.
string
.
selection_default_none
);
}
else
if
(
haveAdaptiveTracks
)
{
// View for using random adaptation.
// View for using random adaptation.
enableRandomAdaptationView
=
(
CheckedTextView
)
inflater
.
inflate
(
enableRandomAdaptationView
=
(
CheckedTextView
)
inflater
.
inflate
(
android
.
R
.
layout
.
simple_list_item_multiple_choice
,
root
,
false
);
android
.
R
.
layout
.
simple_list_item_multiple_choice
,
root
,
false
);
...
...
demo/src/main/res/values/strings.xml
View file @
cbffc14f
...
@@ -30,8 +30,6 @@
...
@@ -30,8 +30,6 @@
<string
name=
"selection_default"
>
Default
</string>
<string
name=
"selection_default"
>
Default
</string>
<string
name=
"selection_default_none"
>
Default (none)
</string>
<string
name=
"unexpected_intent_action"
>
Unexpected intent action:
<xliff:g
id=
"action"
>
%1$s
</xliff:g></string>
<string
name=
"unexpected_intent_action"
>
Unexpected intent action:
<xliff:g
id=
"action"
>
%1$s
</xliff:g></string>
<string
name=
"enable_random_adaptation"
>
Enable random adaptation
</string>
<string
name=
"enable_random_adaptation"
>
Enable random adaptation
</string>
...
...
library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/VorbisBitArrayTest.java
View file @
cbffc14f
...
@@ -25,36 +25,26 @@ public final class VorbisBitArrayTest extends TestCase {
...
@@ -25,36 +25,26 @@ public final class VorbisBitArrayTest extends TestCase {
public
void
testReadBit
()
{
public
void
testReadBit
()
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0x5c
,
0x50
));
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0x5c
,
0x50
));
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
try
{
assertFalse
(
bitArray
.
readBit
());
fail
();
}
catch
(
IllegalStateException
e
)
{
/* ignored */
}
}
}
public
void
testSkipBits
()
{
public
void
testSkipBits
()
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
bitArray
.
skipBits
(
10
);
bitArray
.
skipBits
(
10
);
assertEquals
(
10
,
bitArray
.
getPosition
());
assertEquals
(
10
,
bitArray
.
getPosition
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
...
@@ -64,27 +54,10 @@ public final class VorbisBitArrayTest extends TestCase {
...
@@ -64,27 +54,10 @@ public final class VorbisBitArrayTest extends TestCase {
assertEquals
(
14
,
bitArray
.
getPosition
());
assertEquals
(
14
,
bitArray
.
getPosition
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
// ignored
}
}
public
void
testSkipBitsThrowsErrorIfEOB
()
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
try
{
bitArray
.
skipBits
(
17
);
fail
();
}
catch
(
IllegalStateException
e
)
{
/* ignored */
}
}
}
public
void
testGetPosition
()
throws
Exception
{
public
void
testGetPosition
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
assertEquals
(
0
,
bitArray
.
getPosition
());
assertEquals
(
0
,
bitArray
.
getPosition
());
bitArray
.
readBit
();
bitArray
.
readBit
();
assertEquals
(
1
,
bitArray
.
getPosition
());
assertEquals
(
1
,
bitArray
.
getPosition
());
...
@@ -96,35 +69,11 @@ public final class VorbisBitArrayTest extends TestCase {
...
@@ -96,35 +69,11 @@ public final class VorbisBitArrayTest extends TestCase {
public
void
testSetPosition
()
throws
Exception
{
public
void
testSetPosition
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
assertEquals
(
0
,
bitArray
.
getPosition
());
assertEquals
(
0
,
bitArray
.
getPosition
());
bitArray
.
setPosition
(
4
);
bitArray
.
setPosition
(
4
);
assertEquals
(
4
,
bitArray
.
getPosition
());
assertEquals
(
4
,
bitArray
.
getPosition
());
bitArray
.
setPosition
(
15
);
bitArray
.
setPosition
(
15
);
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
/* ignored */
}
}
public
void
testSetPositionIllegalPositions
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xF0
,
0x0F
));
try
{
bitArray
.
setPosition
(
16
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
try
{
bitArray
.
setPosition
(-
1
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
}
}
public
void
testReadInt32
()
{
public
void
testReadInt32
()
{
...
@@ -136,13 +85,11 @@ public final class VorbisBitArrayTest extends TestCase {
...
@@ -136,13 +85,11 @@ public final class VorbisBitArrayTest extends TestCase {
public
void
testReadBits
()
throws
Exception
{
public
void
testReadBits
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0x03
,
0x22
));
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0x03
,
0x22
));
assertEquals
(
3
,
bitArray
.
readBits
(
2
));
assertEquals
(
3
,
bitArray
.
readBits
(
2
));
bitArray
.
skipBits
(
6
);
bitArray
.
skipBits
(
6
);
assertEquals
(
2
,
bitArray
.
readBits
(
2
));
assertEquals
(
2
,
bitArray
.
readBits
(
2
));
bitArray
.
skipBits
(
2
);
bitArray
.
skipBits
(
2
);
assertEquals
(
2
,
bitArray
.
readBits
(
2
));
assertEquals
(
2
,
bitArray
.
readBits
(
2
));
bitArray
.
reset
();
bitArray
.
reset
();
assertEquals
(
0x2203
,
bitArray
.
readBits
(
16
));
assertEquals
(
0x2203
,
bitArray
.
readBits
(
16
));
}
}
...
@@ -156,7 +103,6 @@ public final class VorbisBitArrayTest extends TestCase {
...
@@ -156,7 +103,6 @@ public final class VorbisBitArrayTest extends TestCase {
public
void
testReadBitsBeyondByteBoundaries
()
throws
Exception
{
public
void
testReadBitsBeyondByteBoundaries
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xFF
,
0x0F
,
0xFF
,
0x0F
));
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xFF
,
0x0F
,
0xFF
,
0x0F
));
assertEquals
(
0x0FFF0FFF
,
bitArray
.
readBits
(
32
));
assertEquals
(
0x0FFF0FFF
,
bitArray
.
readBits
(
32
));
bitArray
.
reset
();
bitArray
.
reset
();
...
@@ -188,83 +134,6 @@ public final class VorbisBitArrayTest extends TestCase {
...
@@ -188,83 +134,6 @@ public final class VorbisBitArrayTest extends TestCase {
assertEquals
(
0
,
bitArray
.
getPosition
());
assertEquals
(
0
,
bitArray
.
getPosition
());
bitArray
.
readBit
();
bitArray
.
readBit
();
assertEquals
(
1
,
bitArray
.
getPosition
());
assertEquals
(
1
,
bitArray
.
getPosition
());
try
{
bitArray
.
readBits
(
24
);
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
1
,
bitArray
.
getPosition
());
}
}
public
void
testLimit
()
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xc0
,
0x02
),
1
);
try
{
bitArray
.
skipBits
(
9
);
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
try
{
bitArray
.
readBits
(
9
);
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
int
byteValue
=
bitArray
.
readBits
(
8
);
assertEquals
(
0xc0
,
byteValue
);
assertEquals
(
8
,
bitArray
.
getPosition
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
8
,
bitArray
.
getPosition
());
}
}
public
void
testBitsLeft
()
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
TestUtil
.
createByteArray
(
0xc0
,
0x02
));
assertEquals
(
16
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
skipBits
(
1
);
assertEquals
(
15
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
skipBits
(
3
);
assertEquals
(
12
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
setPosition
(
6
);
assertEquals
(
10
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
skipBits
(
1
);
assertEquals
(
9
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
skipBits
(
1
);
assertEquals
(
8
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
readBits
(
4
);
assertEquals
(
4
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
readBits
(
4
);
assertEquals
(
0
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
0
,
bitArray
.
bitsLeft
());
}
}
}
}
}
library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableBitArrayTest.java
0 → 100644
View file @
cbffc14f
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
util
;
import
android.test.MoreAsserts
;
import
junit.framework.TestCase
;
/**
* Tests for {@link ParsableBitArray}.
*/
public
final
class
ParsableBitArrayTest
extends
TestCase
{
private
static
final
byte
[]
TEST_DATA
=
new
byte
[]
{
0x3C
,
(
byte
)
0xD2
,
(
byte
)
0x5F
,
(
byte
)
0x01
,
(
byte
)
0xFF
,
(
byte
)
0x14
,
(
byte
)
0x60
,
(
byte
)
0x99
};
public
void
testReadAllBytes
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
byte
[]
bytesRead
=
new
byte
[
TEST_DATA
.
length
];
testArray
.
readBytes
(
bytesRead
,
0
,
TEST_DATA
.
length
);
MoreAsserts
.
assertEquals
(
TEST_DATA
,
bytesRead
);
assertEquals
(
TEST_DATA
.
length
*
8
,
testArray
.
getPosition
());
assertEquals
(
TEST_DATA
.
length
,
testArray
.
getBytePosition
());
}
public
void
testReadBit
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
assertReadBitsToEnd
(
0
,
testArray
);
}
public
void
testReadBits
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
assertEquals
(
getTestDataBits
(
0
,
5
),
testArray
.
readBits
(
5
));
assertEquals
(
getTestDataBits
(
5
,
3
),
testArray
.
readBits
(
3
));
assertEquals
(
getTestDataBits
(
8
,
16
),
testArray
.
readBits
(
16
));
assertEquals
(
getTestDataBits
(
24
,
3
),
testArray
.
readBits
(
3
));
assertEquals
(
getTestDataBits
(
27
,
18
),
testArray
.
readBits
(
18
));
assertEquals
(
getTestDataBits
(
45
,
5
),
testArray
.
readBits
(
5
));
assertEquals
(
getTestDataBits
(
50
,
14
),
testArray
.
readBits
(
14
));
}
public
void
testRead32BitsByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
assertEquals
(
getTestDataBits
(
0
,
32
),
testArray
.
readBits
(
32
));
assertEquals
(
getTestDataBits
(
32
,
32
),
testArray
.
readBits
(
32
));
}
public
void
testRead32BitsNonByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
assertEquals
(
getTestDataBits
(
0
,
5
),
testArray
.
readBits
(
5
));
assertEquals
(
getTestDataBits
(
5
,
32
),
testArray
.
readBits
(
32
));
}
public
void
testSkipBytes
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
skipBytes
(
2
);
assertReadBitsToEnd
(
16
,
testArray
);
}
public
void
testSkipBitsByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
skipBits
(
16
);
assertReadBitsToEnd
(
16
,
testArray
);
}
public
void
testSkipBitsNonByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
skipBits
(
5
);
assertReadBitsToEnd
(
5
,
testArray
);
}
public
void
testSetPositionByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
setPosition
(
16
);
assertReadBitsToEnd
(
16
,
testArray
);
}
public
void
testSetPositionNonByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
setPosition
(
5
);
assertReadBitsToEnd
(
5
,
testArray
);
}
public
void
testByteAlignFromNonByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
setPosition
(
11
);
testArray
.
byteAlign
();
assertEquals
(
2
,
testArray
.
getBytePosition
());
assertEquals
(
16
,
testArray
.
getPosition
());
assertReadBitsToEnd
(
16
,
testArray
);
}
public
void
testByteAlignFromByteAligned
()
{
ParsableBitArray
testArray
=
new
ParsableBitArray
(
TEST_DATA
);
testArray
.
setPosition
(
16
);
testArray
.
byteAlign
();
// Should be a no-op.
assertEquals
(
2
,
testArray
.
getBytePosition
());
assertEquals
(
16
,
testArray
.
getPosition
());
assertReadBitsToEnd
(
16
,
testArray
);
}
private
static
void
assertReadBitsToEnd
(
int
expectedStartPosition
,
ParsableBitArray
testArray
)
{
int
position
=
testArray
.
getPosition
();
assertEquals
(
expectedStartPosition
,
position
);
for
(
int
i
=
position
;
i
<
TEST_DATA
.
length
*
8
;
i
++)
{
assertEquals
(
getTestDataBit
(
i
),
testArray
.
readBit
());
assertEquals
(
i
+
1
,
testArray
.
getPosition
());
}
}
private
static
int
getTestDataBits
(
int
bitPosition
,
int
length
)
{
int
result
=
0
;
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
result
=
result
<<
1
;
if
(
getTestDataBit
(
bitPosition
++))
{
result
|=
0x1
;
}
}
return
result
;
}
private
static
boolean
getTestDataBit
(
int
bitPosition
)
{
return
(
TEST_DATA
[
bitPosition
/
8
]
&
(
0x80
>>>
(
bitPosition
%
8
)))
!=
0
;
}
}
library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArrayTest.java
View file @
cbffc14f
...
@@ -95,7 +95,7 @@ public final class ParsableNalUnitBitArrayTest extends TestCase {
...
@@ -95,7 +95,7 @@ public final class ParsableNalUnitBitArrayTest extends TestCase {
ParsableNalUnitBitArray
array
=
ParsableNalUnitBitArray
array
=
new
ParsableNalUnitBitArray
(
createByteArray
(
0
,
0
,
3
,
128
,
0
),
0
,
5
);
new
ParsableNalUnitBitArray
(
createByteArray
(
0
,
0
,
3
,
128
,
0
),
0
,
5
);
assertFalse
(
array
.
canReadExpGolombCodedNum
());
assertFalse
(
array
.
canReadExpGolombCodedNum
());
array
.
skipBit
s
(
1
);
array
.
skipBit
(
);
assertTrue
(
array
.
canReadExpGolombCodedNum
());
assertTrue
(
array
.
canReadExpGolombCodedNum
());
assertEquals
(
32767
,
array
.
readUnsignedExpGolombCodedInt
());
assertEquals
(
32767
,
array
.
readUnsignedExpGolombCodedInt
());
assertFalse
(
array
.
canReadBits
(
1
));
assertFalse
(
array
.
canReadBits
(
1
));
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
View file @
cbffc14f
...
@@ -24,13 +24,13 @@ public interface ExoPlayerLibraryInfo {
...
@@ -24,13 +24,13 @@ public interface ExoPlayerLibraryInfo {
* The version of the library expressed as a string, for example "1.2.3".
* The version of the library expressed as a string, for example "1.2.3".
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
String
VERSION
=
"2.4.
3
"
;
String
VERSION
=
"2.4.
4
"
;
/**
/**
* The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}.
* The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}.
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
String
VERSION_SLASHY
=
"ExoPlayerLib/2.4.
3
"
;
String
VERSION_SLASHY
=
"ExoPlayerLib/2.4.
4
"
;
/**
/**
* The version of the library expressed as an integer, for example 1002003.
* The version of the library expressed as an integer, for example 1002003.
...
@@ -40,7 +40,7 @@ public interface ExoPlayerLibraryInfo {
...
@@ -40,7 +40,7 @@ public interface ExoPlayerLibraryInfo {
* integer version 123045006 (123-045-006).
* integer version 123045006 (123-045-006).
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
int
VERSION_INT
=
200400
3
;
int
VERSION_INT
=
200400
4
;
/**
/**
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisBitArray.java
View file @
cbffc14f
...
@@ -25,8 +25,9 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -25,8 +25,9 @@ import com.google.android.exoplayer2.util.Assertions;
*/
*/
/* package */
final
class
VorbisBitArray
{
/* package */
final
class
VorbisBitArray
{
public
final
byte
[]
data
;
private
final
byte
[]
data
;
private
final
int
limit
;
private
final
int
byteLimit
;
private
int
byteOffset
;
private
int
byteOffset
;
private
int
bitOffset
;
private
int
bitOffset
;
...
@@ -36,18 +37,8 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -36,18 +37,8 @@ import com.google.android.exoplayer2.util.Assertions;
* @param data the array to wrap.
* @param data the array to wrap.
*/
*/
public
VorbisBitArray
(
byte
[]
data
)
{
public
VorbisBitArray
(
byte
[]
data
)
{
this
(
data
,
data
.
length
);
}
/**
* Creates a new instance that wraps an existing array.
*
* @param data the array to wrap.
* @param limit the limit in bytes.
*/
public
VorbisBitArray
(
byte
[]
data
,
int
limit
)
{
this
.
data
=
data
;
this
.
data
=
data
;
this
.
limit
=
limit
*
8
;
byteLimit
=
data
.
length
;
}
}
/**
/**
...
@@ -64,7 +55,9 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -64,7 +55,9 @@ import com.google.android.exoplayer2.util.Assertions;
* @return {@code true} if the bit is set, {@code false} otherwise.
* @return {@code true} if the bit is set, {@code false} otherwise.
*/
*/
public
boolean
readBit
()
{
public
boolean
readBit
()
{
return
readBits
(
1
)
==
1
;
boolean
returnValue
=
(((
data
[
byteOffset
]
&
0xFF
)
>>
bitOffset
)
&
0x01
)
==
1
;
skipBits
(
1
);
return
returnValue
;
}
}
/**
/**
...
@@ -74,53 +67,32 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -74,53 +67,32 @@ import com.google.android.exoplayer2.util.Assertions;
* @return An integer whose bottom {@code numBits} bits hold the read data.
* @return An integer whose bottom {@code numBits} bits hold the read data.
*/
*/
public
int
readBits
(
int
numBits
)
{
public
int
readBits
(
int
numBits
)
{
Assertions
.
checkState
(
getPosition
()
+
numBits
<=
limit
);
int
tempByteOffset
=
byteOffset
;
if
(
numBits
==
0
)
{
int
bitsRead
=
Math
.
min
(
numBits
,
8
-
bitOffset
);
return
0
;
int
returnValue
=
((
data
[
tempByteOffset
++]
&
0xFF
)
>>
bitOffset
)
&
(
0xFF
>>
(
8
-
bitsRead
));
}
while
(
bitsRead
<
numBits
)
{
int
result
=
0
;
returnValue
|=
(
data
[
tempByteOffset
++]
&
0xFF
)
<<
bitsRead
;
int
bitCount
=
0
;
bitsRead
+=
8
;
if
(
bitOffset
!=
0
)
{
bitCount
=
Math
.
min
(
numBits
,
8
-
bitOffset
);
int
mask
=
0xFF
>>>
(
8
-
bitCount
);
result
=
(
data
[
byteOffset
]
>>>
bitOffset
)
&
mask
;
bitOffset
+=
bitCount
;
if
(
bitOffset
==
8
)
{
byteOffset
++;
bitOffset
=
0
;
}
}
if
(
numBits
-
bitCount
>
7
)
{
int
numBytes
=
(
numBits
-
bitCount
)
/
8
;
for
(
int
i
=
0
;
i
<
numBytes
;
i
++)
{
result
|=
(
data
[
byteOffset
++]
&
0xFF
L
)
<<
bitCount
;
bitCount
+=
8
;
}
}
}
returnValue
&=
0xFFFFFFFF
>>>
(
32
-
numBits
);
if
(
numBits
>
bitCount
)
{
skipBits
(
numBits
);
int
bitsOnNextByte
=
numBits
-
bitCount
;
return
returnValue
;
int
mask
=
0xFF
>>>
(
8
-
bitsOnNextByte
);
result
|=
(
data
[
byteOffset
]
&
mask
)
<<
bitCount
;
bitOffset
+=
bitsOnNextByte
;
}
return
result
;
}
}
/**
/**
* Skips {@code numberOfBits} bits.
* Skips {@code numberOfBits} bits.
*
*
* @param num
berOf
Bits The number of bits to skip.
* @param numBits The number of bits to skip.
*/
*/
public
void
skipBits
(
int
num
berOf
Bits
)
{
public
void
skipBits
(
int
numBits
)
{
Assertions
.
checkState
(
getPosition
()
+
numberOfBits
<=
limit
)
;
int
numBytes
=
numBits
/
8
;
byteOffset
+=
num
berOfBits
/
8
;
byteOffset
+=
num
Bytes
;
bitOffset
+=
num
berOfBits
%
8
;
bitOffset
+=
num
Bits
-
(
numBytes
*
8
)
;
if
(
bitOffset
>
7
)
{
if
(
bitOffset
>
7
)
{
byteOffset
++;
byteOffset
++;
bitOffset
-=
8
;
bitOffset
-=
8
;
}
}
assertValidOffset
();
}
}
/**
/**
...
@@ -136,23 +108,22 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -136,23 +108,22 @@ import com.google.android.exoplayer2.util.Assertions;
* @param position The new reading position in bits.
* @param position The new reading position in bits.
*/
*/
public
void
setPosition
(
int
position
)
{
public
void
setPosition
(
int
position
)
{
Assertions
.
checkArgument
(
position
<
limit
&&
position
>=
0
);
byteOffset
=
position
/
8
;
byteOffset
=
position
/
8
;
bitOffset
=
position
-
(
byteOffset
*
8
);
bitOffset
=
position
-
(
byteOffset
*
8
);
assertValidOffset
();
}
}
/**
/**
* Returns the number of remaining bits.
* Returns the number of remaining bits.
*/
*/
public
int
bitsLeft
()
{
public
int
bitsLeft
()
{
return
limit
-
getPosition
()
;
return
(
byteLimit
-
byteOffset
)
*
8
-
bitOffset
;
}
}
/**
private
void
assertValidOffset
()
{
* Returns the limit in bits.
// It is fine for position to be at the end of the array, but no further.
**/
Assertions
.
checkState
(
byteOffset
>=
0
public
int
limit
()
{
&&
(
byteOffset
<
byteLimit
||
(
byteOffset
==
byteLimit
&&
bitOffset
==
0
)));
return
limit
;
}
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java
View file @
cbffc14f
...
@@ -316,7 +316,7 @@ public final class H264Reader implements ElementaryStreamReader {
...
@@ -316,7 +316,7 @@ public final class H264Reader implements ElementaryStreamReader {
if
(!
bitArray
.
canReadBits
(
8
))
{
if
(!
bitArray
.
canReadBits
(
8
))
{
return
;
return
;
}
}
bitArray
.
skipBit
s
(
1
);
// forbidden_zero_bit
bitArray
.
skipBit
(
);
// forbidden_zero_bit
int
nalRefIdc
=
bitArray
.
readBits
(
2
);
int
nalRefIdc
=
bitArray
.
readBits
(
2
);
bitArray
.
skipBits
(
5
);
// nal_unit_type
bitArray
.
skipBits
(
5
);
// nal_unit_type
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java
View file @
cbffc14f
...
@@ -225,7 +225,7 @@ public final class H265Reader implements ElementaryStreamReader {
...
@@ -225,7 +225,7 @@ public final class H265Reader implements ElementaryStreamReader {
ParsableNalUnitBitArray
bitArray
=
new
ParsableNalUnitBitArray
(
sps
.
nalData
,
0
,
sps
.
nalLength
);
ParsableNalUnitBitArray
bitArray
=
new
ParsableNalUnitBitArray
(
sps
.
nalData
,
0
,
sps
.
nalLength
);
bitArray
.
skipBits
(
40
+
4
);
// NAL header, sps_video_parameter_set_id
bitArray
.
skipBits
(
40
+
4
);
// NAL header, sps_video_parameter_set_id
int
maxSubLayersMinus1
=
bitArray
.
readBits
(
3
);
int
maxSubLayersMinus1
=
bitArray
.
readBits
(
3
);
bitArray
.
skipBit
s
(
1
);
// sps_temporal_id_nesting_flag
bitArray
.
skipBit
(
);
// sps_temporal_id_nesting_flag
// profile_tier_level(1, sps_max_sub_layers_minus1)
// profile_tier_level(1, sps_max_sub_layers_minus1)
bitArray
.
skipBits
(
88
);
// if (profilePresentFlag) {...}
bitArray
.
skipBits
(
88
);
// if (profilePresentFlag) {...}
...
@@ -247,7 +247,7 @@ public final class H265Reader implements ElementaryStreamReader {
...
@@ -247,7 +247,7 @@ public final class H265Reader implements ElementaryStreamReader {
bitArray
.
readUnsignedExpGolombCodedInt
();
// sps_seq_parameter_set_id
bitArray
.
readUnsignedExpGolombCodedInt
();
// sps_seq_parameter_set_id
int
chromaFormatIdc
=
bitArray
.
readUnsignedExpGolombCodedInt
();
int
chromaFormatIdc
=
bitArray
.
readUnsignedExpGolombCodedInt
();
if
(
chromaFormatIdc
==
3
)
{
if
(
chromaFormatIdc
==
3
)
{
bitArray
.
skipBit
s
(
1
);
// separate_colour_plane_flag
bitArray
.
skipBit
(
);
// separate_colour_plane_flag
}
}
int
picWidthInLumaSamples
=
bitArray
.
readUnsignedExpGolombCodedInt
();
int
picWidthInLumaSamples
=
bitArray
.
readUnsignedExpGolombCodedInt
();
int
picHeightInLumaSamples
=
bitArray
.
readUnsignedExpGolombCodedInt
();
int
picHeightInLumaSamples
=
bitArray
.
readUnsignedExpGolombCodedInt
();
...
@@ -288,7 +288,7 @@ public final class H265Reader implements ElementaryStreamReader {
...
@@ -288,7 +288,7 @@ public final class H265Reader implements ElementaryStreamReader {
bitArray
.
skipBits
(
8
);
bitArray
.
skipBits
(
8
);
bitArray
.
readUnsignedExpGolombCodedInt
();
// log2_min_pcm_luma_coding_block_size_minus3
bitArray
.
readUnsignedExpGolombCodedInt
();
// log2_min_pcm_luma_coding_block_size_minus3
bitArray
.
readUnsignedExpGolombCodedInt
();
// log2_diff_max_min_pcm_luma_coding_block_size
bitArray
.
readUnsignedExpGolombCodedInt
();
// log2_diff_max_min_pcm_luma_coding_block_size
bitArray
.
skipBit
s
(
1
);
// pcm_loop_filter_disabled_flag
bitArray
.
skipBit
(
);
// pcm_loop_filter_disabled_flag
}
}
// Skips all short term reference picture sets.
// Skips all short term reference picture sets.
skipShortTermRefPicSets
(
bitArray
);
skipShortTermRefPicSets
(
bitArray
);
...
@@ -365,11 +365,11 @@ public final class H265Reader implements ElementaryStreamReader {
...
@@ -365,11 +365,11 @@ public final class H265Reader implements ElementaryStreamReader {
interRefPicSetPredictionFlag
=
bitArray
.
readBit
();
interRefPicSetPredictionFlag
=
bitArray
.
readBit
();
}
}
if
(
interRefPicSetPredictionFlag
)
{
if
(
interRefPicSetPredictionFlag
)
{
bitArray
.
skipBit
s
(
1
);
// delta_rps_sign
bitArray
.
skipBit
(
);
// delta_rps_sign
bitArray
.
readUnsignedExpGolombCodedInt
();
// abs_delta_rps_minus1
bitArray
.
readUnsignedExpGolombCodedInt
();
// abs_delta_rps_minus1
for
(
int
j
=
0
;
j
<=
previousNumDeltaPocs
;
j
++)
{
for
(
int
j
=
0
;
j
<=
previousNumDeltaPocs
;
j
++)
{
if
(
bitArray
.
readBit
())
{
// used_by_curr_pic_flag[j]
if
(
bitArray
.
readBit
())
{
// used_by_curr_pic_flag[j]
bitArray
.
skipBit
s
(
1
);
// use_delta_flag[j]
bitArray
.
skipBit
(
);
// use_delta_flag[j]
}
}
}
}
}
else
{
}
else
{
...
@@ -378,11 +378,11 @@ public final class H265Reader implements ElementaryStreamReader {
...
@@ -378,11 +378,11 @@ public final class H265Reader implements ElementaryStreamReader {
previousNumDeltaPocs
=
numNegativePics
+
numPositivePics
;
previousNumDeltaPocs
=
numNegativePics
+
numPositivePics
;
for
(
int
i
=
0
;
i
<
numNegativePics
;
i
++)
{
for
(
int
i
=
0
;
i
<
numNegativePics
;
i
++)
{
bitArray
.
readUnsignedExpGolombCodedInt
();
// delta_poc_s0_minus1[i]
bitArray
.
readUnsignedExpGolombCodedInt
();
// delta_poc_s0_minus1[i]
bitArray
.
skipBit
s
(
1
);
// used_by_curr_pic_s0_flag[i]
bitArray
.
skipBit
(
);
// used_by_curr_pic_s0_flag[i]
}
}
for
(
int
i
=
0
;
i
<
numPositivePics
;
i
++)
{
for
(
int
i
=
0
;
i
<
numPositivePics
;
i
++)
{
bitArray
.
readUnsignedExpGolombCodedInt
();
// delta_poc_s1_minus1[i]
bitArray
.
readUnsignedExpGolombCodedInt
();
// delta_poc_s1_minus1[i]
bitArray
.
skipBit
s
(
1
);
// used_by_curr_pic_s1_flag[i]
bitArray
.
skipBit
(
);
// used_by_curr_pic_s1_flag[i]
}
}
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java
View file @
cbffc14f
...
@@ -51,9 +51,10 @@ import java.util.List;
...
@@ -51,9 +51,10 @@ import java.util.List;
Assertions
.
checkArgument
(
MimeTypes
.
APPLICATION_CEA608
.
equals
(
channelMimeType
)
Assertions
.
checkArgument
(
MimeTypes
.
APPLICATION_CEA608
.
equals
(
channelMimeType
)
||
MimeTypes
.
APPLICATION_CEA708
.
equals
(
channelMimeType
),
||
MimeTypes
.
APPLICATION_CEA708
.
equals
(
channelMimeType
),
"Invalid closed caption mime type provided: "
+
channelMimeType
);
"Invalid closed caption mime type provided: "
+
channelMimeType
);
output
.
format
(
Format
.
createTextSampleFormat
(
idGenerator
.
getFormatId
(),
channelMimeType
,
null
,
String
formatId
=
channelFormat
.
id
!=
null
?
channelFormat
.
id
:
idGenerator
.
getFormatId
();
Format
.
NO_VALUE
,
channelFormat
.
selectionFlags
,
channelFormat
.
language
,
output
.
format
(
Format
.
createTextSampleFormat
(
formatId
,
channelMimeType
,
null
,
Format
.
NO_VALUE
,
channelFormat
.
accessibilityChannel
,
null
));
channelFormat
.
selectionFlags
,
channelFormat
.
language
,
channelFormat
.
accessibilityChannel
,
null
));
outputs
[
i
]
=
output
;
outputs
[
i
]
=
output
;
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
cbffc14f
...
@@ -111,7 +111,6 @@ public final class TsExtractor implements Extractor {
...
@@ -111,7 +111,6 @@ public final class TsExtractor implements Extractor {
@Mode
private
final
int
mode
;
@Mode
private
final
int
mode
;
private
final
List
<
TimestampAdjuster
>
timestampAdjusters
;
private
final
List
<
TimestampAdjuster
>
timestampAdjusters
;
private
final
ParsableByteArray
tsPacketBuffer
;
private
final
ParsableByteArray
tsPacketBuffer
;
private
final
ParsableBitArray
tsScratch
;
private
final
SparseIntArray
continuityCounters
;
private
final
SparseIntArray
continuityCounters
;
private
final
TsPayloadReader
.
Factory
payloadReaderFactory
;
private
final
TsPayloadReader
.
Factory
payloadReaderFactory
;
private
final
SparseArray
<
TsPayloadReader
>
tsPayloadReaders
;
// Indexed by pid
private
final
SparseArray
<
TsPayloadReader
>
tsPayloadReaders
;
// Indexed by pid
...
@@ -164,7 +163,6 @@ public final class TsExtractor implements Extractor {
...
@@ -164,7 +163,6 @@ public final class TsExtractor implements Extractor {
timestampAdjusters
.
add
(
timestampAdjuster
);
timestampAdjusters
.
add
(
timestampAdjuster
);
}
}
tsPacketBuffer
=
new
ParsableByteArray
(
BUFFER_SIZE
);
tsPacketBuffer
=
new
ParsableByteArray
(
BUFFER_SIZE
);
tsScratch
=
new
ParsableBitArray
(
new
byte
[
3
]);
trackIds
=
new
SparseBooleanArray
();
trackIds
=
new
SparseBooleanArray
();
tsPayloadReaders
=
new
SparseArray
<>();
tsPayloadReaders
=
new
SparseArray
<>();
continuityCounters
=
new
SparseIntArray
();
continuityCounters
=
new
SparseIntArray
();
...
@@ -250,24 +248,23 @@ public final class TsExtractor implements Extractor {
...
@@ -250,24 +248,23 @@ public final class TsExtractor implements Extractor {
return
RESULT_CONTINUE
;
return
RESULT_CONTINUE
;
}
}
tsPacketBuffer
.
skipBytes
(
1
);
int
tsPacketHeader
=
tsPacketBuffer
.
readInt
();
tsPacketBuffer
.
readBytes
(
tsScratch
,
3
);
if
((
tsPacketHeader
&
0x800000
)
!=
0
)
{
// transport_error_indicator
if
(
tsScratch
.
readBit
())
{
// transport_error_indicator
// There are uncorrectable errors in this packet.
// There are uncorrectable errors in this packet.
tsPacketBuffer
.
setPosition
(
endOfPacket
);
tsPacketBuffer
.
setPosition
(
endOfPacket
);
return
RESULT_CONTINUE
;
return
RESULT_CONTINUE
;
}
}
boolean
payloadUnitStartIndicator
=
tsScratch
.
readBit
()
;
boolean
payloadUnitStartIndicator
=
(
tsPacketHeader
&
0x400000
)
!=
0
;
tsScratch
.
skipBits
(
1
);
// transport_priority
// Ignoring transport_priority (tsPacketHeader & 0x200000)
int
pid
=
tsScratch
.
readBits
(
13
)
;
int
pid
=
(
tsPacketHeader
&
0x1FFF00
)
>>
8
;
tsScratch
.
skipBits
(
2
);
// transport_scrambling_control
// Ignoring transport_scrambling_control (tsPacketHeader & 0xC0)
boolean
adaptationFieldExists
=
tsScratch
.
readBit
()
;
boolean
adaptationFieldExists
=
(
tsPacketHeader
&
0x20
)
!=
0
;
boolean
payloadExists
=
tsScratch
.
readBit
()
;
boolean
payloadExists
=
(
tsPacketHeader
&
0x10
)
!=
0
;
// Discontinuity check.
// Discontinuity check.
boolean
discontinuityFound
=
false
;
boolean
discontinuityFound
=
false
;
int
continuityCounter
=
tsScratch
.
readBits
(
4
);
if
(
mode
!=
MODE_HLS
)
{
if
(
mode
!=
MODE_HLS
)
{
int
continuityCounter
=
tsPacketHeader
&
0xF
;
int
previousCounter
=
continuityCounters
.
get
(
pid
,
continuityCounter
-
1
);
int
previousCounter
=
continuityCounters
.
get
(
pid
,
continuityCounter
-
1
);
continuityCounters
.
put
(
pid
,
continuityCounter
);
continuityCounters
.
put
(
pid
,
continuityCounter
);
if
(
previousCounter
==
continuityCounter
)
{
if
(
previousCounter
==
continuityCounter
)
{
...
@@ -276,7 +273,7 @@ public final class TsExtractor implements Extractor {
...
@@ -276,7 +273,7 @@ public final class TsExtractor implements Extractor {
tsPacketBuffer
.
setPosition
(
endOfPacket
);
tsPacketBuffer
.
setPosition
(
endOfPacket
);
return
RESULT_CONTINUE
;
return
RESULT_CONTINUE
;
}
}
}
else
if
(
continuityCounter
!=
(
previousCounter
+
1
)
%
16
)
{
}
else
if
(
continuityCounter
!=
(
(
previousCounter
+
1
)
&
0xF
)
)
{
discontinuityFound
=
true
;
discontinuityFound
=
true
;
}
}
}
}
...
@@ -296,7 +293,6 @@ public final class TsExtractor implements Extractor {
...
@@ -296,7 +293,6 @@ public final class TsExtractor implements Extractor {
}
}
tsPacketBuffer
.
setLimit
(
endOfPacket
);
tsPacketBuffer
.
setLimit
(
endOfPacket
);
payloadReader
.
consume
(
tsPacketBuffer
,
payloadUnitStartIndicator
);
payloadReader
.
consume
(
tsPacketBuffer
,
payloadUnitStartIndicator
);
Assertions
.
checkState
(
tsPacketBuffer
.
getPosition
()
<=
endOfPacket
);
tsPacketBuffer
.
setLimit
(
limit
);
tsPacketBuffer
.
setLimit
(
limit
);
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamInfo.java
View file @
cbffc14f
...
@@ -47,7 +47,8 @@ public final class FlacStreamInfo {
...
@@ -47,7 +47,8 @@ public final class FlacStreamInfo {
this
.
sampleRate
=
scratch
.
readBits
(
20
);
this
.
sampleRate
=
scratch
.
readBits
(
20
);
this
.
channels
=
scratch
.
readBits
(
3
)
+
1
;
this
.
channels
=
scratch
.
readBits
(
3
)
+
1
;
this
.
bitsPerSample
=
scratch
.
readBits
(
5
)
+
1
;
this
.
bitsPerSample
=
scratch
.
readBits
(
5
)
+
1
;
this
.
totalSamples
=
scratch
.
readBits
(
36
);
this
.
totalSamples
=
((
scratch
.
readBits
(
4
)
&
0xF
L
)
<<
32
)
|
(
scratch
.
readBits
(
32
)
&
0xFFFFFFFF
L
);
// Remaining 16 bytes is md5 value
// Remaining 16 bytes is md5 value
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/NalUnitUtil.java
View file @
cbffc14f
...
@@ -265,7 +265,7 @@ public final class NalUnitUtil {
...
@@ -265,7 +265,7 @@ public final class NalUnitUtil {
}
}
data
.
readUnsignedExpGolombCodedInt
();
// bit_depth_luma_minus8
data
.
readUnsignedExpGolombCodedInt
();
// bit_depth_luma_minus8
data
.
readUnsignedExpGolombCodedInt
();
// bit_depth_chroma_minus8
data
.
readUnsignedExpGolombCodedInt
();
// bit_depth_chroma_minus8
data
.
skipBit
s
(
1
);
// qpprime_y_zero_transform_bypass_flag
data
.
skipBit
(
);
// qpprime_y_zero_transform_bypass_flag
boolean
seqScalingMatrixPresentFlag
=
data
.
readBit
();
boolean
seqScalingMatrixPresentFlag
=
data
.
readBit
();
if
(
seqScalingMatrixPresentFlag
)
{
if
(
seqScalingMatrixPresentFlag
)
{
int
limit
=
(
chromaFormatIdc
!=
3
)
?
8
:
12
;
int
limit
=
(
chromaFormatIdc
!=
3
)
?
8
:
12
;
...
@@ -295,17 +295,17 @@ public final class NalUnitUtil {
...
@@ -295,17 +295,17 @@ public final class NalUnitUtil {
}
}
}
}
data
.
readUnsignedExpGolombCodedInt
();
// max_num_ref_frames
data
.
readUnsignedExpGolombCodedInt
();
// max_num_ref_frames
data
.
skipBit
s
(
1
);
// gaps_in_frame_num_value_allowed_flag
data
.
skipBit
(
);
// gaps_in_frame_num_value_allowed_flag
int
picWidthInMbs
=
data
.
readUnsignedExpGolombCodedInt
()
+
1
;
int
picWidthInMbs
=
data
.
readUnsignedExpGolombCodedInt
()
+
1
;
int
picHeightInMapUnits
=
data
.
readUnsignedExpGolombCodedInt
()
+
1
;
int
picHeightInMapUnits
=
data
.
readUnsignedExpGolombCodedInt
()
+
1
;
boolean
frameMbsOnlyFlag
=
data
.
readBit
();
boolean
frameMbsOnlyFlag
=
data
.
readBit
();
int
frameHeightInMbs
=
(
2
-
(
frameMbsOnlyFlag
?
1
:
0
))
*
picHeightInMapUnits
;
int
frameHeightInMbs
=
(
2
-
(
frameMbsOnlyFlag
?
1
:
0
))
*
picHeightInMapUnits
;
if
(!
frameMbsOnlyFlag
)
{
if
(!
frameMbsOnlyFlag
)
{
data
.
skipBit
s
(
1
);
// mb_adaptive_frame_field_flag
data
.
skipBit
(
);
// mb_adaptive_frame_field_flag
}
}
data
.
skipBit
s
(
1
);
// direct_8x8_inference_flag
data
.
skipBit
(
);
// direct_8x8_inference_flag
int
frameWidth
=
picWidthInMbs
*
16
;
int
frameWidth
=
picWidthInMbs
*
16
;
int
frameHeight
=
frameHeightInMbs
*
16
;
int
frameHeight
=
frameHeightInMbs
*
16
;
boolean
frameCroppingFlag
=
data
.
readBit
();
boolean
frameCroppingFlag
=
data
.
readBit
();
...
@@ -368,7 +368,7 @@ public final class NalUnitUtil {
...
@@ -368,7 +368,7 @@ public final class NalUnitUtil {
data
.
skipBits
(
8
);
// nal_unit
data
.
skipBits
(
8
);
// nal_unit
int
picParameterSetId
=
data
.
readUnsignedExpGolombCodedInt
();
int
picParameterSetId
=
data
.
readUnsignedExpGolombCodedInt
();
int
seqParameterSetId
=
data
.
readUnsignedExpGolombCodedInt
();
int
seqParameterSetId
=
data
.
readUnsignedExpGolombCodedInt
();
data
.
skipBit
s
(
1
);
// entropy_coding_mode_flag
data
.
skipBit
(
);
// entropy_coding_mode_flag
boolean
bottomFieldPicOrderInFramePresentFlag
=
data
.
readBit
();
boolean
bottomFieldPicOrderInFramePresentFlag
=
data
.
readBit
();
return
new
PpsData
(
picParameterSetId
,
seqParameterSetId
,
bottomFieldPicOrderInFramePresentFlag
);
return
new
PpsData
(
picParameterSetId
,
seqParameterSetId
,
bottomFieldPicOrderInFramePresentFlag
);
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/ParsableBitArray.java
View file @
cbffc14f
...
@@ -111,13 +111,25 @@ public final class ParsableBitArray {
...
@@ -111,13 +111,25 @@ public final class ParsableBitArray {
}
}
/**
/**
* Skips a single bit.
*/
public
void
skipBit
()
{
if
(++
bitOffset
==
8
)
{
bitOffset
=
0
;
byteOffset
++;
}
assertValidOffset
();
}
/**
* Skips bits and moves current reading position forward.
* Skips bits and moves current reading position forward.
*
*
* @param n The number of bits to skip.
* @param n
umBits
The number of bits to skip.
*/
*/
public
void
skipBits
(
int
n
)
{
public
void
skipBits
(
int
numBits
)
{
byteOffset
+=
(
n
/
8
);
int
numBytes
=
numBits
/
8
;
bitOffset
+=
(
n
%
8
);
byteOffset
+=
numBytes
;
bitOffset
+=
numBits
-
(
numBytes
*
8
);
if
(
bitOffset
>
7
)
{
if
(
bitOffset
>
7
)
{
byteOffset
++;
byteOffset
++;
bitOffset
-=
8
;
bitOffset
-=
8
;
...
@@ -131,7 +143,9 @@ public final class ParsableBitArray {
...
@@ -131,7 +143,9 @@ public final class ParsableBitArray {
* @return Whether the bit is set.
* @return Whether the bit is set.
*/
*/
public
boolean
readBit
()
{
public
boolean
readBit
()
{
return
readBits
(
1
)
==
1
;
boolean
returnValue
=
(
data
[
byteOffset
]
&
(
0x80
>>
bitOffset
))
!=
0
;
skipBit
();
return
returnValue
;
}
}
/**
/**
...
@@ -141,48 +155,18 @@ public final class ParsableBitArray {
...
@@ -141,48 +155,18 @@ public final class ParsableBitArray {
* @return An integer whose bottom n bits hold the read data.
* @return An integer whose bottom n bits hold the read data.
*/
*/
public
int
readBits
(
int
numBits
)
{
public
int
readBits
(
int
numBits
)
{
if
(
numBits
==
0
)
{
return
0
;
}
int
returnValue
=
0
;
int
returnValue
=
0
;
bitOffset
+=
numBits
;
// Read as many whole bytes as we can.
while
(
bitOffset
>
8
)
{
int
wholeBytes
=
(
numBits
/
8
);
bitOffset
-=
8
;
for
(
int
i
=
0
;
i
<
wholeBytes
;
i
++)
{
returnValue
|=
(
data
[
byteOffset
++]
&
0xFF
)
<<
bitOffset
;
int
byteValue
;
if
(
bitOffset
!=
0
)
{
byteValue
=
((
data
[
byteOffset
]
&
0xFF
)
<<
bitOffset
)
|
((
data
[
byteOffset
+
1
]
&
0xFF
)
>>>
(
8
-
bitOffset
));
}
else
{
byteValue
=
data
[
byteOffset
];
}
numBits
-=
8
;
returnValue
|=
(
byteValue
&
0xFF
)
<<
numBits
;
byteOffset
++;
}
}
returnValue
|=
(
data
[
byteOffset
]
&
0xFF
)
>>
8
-
bitOffset
;
// Read any remaining bits.
returnValue
&=
0xFFFFFFFF
>>>
(
32
-
numBits
);
if
(
numBits
>
0
)
{
if
(
bitOffset
==
8
)
{
int
nextBit
=
bitOffset
+
numBits
;
bitOffset
=
0
;
byte
writeMask
=
(
byte
)
(
0xFF
>>
(
8
-
numBits
));
byteOffset
++;
if
(
nextBit
>
8
)
{
// Combine bits from current byte and next byte.
returnValue
|=
((((
data
[
byteOffset
]
&
0xFF
)
<<
(
nextBit
-
8
)
|
((
data
[
byteOffset
+
1
]
&
0xFF
)
>>
(
16
-
nextBit
)))
&
writeMask
));
byteOffset
++;
}
else
{
// Bits to be read only within current byte.
returnValue
|=
(((
data
[
byteOffset
]
&
0xFF
)
>>
(
8
-
nextBit
))
&
writeMask
);
if
(
nextBit
==
8
)
{
byteOffset
++;
}
}
bitOffset
=
nextBit
%
8
;
}
}
assertValidOffset
();
assertValidOffset
();
return
returnValue
;
return
returnValue
;
}
}
...
@@ -231,7 +215,6 @@ public final class ParsableBitArray {
...
@@ -231,7 +215,6 @@ public final class ParsableBitArray {
private
void
assertValidOffset
()
{
private
void
assertValidOffset
()
{
// It is fine for position to be at the end of the array, but no further.
// It is fine for position to be at the end of the array, but no further.
Assertions
.
checkState
(
byteOffset
>=
0
Assertions
.
checkState
(
byteOffset
>=
0
&&
(
bitOffset
>=
0
&&
bitOffset
<
8
)
&&
(
byteOffset
<
byteLimit
||
(
byteOffset
==
byteLimit
&&
bitOffset
==
0
)));
&&
(
byteOffset
<
byteLimit
||
(
byteOffset
==
byteLimit
&&
bitOffset
==
0
)));
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArray.java
View file @
cbffc14f
...
@@ -55,14 +55,26 @@ public final class ParsableNalUnitBitArray {
...
@@ -55,14 +55,26 @@ public final class ParsableNalUnitBitArray {
}
}
/**
/**
* Skips a single bit.
*/
public
void
skipBit
()
{
if
(++
bitOffset
==
8
)
{
bitOffset
=
0
;
byteOffset
+=
shouldSkipByte
(
byteOffset
+
1
)
?
2
:
1
;
}
assertValidOffset
();
}
/**
* Skips bits and moves current reading position forward.
* Skips bits and moves current reading position forward.
*
*
* @param n The number of bits to skip.
* @param n
umBits
The number of bits to skip.
*/
*/
public
void
skipBits
(
int
n
)
{
public
void
skipBits
(
int
n
umBits
)
{
int
oldByteOffset
=
byteOffset
;
int
oldByteOffset
=
byteOffset
;
byteOffset
+=
(
n
/
8
);
int
numBytes
=
numBits
/
8
;
bitOffset
+=
(
n
%
8
);
byteOffset
+=
numBytes
;
bitOffset
+=
numBits
-
(
numBytes
*
8
);
if
(
bitOffset
>
7
)
{
if
(
bitOffset
>
7
)
{
byteOffset
++;
byteOffset
++;
bitOffset
-=
8
;
bitOffset
-=
8
;
...
@@ -81,13 +93,14 @@ public final class ParsableNalUnitBitArray {
...
@@ -81,13 +93,14 @@ public final class ParsableNalUnitBitArray {
* Returns whether it's possible to read {@code n} bits starting from the current offset. The
* Returns whether it's possible to read {@code n} bits starting from the current offset. The
* offset is not modified.
* offset is not modified.
*
*
* @param n The number of bits.
* @param n
umBits
The number of bits.
* @return Whether it is possible to read {@code n} bits.
* @return Whether it is possible to read {@code n} bits.
*/
*/
public
boolean
canReadBits
(
int
n
)
{
public
boolean
canReadBits
(
int
n
umBits
)
{
int
oldByteOffset
=
byteOffset
;
int
oldByteOffset
=
byteOffset
;
int
newByteOffset
=
byteOffset
+
(
n
/
8
);
int
numBytes
=
numBits
/
8
;
int
newBitOffset
=
bitOffset
+
(
n
%
8
);
int
newByteOffset
=
byteOffset
+
numBytes
;
int
newBitOffset
=
bitOffset
+
numBits
-
(
numBytes
*
8
);
if
(
newBitOffset
>
7
)
{
if
(
newBitOffset
>
7
)
{
newByteOffset
++;
newByteOffset
++;
newBitOffset
-=
8
;
newBitOffset
-=
8
;
...
@@ -108,7 +121,9 @@ public final class ParsableNalUnitBitArray {
...
@@ -108,7 +121,9 @@ public final class ParsableNalUnitBitArray {
* @return Whether the bit is set.
* @return Whether the bit is set.
*/
*/
public
boolean
readBit
()
{
public
boolean
readBit
()
{
return
readBits
(
1
)
==
1
;
boolean
returnValue
=
(
data
[
byteOffset
]
&
(
0x80
>>
bitOffset
))
!=
0
;
skipBit
();
return
returnValue
;
}
}
/**
/**
...
@@ -118,50 +133,19 @@ public final class ParsableNalUnitBitArray {
...
@@ -118,50 +133,19 @@ public final class ParsableNalUnitBitArray {
* @return An integer whose bottom n bits hold the read data.
* @return An integer whose bottom n bits hold the read data.
*/
*/
public
int
readBits
(
int
numBits
)
{
public
int
readBits
(
int
numBits
)
{
if
(
numBits
==
0
)
{
return
0
;
}
int
returnValue
=
0
;
int
returnValue
=
0
;
bitOffset
+=
numBits
;
// Read as many whole bytes as we can.
while
(
bitOffset
>
8
)
{
int
wholeBytes
=
(
numBits
/
8
);
bitOffset
-=
8
;
for
(
int
i
=
0
;
i
<
wholeBytes
;
i
++)
{
returnValue
|=
(
data
[
byteOffset
]
&
0xFF
)
<<
bitOffset
;
int
nextByteOffset
=
shouldSkipByte
(
byteOffset
+
1
)
?
byteOffset
+
2
:
byteOffset
+
1
;
byteOffset
+=
shouldSkipByte
(
byteOffset
+
1
)
?
2
:
1
;
int
byteValue
;
if
(
bitOffset
!=
0
)
{
byteValue
=
((
data
[
byteOffset
]
&
0xFF
)
<<
bitOffset
)
|
((
data
[
nextByteOffset
]
&
0xFF
)
>>>
(
8
-
bitOffset
));
}
else
{
byteValue
=
data
[
byteOffset
];
}
numBits
-=
8
;
returnValue
|=
(
byteValue
&
0xFF
)
<<
numBits
;
byteOffset
=
nextByteOffset
;
}
}
returnValue
|=
(
data
[
byteOffset
]
&
0xFF
)
>>
8
-
bitOffset
;
// Read any remaining bits.
returnValue
&=
0xFFFFFFFF
>>>
(
32
-
numBits
);
if
(
numBits
>
0
)
{
if
(
bitOffset
==
8
)
{
int
nextBit
=
bitOffset
+
numBits
;
bitOffset
=
0
;
byte
writeMask
=
(
byte
)
(
0xFF
>>
(
8
-
numBits
));
byteOffset
+=
shouldSkipByte
(
byteOffset
+
1
)
?
2
:
1
;
int
nextByteOffset
=
shouldSkipByte
(
byteOffset
+
1
)
?
byteOffset
+
2
:
byteOffset
+
1
;
if
(
nextBit
>
8
)
{
// Combine bits from current byte and next byte.
returnValue
|=
((((
data
[
byteOffset
]
&
0xFF
)
<<
(
nextBit
-
8
)
|
((
data
[
nextByteOffset
]
&
0xFF
)
>>
(
16
-
nextBit
)))
&
writeMask
));
byteOffset
=
nextByteOffset
;
}
else
{
// Bits to be read only within current byte.
returnValue
|=
(((
data
[
byteOffset
]
&
0xFF
)
>>
(
8
-
nextBit
))
&
writeMask
);
if
(
nextBit
==
8
)
{
byteOffset
=
nextByteOffset
;
}
}
bitOffset
=
nextBit
%
8
;
}
}
assertValidOffset
();
assertValidOffset
();
return
returnValue
;
return
returnValue
;
}
}
...
@@ -220,7 +204,6 @@ public final class ParsableNalUnitBitArray {
...
@@ -220,7 +204,6 @@ public final class ParsableNalUnitBitArray {
private
void
assertValidOffset
()
{
private
void
assertValidOffset
()
{
// It is fine for position to be at the end of the array, but no further.
// It is fine for position to be at the end of the array, but no further.
Assertions
.
checkState
(
byteOffset
>=
0
Assertions
.
checkState
(
byteOffset
>=
0
&&
(
bitOffset
>=
0
&&
bitOffset
<
8
)
&&
(
byteOffset
<
byteLimit
||
(
byteOffset
==
byteLimit
&&
bitOffset
==
0
)));
&&
(
byteOffset
<
byteLimit
||
(
byteOffset
==
byteLimit
&&
bitOffset
==
0
)));
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
cbffc14f
...
@@ -578,9 +578,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -578,9 +578,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
private
void
maybeNotifyVideoSizeChanged
()
{
private
void
maybeNotifyVideoSizeChanged
()
{
if
(
reportedWidth
!=
currentWidth
||
reportedHeight
!=
currentHeight
if
((
currentWidth
!=
Format
.
NO_VALUE
||
currentHeight
!=
Format
.
NO_VALUE
)
&&
(
reportedWidth
!=
currentWidth
||
reportedHeight
!=
currentHeight
||
reportedUnappliedRotationDegrees
!=
currentUnappliedRotationDegrees
||
reportedUnappliedRotationDegrees
!=
currentUnappliedRotationDegrees
||
reportedPixelWidthHeightRatio
!=
currentPixelWidthHeightRatio
)
{
||
reportedPixelWidthHeightRatio
!=
currentPixelWidthHeightRatio
)
)
{
eventDispatcher
.
videoSizeChanged
(
currentWidth
,
currentHeight
,
currentUnappliedRotationDegrees
,
eventDispatcher
.
videoSizeChanged
(
currentWidth
,
currentHeight
,
currentUnappliedRotationDegrees
,
currentPixelWidthHeightRatio
);
currentPixelWidthHeightRatio
);
reportedWidth
=
currentWidth
;
reportedWidth
=
currentWidth
;
...
@@ -592,8 +593,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -592,8 +593,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private
void
maybeRenotifyVideoSizeChanged
()
{
private
void
maybeRenotifyVideoSizeChanged
()
{
if
(
reportedWidth
!=
Format
.
NO_VALUE
||
reportedHeight
!=
Format
.
NO_VALUE
)
{
if
(
reportedWidth
!=
Format
.
NO_VALUE
||
reportedHeight
!=
Format
.
NO_VALUE
)
{
eventDispatcher
.
videoSizeChanged
(
currentWidth
,
currentHeight
,
currentUnappliedRotationDegrees
,
eventDispatcher
.
videoSizeChanged
(
reportedWidth
,
reportedHeight
,
current
PixelWidthHeightRatio
);
reportedUnappliedRotationDegrees
,
reported
PixelWidthHeightRatio
);
}
}
}
}
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java
View file @
cbffc14f
...
@@ -41,6 +41,38 @@ import java.util.List;
...
@@ -41,6 +41,38 @@ import java.util.List;
public
final
class
HlsPlaylistTracker
implements
Loader
.
Callback
<
ParsingLoadable
<
HlsPlaylist
>>
{
public
final
class
HlsPlaylistTracker
implements
Loader
.
Callback
<
ParsingLoadable
<
HlsPlaylist
>>
{
/**
/**
* Thrown when a playlist is considered to be stuck due to a server side error.
*/
public
static
final
class
PlaylistStuckException
extends
IOException
{
/**
* The url of the stuck playlist.
*/
public
final
String
url
;
private
PlaylistStuckException
(
String
url
)
{
this
.
url
=
url
;
}
}
/**
* Thrown when the media sequence of a new snapshot indicates the server has reset.
*/
public
static
final
class
PlaylistResetException
extends
IOException
{
/**
* The url of the reset playlist.
*/
public
final
String
url
;
private
PlaylistResetException
(
String
url
)
{
this
.
url
=
url
;
}
}
/**
* Listener for primary playlist changes.
* Listener for primary playlist changes.
*/
*/
public
interface
PrimaryPlaylistListener
{
public
interface
PrimaryPlaylistListener
{
...
@@ -76,6 +108,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -76,6 +108,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
}
}
/**
/**
* Coefficient applied on the target duration of a playlist to determine the amount of time after
* which an unchanging playlist is considered stuck.
*/
private
static
final
double
PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT
=
3.5
;
/**
* The minimum number of milliseconds that a url is kept as primary url, if no
* The minimum number of milliseconds that a url is kept as primary url, if no
* {@link #getPlaylistSnapshot} call is made for that url.
* {@link #getPlaylistSnapshot} call is made for that url.
*/
*/
...
@@ -213,14 +250,14 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -213,14 +250,14 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
}
}
/**
/**
* If the playlist is having trouble
loading the playlist referenced by the given {@link HlsUrl},
* If the playlist is having trouble
refreshing the playlist referenced by the given
* this method throws the underlying error.
*
{@link HlsUrl},
this method throws the underlying error.
*
*
* @param url The {@link HlsUrl}.
* @param url The {@link HlsUrl}.
* @throws IOException The underyling error.
* @throws IOException The underyling error.
*/
*/
public
void
maybeThrowPlaylistRefreshError
(
HlsUrl
url
)
throws
IOException
{
public
void
maybeThrowPlaylistRefreshError
(
HlsUrl
url
)
throws
IOException
{
playlistBundles
.
get
(
url
).
m
ediaPlaylistLoader
.
maybeThrow
Error
();
playlistBundles
.
get
(
url
).
m
aybeThrowPlaylistRefresh
Error
();
}
}
/**
/**
...
@@ -441,9 +478,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -441,9 +478,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
private
HlsMediaPlaylist
playlistSnapshot
;
private
HlsMediaPlaylist
playlistSnapshot
;
private
long
lastSnapshotLoadMs
;
private
long
lastSnapshotLoadMs
;
private
long
lastSnapshotChangeMs
;
private
long
lastSnapshotAccessTimeMs
;
private
long
lastSnapshotAccessTimeMs
;
private
long
blacklistUntilMs
;
private
long
blacklistUntilMs
;
private
boolean
pendingRefresh
;
private
boolean
pendingRefresh
;
private
IOException
playlistError
;
public
MediaPlaylistBundle
(
HlsUrl
playlistUrl
,
long
initialLastSnapshotAccessTimeMs
)
{
public
MediaPlaylistBundle
(
HlsUrl
playlistUrl
,
long
initialLastSnapshotAccessTimeMs
)
{
this
.
playlistUrl
=
playlistUrl
;
this
.
playlistUrl
=
playlistUrl
;
...
@@ -483,6 +522,13 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -483,6 +522,13 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
}
}
}
}
public
void
maybeThrowPlaylistRefreshError
()
throws
IOException
{
mediaPlaylistLoader
.
maybeThrowError
();
if
(
playlistError
!=
null
)
{
throw
playlistError
;
}
}
// Loader.Callback implementation.
// Loader.Callback implementation.
@Override
@Override
...
@@ -494,8 +540,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -494,8 +540,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
eventDispatcher
.
loadCompleted
(
loadable
.
dataSpec
,
C
.
DATA_TYPE_MANIFEST
,
elapsedRealtimeMs
,
eventDispatcher
.
loadCompleted
(
loadable
.
dataSpec
,
C
.
DATA_TYPE_MANIFEST
,
elapsedRealtimeMs
,
loadDurationMs
,
loadable
.
bytesLoaded
());
loadDurationMs
,
loadable
.
bytesLoaded
());
}
else
{
}
else
{
onLoadError
(
loadable
,
elapsedRealtimeMs
,
loadDurationMs
,
playlistError
=
new
ParserException
(
"Loaded playlist has unexpected type."
);
new
ParserException
(
"Loaded playlist has unexpected type."
));
}
}
}
}
...
@@ -517,10 +562,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -517,10 +562,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
}
}
boolean
shouldRetry
=
true
;
boolean
shouldRetry
=
true
;
if
(
ChunkedTrackBlacklistUtil
.
shouldBlacklist
(
error
))
{
if
(
ChunkedTrackBlacklistUtil
.
shouldBlacklist
(
error
))
{
blacklistUntilMs
=
blacklistPlaylist
();
SystemClock
.
elapsedRealtime
()
+
ChunkedTrackBlacklistUtil
.
DEFAULT_TRACK_BLACKLIST_MS
;
notifyPlaylistBlacklisting
(
playlistUrl
,
ChunkedTrackBlacklistUtil
.
DEFAULT_TRACK_BLACKLIST_MS
);
shouldRetry
=
primaryHlsUrl
==
playlistUrl
&&
!
maybeSelectNewPrimaryUrl
();
shouldRetry
=
primaryHlsUrl
==
playlistUrl
&&
!
maybeSelectNewPrimaryUrl
();
}
}
return
shouldRetry
?
Loader
.
RETRY
:
Loader
.
DONT_RETRY
;
return
shouldRetry
?
Loader
.
RETRY
:
Loader
.
DONT_RETRY
;
...
@@ -538,14 +580,28 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -538,14 +580,28 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
private
void
processLoadedPlaylist
(
HlsMediaPlaylist
loadedPlaylist
)
{
private
void
processLoadedPlaylist
(
HlsMediaPlaylist
loadedPlaylist
)
{
HlsMediaPlaylist
oldPlaylist
=
playlistSnapshot
;
HlsMediaPlaylist
oldPlaylist
=
playlistSnapshot
;
lastSnapshotLoadMs
=
SystemClock
.
elapsedRealtime
();
long
currentTimeMs
=
SystemClock
.
elapsedRealtime
();
lastSnapshotLoadMs
=
currentTimeMs
;
playlistSnapshot
=
getLatestPlaylistSnapshot
(
oldPlaylist
,
loadedPlaylist
);
playlistSnapshot
=
getLatestPlaylistSnapshot
(
oldPlaylist
,
loadedPlaylist
);
long
refreshDelayUs
=
C
.
TIME_UNSET
;
long
refreshDelayUs
=
C
.
TIME_UNSET
;
if
(
playlistSnapshot
!=
oldPlaylist
)
{
if
(
playlistSnapshot
!=
oldPlaylist
)
{
playlistError
=
null
;
lastSnapshotChangeMs
=
currentTimeMs
;
if
(
onPlaylistUpdated
(
playlistUrl
,
playlistSnapshot
))
{
if
(
onPlaylistUpdated
(
playlistUrl
,
playlistSnapshot
))
{
refreshDelayUs
=
playlistSnapshot
.
targetDurationUs
;
refreshDelayUs
=
playlistSnapshot
.
targetDurationUs
;
}
}
}
else
if
(!
playlistSnapshot
.
hasEndTag
)
{
}
else
if
(!
playlistSnapshot
.
hasEndTag
)
{
if
(
currentTimeMs
-
lastSnapshotChangeMs
>
C
.
usToMs
(
playlistSnapshot
.
targetDurationUs
)
*
PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT
)
{
// The playlist seems to be stuck, we blacklist it.
playlistError
=
new
PlaylistStuckException
(
playlistUrl
.
url
);
blacklistPlaylist
();
}
else
if
(
loadedPlaylist
.
mediaSequence
+
loadedPlaylist
.
segments
.
size
()
<
playlistSnapshot
.
mediaSequence
)
{
// The media sequence has jumped backwards. The server has likely reset.
playlistError
=
new
PlaylistResetException
(
playlistUrl
.
url
);
}
refreshDelayUs
=
playlistSnapshot
.
targetDurationUs
/
2
;
refreshDelayUs
=
playlistSnapshot
.
targetDurationUs
/
2
;
}
}
if
(
refreshDelayUs
!=
C
.
TIME_UNSET
)
{
if
(
refreshDelayUs
!=
C
.
TIME_UNSET
)
{
...
@@ -554,6 +610,12 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -554,6 +610,12 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
}
}
}
}
private
void
blacklistPlaylist
()
{
blacklistUntilMs
=
SystemClock
.
elapsedRealtime
()
+
ChunkedTrackBlacklistUtil
.
DEFAULT_TRACK_BLACKLIST_MS
;
notifyPlaylistBlacklisting
(
playlistUrl
,
ChunkedTrackBlacklistUtil
.
DEFAULT_TRACK_BLACKLIST_MS
);
}
}
}
}
}
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
View file @
cbffc14f
...
@@ -712,7 +712,12 @@ public class PlaybackControlView extends FrameLayout {
...
@@ -712,7 +712,12 @@ public class PlaybackControlView extends FrameLayout {
if
(
fastForwardMs
<=
0
)
{
if
(
fastForwardMs
<=
0
)
{
return
;
return
;
}
}
seekTo
(
Math
.
min
(
player
.
getCurrentPosition
()
+
fastForwardMs
,
player
.
getDuration
()));
long
durationMs
=
player
.
getDuration
();
long
seekPositionMs
=
player
.
getCurrentPosition
()
+
fastForwardMs
;
if
(
durationMs
!=
C
.
TIME_UNSET
)
{
seekPositionMs
=
Math
.
min
(
seekPositionMs
,
durationMs
);
}
seekTo
(
seekPositionMs
);
}
}
private
void
seekTo
(
long
positionMs
)
{
private
void
seekTo
(
long
positionMs
)
{
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
View file @
cbffc14f
...
@@ -574,7 +574,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -574,7 +574,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
/**
/**
* Sets the rewind increment in milliseconds.
* Sets the rewind increment in milliseconds.
*
*
* @param rewindMs The rewind increment in milliseconds.
* @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
* rewind button to be disabled.
*/
*/
public
void
setRewindIncrementMs
(
int
rewindMs
)
{
public
void
setRewindIncrementMs
(
int
rewindMs
)
{
Assertions
.
checkState
(
controller
!=
null
);
Assertions
.
checkState
(
controller
!=
null
);
...
@@ -584,7 +585,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -584,7 +585,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
/**
/**
* Sets the fast forward increment in milliseconds.
* Sets the fast forward increment in milliseconds.
*
*
* @param fastForwardMs The fast forward increment in milliseconds.
* @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
* cause the fast forward button to be disabled.
*/
*/
public
void
setFastForwardIncrementMs
(
int
fastForwardMs
)
{
public
void
setFastForwardIncrementMs
(
int
fastForwardMs
)
{
Assertions
.
checkState
(
controller
!=
null
);
Assertions
.
checkState
(
controller
!=
null
);
...
...
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