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
0c8f3c72
authored
Oct 27, 2016
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge branch 'dev-v2' into dev-v2-id3
parents
8caaf0b5
8a89abcb
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
668 additions
and
376 deletions
demo/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java
demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java
extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java
extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java
library/src/androidTest/assets/ts/sample_with_sdt.ts
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
library/src/main/java/com/google/android/exoplayer2/DefaultLoadControl.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
library/src/main/java/com/google/android/exoplayer2/LoadControl.java
library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionPayloadReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java
library/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java
library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
library/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java
library/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelections.java → library/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionArray.java
library/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java
library/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java
library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
library/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java
library/src/main/res/layout/exo_playback_control_view.xml
library/src/main/res/layout/exo_simple_player_view.xml
library/src/main/res/values/attrs.xml
library/src/main/res/values/ids.xml
library/src/main/res/values/styles.xml
playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java
playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/util/ExoHostedTest.java
demo/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java
View file @
0c8f3c72
...
...
@@ -40,10 +40,10 @@ import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import
com.google.android.exoplayer2.source.ExtractorMediaSource
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelections
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.video.VideoRendererEventListener
;
import
java.io.IOException
;
...
...
@@ -56,7 +56,7 @@ import java.util.Locale;
/* package */
final
class
EventLogger
implements
ExoPlayer
.
EventListener
,
AudioRendererEventListener
,
VideoRendererEventListener
,
AdaptiveMediaSourceEventListener
,
ExtractorMediaSource
.
EventListener
,
StreamingDrmSessionManager
.
EventListener
,
TrackSelector
.
EventListener
<
MappedTrackInfo
>,
MetadataRenderer
.
Output
{
MetadataRenderer
.
Output
{
private
static
final
String
TAG
=
"EventLogger"
;
private
static
final
int
MAX_TIMELINE_ITEM_LINES
=
3
;
...
...
@@ -68,11 +68,13 @@ import java.util.Locale;
TIME_FORMAT
.
setGroupingUsed
(
false
);
}
private
final
MappingTrackSelector
trackSelector
;
private
final
Timeline
.
Window
window
;
private
final
Timeline
.
Period
period
;
private
final
long
startTimeMs
;
public
EventLogger
()
{
public
EventLogger
(
MappingTrackSelector
trackSelector
)
{
this
.
trackSelector
=
trackSelector
;
window
=
new
Timeline
.
Window
();
period
=
new
Timeline
.
Period
();
startTimeMs
=
SystemClock
.
elapsedRealtime
();
...
...
@@ -127,27 +129,29 @@ import java.util.Locale;
Log
.
e
(
TAG
,
"playerFailed ["
+
getSessionTimeString
()
+
"]"
,
e
);
}
// MappingTrackSelector.EventListener
@Override
public
void
onTrackSelectionsChanged
(
TrackSelections
<?
extends
MappedTrackInfo
>
trackSelections
)
{
public
void
onTracksChanged
(
TrackGroupArray
ignored
,
TrackSelectionArray
trackSelections
)
{
MappedTrackInfo
mappedTrackInfo
=
trackSelector
.
getCurrentMappedTrackInfo
();
if
(
mappedTrackInfo
==
null
)
{
Log
.
d
(
TAG
,
"Tracks []"
);
return
;
}
Log
.
d
(
TAG
,
"Tracks ["
);
// Log tracks associated to renderers.
MappedTrackInfo
info
=
trackSelections
.
info
;
for
(
int
rendererIndex
=
0
;
rendererIndex
<
trackSelections
.
length
;
rendererIndex
++)
{
TrackGroupArray
trackGroups
=
info
.
getTrackGroups
(
rendererIndex
);
for
(
int
rendererIndex
=
0
;
rendererIndex
<
mappedTrackInfo
.
length
;
rendererIndex
++)
{
TrackGroupArray
rendererTrackGroups
=
mappedTrackInfo
.
getTrackGroups
(
rendererIndex
);
TrackSelection
trackSelection
=
trackSelections
.
get
(
rendererIndex
);
if
(
t
rackGroups
.
length
>
0
)
{
if
(
rendererT
rackGroups
.
length
>
0
)
{
Log
.
d
(
TAG
,
" Renderer:"
+
rendererIndex
+
" ["
);
for
(
int
groupIndex
=
0
;
groupIndex
<
t
rackGroups
.
length
;
groupIndex
++)
{
TrackGroup
trackGroup
=
t
rackGroups
.
get
(
groupIndex
);
String
adaptiveSupport
=
getAdaptiveSupportString
(
trackGroup
.
length
,
i
nfo
.
getAdaptiveSupport
(
rendererIndex
,
groupIndex
,
false
));
for
(
int
groupIndex
=
0
;
groupIndex
<
rendererT
rackGroups
.
length
;
groupIndex
++)
{
TrackGroup
trackGroup
=
rendererT
rackGroups
.
get
(
groupIndex
);
String
adaptiveSupport
=
getAdaptiveSupportString
(
trackGroup
.
length
,
mappedTrackI
nfo
.
getAdaptiveSupport
(
rendererIndex
,
groupIndex
,
false
));
Log
.
d
(
TAG
,
" Group:"
+
groupIndex
+
", adaptive_supported="
+
adaptiveSupport
+
" ["
);
for
(
int
trackIndex
=
0
;
trackIndex
<
trackGroup
.
length
;
trackIndex
++)
{
String
status
=
getTrackStatusString
(
trackSelection
,
trackGroup
,
trackIndex
);
String
formatSupport
=
getFormatSupportString
(
i
nfo
.
getTrackFormatSupport
(
rendererIndex
,
groupIndex
,
trackIndex
));
mappedTrackI
nfo
.
getTrackFormatSupport
(
rendererIndex
,
groupIndex
,
trackIndex
));
Log
.
d
(
TAG
,
" "
+
status
+
" Track:"
+
trackIndex
+
", "
+
getFormatString
(
trackGroup
.
getFormat
(
trackIndex
))
+
", supported="
+
formatSupport
);
...
...
@@ -170,12 +174,12 @@ import java.util.Locale;
}
}
// Log tracks not associated with a renderer.
TrackGroupArray
trackGroups
=
i
nfo
.
getUnassociatedTrackGroups
();
if
(
t
rackGroups
.
length
>
0
)
{
TrackGroupArray
unassociatedTrackGroups
=
mappedTrackI
nfo
.
getUnassociatedTrackGroups
();
if
(
unassociatedT
rackGroups
.
length
>
0
)
{
Log
.
d
(
TAG
,
" Renderer:None ["
);
for
(
int
groupIndex
=
0
;
groupIndex
<
t
rackGroups
.
length
;
groupIndex
++)
{
for
(
int
groupIndex
=
0
;
groupIndex
<
unassociatedT
rackGroups
.
length
;
groupIndex
++)
{
Log
.
d
(
TAG
,
" Group:"
+
groupIndex
+
" ["
);
TrackGroup
trackGroup
=
t
rackGroups
.
get
(
groupIndex
);
TrackGroup
trackGroup
=
unassociatedT
rackGroups
.
get
(
groupIndex
);
for
(
int
trackIndex
=
0
;
trackIndex
<
trackGroup
.
length
;
trackIndex
++)
{
String
status
=
getTrackStatusString
(
false
);
String
formatSupport
=
getFormatSupportString
(
...
...
demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
View file @
0c8f3c72
...
...
@@ -58,8 +58,7 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelections
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.ui.DebugTextViewHelper
;
import
com.google.android.exoplayer2.ui.PlaybackControlView
;
import
com.google.android.exoplayer2.ui.SimpleExoPlayerView
;
...
...
@@ -78,7 +77,7 @@ import java.util.UUID;
* An activity that plays media using {@link SimpleExoPlayer}.
*/
public
class
PlayerActivity
extends
Activity
implements
OnClickListener
,
ExoPlayer
.
EventListener
,
TrackSelector
.
EventListener
<
MappedTrackInfo
>,
PlaybackControlView
.
VisibilityListener
{
PlaybackControlView
.
VisibilityListener
{
public
static
final
String
DRM_SCHEME_UUID_EXTRA
=
"drm_scheme_uuid"
;
public
static
final
String
DRM_LICENSE_URL
=
"drm_license_url"
;
...
...
@@ -203,8 +202,11 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
if
(
view
==
retryButton
)
{
initializePlayer
();
}
else
if
(
view
.
getParent
()
==
debugRootView
)
{
trackSelectionHelper
.
showSelectionDialog
(
this
,
((
Button
)
view
).
getText
(),
trackSelector
.
getCurrentSelections
().
info
,
(
int
)
view
.
getTag
());
MappedTrackInfo
mappedTrackInfo
=
trackSelector
.
getCurrentMappedTrackInfo
();
if
(
mappedTrackInfo
!=
null
)
{
trackSelectionHelper
.
showSelectionDialog
(
this
,
((
Button
)
view
).
getText
(),
trackSelector
.
getCurrentMappedTrackInfo
(),
(
int
)
view
.
getTag
());
}
}
}
...
...
@@ -249,20 +251,20 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
}
eventLogger
=
new
EventLogger
();
TrackSelection
.
Factory
videoTrackSelectionFactory
=
new
AdaptiveVideoTrackSelection
.
Factory
(
BANDWIDTH_METER
);
trackSelector
=
new
DefaultTrackSelector
(
mainHandler
,
videoTrackSelectionFactory
);
trackSelector
.
addListener
(
this
);
trackSelector
.
addListener
(
eventLogger
);
trackSelector
=
new
DefaultTrackSelector
(
videoTrackSelectionFactory
);
trackSelectionHelper
=
new
TrackSelectionHelper
(
trackSelector
,
videoTrackSelectionFactory
);
player
=
ExoPlayerFactory
.
newSimpleInstance
(
this
,
trackSelector
,
new
DefaultLoadControl
(),
drmSessionManager
,
preferExtensionDecoders
);
player
.
addListener
(
this
);
eventLogger
=
new
EventLogger
(
trackSelector
);
player
.
addListener
(
eventLogger
);
player
.
setAudioDebugListener
(
eventLogger
);
player
.
setVideoDebugListener
(
eventLogger
);
player
.
setId3Output
(
eventLogger
);
simpleExoPlayerView
.
setPlayer
(
player
);
if
(
isTimelineStatic
)
{
if
(
playerPosition
==
C
.
TIME_UNSET
)
{
...
...
@@ -447,17 +449,17 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
showControls
();
}
// MappingTrackSelector.EventListener implementation
@Override
public
void
onTrack
SelectionsChanged
(
TrackSelections
<?
extends
MappedTrackInfo
>
trackSelections
)
{
public
void
onTrack
sChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
)
{
updateButtonVisibilities
();
MappedTrackInfo
trackInfo
=
trackSelections
.
info
;
if
(
trackInfo
.
hasOnlyUnplayableTracks
(
C
.
TRACK_TYPE_VIDEO
))
{
showToast
(
R
.
string
.
error_unsupported_video
);
}
if
(
trackInfo
.
hasOnlyUnplayableTracks
(
C
.
TRACK_TYPE_AUDIO
))
{
showToast
(
R
.
string
.
error_unsupported_audio
);
MappedTrackInfo
mappedTrackInfo
=
trackSelector
.
getCurrentMappedTrackInfo
();
if
(
mappedTrackInfo
!=
null
)
{
if
(
mappedTrackInfo
.
hasOnlyUnplayableTracks
(
C
.
TRACK_TYPE_VIDEO
))
{
showToast
(
R
.
string
.
error_unsupported_video
);
}
if
(
mappedTrackInfo
.
hasOnlyUnplayableTracks
(
C
.
TRACK_TYPE_AUDIO
))
{
showToast
(
R
.
string
.
error_unsupported_audio
);
}
}
}
...
...
@@ -473,14 +475,13 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
return
;
}
TrackSelections
<
MappedTrackInfo
>
trackSelections
=
trackSelector
.
getCurrentSelections
();
if
(
trackSelections
==
null
)
{
MappedTrackInfo
mappedTrackInfo
=
trackSelector
.
getCurrentMappedTrackInfo
();
if
(
mappedTrackInfo
==
null
)
{
return
;
}
int
rendererCount
=
trackSelections
.
length
;
for
(
int
i
=
0
;
i
<
rendererCount
;
i
++)
{
TrackGroupArray
trackGroups
=
trackSelections
.
info
.
getTrackGroups
(
i
);
for
(
int
i
=
0
;
i
<
mappedTrackInfo
.
length
;
i
++)
{
TrackGroupArray
trackGroups
=
mappedTrackInfo
.
getTrackGroups
(
i
);
if
(
trackGroups
.
length
!=
0
)
{
Button
button
=
new
Button
(
this
);
int
label
;
...
...
extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java
View file @
0c8f3c72
...
...
@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.ext.flac;
import
android.content.Context
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.test.InstrumentationTestCase
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
...
...
@@ -27,7 +26,9 @@ import com.google.android.exoplayer2.Renderer;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
;
import
com.google.android.exoplayer2.source.ExtractorMediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
;
/**
...
...
@@ -72,7 +73,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
public
void
run
()
{
Looper
.
prepare
();
LibflacAudioRenderer
audioRenderer
=
new
LibflacAudioRenderer
();
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
(
new
Handler
()
);
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
();
player
=
ExoPlayerFactory
.
newInstance
(
new
Renderer
[]
{
audioRenderer
},
trackSelector
);
player
.
addListener
(
this
);
ExtractorMediaSource
mediaSource
=
new
ExtractorMediaSource
(
...
...
@@ -92,6 +93,11 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
)
{
// Do nothing.
}
@Override
public
void
onPositionDiscontinuity
()
{
// Do nothing.
}
...
...
extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java
View file @
0c8f3c72
...
...
@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.ext.opus;
import
android.content.Context
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.test.InstrumentationTestCase
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
...
...
@@ -27,7 +26,9 @@ import com.google.android.exoplayer2.Renderer;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
;
import
com.google.android.exoplayer2.source.ExtractorMediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
;
/**
...
...
@@ -72,7 +73,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
public
void
run
()
{
Looper
.
prepare
();
LibopusAudioRenderer
audioRenderer
=
new
LibopusAudioRenderer
();
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
(
new
Handler
()
);
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
();
player
=
ExoPlayerFactory
.
newInstance
(
new
Renderer
[]
{
audioRenderer
},
trackSelector
);
player
.
addListener
(
this
);
ExtractorMediaSource
mediaSource
=
new
ExtractorMediaSource
(
...
...
@@ -92,6 +93,11 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
)
{
// Do nothing.
}
@Override
public
void
onPositionDiscontinuity
()
{
// Do nothing.
}
...
...
extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java
View file @
0c8f3c72
...
...
@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.ext.vp9;
import
android.content.Context
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.test.InstrumentationTestCase
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
...
...
@@ -27,7 +26,9 @@ import com.google.android.exoplayer2.Renderer;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
;
import
com.google.android.exoplayer2.source.ExtractorMediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
;
/**
...
...
@@ -88,7 +89,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
public
void
run
()
{
Looper
.
prepare
();
LibvpxVideoRenderer
videoRenderer
=
new
LibvpxVideoRenderer
(
true
,
0
);
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
(
new
Handler
()
);
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
();
player
=
ExoPlayerFactory
.
newInstance
(
new
Renderer
[]
{
videoRenderer
},
trackSelector
);
player
.
addListener
(
this
);
ExtractorMediaSource
mediaSource
=
new
ExtractorMediaSource
(
...
...
@@ -111,6 +112,11 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
)
{
// Do nothing.
}
@Override
public
void
onPositionDiscontinuity
()
{
// Do nothing.
}
...
...
library/src/androidTest/assets/ts/sample_with_sdt.ts
0 → 100644
View file @
0c8f3c72
No preview for this file type
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
View file @
0c8f3c72
...
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
android.test.InstrumentationTestCase
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
...
...
@@ -73,7 +74,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
}
public
void
testCustomPesReader
()
throws
Exception
{
Custom
EsReaderFactory
factory
=
new
CustomEsReaderFactory
(
);
Custom
TsPayloadReaderFactory
factory
=
new
CustomTsPayloadReaderFactory
(
true
,
false
);
TsExtractor
tsExtractor
=
new
TsExtractor
(
new
TimestampAdjuster
(
0
),
factory
,
false
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample.ts"
))
...
...
@@ -82,13 +83,12 @@ public final class TsExtractorTest extends InstrumentationTestCase {
.
setSimulatePartialReads
(
false
).
build
();
FakeExtractorOutput
output
=
new
FakeExtractorOutput
();
tsExtractor
.
init
(
output
);
tsExtractor
.
seek
(
input
.
getPosition
());
PositionHolder
seekPositionHolder
=
new
PositionHolder
();
int
readResult
=
Extractor
.
RESULT_CONTINUE
;
while
(
readResult
!=
Extractor
.
RESULT_END_OF_INPUT
)
{
readResult
=
tsExtractor
.
read
(
input
,
seekPositionHolder
);
}
CustomEsReader
reader
=
factory
.
r
eader
;
CustomEsReader
reader
=
factory
.
esR
eader
;
assertEquals
(
2
,
reader
.
packetsRead
);
TrackOutput
trackOutput
=
reader
.
getTrackOutput
();
assertTrue
(
trackOutput
==
output
.
trackOutputs
.
get
(
257
/* PID of audio track. */
));
...
...
@@ -97,6 +97,23 @@ public final class TsExtractorTest extends InstrumentationTestCase {
((
FakeTrackOutput
)
trackOutput
).
format
);
}
public
void
testCustomInitialSectionReader
()
throws
Exception
{
CustomTsPayloadReaderFactory
factory
=
new
CustomTsPayloadReaderFactory
(
false
,
true
);
TsExtractor
tsExtractor
=
new
TsExtractor
(
new
TimestampAdjuster
(
0
),
factory
,
false
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample_with_sdt.ts"
))
.
setSimulateIOErrors
(
false
)
.
setSimulateUnknownLength
(
false
)
.
setSimulatePartialReads
(
false
).
build
();
tsExtractor
.
init
(
new
FakeExtractorOutput
());
PositionHolder
seekPositionHolder
=
new
PositionHolder
();
int
readResult
=
Extractor
.
RESULT_CONTINUE
;
while
(
readResult
!=
Extractor
.
RESULT_END_OF_INPUT
)
{
readResult
=
tsExtractor
.
read
(
input
,
seekPositionHolder
);
}
assertEquals
(
1
,
factory
.
sdtReader
.
consumedSdts
);
}
private
static
void
writeJunkData
(
ByteArrayOutputStream
out
,
int
length
)
throws
IOException
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
if
(((
byte
)
i
)
==
TS_SYNC_BYTE
)
{
...
...
@@ -107,6 +124,45 @@ public final class TsExtractorTest extends InstrumentationTestCase {
}
}
private
static
final
class
CustomTsPayloadReaderFactory
implements
TsPayloadReader
.
Factory
{
private
final
boolean
provideSdtReader
;
private
final
boolean
provideCustomEsReader
;
private
final
TsPayloadReader
.
Factory
defaultFactory
;
private
CustomEsReader
esReader
;
private
SdtSectionReader
sdtReader
;
public
CustomTsPayloadReaderFactory
(
boolean
provideCustomEsReader
,
boolean
provideSdtReader
)
{
this
.
provideCustomEsReader
=
provideCustomEsReader
;
this
.
provideSdtReader
=
provideSdtReader
;
defaultFactory
=
new
DefaultTsPayloadReaderFactory
();
}
@Override
public
SparseArray
<
TsPayloadReader
>
createInitialPayloadReaders
()
{
if
(
provideSdtReader
)
{
assertNull
(
sdtReader
);
SparseArray
<
TsPayloadReader
>
mapping
=
new
SparseArray
<>();
sdtReader
=
new
SdtSectionReader
();
mapping
.
put
(
17
,
new
SectionReader
(
sdtReader
));
return
mapping
;
}
else
{
return
defaultFactory
.
createInitialPayloadReaders
();
}
}
@Override
public
TsPayloadReader
createPayloadReader
(
int
streamType
,
EsInfo
esInfo
)
{
if
(
provideCustomEsReader
&&
streamType
==
3
)
{
esReader
=
new
CustomEsReader
(
esInfo
.
language
);
return
new
PesReader
(
esReader
);
}
else
{
return
defaultFactory
.
createPayloadReader
(
streamType
,
esInfo
);
}
}
}
private
static
final
class
CustomEsReader
implements
ElementaryStreamReader
{
private
final
String
language
;
...
...
@@ -147,23 +203,44 @@ public final class TsExtractorTest extends InstrumentationTestCase {
}
private
static
final
class
CustomEsReaderFactory
implements
TsPayloadReader
.
Factory
{
private
static
final
class
SdtSectionReader
implements
SectionPayloadReader
{
private
final
TsPayloadReader
.
Factory
defaultFactory
;
private
CustomEsReader
reader
;
private
int
consumedSdts
;
public
CustomEsReaderFactory
()
{
defaultFactory
=
new
DefaultTsPayloadReaderFactory
();
@Override
public
void
init
(
TimestampAdjuster
timestampAdjuster
,
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
// Do nothing.
}
@Override
public
TsPayloadReader
createPayloadReader
(
int
streamType
,
EsInfo
esInfo
)
{
if
(
streamType
==
3
)
{
reader
=
new
CustomEsReader
(
esInfo
.
language
);
return
new
PesReader
(
reader
);
}
else
{
return
defaultFactory
.
createPayloadReader
(
streamType
,
esInfo
);
public
void
consume
(
ParsableByteArray
sectionData
)
{
// table_id(8), section_syntax_indicator(1), reserved_future_use(1), reserved(2),
// section_length(12), transport_stream_id(16), reserved(2), version_number(5),
// current_next_indicator(1), section_number(8), last_section_number(8),
// original_network_id(16), reserved_future_use(8)
sectionData
.
skipBytes
(
11
);
// Start of the service loop.
assertEquals
(
0x5566
/* arbitrary service id */
,
sectionData
.
readUnsignedShort
());
// reserved_future_use(6), EIT_schedule_flag(1), EIT_present_following_flag(1)
sectionData
.
skipBytes
(
1
);
// Assert there is only one service.
// Remove running_status(3), free_CA_mode(1) from the descriptors_loop_length with the mask.
assertEquals
(
sectionData
.
readUnsignedShort
()
&
0xFFF
,
sectionData
.
bytesLeft
());
while
(
sectionData
.
bytesLeft
()
>
0
)
{
int
descriptorTag
=
sectionData
.
readUnsignedByte
();
int
descriptorLength
=
sectionData
.
readUnsignedByte
();
if
(
descriptorTag
==
72
/* service descriptor */
)
{
assertEquals
(
1
,
sectionData
.
readUnsignedByte
());
// Service type: Digital TV.
int
serviceProviderNameLength
=
sectionData
.
readUnsignedByte
();
assertEquals
(
"Some provider"
,
sectionData
.
readString
(
serviceProviderNameLength
));
int
serviceNameLength
=
sectionData
.
readUnsignedByte
();
assertEquals
(
"Some Channel"
,
sectionData
.
readString
(
serviceNameLength
));
}
else
{
sectionData
.
skipBytes
(
descriptorLength
);
}
}
consumedSdts
++;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/DefaultLoadControl.java
View file @
0c8f3c72
...
...
@@ -16,7 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
s
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
Array
;
import
com.google.android.exoplayer2.upstream.Allocator
;
import
com.google.android.exoplayer2.upstream.DefaultAllocator
;
import
com.google.android.exoplayer2.util.Util
;
...
...
@@ -111,7 +111,7 @@ public final class DefaultLoadControl implements LoadControl {
@Override
public
void
onTracksSelected
(
Renderer
[]
renderers
,
TrackGroupArray
trackGroups
,
TrackSelection
s
<?>
trackSelections
)
{
TrackSelection
Array
trackSelections
)
{
targetBufferSize
=
0
;
for
(
int
i
=
0
;
i
<
renderers
.
length
;
i
++)
{
if
(
trackSelections
.
get
(
i
)
!=
null
)
{
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java
View file @
0c8f3c72
...
...
@@ -22,11 +22,13 @@ import com.google.android.exoplayer2.source.ExtractorMediaSource;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.MergingMediaSource
;
import
com.google.android.exoplayer2.source.SingleSampleMediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.dash.DashMediaSource
;
import
com.google.android.exoplayer2.source.hls.HlsMediaSource
;
import
com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource
;
import
com.google.android.exoplayer2.text.TextRenderer
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.video.MediaCodecVideoRenderer
;
...
...
@@ -111,6 +113,15 @@ public interface ExoPlayer {
interface
EventListener
{
/**
* Called when the available or selected tracks change.
*
* @param trackGroups The available tracks. Never null, but may be of length zero.
* @param trackSelections The track selections for each {@link Renderer}. Never null and always
* of length {@link #getRendererCount()}, but may contain null elements.
*/
void
onTracksChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
);
/**
* Called when the player starts or stops loading the source.
*
* @param isLoading Whether the source is currently being loaded.
...
...
@@ -259,11 +270,11 @@ public interface ExoPlayer {
* @param resetPosition Whether the playback position should be reset to the default position in
* the first {@link Timeline.Window}. If false, playback will start from the position defined
* by {@link #getCurrentWindowIndex()} and {@link #getCurrentPosition()}.
* @param reset
Timeline Whether the timeline and manifest should be reset. Should be true unless
*
the player is being prepared to play the same media as it was playing previously (e.g. if
* playback failed and is being retried).
* @param reset
State Whether the timeline, manifest, tracks and track selections should be reset.
*
Should be true unless the player is being prepared to play the same media as it was playing
* p
reviously (e.g. if p
layback failed and is being retried).
*/
void
prepare
(
MediaSource
mediaSource
,
boolean
resetPosition
,
boolean
reset
Timelin
e
);
void
prepare
(
MediaSource
mediaSource
,
boolean
resetPosition
,
boolean
reset
Stat
e
);
/**
* Sets whether playback should proceed when {@link #getPlaybackState()} == {@link #STATE_READY}.
...
...
@@ -357,6 +368,30 @@ public interface ExoPlayer {
void
blockingSendMessages
(
ExoPlayerMessage
...
messages
);
/**
* Returns the number of renderers.
*/
int
getRendererCount
();
/**
* Returns the track type that the renderer at a given index handles.
*
* @see Renderer#getTrackType()
* @param index The index of the renderer.
* @return One of the {@code TRACK_TYPE_*} constants defined in {@link C}.
*/
int
getRendererType
(
int
index
);
/**
* Returns the available track groups.
*/
TrackGroupArray
getCurrentTrackGroups
();
/**
* Returns the current track selections for each renderer.
*/
TrackSelectionArray
getCurrentTrackSelections
();
/**
* Returns the current manifest. The type depends on the {@link MediaSource} passed to
* {@link #prepare}.
*/
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java
View file @
0c8f3c72
...
...
@@ -42,7 +42,7 @@ public final class ExoPlayerFactory {
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param loadControl The {@link LoadControl} that will be used by the instance.
*/
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
<?>
trackSelector
,
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
trackSelector
,
LoadControl
loadControl
)
{
return
newSimpleInstance
(
context
,
trackSelector
,
loadControl
,
null
);
}
...
...
@@ -57,7 +57,7 @@ public final class ExoPlayerFactory {
* @param drmSessionManager An optional {@link DrmSessionManager}. May be null if the instance
* will not be used for DRM protected playbacks.
*/
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
<?>
trackSelector
,
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
trackSelector
,
LoadControl
loadControl
,
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
)
{
return
newSimpleInstance
(
context
,
trackSelector
,
loadControl
,
drmSessionManager
,
false
);
}
...
...
@@ -75,7 +75,7 @@ public final class ExoPlayerFactory {
* available extensions over those defined in the core library. Note that extensions must be
* included in the application build for setting this flag to have any effect.
*/
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
<?>
trackSelector
,
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
trackSelector
,
LoadControl
loadControl
,
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
,
boolean
preferExtensionDecoders
)
{
return
newSimpleInstance
(
context
,
trackSelector
,
loadControl
,
drmSessionManager
,
...
...
@@ -97,7 +97,7 @@ public final class ExoPlayerFactory {
* @param allowedVideoJoiningTimeMs The maximum duration for which a video renderer can attempt to
* seamlessly join an ongoing playback.
*/
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
<?>
trackSelector
,
public
static
SimpleExoPlayer
newSimpleInstance
(
Context
context
,
TrackSelector
trackSelector
,
LoadControl
loadControl
,
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
,
boolean
preferExtensionDecoders
,
long
allowedVideoJoiningTimeMs
)
{
return
new
SimpleExoPlayer
(
context
,
trackSelector
,
loadControl
,
drmSessionManager
,
...
...
@@ -111,7 +111,7 @@ public final class ExoPlayerFactory {
* @param renderers The {@link Renderer}s that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
*/
public
static
ExoPlayer
newInstance
(
Renderer
[]
renderers
,
TrackSelector
<?>
trackSelector
)
{
public
static
ExoPlayer
newInstance
(
Renderer
[]
renderers
,
TrackSelector
trackSelector
)
{
return
newInstance
(
renderers
,
trackSelector
,
new
DefaultLoadControl
());
}
...
...
@@ -123,7 +123,7 @@ public final class ExoPlayerFactory {
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param loadControl The {@link LoadControl} that will be used by the instance.
*/
public
static
ExoPlayer
newInstance
(
Renderer
[]
renderers
,
TrackSelector
<?>
trackSelector
,
public
static
ExoPlayer
newInstance
(
Renderer
[]
renderers
,
TrackSelector
trackSelector
,
LoadControl
loadControl
)
{
return
new
ExoPlayerImpl
(
renderers
,
trackSelector
,
loadControl
);
}
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
View file @
0c8f3c72
...
...
@@ -22,7 +22,11 @@ import android.os.Message;
import
android.util.Log
;
import
android.util.Pair
;
import
com.google.android.exoplayer2.ExoPlayerImplInternal.PlaybackInfo
;
import
com.google.android.exoplayer2.ExoPlayerImplInternal.TrackInfo
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.util.concurrent.CopyOnWriteArraySet
;
...
...
@@ -34,12 +38,16 @@ import java.util.concurrent.CopyOnWriteArraySet;
private
static
final
String
TAG
=
"ExoPlayerImpl"
;
private
final
Renderer
[]
renderers
;
private
final
TrackSelector
trackSelector
;
private
final
TrackSelectionArray
emptyTrackSelections
;
private
final
Handler
eventHandler
;
private
final
ExoPlayerImplInternal
<?>
internalPlayer
;
private
final
ExoPlayerImplInternal
internalPlayer
;
private
final
CopyOnWriteArraySet
<
EventListener
>
listeners
;
private
final
Timeline
.
Window
window
;
private
final
Timeline
.
Period
period
;
private
boolean
tracksSelected
;
private
boolean
pendingInitialSeek
;
private
boolean
playWhenReady
;
private
int
playbackState
;
...
...
@@ -47,6 +55,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
private
boolean
isLoading
;
private
Timeline
timeline
;
private
Object
manifest
;
private
TrackGroupArray
trackGroups
;
private
TrackSelectionArray
trackSelections
;
// Playback information when there is no pending seek/set source operation.
private
PlaybackInfo
playbackInfo
;
...
...
@@ -63,16 +73,19 @@ import java.util.concurrent.CopyOnWriteArraySet;
* @param loadControl The {@link LoadControl} that will be used by the instance.
*/
@SuppressLint
(
"HandlerLeak"
)
public
ExoPlayerImpl
(
Renderer
[]
renderers
,
TrackSelector
<?>
trackSelector
,
LoadControl
loadControl
)
{
public
ExoPlayerImpl
(
Renderer
[]
renderers
,
TrackSelector
trackSelector
,
LoadControl
loadControl
)
{
Log
.
i
(
TAG
,
"Init "
+
ExoPlayerLibraryInfo
.
VERSION
);
Assertions
.
checkNotNull
(
renderers
);
Assertions
.
checkState
(
renderers
.
length
>
0
);
this
.
renderers
=
Assertions
.
checkNotNull
(
renderers
);
this
.
trackSelector
=
Assertions
.
checkNotNull
(
trackSelector
);
this
.
playWhenReady
=
false
;
this
.
playbackState
=
STATE_IDLE
;
this
.
listeners
=
new
CopyOnWriteArraySet
<>();
emptyTrackSelections
=
new
TrackSelectionArray
(
new
TrackSelection
[
renderers
.
length
]);
window
=
new
Timeline
.
Window
();
period
=
new
Timeline
.
Period
();
trackGroups
=
TrackGroupArray
.
EMPTY
;
trackSelections
=
emptyTrackSelections
;
eventHandler
=
new
Handler
()
{
@Override
public
void
handleMessage
(
Message
msg
)
{
...
...
@@ -80,8 +93,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
};
playbackInfo
=
new
ExoPlayerImplInternal
.
PlaybackInfo
(
0
,
0
);
internalPlayer
=
new
ExoPlayerImplInternal
<>(
renderers
,
trackSelector
,
loadControl
,
playWhenReady
,
eventHandler
,
playbackInfo
);
internalPlayer
=
new
ExoPlayerImplInternal
(
renderers
,
trackSelector
,
loadControl
,
playWhenReady
,
eventHandler
,
playbackInfo
);
}
@Override
...
...
@@ -105,12 +118,23 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
@Override
public
void
prepare
(
MediaSource
mediaSource
,
boolean
resetPosition
,
boolean
resetTimeline
)
{
if
(
resetTimeline
&&
(
timeline
!=
null
||
manifest
!=
null
))
{
timeline
=
null
;
manifest
=
null
;
for
(
EventListener
listener
:
listeners
)
{
listener
.
onTimelineChanged
(
null
,
null
);
public
void
prepare
(
MediaSource
mediaSource
,
boolean
resetPosition
,
boolean
resetState
)
{
if
(
resetState
)
{
if
(
timeline
!=
null
||
manifest
!=
null
)
{
timeline
=
null
;
manifest
=
null
;
for
(
EventListener
listener
:
listeners
)
{
listener
.
onTimelineChanged
(
null
,
null
);
}
}
if
(
tracksSelected
)
{
tracksSelected
=
false
;
trackGroups
=
TrackGroupArray
.
EMPTY
;
trackSelections
=
emptyTrackSelections
;
trackSelector
.
onSelectionActivated
(
null
);
for
(
EventListener
listener
:
listeners
)
{
listener
.
onTracksChanged
(
trackGroups
,
trackSelections
);
}
}
}
internalPlayer
.
prepare
(
mediaSource
,
resetPosition
);
...
...
@@ -267,6 +291,26 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
@Override
public
int
getRendererCount
()
{
return
renderers
.
length
;
}
@Override
public
int
getRendererType
(
int
index
)
{
return
renderers
[
index
].
getTrackType
();
}
@Override
public
TrackGroupArray
getCurrentTrackGroups
()
{
return
trackGroups
;
}
@Override
public
TrackSelectionArray
getCurrentTrackSelections
()
{
return
trackSelections
;
}
@Override
public
Timeline
getCurrentTimeline
()
{
return
timeline
;
}
...
...
@@ -293,6 +337,17 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
break
;
}
case
ExoPlayerImplInternal
.
MSG_TRACKS_CHANGED
:
{
TrackInfo
trackInfo
=
(
TrackInfo
)
msg
.
obj
;
tracksSelected
=
true
;
trackGroups
=
trackInfo
.
groups
;
trackSelections
=
trackInfo
.
selections
;
trackSelector
.
onSelectionActivated
(
trackInfo
.
info
);
for
(
EventListener
listener
:
listeners
)
{
listener
.
onTracksChanged
(
trackGroups
,
trackSelections
);
}
break
;
}
case
ExoPlayerImplInternal
.
MSG_SEEK_ACK
:
{
if
(--
pendingSeekAcks
==
0
)
{
playbackInfo
=
(
ExoPlayerImplInternal
.
PlaybackInfo
)
msg
.
obj
;
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
View file @
0c8f3c72
...
...
@@ -26,8 +26,9 @@ import com.google.android.exoplayer2.ExoPlayer.ExoPlayerMessage;
import
com.google.android.exoplayer2.source.MediaPeriod
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.SampleStream
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
s
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
Array
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.MediaClock
;
...
...
@@ -40,7 +41,7 @@ import java.io.IOException;
/**
* Implements the internal behavior of {@link ExoPlayerImpl}.
*/
/* package */
final
class
ExoPlayerImplInternal
<
T
>
implements
Handler
.
Callback
,
/* package */
final
class
ExoPlayerImplInternal
implements
Handler
.
Callback
,
MediaPeriod
.
Callback
,
TrackSelector
.
InvalidationListener
,
MediaSource
.
Listener
{
/**
...
...
@@ -64,15 +65,30 @@ import java.io.IOException;
}
public
static
final
class
TrackInfo
{
public
final
TrackGroupArray
groups
;
public
final
TrackSelectionArray
selections
;
public
final
Object
info
;
public
TrackInfo
(
TrackGroupArray
groups
,
TrackSelectionArray
selections
,
Object
info
)
{
this
.
groups
=
groups
;
this
.
selections
=
selections
;
this
.
info
=
info
;
}
}
private
static
final
String
TAG
=
"ExoPlayerImplInternal"
;
// External messages
public
static
final
int
MSG_STATE_CHANGED
=
1
;
public
static
final
int
MSG_LOADING_CHANGED
=
2
;
public
static
final
int
MSG_SEEK_ACK
=
3
;
public
static
final
int
MSG_POSITION_DISCONTINUITY
=
4
;
public
static
final
int
MSG_SOURCE_INFO_REFRESHED
=
5
;
public
static
final
int
MSG_ERROR
=
6
;
public
static
final
int
MSG_TRACKS_CHANGED
=
3
;
public
static
final
int
MSG_SEEK_ACK
=
4
;
public
static
final
int
MSG_POSITION_DISCONTINUITY
=
5
;
public
static
final
int
MSG_SOURCE_INFO_REFRESHED
=
6
;
public
static
final
int
MSG_ERROR
=
7
;
// Internal messages
private
static
final
int
MSG_PREPARE
=
0
;
...
...
@@ -100,7 +116,7 @@ import java.io.IOException;
private
final
Renderer
[]
renderers
;
private
final
RendererCapabilities
[]
rendererCapabilities
;
private
final
TrackSelector
<
T
>
trackSelector
;
private
final
TrackSelector
trackSelector
;
private
final
LoadControl
loadControl
;
private
final
StandaloneMediaClock
standaloneMediaClock
;
private
final
Handler
handler
;
...
...
@@ -128,13 +144,13 @@ import java.io.IOException;
private
boolean
isTimelineReady
;
private
boolean
isTimelineEnded
;
private
int
bufferAheadPeriodCount
;
private
MediaPeriodHolder
<
T
>
playingPeriodHolder
;
private
MediaPeriodHolder
<
T
>
readingPeriodHolder
;
private
MediaPeriodHolder
<
T
>
loadingPeriodHolder
;
private
MediaPeriodHolder
playingPeriodHolder
;
private
MediaPeriodHolder
readingPeriodHolder
;
private
MediaPeriodHolder
loadingPeriodHolder
;
private
Timeline
timeline
;
public
ExoPlayerImplInternal
(
Renderer
[]
renderers
,
TrackSelector
<
T
>
trackSelector
,
public
ExoPlayerImplInternal
(
Renderer
[]
renderers
,
TrackSelector
trackSelector
,
LoadControl
loadControl
,
boolean
playWhenReady
,
Handler
eventHandler
,
PlaybackInfo
playbackInfo
)
{
this
.
renderers
=
renderers
;
...
...
@@ -538,7 +554,7 @@ import java.io.IOException;
periodIndex
=
C
.
INDEX_UNSET
;
}
MediaPeriodHolder
<
T
>
newPlayingPeriodHolder
=
null
;
MediaPeriodHolder
newPlayingPeriodHolder
=
null
;
if
(
playingPeriodHolder
==
null
)
{
// We're still waiting for the first period to be prepared.
if
(
loadingPeriodHolder
!=
null
)
{
...
...
@@ -546,7 +562,7 @@ import java.io.IOException;
}
}
else
{
// Clear the timeline, but keep the requested period if it is already prepared.
MediaPeriodHolder
<
T
>
periodHolder
=
playingPeriodHolder
;
MediaPeriodHolder
periodHolder
=
playingPeriodHolder
;
while
(
periodHolder
!=
null
)
{
if
(
periodHolder
.
index
==
periodIndex
&&
periodHolder
.
prepared
)
{
newPlayingPeriodHolder
=
periodHolder
;
...
...
@@ -680,7 +696,7 @@ import java.io.IOException;
return
;
}
// Reselect tracks on each period in turn, until the selection changes.
MediaPeriodHolder
<
T
>
periodHolder
=
playingPeriodHolder
;
MediaPeriodHolder
periodHolder
=
playingPeriodHolder
;
boolean
selectionsChangedForReadPeriod
=
true
;
while
(
true
)
{
if
(
periodHolder
==
null
||
!
periodHolder
.
prepared
)
{
...
...
@@ -745,7 +761,7 @@ import java.io.IOException;
}
}
}
trackSelector
.
onSelectionActivated
(
playingPeriodHolder
.
trackSelections
);
eventHandler
.
obtainMessage
(
MSG_TRACKS_CHANGED
,
periodHolder
.
getTrackInfo
()).
sendToTarget
(
);
enableRenderers
(
rendererWasEnabledFlags
,
enabledRendererCount
);
}
else
{
// Release and re-prepare/buffer periods after the one whose selection changed.
...
...
@@ -817,11 +833,11 @@ import java.io.IOException;
playingPeriodHolder
.
setIndex
(
timeline
,
timeline
.
getWindow
(
period
.
windowIndex
,
window
),
index
);
MediaPeriodHolder
<
T
>
previousPeriodHolder
=
playingPeriodHolder
;
MediaPeriodHolder
previousPeriodHolder
=
playingPeriodHolder
;
boolean
seenReadingPeriod
=
false
;
bufferAheadPeriodCount
=
0
;
while
(
previousPeriodHolder
.
next
!=
null
)
{
MediaPeriodHolder
<
T
>
periodHolder
=
previousPeriodHolder
.
next
;
MediaPeriodHolder
periodHolder
=
previousPeriodHolder
.
next
;
index
++;
timeline
.
getPeriod
(
index
,
period
,
true
);
if
(!
periodHolder
.
uid
.
equals
(
period
.
uid
))
{
...
...
@@ -962,9 +978,8 @@ import java.io.IOException;
MediaPeriod
newMediaPeriod
=
mediaSource
.
createPeriod
(
newLoadingPeriodIndex
,
loadControl
.
getAllocator
(),
periodStartPositionUs
);
newMediaPeriod
.
prepare
(
this
);
MediaPeriodHolder
<
T
>
newPeriodHolder
=
new
MediaPeriodHolder
<>(
renderers
,
rendererCapabilities
,
trackSelector
,
mediaSource
,
newMediaPeriod
,
newPeriodUid
,
periodStartPositionUs
);
MediaPeriodHolder
newPeriodHolder
=
new
MediaPeriodHolder
(
renderers
,
rendererCapabilities
,
trackSelector
,
mediaSource
,
newMediaPeriod
,
newPeriodUid
,
periodStartPositionUs
);
timeline
.
getWindow
(
windowIndex
,
window
);
newPeriodHolder
.
setIndex
(
timeline
,
window
,
newLoadingPeriodIndex
);
if
(
loadingPeriodHolder
!=
null
)
{
...
...
@@ -1018,9 +1033,9 @@ import java.io.IOException;
}
}
if
(
readingPeriodHolder
.
next
!=
null
&&
readingPeriodHolder
.
next
.
prepared
)
{
TrackSelection
s
<
T
>
oldTrackSelections
=
readingPeriodHolder
.
trackSelections
;
TrackSelection
Array
oldTrackSelections
=
readingPeriodHolder
.
trackSelections
;
readingPeriodHolder
=
readingPeriodHolder
.
next
;
TrackSelection
s
<
T
>
newTrackSelections
=
readingPeriodHolder
.
trackSelections
;
TrackSelection
Array
newTrackSelections
=
readingPeriodHolder
.
trackSelections
;
for
(
int
i
=
0
;
i
<
renderers
.
length
;
i
++)
{
Renderer
renderer
=
renderers
[
i
];
TrackSelection
oldSelection
=
oldTrackSelections
.
get
(
i
);
...
...
@@ -1094,14 +1109,14 @@ import java.io.IOException;
}
}
private
void
releasePeriodHoldersFrom
(
MediaPeriodHolder
<
T
>
periodHolder
)
{
private
void
releasePeriodHoldersFrom
(
MediaPeriodHolder
periodHolder
)
{
while
(
periodHolder
!=
null
)
{
periodHolder
.
release
();
periodHolder
=
periodHolder
.
next
;
}
}
private
void
setPlayingPeriodHolder
(
MediaPeriodHolder
<
T
>
periodHolder
)
private
void
setPlayingPeriodHolder
(
MediaPeriodHolder
periodHolder
)
throws
ExoPlaybackException
{
int
enabledRendererCount
=
0
;
boolean
[]
rendererWasEnabledFlags
=
new
boolean
[
renderers
.
length
];
...
...
@@ -1125,7 +1140,7 @@ import java.io.IOException;
}
}
trackSelector
.
onSelectionActivated
(
periodHolder
.
trackSelections
);
eventHandler
.
obtainMessage
(
MSG_TRACKS_CHANGED
,
periodHolder
.
getTrackInfo
()).
sendToTarget
(
);
playingPeriodHolder
=
periodHolder
;
enableRenderers
(
rendererWasEnabledFlags
,
enabledRendererCount
);
}
...
...
@@ -1182,7 +1197,7 @@ import java.io.IOException;
/**
* Holds a {@link MediaPeriod} with information required to play it as part of a timeline.
*/
private
static
final
class
MediaPeriodHolder
<
T
>
{
private
static
final
class
MediaPeriodHolder
{
public
final
MediaPeriod
mediaPeriod
;
public
final
Object
uid
;
...
...
@@ -1196,19 +1211,21 @@ import java.io.IOException;
public
boolean
prepared
;
public
boolean
hasEnabledTracks
;
public
long
rendererPositionOffsetUs
;
public
MediaPeriodHolder
<
T
>
next
;
public
MediaPeriodHolder
next
;
public
boolean
needsContinueLoading
;
private
final
Renderer
[]
renderers
;
private
final
RendererCapabilities
[]
rendererCapabilities
;
private
final
TrackSelector
<
T
>
trackSelector
;
private
final
TrackSelector
trackSelector
;
private
final
MediaSource
mediaSource
;
private
TrackSelections
<
T
>
trackSelections
;
private
TrackSelections
<
T
>
periodTrackSelections
;
private
Object
trackSelectionsInfo
;
private
TrackGroupArray
trackGroups
;
private
TrackSelectionArray
trackSelections
;
private
TrackSelectionArray
periodTrackSelections
;
public
MediaPeriodHolder
(
Renderer
[]
renderers
,
RendererCapabilities
[]
rendererCapabilities
,
TrackSelector
<
T
>
trackSelector
,
MediaSource
mediaSource
,
MediaPeriod
mediaPeriod
,
TrackSelector
trackSelector
,
MediaSource
mediaSource
,
MediaPeriod
mediaPeriod
,
Object
uid
,
long
positionUs
)
{
this
.
renderers
=
renderers
;
this
.
rendererCapabilities
=
rendererCapabilities
;
...
...
@@ -1221,7 +1238,7 @@ import java.io.IOException;
startPositionUs
=
positionUs
;
}
public
void
setNext
(
MediaPeriodHolder
<
T
>
next
)
{
public
void
setNext
(
MediaPeriodHolder
next
)
{
this
.
next
=
next
;
}
...
...
@@ -1238,17 +1255,20 @@ import java.io.IOException;
public
void
handlePrepared
(
long
positionUs
,
LoadControl
loadControl
)
throws
ExoPlaybackException
{
prepared
=
true
;
trackGroups
=
mediaPeriod
.
getTrackGroups
();
selectTracks
();
startPositionUs
=
updatePeriodTrackSelection
(
positionUs
,
loadControl
,
false
);
}
public
boolean
selectTracks
()
throws
ExoPlaybackException
{
TrackSelections
<
T
>
newTrackSelections
=
trackSelector
.
selectTracks
(
rendererCapabilities
,
mediaPeriod
.
getTrackGroups
());
Pair
<
TrackSelectionArray
,
Object
>
selectorResult
=
trackSelector
.
selectTracks
(
rendererCapabilities
,
trackGroups
);
TrackSelectionArray
newTrackSelections
=
selectorResult
.
first
;
if
(
newTrackSelections
.
equals
(
periodTrackSelections
))
{
return
false
;
}
trackSelections
=
newTrackSelections
;
trackSelectionsInfo
=
selectorResult
.
second
;
return
true
;
}
...
...
@@ -1283,10 +1303,14 @@ import java.io.IOException;
}
// The track selection has changed.
loadControl
.
onTracksSelected
(
renderers
,
mediaPeriod
.
getTrackGroups
()
,
trackSelections
);
loadControl
.
onTracksSelected
(
renderers
,
trackGroups
,
trackSelections
);
return
positionUs
;
}
public
TrackInfo
getTrackInfo
()
{
return
new
TrackInfo
(
trackGroups
,
trackSelections
,
trackSelectionsInfo
);
}
public
void
release
()
{
try
{
mediaSource
.
releasePeriod
(
mediaPeriod
);
...
...
library/src/main/java/com/google/android/exoplayer2/LoadControl.java
View file @
0c8f3c72
...
...
@@ -17,7 +17,7 @@ package com.google.android.exoplayer2;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
s
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
Array
;
import
com.google.android.exoplayer2.upstream.Allocator
;
/**
...
...
@@ -38,7 +38,7 @@ public interface LoadControl {
* @param trackSelections The track selections that were made.
*/
void
onTracksSelected
(
Renderer
[]
renderers
,
TrackGroupArray
trackGroups
,
TrackSelection
s
<?>
trackSelections
);
TrackSelection
Array
trackSelections
);
/**
* Called by the player when stopped.
...
...
library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
0c8f3c72
...
...
@@ -39,9 +39,10 @@ import com.google.android.exoplayer2.metadata.Metadata;
import
com.google.android.exoplayer2.metadata.MetadataRenderer
;
import
com.google.android.exoplayer2.metadata.id3.Id3Decoder
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.TextRenderer
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
s
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
Array
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.video.MediaCodecVideoRenderer
;
import
com.google.android.exoplayer2.video.VideoRendererEventListener
;
...
...
@@ -86,11 +87,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
*/
void
onRenderedFirstFrame
();
/**
* Called when a video track is no longer selected.
*/
void
onVideoTracksDisabled
();
}
private
static
final
String
TAG
=
"SimpleExoPlayer"
;
...
...
@@ -103,7 +99,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
private
final
int
videoRendererCount
;
private
final
int
audioRendererCount
;
private
boolean
videoTracksEnabled
;
private
Format
videoFormat
;
private
Format
audioFormat
;
...
...
@@ -122,12 +117,11 @@ public final class SimpleExoPlayer implements ExoPlayer {
private
float
volume
;
private
PlaybackParamsHolder
playbackParamsHolder
;
/* package */
SimpleExoPlayer
(
Context
context
,
TrackSelector
<?>
trackSelector
,
/* package */
SimpleExoPlayer
(
Context
context
,
TrackSelector
trackSelector
,
LoadControl
loadControl
,
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
,
boolean
preferExtensionDecoders
,
long
allowedVideoJoiningTimeMs
)
{
mainHandler
=
new
Handler
();
componentListener
=
new
ComponentListener
();
trackSelector
.
addListener
(
componentListener
);
// Build the renderers.
ArrayList
<
Renderer
>
renderersList
=
new
ArrayList
<>();
...
...
@@ -165,26 +159,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
/**
* Returns the number of renderers.
*
* @return The number of renderers.
*/
public
int
getRendererCount
()
{
return
renderers
.
length
;
}
/**
* Returns the track type that the renderer at a given index handles.
*
* @see Renderer#getTrackType()
* @param index The index of the renderer.
* @return One of the {@code TRACK_TYPE_*} constants defined in {@link C}.
*/
public
int
getRendererType
(
int
index
)
{
return
renderers
[
index
].
getTrackType
();
}
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
...
...
@@ -527,6 +501,26 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
@Override
public
int
getRendererCount
()
{
return
player
.
getRendererCount
();
}
@Override
public
int
getRendererType
(
int
index
)
{
return
player
.
getRendererType
(
index
);
}
@Override
public
TrackGroupArray
getCurrentTrackGroups
()
{
return
player
.
getCurrentTrackGroups
();
}
@Override
public
TrackSelectionArray
getCurrentTrackSelections
()
{
return
player
.
getCurrentTrackSelections
();
}
@Override
public
Timeline
getCurrentTimeline
()
{
return
player
.
getCurrentTimeline
();
}
...
...
@@ -660,8 +654,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
private
final
class
ComponentListener
implements
VideoRendererEventListener
,
AudioRendererEventListener
,
TextRenderer
.
Output
,
MetadataRenderer
.
Output
,
SurfaceHolder
.
Callback
,
TextureView
.
SurfaceTextureListener
,
TrackSelector
.
EventListener
<
Object
>
{
SurfaceHolder
.
Callback
,
TextureView
.
SurfaceTextureListener
{
// VideoRendererEventListener implementation
...
...
@@ -840,23 +833,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
// Do nothing.
}
// TrackSelector.EventListener implementation
@Override
public
void
onTrackSelectionsChanged
(
TrackSelections
<?>
trackSelections
)
{
boolean
videoTracksEnabled
=
false
;
for
(
int
i
=
0
;
i
<
renderers
.
length
;
i
++)
{
if
(
renderers
[
i
].
getTrackType
()
==
C
.
TRACK_TYPE_VIDEO
&&
trackSelections
.
get
(
i
)
!=
null
)
{
videoTracksEnabled
=
true
;
break
;
}
}
if
(
videoListener
!=
null
&&
SimpleExoPlayer
.
this
.
videoTracksEnabled
&&
!
videoTracksEnabled
)
{
videoListener
.
onVideoTracksDisabled
();
}
SimpleExoPlayer
.
this
.
videoTracksEnabled
=
videoTracksEnabled
;
}
}
@TargetApi
(
23
)
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java
View file @
0c8f3c72
...
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
android.support.annotation.IntDef
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
...
...
@@ -50,6 +51,11 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
}
@Override
public
SparseArray
<
TsPayloadReader
>
createInitialPayloadReaders
()
{
return
new
SparseArray
<>();
}
@Override
public
TsPayloadReader
createPayloadReader
(
int
streamType
,
EsInfo
esInfo
)
{
switch
(
streamType
)
{
case
TsExtractor
.
TS_STREAM_TYPE_MPA
:
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionPayloadReader.java
View file @
0c8f3c72
...
...
@@ -15,6 +15,10 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
/**
...
...
@@ -23,6 +27,17 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
public
interface
SectionPayloadReader
{
/**
* Initializes the section payload reader.
*
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param extractorOutput The {@link ExtractorOutput} that receives the extracted data.
* @param idGenerator A {@link PesReader.TrackIdGenerator} that generates unique track ids for the
* {@link TrackOutput}s.
*/
void
init
(
TimestampAdjuster
timestampAdjuster
,
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
);
/**
* Called by a {@link SectionReader} when a full section is received.
*
* @param sectionData The data belonging to a section, including the section header but excluding
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionReader.java
View file @
0c8f3c72
...
...
@@ -43,8 +43,7 @@ public final class SectionReader implements TsPayloadReader {
@Override
public
void
init
(
TimestampAdjuster
timestampAdjuster
,
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
// TODO: Injectable section readers might want to generate metadata tracks.
// Do nothing.
reader
.
init
(
timestampAdjuster
,
extractorOutput
,
idGenerator
);
}
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
0c8f3c72
...
...
@@ -65,8 +65,6 @@ public final class TsExtractor implements Extractor {
public
static
final
int
TS_STREAM_TYPE_H265
=
0x24
;
public
static
final
int
TS_STREAM_TYPE_ID3
=
0x15
;
private
static
final
String
TAG
=
"TsExtractor"
;
private
static
final
int
TS_PACKET_SIZE
=
188
;
private
static
final
int
TS_SYNC_BYTE
=
0x47
;
// First byte of each TS packet.
private
static
final
int
TS_PAT_PID
=
0
;
...
...
@@ -253,6 +251,12 @@ public final class TsExtractor implements Extractor {
private
void
resetPayloadReaders
()
{
trackIds
.
clear
();
tsPayloadReaders
.
clear
();
SparseArray
<
TsPayloadReader
>
initialPayloadReaders
=
payloadReaderFactory
.
createInitialPayloadReaders
();
int
initialPayloadReadersSize
=
initialPayloadReaders
.
size
();
for
(
int
i
=
0
;
i
<
initialPayloadReadersSize
;
i
++)
{
tsPayloadReaders
.
put
(
initialPayloadReaders
.
keyAt
(
i
),
initialPayloadReaders
.
valueAt
(
i
));
}
tsPayloadReaders
.
put
(
TS_PAT_PID
,
new
SectionReader
(
new
PatReader
()));
id3Reader
=
null
;
}
...
...
@@ -269,6 +273,12 @@ public final class TsExtractor implements Extractor {
}
@Override
public
void
init
(
TimestampAdjuster
timestampAdjuster
,
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
// Do nothing.
}
@Override
public
void
consume
(
ParsableByteArray
sectionData
)
{
// table_id(8), section_syntax_indicator(1), '0'(1), reserved(2), section_length(12),
// transport_stream_id (16), reserved (2), version_number (5), current_next_indicator (1),
...
...
@@ -311,6 +321,12 @@ public final class TsExtractor implements Extractor {
}
@Override
public
void
init
(
TimestampAdjuster
timestampAdjuster
,
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
// Do nothing.
}
@Override
public
void
consume
(
ParsableByteArray
sectionData
)
{
// table_id(8), section_syntax_indicator(1), '0'(1), reserved(2), section_length(12),
// program_number (16), reserved (2), version_number (5), current_next_indicator (1),
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java
View file @
0c8f3c72
...
...
@@ -15,6 +15,7 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
...
...
@@ -31,6 +32,15 @@ public interface TsPayloadReader {
interface
Factory
{
/**
* Returns the initial mapping from PIDs to payload readers.
* <p>
* This method allows the injection of payload readers for reserved PIDs, excluding PID 0.
*
* @return A {@link SparseArray} that maps PIDs to payload readers.
*/
SparseArray
<
TsPayloadReader
>
createInitialPayloadReaders
();
/**
* Returns a {@link TsPayloadReader} for a given stream type and elementary stream information.
* May return null if the stream type is not supported.
*
...
...
@@ -89,9 +99,10 @@ public interface TsPayloadReader {
/**
* Initializes the payload reader.
*
* @param timestampAdjuster
* @param extractorOutput
* @param idGenerator
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param extractorOutput The {@link ExtractorOutput} that receives the extracted data.
* @param idGenerator A {@link PesReader.TrackIdGenerator} that generates unique track ids for the
* {@link TrackOutput}s.
*/
void
init
(
TimestampAdjuster
timestampAdjuster
,
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
);
...
...
library/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java
View file @
0c8f3c72
...
...
@@ -24,6 +24,11 @@ import java.util.Arrays;
public
final
class
TrackGroupArray
{
/**
* The empty array.
*/
public
static
final
TrackGroupArray
EMPTY
=
new
TrackGroupArray
();
/**
* The number of groups in the array. Greater than or equal to zero.
*/
public
final
int
length
;
...
...
library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
View file @
0c8f3c72
...
...
@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.trackselection;
import
android.content.Context
;
import
android.graphics.Point
;
import
android.os.Handler
;
import
android.text.TextUtils
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
...
...
@@ -326,25 +325,18 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/**
* Constructs an instance that does not support adaptive video.
*
* @param eventHandler A handler to use when delivering events to listeners. May be null if
* listeners will not be added.
*/
public
DefaultTrackSelector
(
Handler
eventHandler
)
{
this
(
eventHandler
,
null
);
public
DefaultTrackSelector
()
{
this
(
null
);
}
/**
* Constructs an instance that uses a factory to create adaptive video track selections.
*
* @param eventHandler A handler to use when delivering events to listeners. May be null if
* listeners will not be added.
* @param adaptiveVideoTrackSelectionFactory A factory for adaptive video {@link TrackSelection}s,
* or null if the selector should not support adaptive video.
*/
public
DefaultTrackSelector
(
Handler
eventHandler
,
TrackSelection
.
Factory
adaptiveVideoTrackSelectionFactory
)
{
super
(
eventHandler
);
public
DefaultTrackSelector
(
TrackSelection
.
Factory
adaptiveVideoTrackSelectionFactory
)
{
this
.
adaptiveVideoTrackSelectionFactory
=
adaptiveVideoTrackSelectionFactory
;
params
=
new
AtomicReference
<>(
new
Parameters
());
}
...
...
library/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java
View file @
0c8f3c72
...
...
@@ -15,14 +15,13 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
trackselection
;
import
android.
os.Handle
r
;
import
android.
util.Pai
r
;
import
android.util.SparseArray
;
import
android.util.SparseBooleanArray
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.Arrays
;
import
java.util.HashMap
;
...
...
@@ -32,7 +31,7 @@ import java.util.Map;
* Base class for {@link TrackSelector}s that first establish a mapping between {@link TrackGroup}s
* and renderers, and then from that mapping create a {@link TrackSelection} for each renderer.
*/
public
abstract
class
MappingTrackSelector
extends
TrackSelector
<
MappedTrackInfo
>
{
public
abstract
class
MappingTrackSelector
extends
TrackSelector
{
/**
* A track selection override.
...
...
@@ -83,17 +82,22 @@ public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo
private
final
SparseArray
<
Map
<
TrackGroupArray
,
SelectionOverride
>>
selectionOverrides
;
private
final
SparseBooleanArray
rendererDisabledFlags
;
/**
* @param eventHandler A handler to use when delivering events to listeners added via
* {@link #addListener(EventListener)}.
*/
public
MappingTrackSelector
(
Handler
eventHandler
)
{
super
(
eventHandler
);
private
MappedTrackInfo
currentMappedTrackInfo
;
public
MappingTrackSelector
()
{
selectionOverrides
=
new
SparseArray
<>();
rendererDisabledFlags
=
new
SparseBooleanArray
();
}
/**
* Returns the mapping information associated with the current track selections, or null if no
* selection is currently active.
*/
public
final
MappedTrackInfo
getCurrentMappedTrackInfo
()
{
return
currentMappedTrackInfo
;
}
/**
* Sets whether the renderer at the specified index is disabled.
*
* @param rendererIndex The renderer index.
...
...
@@ -224,7 +228,7 @@ public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo
// TrackSelector implementation.
@Override
public
final
TrackSelections
<
MappedTrackInfo
>
selectTracks
(
public
final
Pair
<
TrackSelectionArray
,
Object
>
selectTracks
(
RendererCapabilities
[]
rendererCapabilities
,
TrackGroupArray
trackGroups
)
throws
ExoPlaybackException
{
// Structures into which data will be written during the selection. The extra item at the end
...
...
@@ -294,7 +298,13 @@ public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo
MappedTrackInfo
mappedTrackInfo
=
new
MappedTrackInfo
(
rendererTrackTypes
,
rendererTrackGroupArrays
,
mixedMimeTypeAdaptationSupport
,
rendererFormatSupports
,
unassociatedTrackGroupArray
);
return
new
TrackSelections
<>(
mappedTrackInfo
,
trackSelections
);
return
Pair
.<
TrackSelectionArray
,
Object
>
create
(
new
TrackSelectionArray
(
trackSelections
),
mappedTrackInfo
);
}
@Override
public
final
void
onSelectionActivated
(
Object
info
)
{
currentMappedTrackInfo
=
(
MappedTrackInfo
)
info
;
}
/**
...
...
@@ -409,12 +419,16 @@ public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo
*/
public
static
final
int
RENDERER_SUPPORT_PLAYABLE_TRACKS
=
2
;
/**
* The number of renderers to which tracks are mapped.
*/
public
final
int
length
;
private
final
int
[]
rendererTrackTypes
;
private
final
TrackGroupArray
[]
trackGroups
;
private
final
int
[]
mixedMimeTypeAdaptiveSupport
;
private
final
int
[][][]
formatSupport
;
private
final
TrackGroupArray
unassociatedTrackGroups
;
private
final
int
rendererCount
;
/**
* @param rendererTrackTypes The track type supported by each renderer.
...
...
@@ -433,7 +447,7 @@ public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo
this
.
formatSupport
=
formatSupport
;
this
.
mixedMimeTypeAdaptiveSupport
=
mixedMimeTypeAdaptiveSupport
;
this
.
unassociatedTrackGroups
=
unassociatedTrackGroups
;
this
.
rendererCount
=
trackGroups
.
length
;
this
.
length
=
trackGroups
.
length
;
}
/**
...
...
@@ -573,7 +587,7 @@ public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo
*/
public
boolean
hasOnlyUnplayableTracks
(
int
trackType
)
{
int
rendererSupport
=
RENDERER_SUPPORT_NO_TRACKS
;
for
(
int
i
=
0
;
i
<
rendererCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
if
(
rendererTrackTypes
[
i
]
==
trackType
)
{
rendererSupport
=
Math
.
max
(
rendererSupport
,
getRendererSupport
(
i
));
}
...
...
library/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection
s
.java
→
library/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection
Array
.java
View file @
0c8f3c72
...
...
@@ -20,13 +20,9 @@ import java.util.Arrays;
/**
* The result of a {@link TrackSelector} operation.
*/
public
final
class
TrackSelection
s
<
T
>
{
public
final
class
TrackSelection
Array
{
/**
* Opaque information associated with the result.
*/
public
final
T
info
;
/**
* The number of selections in the result. Greater than or equal to zero.
*/
public
final
int
length
;
...
...
@@ -37,11 +33,9 @@ public final class TrackSelections<T> {
private
int
hashCode
;
/**
* @param info Opaque information associated with the result.
* @param trackSelections The selections. Must not be null, but may contain null elements.
*/
public
TrackSelections
(
T
info
,
TrackSelection
...
trackSelections
)
{
this
.
info
=
info
;
public
TrackSelectionArray
(
TrackSelection
...
trackSelections
)
{
this
.
trackSelections
=
trackSelections
;
this
.
length
=
trackSelections
.
length
;
}
...
...
@@ -81,7 +75,7 @@ public final class TrackSelections<T> {
if
(
obj
==
null
||
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
TrackSelection
s
<?>
other
=
(
TrackSelections
<?>
)
obj
;
TrackSelection
Array
other
=
(
TrackSelectionArray
)
obj
;
return
Arrays
.
equals
(
trackSelections
,
other
.
trackSelections
);
}
...
...
library/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java
View file @
0c8f3c72
...
...
@@ -15,15 +15,13 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
trackselection
;
import
android.
os.Handle
r
;
import
android.
util.Pai
r
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.util.concurrent.CopyOnWriteArraySet
;
/** Selects tracks to be consumed by available renderers. */
public
abstract
class
TrackSelector
<
T
>
{
public
abstract
class
TrackSelector
{
/**
* Notified when previous selections by a {@link TrackSelector} are no longer valid.
...
...
@@ -37,55 +35,7 @@ public abstract class TrackSelector<T> {
}
/** Listener of {@link TrackSelector} events. */
public
interface
EventListener
<
T
>
{
/**
* Called when the track selections have changed.
*
* @param trackSelections The new track selections.
*/
void
onTrackSelectionsChanged
(
TrackSelections
<?
extends
T
>
trackSelections
);
}
private
final
Handler
eventHandler
;
private
final
CopyOnWriteArraySet
<
MappingTrackSelector
.
EventListener
<?
super
T
>>
listeners
;
private
InvalidationListener
listener
;
private
TrackSelections
<
T
>
activeSelections
;
/**
* @param eventHandler A handler to use when delivering events to listeners added via {@link
* #addListener(EventListener)}.
*/
public
TrackSelector
(
Handler
eventHandler
)
{
this
.
eventHandler
=
Assertions
.
checkNotNull
(
eventHandler
);
this
.
listeners
=
new
CopyOnWriteArraySet
<>();
}
/**
* Registers a listener to receive events from the selector. The listener's methods will be called
* using the {@link Handler} that was passed to the constructor.
*
* @param listener The listener to register.
*/
public
final
void
addListener
(
EventListener
<?
super
T
>
listener
)
{
listeners
.
add
(
listener
);
}
/**
* Unregister a listener. The listener will no longer receive events from the selector.
*
* @param listener The listener to unregister.
*/
public
final
void
removeListener
(
EventListener
<?
super
T
>
listener
)
{
listeners
.
remove
(
listener
);
}
/** Returns the current track selections. */
public
final
TrackSelections
<
T
>
getCurrentSelections
()
{
return
activeSelections
;
}
/**
* Initializes the selector.
...
...
@@ -97,28 +47,27 @@ public abstract class TrackSelector<T> {
}
/**
* Generates {@link TrackSelection
s
} for the renderers.
* Generates {@link TrackSelection
Array
} for the renderers.
*
* @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which
{@link
* TrackSelection}s are to be generated.
* @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which
*
{@link
TrackSelection}s are to be generated.
* @param trackGroups The available track groups.
* @return The track selections.
* @return The track selections, and an implementation specific object that will be returned to
* the selector via {@link #onSelectionActivated(Object)} should the selections be activated.
* @throws ExoPlaybackException If an error occurs selecting tracks.
*/
public
abstract
TrackSelections
<
T
>
selectTracks
(
public
abstract
Pair
<
TrackSelectionArray
,
Object
>
selectTracks
(
RendererCapabilities
[]
rendererCapabilities
,
TrackGroupArray
trackGroups
)
throws
ExoPlaybackException
;
/**
* Called when {@link TrackSelection
s} previously generated by {@link
* #selectTracks(RendererCapabilities[], TrackGroupArray)} are activated.
* Called when {@link TrackSelection
Array} previously generated by
*
{@link
#selectTracks(RendererCapabilities[], TrackGroupArray)} are activated.
*
* @param activeSelections The activated {@link TrackSelections}.
* @param info The information associated with the selections, or null if the selected tracks are
* being cleared.
*/
public
final
void
onSelectionActivated
(
TrackSelections
<
T
>
activeSelections
)
{
this
.
activeSelections
=
activeSelections
;
notifyTrackSelectionsChanged
(
activeSelections
);
}
public
abstract
void
onSelectionActivated
(
Object
info
);
/**
* Invalidates all previously generated track selections.
...
...
@@ -129,18 +78,4 @@ public abstract class TrackSelector<T> {
}
}
private
void
notifyTrackSelectionsChanged
(
final
TrackSelections
<
T
>
activeSelections
)
{
if
(
eventHandler
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
for
(
EventListener
<?
super
T
>
listener
:
listeners
)
{
listener
.
onTrackSelectionsChanged
(
activeSelections
);
}
}
});
}
}
}
library/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java
View file @
0c8f3c72
...
...
@@ -22,6 +22,8 @@ import com.google.android.exoplayer2.Format;
import
com.google.android.exoplayer2.SimpleExoPlayer
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.decoder.DecoderCounters
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
/**
* A helper class for periodically updating a {@link TextView} with debug information obtained from
...
...
@@ -98,6 +100,11 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
// Do nothing.
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
tracks
,
TrackSelectionArray
selections
)
{
// Do nothing.
}
// Runnable implementation.
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
View file @
0c8f3c72
...
...
@@ -24,7 +24,6 @@ import android.view.KeyEvent;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.widget.FrameLayout
;
import
android.widget.ImageButton
;
import
android.widget.SeekBar
;
import
android.widget.TextView
;
import
com.google.android.exoplayer2.C
;
...
...
@@ -32,12 +31,24 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import
com.google.android.exoplayer2.ExoPlayer
;
import
com.google.android.exoplayer2.R
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.Formatter
;
import
java.util.Locale
;
/**
* A view to control video playback of an {@link ExoPlayer}.
*
* By setting the view attribute {@code controller_layout_id} a layout resource to use can
* be customized. All views are optional but if the buttons should have an appropriate logic
* assigned, the id of the views in the layout have to match the expected ids as follows:
*
* <ul>
* <li>Playback: {@code exo_play}, {@code exo_pause}, {@code exo_ffwd}, {@code exo_rew}.</li>
* <li>Progress: {@code exo_progress}, {@code exo_time_current}, {@code exo_time}.</li>
* <li>Playlist navigation: {@code exo_previous}, {@code exo_next}.</li>
* </ul>
*/
public
class
PlaybackControlView
extends
FrameLayout
{
...
...
@@ -63,12 +74,13 @@ public class PlaybackControlView extends FrameLayout {
private
final
ComponentListener
componentListener
;
private
final
View
previousButton
;
private
final
View
nextButton
;
private
final
ImageButton
playButton
;
private
final
View
playButton
;
private
final
View
pauseButton
;
private
final
View
fastForwardButton
;
private
final
View
rewindButton
;
private
final
TextView
time
;
private
final
TextView
timeCurrent
;
private
final
SeekBar
progressBar
;
private
final
View
fastForwardButton
;
private
final
View
rewindButton
;
private
final
StringBuilder
formatBuilder
;
private
final
Formatter
formatter
;
private
final
Timeline
.
Window
currentWindow
;
...
...
@@ -108,6 +120,7 @@ public class PlaybackControlView extends FrameLayout {
public
PlaybackControlView
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
)
{
super
(
context
,
attrs
,
defStyleAttr
);
int
layoutResourceId
=
R
.
layout
.
exo_playback_control_view
;
rewindMs
=
DEFAULT_REWIND_MS
;
fastForwardMs
=
DEFAULT_FAST_FORWARD_MS
;
showTimeoutMs
=
DEFAULT_SHOW_TIMEOUT_MS
;
...
...
@@ -119,32 +132,49 @@ public class PlaybackControlView extends FrameLayout {
fastForwardMs
=
a
.
getInt
(
R
.
styleable
.
PlaybackControlView_fastforward_increment
,
fastForwardMs
);
showTimeoutMs
=
a
.
getInt
(
R
.
styleable
.
PlaybackControlView_show_timeout
,
showTimeoutMs
);
layoutResourceId
=
a
.
getResourceId
(
R
.
styleable
.
PlaybackControlView_controller_layout_id
,
layoutResourceId
);
}
finally
{
a
.
recycle
();
}
}
currentWindow
=
new
Timeline
.
Window
();
formatBuilder
=
new
StringBuilder
();
formatter
=
new
Formatter
(
formatBuilder
,
Locale
.
getDefault
());
componentListener
=
new
ComponentListener
();
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
exo_playback_control_view
,
this
);
time
=
(
TextView
)
findViewById
(
R
.
id
.
time
);
timeCurrent
=
(
TextView
)
findViewById
(
R
.
id
.
time_current
);
progressBar
=
(
SeekBar
)
findViewById
(
R
.
id
.
mediacontroller_progress
);
progressBar
.
setOnSeekBarChangeListener
(
componentListener
);
progressBar
.
setMax
(
PROGRESS_BAR_MAX
);
playButton
=
(
ImageButton
)
findViewById
(
R
.
id
.
play
);
playButton
.
setOnClickListener
(
componentListener
);
previousButton
=
findViewById
(
R
.
id
.
prev
);
previousButton
.
setOnClickListener
(
componentListener
);
nextButton
=
findViewById
(
R
.
id
.
next
);
nextButton
.
setOnClickListener
(
componentListener
);
rewindButton
=
findViewById
(
R
.
id
.
rew
);
rewindButton
.
setOnClickListener
(
componentListener
);
fastForwardButton
=
findViewById
(
R
.
id
.
ffwd
);
fastForwardButton
.
setOnClickListener
(
componentListener
);
LayoutInflater
.
from
(
context
).
inflate
(
layoutResourceId
,
this
);
time
=
(
TextView
)
findViewById
(
R
.
id
.
exo_time
);
timeCurrent
=
(
TextView
)
findViewById
(
R
.
id
.
exo_time_current
);
progressBar
=
(
SeekBar
)
findViewById
(
R
.
id
.
exo_progress
);
if
(
progressBar
!=
null
)
{
progressBar
.
setOnSeekBarChangeListener
(
componentListener
);
progressBar
.
setMax
(
PROGRESS_BAR_MAX
);
}
playButton
=
findViewById
(
R
.
id
.
exo_play
);
if
(
playButton
!=
null
)
{
playButton
.
setOnClickListener
(
componentListener
);
}
pauseButton
=
findViewById
(
R
.
id
.
exo_pause
);
if
(
pauseButton
!=
null
)
{
pauseButton
.
setOnClickListener
(
componentListener
);
}
previousButton
=
findViewById
(
R
.
id
.
exo_prev
);
if
(
previousButton
!=
null
)
{
previousButton
.
setOnClickListener
(
componentListener
);
}
nextButton
=
findViewById
(
R
.
id
.
exo_next
);
if
(
nextButton
!=
null
)
{
nextButton
.
setOnClickListener
(
componentListener
);
}
rewindButton
=
findViewById
(
R
.
id
.
exo_rew
);
if
(
rewindButton
!=
null
)
{
rewindButton
.
setOnClickListener
(
componentListener
);
}
fastForwardButton
=
findViewById
(
R
.
id
.
exo_ffwd
);
if
(
fastForwardButton
!=
null
)
{
fastForwardButton
.
setOnClickListener
(
componentListener
);
}
}
/**
...
...
@@ -285,11 +315,12 @@ public class PlaybackControlView extends FrameLayout {
return
;
}
boolean
playing
=
player
!=
null
&&
player
.
getPlayWhenReady
();
String
contentDescription
=
getResources
().
getString
(
playing
?
R
.
string
.
exo_controls_pause_description
:
R
.
string
.
exo_controls_play_description
);
playButton
.
setContentDescription
(
contentDescription
);
playButton
.
setImageResource
(
playing
?
R
.
drawable
.
exo_controls_pause
:
R
.
drawable
.
exo_controls_play
);
if
(
playButton
!=
null
)
{
playButton
.
setVisibility
(
playing
?
GONE
:
VISIBLE
);
}
if
(
pauseButton
!=
null
)
{
pauseButton
.
setVisibility
(
playing
?
VISIBLE
:
GONE
);
}
}
private
void
updateNavigation
()
{
...
...
@@ -313,7 +344,9 @@ public class PlaybackControlView extends FrameLayout {
setButtonEnabled
(
enableNext
,
nextButton
);
setButtonEnabled
(
fastForwardMs
>
0
&&
isSeekable
,
fastForwardButton
);
setButtonEnabled
(
rewindMs
>
0
&&
isSeekable
,
rewindButton
);
progressBar
.
setEnabled
(
isSeekable
);
if
(
progressBar
!=
null
)
{
progressBar
.
setEnabled
(
isSeekable
);
}
}
private
void
updateProgress
()
{
...
...
@@ -322,16 +355,21 @@ public class PlaybackControlView extends FrameLayout {
}
long
duration
=
player
==
null
?
0
:
player
.
getDuration
();
long
position
=
player
==
null
?
0
:
player
.
getCurrentPosition
();
time
.
setText
(
stringForTime
(
duration
));
if
(!
dragging
)
{
if
(
time
!=
null
)
{
time
.
setText
(
stringForTime
(
duration
));
}
if
(
timeCurrent
!=
null
&&
!
dragging
)
{
timeCurrent
.
setText
(
stringForTime
(
position
));
}
if
(!
dragging
)
{
progressBar
.
setProgress
(
progressBarValue
(
position
));
if
(
progressBar
!=
null
)
{
if
(!
dragging
)
{
progressBar
.
setProgress
(
progressBarValue
(
position
));
}
long
bufferedPosition
=
player
==
null
?
0
:
player
.
getBufferedPosition
();
progressBar
.
setSecondaryProgress
(
progressBarValue
(
bufferedPosition
));
// Remove scheduled updates.
}
long
bufferedPosition
=
player
==
null
?
0
:
player
.
getBufferedPosition
();
progressBar
.
setSecondaryProgress
(
progressBarValue
(
bufferedPosition
));
// Remove scheduled updates.
removeCallbacks
(
updateProgressAction
);
// Schedule an update if necessary.
int
playbackState
=
player
==
null
?
ExoPlayer
.
STATE_IDLE
:
player
.
getPlaybackState
();
...
...
@@ -350,6 +388,9 @@ public class PlaybackControlView extends FrameLayout {
}
private
void
setButtonEnabled
(
boolean
enabled
,
View
view
)
{
if
(
view
==
null
)
{
return
;
}
view
.
setEnabled
(
enabled
);
if
(
Util
.
SDK_INT
>=
11
)
{
setViewAlphaV11
(
view
,
enabled
?
1
f
:
0.3f
);
...
...
@@ -500,7 +541,7 @@ public class PlaybackControlView extends FrameLayout {
@Override
public
void
onProgressChanged
(
SeekBar
seekBar
,
int
progress
,
boolean
fromUser
)
{
if
(
fromUser
)
{
if
(
fromUser
&&
timeCurrent
!=
null
)
{
timeCurrent
.
setText
(
stringForTime
(
positionValue
(
progress
)));
}
}
...
...
@@ -508,7 +549,9 @@ public class PlaybackControlView extends FrameLayout {
@Override
public
void
onStopTrackingTouch
(
SeekBar
seekBar
)
{
dragging
=
false
;
player
.
seekTo
(
positionValue
(
seekBar
.
getProgress
()));
if
(
player
!=
null
)
{
player
.
seekTo
(
positionValue
(
seekBar
.
getProgress
()));
}
hideAfterTimeout
();
}
...
...
@@ -536,23 +579,31 @@ public class PlaybackControlView extends FrameLayout {
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
tracks
,
TrackSelectionArray
selections
)
{
// Do nothing.
}
@Override
public
void
onPlayerError
(
ExoPlaybackException
error
)
{
// Do nothing.
}
@Override
public
void
onClick
(
View
view
)
{
Timeline
currentTimeline
=
player
.
getCurrentTimeline
();
if
(
nextButton
==
view
)
{
next
();
}
else
if
(
previousButton
==
view
)
{
previous
();
}
else
if
(
fastForwardButton
==
view
)
{
fastForward
();
}
else
if
(
rewindButton
==
view
&&
currentTimeline
!=
null
)
{
rewind
();
}
else
if
(
playButton
==
view
)
{
player
.
setPlayWhenReady
(!
player
.
getPlayWhenReady
());
if
(
player
!=
null
)
{
if
(
nextButton
==
view
)
{
next
();
}
else
if
(
previousButton
==
view
)
{
previous
();
}
else
if
(
fastForwardButton
==
view
)
{
fastForward
();
}
else
if
(
rewindButton
==
view
)
{
rewind
();
}
else
if
(
playButton
==
view
)
{
player
.
setPlayWhenReady
(
true
);
}
else
if
(
pauseButton
==
view
)
{
player
.
setPlayWhenReady
(
false
);
}
}
hideAfterTimeout
();
}
...
...
library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
View file @
0c8f3c72
...
...
@@ -27,13 +27,16 @@ import android.view.TextureView;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.FrameLayout
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.ExoPlayer
;
import
com.google.android.exoplayer2.R
;
import
com.google.android.exoplayer2.SimpleExoPlayer
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.TextRenderer
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
java.util.List
;
/**
...
...
@@ -90,23 +93,30 @@ public final class SimpleExoPlayerView extends FrameLayout {
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
exo_simple_player_view
,
this
);
componentListener
=
new
ComponentListener
();
layout
=
(
AspectRatioFrameLayout
)
findViewById
(
R
.
id
.
video_frame
);
layout
=
(
AspectRatioFrameLayout
)
findViewById
(
R
.
id
.
exo_
video_frame
);
layout
.
setResizeMode
(
resizeMode
);
shutterView
=
findViewById
(
R
.
id
.
shutter
);
subtitleLayout
=
(
SubtitleView
)
findViewById
(
R
.
id
.
subtitles
);
shutterView
=
findViewById
(
R
.
id
.
exo_
shutter
);
subtitleLayout
=
(
SubtitleView
)
findViewById
(
R
.
id
.
exo_
subtitles
);
subtitleLayout
.
setUserDefaultStyle
();
subtitleLayout
.
setUserDefaultTextSize
();
controller
=
(
PlaybackControlView
)
findViewById
(
R
.
id
.
control
);
controller
.
hide
();
View
controllerPlaceholder
=
findViewById
(
R
.
id
.
exo_controller_placeholder
);
controller
=
new
PlaybackControlView
(
context
,
attrs
);
controller
.
setRewindIncrementMs
(
rewindMs
);
controller
.
setFastForwardIncrementMs
(
fastForwardMs
);
controller
.
setLayoutParams
(
controllerPlaceholder
.
getLayoutParams
());
controller
.
hide
();
this
.
controllerShowTimeoutMs
=
controllerShowTimeoutMs
;
ViewGroup
parent
=
((
ViewGroup
)
controllerPlaceholder
.
getParent
());
int
controllerIndex
=
parent
.
indexOfChild
(
controllerPlaceholder
);
parent
.
removeView
(
controllerPlaceholder
);
parent
.
addView
(
controller
,
controllerIndex
);
View
view
=
useTextureView
?
new
TextureView
(
context
)
:
new
SurfaceView
(
context
);
ViewGroup
.
LayoutParams
params
=
new
ViewGroup
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
);
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
);
view
.
setLayoutParams
(
params
);
surfaceView
=
view
;
layout
.
addView
(
surfaceView
,
0
);
...
...
@@ -318,7 +328,13 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
@Override
public
void
onVideoTracksDisabled
()
{
public
void
onTracksChanged
(
TrackGroupArray
tracks
,
TrackSelectionArray
selections
)
{
for
(
int
i
=
0
;
i
<
selections
.
length
;
i
++)
{
if
(
player
.
getRendererType
(
i
)
==
C
.
TRACK_TYPE_VIDEO
&&
selections
.
get
(
i
)
!=
null
)
{
return
;
}
}
// No enabled video renderers. Close the shutter.
shutterView
.
setVisibility
(
VISIBLE
);
}
...
...
library/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java
View file @
0c8f3c72
...
...
@@ -122,10 +122,10 @@ public final class SubtitleView extends View implements TextRenderer.Output {
/**
* Sets the text size to one derived from {@link CaptioningManager#getFontScale()}, or to a
* default size
on API level 19 and earlier
.
* default size
before API level 19
.
*/
public
void
setUserDefaultTextSize
()
{
float
fontScale
=
Util
.
SDK_INT
>=
19
?
getUserCaptionFontScaleV19
()
:
1
f
;
float
fontScale
=
Util
.
SDK_INT
>=
19
&&
!
isInEditMode
()
?
getUserCaptionFontScaleV19
()
:
1
f
;
setFractionalTextSize
(
DEFAULT_TEXT_SIZE_FRACTION
*
fontScale
);
}
...
...
@@ -180,10 +180,11 @@ public final class SubtitleView extends View implements TextRenderer.Output {
/**
* Sets the caption style to be equivalent to the one returned by
* {@link CaptioningManager#getUserStyle()}, or to a default style
on API level 19 and earlier
.
* {@link CaptioningManager#getUserStyle()}, or to a default style
before API level 19
.
*/
public
void
setUserDefaultStyle
()
{
setStyle
(
Util
.
SDK_INT
>=
19
?
getUserCaptionStyleV19
()
:
CaptionStyleCompat
.
DEFAULT
);
setStyle
(
Util
.
SDK_INT
>=
19
&&
!
isInEditMode
()
?
getUserCaptionStyleV19
()
:
CaptionStyleCompat
.
DEFAULT
);
}
/**
...
...
library/src/main/res/layout/exo_playback_control_view.xml
View file @
0c8f3c72
...
...
@@ -14,7 +14,6 @@
limitations under the License.
-->
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"bottom"
...
...
@@ -29,24 +28,22 @@
android:paddingTop=
"4dp"
android:orientation=
"horizontal"
>
<ImageButton
android:id=
"@+id/prev"
android:contentDescription=
"@string/exo_controls_previous_description"
<ImageButton
android:id=
"@+id/exo_prev"
style=
"@style/ExoMediaButton.Previous"
/>
<ImageButton
android:id=
"@+id/rew"
android:contentDescription=
"@string/exo_controls_rewind_description"
<ImageButton
android:id=
"@+id/exo_rew"
style=
"@style/ExoMediaButton.Rewind"
/>
<ImageButton
android:id=
"@+id/play"
tools:ignore=
"ContentDescription"
style=
"@style/ExoMediaButton"
/>
<ImageButton
android:id=
"@+id/exo_play"
style=
"@style/ExoMediaButton.Play"
/>
<ImageButton
android:id=
"@+id/ffwd"
android:contentDescription=
"@string/exo_controls_fastforward_description"
<ImageButton
android:id=
"@+id/exo_pause"
style=
"@style/ExoMediaButton.Pause"
/>
<ImageButton
android:id=
"@+id/exo_ffwd"
style=
"@style/ExoMediaButton.FastForward"
/>
<ImageButton
android:id=
"@+id/next"
android:contentDescription=
"@string/exo_controls_previous_description"
<ImageButton
android:id=
"@+id/exo_next"
style=
"@style/ExoMediaButton.Next"
/>
</LinearLayout>
...
...
@@ -56,7 +53,7 @@
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
>
<TextView
android:id=
"@+id/time_current"
<TextView
android:id=
"@+id/
exo_
time_current"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
...
...
@@ -67,13 +64,13 @@
android:paddingEnd=
"4dp"
android:textColor=
"#FFBEBEBE"
/>
<SeekBar
android:id=
"@+id/
mediacontroller
_progress"
<SeekBar
android:id=
"@+id/
exo
_progress"
android:layout_width=
"0dp"
android:layout_weight=
"1"
android:layout_height=
"32dp"
style=
"?android:attr/progressBarStyleHorizontal"
/>
<TextView
android:id=
"@+id/time"
<TextView
android:id=
"@+id/
exo_
time"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
...
...
library/src/main/res/layout/exo_simple_player_view.xml
View file @
0c8f3c72
...
...
@@ -17,23 +17,23 @@
android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
>
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout
android:id=
"@+id/video_frame"
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout
android:id=
"@+id/
exo_
video_frame"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
>
<View
android:id=
"@+id/shutter"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/black"
/>
<View
android:id=
"@+id/
exo_
shutter"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/black"
/>
<com.google.android.exoplayer2.ui.SubtitleView
android:id=
"@+id/subtitles"
<com.google.android.exoplayer2.ui.SubtitleView
android:id=
"@+id/
exo_
subtitles"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
<
com.google.android.exoplayer2.ui.PlaybackControlView
android:id=
"@+id/control
"
<
View
android:id=
"@+id/exo_controller_placeholder
"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
...
...
library/src/main/res/values/attrs.xml
View file @
0c8f3c72
...
...
@@ -23,6 +23,7 @@
<attr
name=
"show_timeout"
format=
"integer"
/>
<attr
name=
"rewind_increment"
format=
"integer"
/>
<attr
name=
"fastforward_increment"
format=
"integer"
/>
<attr
name=
"controller_layout_id"
format=
"reference"
/>
<declare-styleable
name=
"SimpleExoPlayerView"
>
<attr
name=
"use_controller"
format=
"boolean"
/>
...
...
@@ -31,6 +32,7 @@
<attr
name=
"rewind_increment"
/>
<attr
name=
"fastforward_increment"
/>
<attr
name=
"resize_mode"
/>
<attr
name=
"controller_layout_id"
/>
</declare-styleable>
<declare-styleable
name=
"AspectRatioFrameLayout"
>
...
...
@@ -41,6 +43,7 @@
<attr
name=
"show_timeout"
/>
<attr
name=
"rewind_increment"
/>
<attr
name=
"fastforward_increment"
/>
<attr
name=
"controller_layout_id"
/>
</declare-styleable>
</resources>
library/src/main/res/values/ids.xml
0 → 100644
View file @
0c8f3c72
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<resources>
<item
name=
"exo_play"
type=
"id"
/>
<item
name=
"exo_pause"
type=
"id"
/>
<item
name=
"exo_rew"
type=
"id"
/>
<item
name=
"exo_ffwd"
type=
"id"
/>
<item
name=
"exo_prev"
type=
"id"
/>
<item
name=
"exo_next"
type=
"id"
/>
<item
name=
"exo_time"
type=
"id"
/>
<item
name=
"exo_time_current"
type=
"id"
/>
<item
name=
"exo_progress"
type=
"id"
/>
</resources>
library/src/main/res/values/styles.xml
View file @
0c8f3c72
...
...
@@ -41,4 +41,14 @@
<item
name=
"android:contentDescription"
>
@string/exo_controls_rewind_description
</item>
</style>
<style
name=
"ExoMediaButton.Play"
>
<item
name=
"android:src"
>
@drawable/exo_controls_play
</item>
<item
name=
"android:contentDescription"
>
@string/exo_controls_play_description
</item>
</style>
<style
name=
"ExoMediaButton.Pause"
>
<item
name=
"android:src"
>
@drawable/exo_controls_pause
</item>
<item
name=
"android:contentDescription"
>
@string/exo_controls_pause_description
</item>
</style>
</resources>
playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java
View file @
0c8f3c72
...
...
@@ -19,8 +19,6 @@ import android.annotation.TargetApi;
import
android.media.MediaDrm
;
import
android.media.UnsupportedSchemeException
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.test.ActivityInstrumentationTestCase2
;
import
android.util.Log
;
import
com.google.android.exoplayer2.C
;
...
...
@@ -805,7 +803,6 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
private
DashTestTrackSelector
(
String
audioFormatId
,
String
[]
videoFormatIds
,
boolean
canIncludeAdditionalVideoFormats
)
{
super
(
new
Handler
(
Looper
.
getMainLooper
()));
this
.
audioFormatId
=
audioFormatId
;
this
.
videoFormatIds
=
videoFormatIds
;
this
.
canIncludeAdditionalVideoFormats
=
canIncludeAdditionalVideoFormats
;
...
...
playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/util/ExoHostedTest.java
View file @
0c8f3c72
...
...
@@ -33,9 +33,11 @@ import com.google.android.exoplayer2.drm.DrmSessionManager;
import
com.google.android.exoplayer2.drm.FrameworkMediaCrypto
;
import
com.google.android.exoplayer2.playbacktests.util.HostActivity.HostedTest
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.AdaptiveVideoTrackSelection
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.upstream.BandwidthMeter
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DefaultBandwidthMeter
;
...
...
@@ -187,6 +189,11 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
)
{
// Do nothing.
}
@Override
public
final
void
onPlayerStateChanged
(
boolean
playWhenReady
,
int
playbackState
)
{
Log
.
d
(
tag
,
"state ["
+
playWhenReady
+
", "
+
playbackState
+
"]"
);
playerWasPrepared
|=
playbackState
!=
ExoPlayer
.
STATE_IDLE
;
...
...
@@ -305,7 +312,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
@SuppressWarnings
(
"unused"
)
protected
MappingTrackSelector
buildTrackSelector
(
HostActivity
host
,
BandwidthMeter
bandwidthMeter
)
{
return
new
DefaultTrackSelector
(
n
ull
,
n
ew
AdaptiveVideoTrackSelection
.
Factory
(
bandwidthMeter
));
return
new
DefaultTrackSelector
(
new
AdaptiveVideoTrackSelection
.
Factory
(
bandwidthMeter
));
}
@SuppressWarnings
(
"unused"
)
...
...
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