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
a7ace587
authored
Oct 15, 2018
by
Lieblich, Jonathan
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge branch 'dev-v2' into program_information
parents
ced302fd
6fb8f66b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
538 additions
and
127 deletions
RELEASENOTES.md
demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java
library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java
library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java
library/core/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java
library/core/src/main/java/com/google/android/exoplayer2/Renderer.java
library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
library/core/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
library/core/src/test/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRendererTest.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
library/ui/src/main/res/values-mr/strings.xml
testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/ActionSchedule.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/DebugRenderersFactory.java
RELEASENOTES.md
View file @
a7ace587
...
@@ -19,12 +19,17 @@
...
@@ -19,12 +19,17 @@
(
[
#4788
](
https://github.com/google/ExoPlayer/issues/4788
)
).
(
[
#4788
](
https://github.com/google/ExoPlayer/issues/4788
)
).
*
SubRip: Add support for alignment tags, and remove tags from the displayed
*
SubRip: Add support for alignment tags, and remove tags from the displayed
captions (
[
#4306
](
https://github.com/google/ExoPlayer/issues/4306
)
).
captions (
[
#4306
](
https://github.com/google/ExoPlayer/issues/4306
)
).
*
Fix issue where buffered position is not updated correctly when transitioning
between periods
(
[
#4899
](
https://github.com/google/ExoPlayer/issues/4899
)
).
*
IMA extension:
*
For preroll to live stream transitions, project forward the loading position
to avoid being behind the live window.
### 2.9.0 ###
### 2.9.0 ###
*
Turn on Java 8 compiler support for the ExoPlayer library. Apps that depend
*
Turn on Java 8 compiler support for the ExoPlayer library. Apps may need to
on ExoPlayer via its source code rather than an AAR may need to add
add
`compileOptions { targetCompatibility JavaVersion.VERSION_1_8 }`
to their
`compileOptions { targetCompatibility JavaVersion.VERSION_1_8 }`
to their
gradle settings to ensure bytecode compatibility.
gradle settings to ensure bytecode compatibility.
*
Set
`compileSdkVersion`
and
`targetSdkVersion`
to 28.
*
Set
`compileSdkVersion`
and
`targetSdkVersion`
to 28.
*
Support for automatic audio focus handling via
*
Support for automatic audio focus handling via
...
@@ -346,18 +351,18 @@
...
@@ -346,18 +351,18 @@
begins, and poll the audio timestamp less frequently once it starts
begins, and poll the audio timestamp less frequently once it starts
advancing (
[
#3841
](
https://github.com/google/ExoPlayer/issues/3841
)
).
advancing (
[
#3841
](
https://github.com/google/ExoPlayer/issues/3841
)
).
*
Add an option to skip silent audio in
`PlaybackParameters`
*
Add an option to skip silent audio in
`PlaybackParameters`
(
(#2635)
[
https://github.com/google/ExoPlayer/issues/2635
]
).
(
[
#2635
](
https://github.com/google/ExoPlayer/issues/2635
)
).
*
Fix an issue where playback of TrueHD streams would get stuck after seeking
*
Fix an issue where playback of TrueHD streams would get stuck after seeking
due to not finding a syncframe
due to not finding a syncframe
(
(#3845)
[
https://github.com/google/ExoPlayer/issues/3845
]
).
(
[
#3845
](
https://github.com/google/ExoPlayer/issues/3845
)
).
*
Fix an issue with eac3-joc playback where a codec would fail to configure
*
Fix an issue with eac3-joc playback where a codec would fail to configure
(
(#4165)
[
https://github.com/google/ExoPlayer/issues/4165
]
).
(
[
#4165
](
https://github.com/google/ExoPlayer/issues/4165
)
).
*
Handle non-empty end-of-stream buffers, to fix gapless playback of streams
*
Handle non-empty end-of-stream buffers, to fix gapless playback of streams
with encoder padding when the decoder returns a non-empty final buffer.
with encoder padding when the decoder returns a non-empty final buffer.
*
Allow trimming more than one sample when applying an elst audio edit via
*
Allow trimming more than one sample when applying an elst audio edit via
gapless playback info.
gapless playback info.
*
Allow overriding skipping/scaling with custom
`AudioProcessor`
s
*
Allow overriding skipping/scaling with custom
`AudioProcessor`
s
(
(#3142)
[
https://github.com/google/ExoPlayer/issues/3142
]
).
(
[
#3142
](
https://github.com/google/ExoPlayer/issues/3142
)
).
*
Caching:
*
Caching:
*
Add release method to the
`Cache`
interface, and prevent multiple instances
*
Add release method to the
`Cache`
interface, and prevent multiple instances
of
`SimpleCache`
using the same folder at the same time.
of
`SimpleCache`
using the same folder at the same time.
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java
View file @
a7ace587
...
@@ -350,8 +350,7 @@ public class SampleChooserActivity extends Activity
...
@@ -350,8 +350,7 @@ public class SampleChooserActivity extends Activity
?
null
?
null
:
new
DrmInfo
(
drmScheme
,
drmLicenseUrl
,
drmKeyRequestProperties
,
drmMultiSession
);
:
new
DrmInfo
(
drmScheme
,
drmLicenseUrl
,
drmKeyRequestProperties
,
drmMultiSession
);
if
(
playlistSamples
!=
null
)
{
if
(
playlistSamples
!=
null
)
{
UriSample
[]
playlistSamplesArray
=
playlistSamples
.
toArray
(
UriSample
[]
playlistSamplesArray
=
playlistSamples
.
toArray
(
new
UriSample
[
0
]);
new
UriSample
[
playlistSamples
.
size
()]);
return
new
PlaylistSample
(
sampleName
,
drmInfo
,
playlistSamplesArray
);
return
new
PlaylistSample
(
sampleName
,
drmInfo
,
playlistSamplesArray
);
}
else
{
}
else
{
return
new
UriSample
(
return
new
UriSample
(
...
...
library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java
View file @
a7ace587
...
@@ -153,6 +153,12 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
...
@@ -153,6 +153,12 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
onDisabled
();
onDisabled
();
}
}
@Override
public
final
void
reset
()
{
Assertions
.
checkState
(
state
==
STATE_DISABLED
);
onReset
();
}
// RendererCapabilities implementation.
// RendererCapabilities implementation.
@Override
@Override
...
@@ -247,6 +253,15 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
...
@@ -247,6 +253,15 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
// Do nothing.
// Do nothing.
}
}
/**
* Called when the renderer is reset.
*
* <p>The default implementation is a no-op.
*/
protected
void
onReset
()
{
// Do nothing.
}
// Methods to be called by subclasses.
// Methods to be called by subclasses.
/** Returns the formats of the currently enabled stream. */
/** Returns the formats of the currently enabled stream. */
...
...
library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java
View file @
a7ace587
...
@@ -187,7 +187,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
...
@@ -187,7 +187,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
extensionRendererMode
,
renderersList
);
extensionRendererMode
,
renderersList
);
buildCameraMotionRenderers
(
context
,
extensionRendererMode
,
renderersList
);
buildCameraMotionRenderers
(
context
,
extensionRendererMode
,
renderersList
);
buildMiscellaneousRenderers
(
context
,
eventHandler
,
extensionRendererMode
,
renderersList
);
buildMiscellaneousRenderers
(
context
,
eventHandler
,
extensionRendererMode
,
renderersList
);
return
renderersList
.
toArray
(
new
Renderer
[
renderersList
.
size
()
]);
return
renderersList
.
toArray
(
new
Renderer
[
0
]);
}
}
/**
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
View file @
a7ace587
...
@@ -619,7 +619,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
...
@@ -619,7 +619,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
if
(
playbackInfo
.
startPositionUs
==
C
.
TIME_UNSET
)
{
if
(
playbackInfo
.
startPositionUs
==
C
.
TIME_UNSET
)
{
// Replace internal unset start position with externally visible start position of zero.
// Replace internal unset start position with externally visible start position of zero.
playbackInfo
=
playbackInfo
=
playbackInfo
.
from
NewPosition
(
playbackInfo
.
resetTo
NewPosition
(
playbackInfo
.
periodId
,
/* startPositionUs= */
0
,
playbackInfo
.
contentPositionUs
);
playbackInfo
.
periodId
,
/* startPositionUs= */
0
,
playbackInfo
.
contentPositionUs
);
}
}
if
((!
this
.
playbackInfo
.
timeline
.
isEmpty
()
||
hasPendingPrepare
)
if
((!
this
.
playbackInfo
.
timeline
.
isEmpty
()
||
hasPendingPrepare
)
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
View file @
a7ace587
This diff is collapsed.
Click to expand it.
library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java
View file @
a7ace587
...
@@ -133,23 +133,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -133,23 +133,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
}
/**
/**
* Returns the buffered position in microseconds. If the period is buffered to the end then
* Returns the buffered position in microseconds. If the period is buffered to the end, then the
* {@link C#TIME_END_OF_SOURCE} is returned unless {@code convertEosToDuration} is true, in which
* period duration is returned.
* case the period duration is returned.
*
*
* @param convertEosToDuration Whether to return the period duration rather than
* {@link C#TIME_END_OF_SOURCE} if the period is fully buffered.
* @return The buffered position in microseconds.
* @return The buffered position in microseconds.
*/
*/
public
long
getBufferedPositionUs
(
boolean
convertEosToDuration
)
{
public
long
getBufferedPositionUs
()
{
if
(!
prepared
)
{
if
(!
prepared
)
{
return
info
.
startPositionUs
;
return
info
.
startPositionUs
;
}
}
long
bufferedPositionUs
=
long
bufferedPositionUs
=
hasEnabledTracks
?
mediaPeriod
.
getBufferedPositionUs
()
:
C
.
TIME_END_OF_SOURCE
;
hasEnabledTracks
?
mediaPeriod
.
getBufferedPositionUs
()
:
C
.
TIME_END_OF_SOURCE
;
return
bufferedPositionUs
==
C
.
TIME_END_OF_SOURCE
&&
convertEosToDuration
return
bufferedPositionUs
==
C
.
TIME_END_OF_SOURCE
?
info
.
durationUs
:
bufferedPositionUs
;
?
info
.
durationUs
:
bufferedPositionUs
;
}
}
/**
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java
View file @
a7ace587
...
@@ -533,6 +533,11 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -533,6 +533,11 @@ import com.google.android.exoplayer2.util.Assertions;
// until the timeline is updated. Store whether the next timeline period is ready when the
// until the timeline is updated. Store whether the next timeline period is ready when the
// timeline is updated, to avoid repeatedly checking the same timeline.
// timeline is updated, to avoid repeatedly checking the same timeline.
MediaPeriodInfo
mediaPeriodInfo
=
mediaPeriodHolder
.
info
;
MediaPeriodInfo
mediaPeriodInfo
=
mediaPeriodHolder
.
info
;
// The expected delay until playback transitions to the new period is equal the duration of
// media that's currently buffered (assuming no interruptions). This is used to project forward
// the start position for transitions to new windows.
long
bufferedDurationUs
=
mediaPeriodHolder
.
getRendererOffset
()
+
mediaPeriodInfo
.
durationUs
-
rendererPositionUs
;
if
(
mediaPeriodInfo
.
isLastInTimelinePeriod
)
{
if
(
mediaPeriodInfo
.
isLastInTimelinePeriod
)
{
int
currentPeriodIndex
=
timeline
.
getIndexOfPeriod
(
mediaPeriodInfo
.
id
.
periodUid
);
int
currentPeriodIndex
=
timeline
.
getIndexOfPeriod
(
mediaPeriodInfo
.
id
.
periodUid
);
int
nextPeriodIndex
=
int
nextPeriodIndex
=
...
@@ -550,19 +555,15 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -550,19 +555,15 @@ import com.google.android.exoplayer2.util.Assertions;
long
windowSequenceNumber
=
mediaPeriodInfo
.
id
.
windowSequenceNumber
;
long
windowSequenceNumber
=
mediaPeriodInfo
.
id
.
windowSequenceNumber
;
if
(
timeline
.
getWindow
(
nextWindowIndex
,
window
).
firstPeriodIndex
==
nextPeriodIndex
)
{
if
(
timeline
.
getWindow
(
nextWindowIndex
,
window
).
firstPeriodIndex
==
nextPeriodIndex
)
{
// We're starting to buffer a new window. When playback transitions to this window we'll
// We're starting to buffer a new window. When playback transitions to this window we'll
// want it to be from its default start position. The expected delay until playback
// want it to be from its default start position, so project the default start position
// transitions is equal the duration of media that's currently buffered (assuming no
// forward by the duration of the buffer, and start buffering from this point.
// interruptions). Hence we project the default start position forward by the duration of
// the buffer, and start buffering from this point.
long
defaultPositionProjectionUs
=
mediaPeriodHolder
.
getRendererOffset
()
+
mediaPeriodInfo
.
durationUs
-
rendererPositionUs
;
Pair
<
Object
,
Long
>
defaultPosition
=
Pair
<
Object
,
Long
>
defaultPosition
=
timeline
.
getPeriodPosition
(
timeline
.
getPeriodPosition
(
window
,
window
,
period
,
period
,
nextWindowIndex
,
nextWindowIndex
,
C
.
TIME_UNSET
,
/* windowPositionUs= */
C
.
TIME_UNSET
,
Math
.
max
(
0
,
defaultPositionProjec
tionUs
));
/* defaultPositionProjectionUs= */
Math
.
max
(
0
,
bufferedDura
tionUs
));
if
(
defaultPosition
==
null
)
{
if
(
defaultPosition
==
null
)
{
return
null
;
return
null
;
}
}
...
@@ -603,11 +604,27 @@ import com.google.android.exoplayer2.util.Assertions;
...
@@ -603,11 +604,27 @@ import com.google.android.exoplayer2.util.Assertions;
mediaPeriodInfo
.
contentPositionUs
,
mediaPeriodInfo
.
contentPositionUs
,
currentPeriodId
.
windowSequenceNumber
);
currentPeriodId
.
windowSequenceNumber
);
}
else
{
}
else
{
// Play content from the ad group position.
// Play content from the ad group position. As a special case, if we're transitioning from a
// preroll ad group to content and there are no other ad groups, project the start position
// forward as if this were a transition to a new window. No attempt is made to handle
// midrolls in live streams, as it's unclear what content position should play after an ad
// (server-side dynamic ad insertion is more appropriate for this use case).
long
startPositionUs
=
mediaPeriodInfo
.
contentPositionUs
;
if
(
period
.
getAdGroupCount
()
==
1
&&
period
.
getAdGroupTimeUs
(
0
)
==
0
)
{
Pair
<
Object
,
Long
>
defaultPosition
=
timeline
.
getPeriodPosition
(
window
,
period
,
period
.
windowIndex
,
/* windowPositionUs= */
C
.
TIME_UNSET
,
/* defaultPositionProjectionUs= */
Math
.
max
(
0
,
bufferedDurationUs
));
if
(
defaultPosition
==
null
)
{
return
null
;
}
startPositionUs
=
defaultPosition
.
second
;
}
return
getMediaPeriodInfoForContent
(
return
getMediaPeriodInfoForContent
(
currentPeriodId
.
periodUid
,
currentPeriodId
.
periodUid
,
startPositionUs
,
currentPeriodId
.
windowSequenceNumber
);
mediaPeriodInfo
.
contentPositionUs
,
currentPeriodId
.
windowSequenceNumber
);
}
}
}
else
if
(
mediaPeriodInfo
.
id
.
endPositionUs
!=
C
.
TIME_END_OF_SOURCE
)
{
}
else
if
(
mediaPeriodInfo
.
id
.
endPositionUs
!=
C
.
TIME_END_OF_SOURCE
)
{
// Play the next ad group if it's available.
// Play the next ad group if it's available.
...
...
library/core/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java
View file @
a7ace587
...
@@ -159,6 +159,12 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities
...
@@ -159,6 +159,12 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities
}
}
@Override
@Override
public
final
void
reset
()
{
Assertions
.
checkState
(
state
==
STATE_DISABLED
);
onReset
();
}
@Override
public
boolean
isReady
()
{
public
boolean
isReady
()
{
return
true
;
return
true
;
}
}
...
@@ -260,6 +266,15 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities
...
@@ -260,6 +266,15 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities
// Do nothing.
// Do nothing.
}
}
/**
* Called when the renderer is reset.
*
* <p>The default implementation is a no-op.
*/
protected
void
onReset
()
{
// Do nothing.
}
// Methods to be called by subclasses.
// Methods to be called by subclasses.
/**
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java
View file @
a7ace587
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
;
package
com
.
google
.
android
.
exoplayer2
;
import
android.support.annotation.CheckResult
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.source.MediaSource.MediaPeriodId
;
import
com.google.android.exoplayer2.source.MediaSource.MediaPeriodId
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
...
@@ -40,7 +41,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -40,7 +41,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public
final
MediaPeriodId
periodId
;
public
final
MediaPeriodId
periodId
;
/**
/**
* The start position at which playback started in {@link #periodId} relative to the start of the
* The start position at which playback started in {@link #periodId} relative to the start of the
* associated period in the {@link #timeline}, in microseconds.
* associated period in the {@link #timeline}, in microseconds. Note that this value changes for
* each position discontinuity.
*/
*/
public
final
long
startPositionUs
;
public
final
long
startPositionUs
;
/**
/**
...
@@ -103,6 +105,23 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -103,6 +105,23 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
startPositionUs
);
startPositionUs
);
}
}
/**
* Create playback info.
*
* @param timeline See {@link #timeline}.
* @param manifest See {@link #manifest}.
* @param periodId See {@link #periodId}.
* @param startPositionUs See {@link #startPositionUs}.
* @param contentPositionUs See {@link #contentPositionUs}.
* @param playbackState See {@link #playbackState}.
* @param isLoading See {@link #isLoading}.
* @param trackGroups See {@link #trackGroups}.
* @param trackSelectorResult See {@link #trackSelectorResult}.
* @param loadingMediaPeriodId See {@link #loadingMediaPeriodId}.
* @param bufferedPositionUs See {@link #bufferedPositionUs}.
* @param totalBufferedDurationUs See {@link #totalBufferedDurationUs}.
* @param positionUs See {@link #positionUs}.
*/
public
PlaybackInfo
(
public
PlaybackInfo
(
Timeline
timeline
,
Timeline
timeline
,
@Nullable
Object
manifest
,
@Nullable
Object
manifest
,
...
@@ -132,7 +151,17 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -132,7 +151,17 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
this
.
positionUs
=
positionUs
;
this
.
positionUs
=
positionUs
;
}
}
public
PlaybackInfo
fromNewPosition
(
/**
* Copies playback info and resets playing and loading position.
*
* @param periodId New playing and loading {@link MediaPeriodId}.
* @param startPositionUs New start position. See {@link #startPositionUs}.
* @param contentPositionUs New content position. See {@link #contentPositionUs}. Value is ignored
* if {@code periodId.isAd()} is true.
* @return Copied playback info with reset position.
*/
@CheckResult
public
PlaybackInfo
resetToNewPosition
(
MediaPeriodId
periodId
,
long
startPositionUs
,
long
contentPositionUs
)
{
MediaPeriodId
periodId
,
long
startPositionUs
,
long
contentPositionUs
)
{
return
new
PlaybackInfo
(
return
new
PlaybackInfo
(
timeline
,
timeline
,
...
@@ -150,6 +179,46 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -150,6 +179,46 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
startPositionUs
);
startPositionUs
);
}
}
/**
* Copied playback info with new playing position.
*
* @param periodId New playing media period. See {@link #periodId}.
* @param positionUs New position. See {@link #positionUs}.
* @param contentPositionUs New content position. See {@link #contentPositionUs}. Value is ignored
* if {@code periodId.isAd()} is true.
* @param totalBufferedDurationUs New buffered duration. See {@link #totalBufferedDurationUs}.
* @return Copied playback info with new playing position.
*/
@CheckResult
public
PlaybackInfo
copyWithNewPosition
(
MediaPeriodId
periodId
,
long
positionUs
,
long
contentPositionUs
,
long
totalBufferedDurationUs
)
{
return
new
PlaybackInfo
(
timeline
,
manifest
,
periodId
,
positionUs
,
periodId
.
isAd
()
?
contentPositionUs
:
C
.
TIME_UNSET
,
playbackState
,
isLoading
,
trackGroups
,
trackSelectorResult
,
loadingMediaPeriodId
,
bufferedPositionUs
,
totalBufferedDurationUs
,
positionUs
);
}
/**
* Copies playback info with new timeline and manifest.
*
* @param timeline New timeline. See {@link #timeline}.
* @param manifest New manifest. See {@link #manifest}.
* @return Copied playback info with new timeline and manifest.
*/
@CheckResult
public
PlaybackInfo
copyWithTimeline
(
Timeline
timeline
,
Object
manifest
)
{
public
PlaybackInfo
copyWithTimeline
(
Timeline
timeline
,
Object
manifest
)
{
return
new
PlaybackInfo
(
return
new
PlaybackInfo
(
timeline
,
timeline
,
...
@@ -167,6 +236,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -167,6 +236,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
positionUs
);
positionUs
);
}
}
/**
* Copies playback info with new playback state.
*
* @param playbackState New playback state. See {@link #playbackState}.
* @return Copied playback info with new playback state.
*/
@CheckResult
public
PlaybackInfo
copyWithPlaybackState
(
int
playbackState
)
{
public
PlaybackInfo
copyWithPlaybackState
(
int
playbackState
)
{
return
new
PlaybackInfo
(
return
new
PlaybackInfo
(
timeline
,
timeline
,
...
@@ -184,6 +260,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -184,6 +260,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
positionUs
);
positionUs
);
}
}
/**
* Copies playback info with new loading state.
*
* @param isLoading New loading state. See {@link #isLoading}.
* @return Copied playback info with new loading state.
*/
@CheckResult
public
PlaybackInfo
copyWithIsLoading
(
boolean
isLoading
)
{
public
PlaybackInfo
copyWithIsLoading
(
boolean
isLoading
)
{
return
new
PlaybackInfo
(
return
new
PlaybackInfo
(
timeline
,
timeline
,
...
@@ -201,6 +284,14 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -201,6 +284,14 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
positionUs
);
positionUs
);
}
}
/**
* Copies playback info with new track information.
*
* @param trackGroups New track groups. See {@link #trackGroups}.
* @param trackSelectorResult New track selector result. See {@link #trackSelectorResult}.
* @return Copied playback info with new track information.
*/
@CheckResult
public
PlaybackInfo
copyWithTrackInfo
(
public
PlaybackInfo
copyWithTrackInfo
(
TrackGroupArray
trackGroups
,
TrackSelectorResult
trackSelectorResult
)
{
TrackGroupArray
trackGroups
,
TrackSelectorResult
trackSelectorResult
)
{
return
new
PlaybackInfo
(
return
new
PlaybackInfo
(
...
@@ -219,6 +310,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -219,6 +310,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
positionUs
);
positionUs
);
}
}
/**
* Copies playback info with new loading media period.
*
* @param loadingMediaPeriodId New loading media period id. See {@link #loadingMediaPeriodId}.
* @return Copied playback info with new loading media period.
*/
@CheckResult
public
PlaybackInfo
copyWithLoadingMediaPeriodId
(
MediaPeriodId
loadingMediaPeriodId
)
{
public
PlaybackInfo
copyWithLoadingMediaPeriodId
(
MediaPeriodId
loadingMediaPeriodId
)
{
return
new
PlaybackInfo
(
return
new
PlaybackInfo
(
timeline
,
timeline
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/Renderer.java
View file @
a7ace587
...
@@ -44,12 +44,16 @@ public interface Renderer extends PlayerMessage.Target {
...
@@ -44,12 +44,16 @@ public interface Renderer extends PlayerMessage.Target {
@IntDef
({
STATE_DISABLED
,
STATE_ENABLED
,
STATE_STARTED
})
@IntDef
({
STATE_DISABLED
,
STATE_ENABLED
,
STATE_STARTED
})
@interface
State
{}
@interface
State
{}
/**
/**
* The renderer is disabled.
* The renderer is disabled. A renderer in this state may hold resources that it requires for
* rendering (e.g. media decoders), for use if it's subsequently enabled. {@link #reset()} can be
* called to force the renderer to release these resources.
*/
*/
int
STATE_DISABLED
=
0
;
int
STATE_DISABLED
=
0
;
/**
/**
* The renderer is enabled but not started. A renderer in this state is not actively rendering
* The renderer is enabled but not started. A renderer in this state may render media at the
* media, but will typically hold resources that it requires for rendering (e.g. media decoders).
* current position (e.g. an initial video frame), but the position will not advance. A renderer
* in this state will typically hold resources that it requires for rendering (e.g. media
* decoders).
*/
*/
int
STATE_ENABLED
=
1
;
int
STATE_ENABLED
=
1
;
/**
/**
...
@@ -279,4 +283,12 @@ public interface Renderer extends PlayerMessage.Target {
...
@@ -279,4 +283,12 @@ public interface Renderer extends PlayerMessage.Target {
*/
*/
void
disable
();
void
disable
();
/**
* Forces the renderer to give up any resources (e.g. media decoders) that it may be holding. If
* the renderer is not holding any resources, the call is a no-op.
*
* <p>This method may be called when the renderer is in the following states: {@link
* #STATE_DISABLED}.
*/
void
reset
();
}
}
library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
View file @
a7ace587
...
@@ -351,8 +351,7 @@ public final class DefaultAudioSink implements AudioSink {
...
@@ -351,8 +351,7 @@ public final class DefaultAudioSink implements AudioSink {
channelMappingAudioProcessor
,
channelMappingAudioProcessor
,
trimmingAudioProcessor
);
trimmingAudioProcessor
);
Collections
.
addAll
(
toIntPcmAudioProcessors
,
audioProcessorChain
.
getAudioProcessors
());
Collections
.
addAll
(
toIntPcmAudioProcessors
,
audioProcessorChain
.
getAudioProcessors
());
toIntPcmAvailableAudioProcessors
=
toIntPcmAvailableAudioProcessors
=
toIntPcmAudioProcessors
.
toArray
(
new
AudioProcessor
[
0
]);
toIntPcmAudioProcessors
.
toArray
(
new
AudioProcessor
[
toIntPcmAudioProcessors
.
size
()]);
toFloatPcmAvailableAudioProcessors
=
new
AudioProcessor
[]
{
new
FloatResamplingAudioProcessor
()};
toFloatPcmAvailableAudioProcessors
=
new
AudioProcessor
[]
{
new
FloatResamplingAudioProcessor
()};
volume
=
1.0f
;
volume
=
1.0f
;
startMediaTimeState
=
START_NOT_SET
;
startMediaTimeState
=
START_NOT_SET
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java
View file @
a7ace587
...
@@ -97,7 +97,7 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
...
@@ -97,7 +97,7 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
* @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
* @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
*/
*/
public
DrmInitData
(
List
<
SchemeData
>
schemeDatas
)
{
public
DrmInitData
(
List
<
SchemeData
>
schemeDatas
)
{
this
(
null
,
false
,
schemeDatas
.
toArray
(
new
SchemeData
[
schemeDatas
.
size
()
]));
this
(
null
,
false
,
schemeDatas
.
toArray
(
new
SchemeData
[
0
]));
}
}
/**
/**
...
@@ -105,7 +105,7 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
...
@@ -105,7 +105,7 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
* @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
* @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
*/
*/
public
DrmInitData
(
@Nullable
String
schemeType
,
List
<
SchemeData
>
schemeDatas
)
{
public
DrmInitData
(
@Nullable
String
schemeType
,
List
<
SchemeData
>
schemeDatas
)
{
this
(
schemeType
,
false
,
schemeDatas
.
toArray
(
new
SchemeData
[
schemeDatas
.
size
()
]));
this
(
schemeType
,
false
,
schemeDatas
.
toArray
(
new
SchemeData
[
0
]));
}
}
/**
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java
View file @
a7ace587
...
@@ -81,8 +81,9 @@ public abstract class BinarySearchSeeker {
...
@@ -81,8 +81,9 @@ public abstract class BinarySearchSeeker {
*/
*/
public
static
final
class
OutputFrameHolder
{
public
static
final
class
OutputFrameHolder
{
public
final
ByteBuffer
byteBuffer
;
public
long
timeUs
;
public
long
timeUs
;
public
ByteBuffer
byteBuffer
;
/** Constructs an instance, wrapping the given byte buffer. */
/** Constructs an instance, wrapping the given byte buffer. */
public
OutputFrameHolder
(
ByteBuffer
outputByteBuffer
)
{
public
OutputFrameHolder
(
ByteBuffer
outputByteBuffer
)
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
View file @
a7ace587
...
@@ -157,6 +157,7 @@ public final class MatroskaExtractor implements Extractor {
...
@@ -157,6 +157,7 @@ public final class MatroskaExtractor implements Extractor {
private
static
final
int
ID_FLAG_DEFAULT
=
0x88
;
private
static
final
int
ID_FLAG_DEFAULT
=
0x88
;
private
static
final
int
ID_FLAG_FORCED
=
0x55AA
;
private
static
final
int
ID_FLAG_FORCED
=
0x55AA
;
private
static
final
int
ID_DEFAULT_DURATION
=
0x23E383
;
private
static
final
int
ID_DEFAULT_DURATION
=
0x23E383
;
private
static
final
int
ID_NAME
=
0x536E
;
private
static
final
int
ID_CODEC_ID
=
0x86
;
private
static
final
int
ID_CODEC_ID
=
0x86
;
private
static
final
int
ID_CODEC_PRIVATE
=
0x63A2
;
private
static
final
int
ID_CODEC_PRIVATE
=
0x63A2
;
private
static
final
int
ID_CODEC_DELAY
=
0x56AA
;
private
static
final
int
ID_CODEC_DELAY
=
0x56AA
;
...
@@ -815,6 +816,9 @@ public final class MatroskaExtractor implements Extractor {
...
@@ -815,6 +816,9 @@ public final class MatroskaExtractor implements Extractor {
throw
new
ParserException
(
"DocType "
+
value
+
" not supported"
);
throw
new
ParserException
(
"DocType "
+
value
+
" not supported"
);
}
}
break
;
break
;
case
ID_NAME:
currentTrack
.
name
=
value
;
break
;
case
ID_CODEC_ID:
case
ID_CODEC_ID:
currentTrack
.
codecId
=
value
;
currentTrack
.
codecId
=
value
;
break
;
break
;
...
@@ -1463,6 +1467,7 @@ public final class MatroskaExtractor implements Extractor {
...
@@ -1463,6 +1467,7 @@ public final class MatroskaExtractor implements Extractor {
case
ID_MAX_FALL:
case
ID_MAX_FALL:
return
TYPE_UNSIGNED_INT
;
return
TYPE_UNSIGNED_INT
;
case
ID_DOC_TYPE:
case
ID_DOC_TYPE:
case
ID_NAME:
case
ID_CODEC_ID:
case
ID_CODEC_ID:
case
ID_LANGUAGE:
case
ID_LANGUAGE:
return
TYPE_STRING
;
return
TYPE_STRING
;
...
@@ -1609,6 +1614,7 @@ public final class MatroskaExtractor implements Extractor {
...
@@ -1609,6 +1614,7 @@ public final class MatroskaExtractor implements Extractor {
private
static
final
int
DEFAULT_MAX_FALL
=
200
;
// nits.
private
static
final
int
DEFAULT_MAX_FALL
=
200
;
// nits.
// Common elements.
// Common elements.
public
String
name
;
public
String
codecId
;
public
String
codecId
;
public
int
number
;
public
int
number
;
public
int
type
;
public
int
type
;
...
@@ -1833,10 +1839,34 @@ public final class MatroskaExtractor implements Extractor {
...
@@ -1833,10 +1839,34 @@ public final class MatroskaExtractor implements Extractor {
byte
[]
hdrStaticInfo
=
getHdrStaticInfo
();
byte
[]
hdrStaticInfo
=
getHdrStaticInfo
();
colorInfo
=
new
ColorInfo
(
colorSpace
,
colorRange
,
colorTransfer
,
hdrStaticInfo
);
colorInfo
=
new
ColorInfo
(
colorSpace
,
colorRange
,
colorTransfer
,
hdrStaticInfo
);
}
}
format
=
Format
.
createVideoSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
null
,
int
rotationDegrees
=
Format
.
NO_VALUE
;
Format
.
NO_VALUE
,
maxInputSize
,
width
,
height
,
Format
.
NO_VALUE
,
initializationData
,
// Some HTC devices signal rotation in track names.
Format
.
NO_VALUE
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
colorInfo
,
if
(
"htc_video_rotA-000"
.
equals
(
name
))
{
drmInitData
);
rotationDegrees
=
0
;
}
else
if
(
"htc_video_rotA-090"
.
equals
(
name
))
{
rotationDegrees
=
90
;
}
else
if
(
"htc_video_rotA-180"
.
equals
(
name
))
{
rotationDegrees
=
180
;
}
else
if
(
"htc_video_rotA-270"
.
equals
(
name
))
{
rotationDegrees
=
270
;
}
format
=
Format
.
createVideoSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
/* codecs= */
null
,
/* bitrate= */
Format
.
NO_VALUE
,
maxInputSize
,
width
,
height
,
/* frameRate= */
Format
.
NO_VALUE
,
initializationData
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
colorInfo
,
drmInitData
);
}
else
if
(
MimeTypes
.
APPLICATION_SUBRIP
.
equals
(
mimeType
))
{
}
else
if
(
MimeTypes
.
APPLICATION_SUBRIP
.
equals
(
mimeType
))
{
type
=
C
.
TRACK_TYPE_TEXT
;
type
=
C
.
TRACK_TYPE_TEXT
;
format
=
Format
.
createTextSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
selectionFlags
,
format
=
Format
.
createTextSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
selectionFlags
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java
View file @
a7ace587
...
@@ -423,7 +423,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
...
@@ -423,7 +423,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
}
}
this
.
firstVideoTrackIndex
=
firstVideoTrackIndex
;
this
.
firstVideoTrackIndex
=
firstVideoTrackIndex
;
this
.
durationUs
=
durationUs
;
this
.
durationUs
=
durationUs
;
this
.
tracks
=
tracks
.
toArray
(
new
Mp4Track
[
tracks
.
size
()
]);
this
.
tracks
=
tracks
.
toArray
(
new
Mp4Track
[
0
]);
accumulatedSampleSizes
=
calculateAccumulatedSampleSizes
(
this
.
tracks
);
accumulatedSampleSizes
=
calculateAccumulatedSampleSizes
(
this
.
tracks
);
extractorOutput
.
endTracks
();
extractorOutput
.
endTracks
();
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
View file @
a7ace587
...
@@ -546,9 +546,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -546,9 +546,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
protected
void
onPositionReset
(
long
positionUs
,
boolean
joining
)
throws
ExoPlaybackException
{
protected
void
onPositionReset
(
long
positionUs
,
boolean
joining
)
throws
ExoPlaybackException
{
inputStreamEnded
=
false
;
inputStreamEnded
=
false
;
outputStreamEnded
=
false
;
outputStreamEnded
=
false
;
if
(
codec
!=
null
)
{
flushOrReinitCodec
();
flushCodec
();
}
formatQueue
.
clear
();
formatQueue
.
clear
();
}
}
...
@@ -560,6 +558,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -560,6 +558,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
@Override
@Override
protected
void
onDisabled
()
{
protected
void
onDisabled
()
{
if
(
drmSession
!=
null
||
pendingDrmSession
!=
null
)
{
// TODO: Do something better with this case.
onReset
();
}
else
{
flushOrReleaseCodec
();
}
}
@Override
protected
void
onReset
()
{
format
=
null
;
format
=
null
;
availableCodecInfos
=
null
;
availableCodecInfos
=
null
;
try
{
try
{
...
@@ -687,10 +695,36 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -687,10 +695,36 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
decoderCounters
.
ensureUpdated
();
decoderCounters
.
ensureUpdated
();
}
}
protected
void
flushCodec
()
throws
ExoPlaybackException
{
/**
* Flushes the codec. If flushing is not possible, the codec will be released and re-instantiated.
* This method is a no-op if the codec is {@code null}.
*
* <p>The implementation of this method calls {@link #flushOrReleaseCodec()}, and {@link
* #maybeInitCodec()} if the codec needs to be re-instantiated.
*
* @throws ExoPlaybackException If an error occurs re-instantiating the codec.
*/
protected
final
void
flushOrReinitCodec
()
throws
ExoPlaybackException
{
if
(
flushOrReleaseCodec
())
{
maybeInitCodec
();
}
}
/**
* Flushes the codec. If flushing is not possible, the codec will be released. This method is a
* no-op if the codec is {@code null}.
*
* @return Whether the codec was released.
*/
protected
boolean
flushOrReleaseCodec
()
{
if
(
codec
==
null
)
{
// Nothing to do.
return
false
;
}
codecHotswapDeadlineMs
=
C
.
TIME_UNSET
;
codecHotswapDeadlineMs
=
C
.
TIME_UNSET
;
resetInputBuffer
();
resetInputBuffer
();
resetOutputBuffer
();
resetOutputBuffer
();
codecReceivedBuffers
=
false
;
waitingForFirstSyncFrame
=
true
;
waitingForFirstSyncFrame
=
true
;
waitingForKeys
=
false
;
waitingForKeys
=
false
;
shouldSkipOutputBuffer
=
false
;
shouldSkipOutputBuffer
=
false
;
...
@@ -699,28 +733,27 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -699,28 +733,27 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
shouldSkipAdaptationWorkaroundOutputBuffer
=
false
;
shouldSkipAdaptationWorkaroundOutputBuffer
=
false
;
if
(
codecNeedsFlushWorkaround
||
(
codecNeedsEosFlushWorkaround
&&
codecReceivedEos
))
{
if
(
codecNeedsFlushWorkaround
||
(
codecNeedsEosFlushWorkaround
&&
codecReceivedEos
))
{
releaseCodec
();
releaseCodec
();
maybeInitCodec
()
;
return
true
;
}
else
if
(
codecReinitializationState
!=
REINITIALIZATION_STATE_NONE
)
{
}
else
if
(
codecReinitializationState
!=
REINITIALIZATION_STATE_NONE
)
{
// We're already waiting to re-initialize the codec. Since we're now flushing, there's no need
// We're already waiting to re-initialize the codec. Since we're now flushing, there's no need
// to wait any longer.
// to wait any longer.
if
(
codecReinitializationIsRelease
)
{
if
(
codecReinitializationIsRelease
)
{
releaseCodec
();
releaseCodec
();
maybeInitCodec
()
;
return
true
;
}
else
{
}
else
{
codec
.
flush
();
codec
.
flush
();
codecReceivedBuffers
=
false
;
codecReinitializationState
=
REINITIALIZATION_STATE_NONE
;
codecReinitializationState
=
REINITIALIZATION_STATE_NONE
;
}
}
}
else
{
}
else
{
// We can flush and re-use the existing decoder.
// We can flush and re-use the existing decoder.
codec
.
flush
();
codec
.
flush
();
codecReceivedBuffers
=
false
;
}
}
if
(
codecReconfigured
&&
format
!=
null
)
{
if
(
codecReconfigured
&&
format
!=
null
)
{
// Any reconfiguration data that we send shortly before the flush may be discarded. We
// Any reconfiguration data that we send shortly before the flush may be discarded. We
// avoid this issue by sending reconfiguration data following every flush.
// avoid this issue by sending reconfiguration data following every flush.
codecReconfigurationState
=
RECONFIGURATION_STATE_WRITE_PENDING
;
codecReconfigurationState
=
RECONFIGURATION_STATE_WRITE_PENDING
;
}
}
return
false
;
}
}
private
boolean
initCodecWithFallback
(
MediaCrypto
crypto
,
boolean
drmSessionRequiresSecureDecoder
)
private
boolean
initCodecWithFallback
(
MediaCrypto
crypto
,
boolean
drmSessionRequiresSecureDecoder
)
...
@@ -1496,7 +1529,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1496,7 +1529,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
releaseCodec
();
releaseCodec
();
maybeInitCodec
();
maybeInitCodec
();
}
else
{
}
else
{
flushCodec
();
flush
OrReinit
Codec
();
}
}
}
else
{
}
else
{
outputStreamEnded
=
true
;
outputStreamEnded
=
true
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java
View file @
a7ace587
...
@@ -801,6 +801,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
...
@@ -801,6 +801,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
public
final
MediaSource
mediaSource
;
public
final
MediaSource
mediaSource
;
public
final
Object
uid
;
public
final
Object
uid
;
public
final
List
<
DeferredMediaPeriod
>
activeMediaPeriods
;
public
DeferredTimeline
timeline
;
public
DeferredTimeline
timeline
;
public
int
childIndex
;
public
int
childIndex
;
...
@@ -809,7 +810,6 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
...
@@ -809,7 +810,6 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
public
boolean
hasStartedPreparing
;
public
boolean
hasStartedPreparing
;
public
boolean
isPrepared
;
public
boolean
isPrepared
;
public
boolean
isRemoved
;
public
boolean
isRemoved
;
public
List
<
DeferredMediaPeriod
>
activeMediaPeriods
;
public
MediaSourceHolder
(
MediaSource
mediaSource
)
{
public
MediaSourceHolder
(
MediaSource
mediaSource
)
{
this
.
mediaSource
=
mediaSource
;
this
.
mediaSource
=
mediaSource
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java
View file @
a7ace587
...
@@ -308,7 +308,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
...
@@ -308,7 +308,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
// chunk even if the sample timestamps are slightly offset from the chunk start times.
// chunk even if the sample timestamps are slightly offset from the chunk start times.
seekInsideBuffer
=
seekInsideBuffer
=
primarySampleQueue
.
setReadPosition
(
seekToMediaChunk
.
getFirstSampleIndex
(
0
));
primarySampleQueue
.
setReadPosition
(
seekToMediaChunk
.
getFirstSampleIndex
(
0
));
decodeOnlyUntilPositionUs
=
Long
.
MIN_VALUE
;
decodeOnlyUntilPositionUs
=
0
;
}
else
{
}
else
{
seekInsideBuffer
=
seekInsideBuffer
=
primarySampleQueue
.
advanceTo
(
primarySampleQueue
.
advanceTo
(
...
@@ -583,7 +583,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
...
@@ -583,7 +583,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if
(
pendingReset
)
{
if
(
pendingReset
)
{
boolean
resetToMediaChunk
=
mediaChunk
.
startTimeUs
==
pendingResetPositionUs
;
boolean
resetToMediaChunk
=
mediaChunk
.
startTimeUs
==
pendingResetPositionUs
;
// Only enable setting of the decode only flag if we're not resetting to a chunk boundary.
// Only enable setting of the decode only flag if we're not resetting to a chunk boundary.
decodeOnlyUntilPositionUs
=
resetToMediaChunk
?
Long
.
MIN_VALUE
:
pendingResetPositionUs
;
decodeOnlyUntilPositionUs
=
resetToMediaChunk
?
0
:
pendingResetPositionUs
;
pendingResetPositionUs
=
C
.
TIME_UNSET
;
pendingResetPositionUs
=
C
.
TIME_UNSET
;
}
}
mediaChunk
.
init
(
mediaChunkOutput
);
mediaChunk
.
init
(
mediaChunkOutput
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java
View file @
a7ace587
...
@@ -117,19 +117,6 @@ public final class DefaultAllocator implements Allocator {
...
@@ -117,19 +117,6 @@ public final class DefaultAllocator implements Allocator {
Math
.
max
(
availableAllocations
.
length
*
2
,
availableCount
+
allocations
.
length
));
Math
.
max
(
availableAllocations
.
length
*
2
,
availableCount
+
allocations
.
length
));
}
}
for
(
Allocation
allocation
:
allocations
)
{
for
(
Allocation
allocation
:
allocations
)
{
// Weak sanity check that the allocation probably originated from this pool.
if
(
allocation
.
data
!=
initialAllocationBlock
&&
allocation
.
data
.
length
!=
individualAllocationSize
)
{
throw
new
IllegalArgumentException
(
"Unexpected allocation: "
+
System
.
identityHashCode
(
allocation
.
data
)
+
", "
+
System
.
identityHashCode
(
initialAllocationBlock
)
+
", "
+
allocation
.
data
.
length
+
", "
+
individualAllocationSize
);
}
availableAllocations
[
availableCount
++]
=
allocation
;
availableAllocations
[
availableCount
++]
=
allocation
;
}
}
allocatedCount
-=
allocations
.
length
;
allocatedCount
-=
allocations
.
length
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java
View file @
a7ace587
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream.cache;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream.cache;
import
android.support.annotation.NonNull
;
import
android.support.annotation.NonNull
;
import
com.google.android.exoplayer2.extractor.ChunkIndex
;
import
com.google.android.exoplayer2.extractor.ChunkIndex
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.NavigableSet
;
import
java.util.NavigableSet
;
...
@@ -195,8 +196,7 @@ public final class CachedRegionTracker implements Cache.Listener {
...
@@ -195,8 +196,7 @@ public final class CachedRegionTracker implements Cache.Listener {
@Override
@Override
public
int
compareTo
(
@NonNull
Region
another
)
{
public
int
compareTo
(
@NonNull
Region
another
)
{
return
startOffset
<
another
.
startOffset
?
-
1
return
Util
.
compareLong
(
startOffset
,
another
.
startOffset
);
:
startOffset
==
another
.
startOffset
?
0
:
1
;
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
a7ace587
...
@@ -520,9 +520,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -520,9 +520,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@CallSuper
@CallSuper
@Override
@Override
protected
void
flushCodec
()
throws
ExoPlaybackException
{
protected
boolean
flushOrReleaseCodec
()
{
super
.
flushCodec
();
try
{
buffersInCodecCount
=
0
;
return
super
.
flushOrReleaseCodec
();
}
finally
{
buffersInCodecCount
=
0
;
}
}
}
@Override
@Override
...
@@ -859,7 +862,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -859,7 +862,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// We dropped some buffers to catch up, so update the decoder counters and flush the codec,
// We dropped some buffers to catch up, so update the decoder counters and flush the codec,
// which releases all pending buffers buffers including the current output buffer.
// which releases all pending buffers buffers including the current output buffer.
updateDroppedBufferCounters
(
buffersInCodecCount
+
droppedSourceBufferCount
);
updateDroppedBufferCounters
(
buffersInCodecCount
+
droppedSourceBufferCount
);
flushCodec
();
flush
OrReinit
Codec
();
return
true
;
return
true
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java
View file @
a7ace587
...
@@ -72,12 +72,12 @@ public class CameraMotionRenderer extends BaseRenderer {
...
@@ -72,12 +72,12 @@ public class CameraMotionRenderer extends BaseRenderer {
@Override
@Override
protected
void
onPositionReset
(
long
positionUs
,
boolean
joining
)
throws
ExoPlaybackException
{
protected
void
onPositionReset
(
long
positionUs
,
boolean
joining
)
throws
ExoPlaybackException
{
reset
();
reset
Listener
();
}
}
@Override
@Override
protected
void
onDisabled
()
{
protected
void
onDisabled
()
{
reset
();
reset
Listener
();
}
}
@Override
@Override
...
@@ -124,7 +124,7 @@ public class CameraMotionRenderer extends BaseRenderer {
...
@@ -124,7 +124,7 @@ public class CameraMotionRenderer extends BaseRenderer {
return
result
;
return
result
;
}
}
private
void
reset
()
{
private
void
reset
Listener
()
{
lastTimestampUs
=
0
;
lastTimestampUs
=
0
;
if
(
listener
!=
null
)
{
if
(
listener
!=
null
)
{
listener
.
onCameraMotionReset
();
listener
.
onCameraMotionReset
();
...
...
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
View file @
a7ace587
...
@@ -2534,6 +2534,59 @@ public final class ExoPlayerTest {
...
@@ -2534,6 +2534,59 @@ public final class ExoPlayerTest {
assertThat
(
positionWhenReady
.
get
()).
isEqualTo
(
periodDurationMs
+
10
);
assertThat
(
positionWhenReady
.
get
()).
isEqualTo
(
periodDurationMs
+
10
);
}
}
@Test
public
void
periodTransitionReportsCorrectBufferedPosition
()
throws
Exception
{
int
periodCount
=
3
;
long
periodDurationUs
=
5
*
C
.
MICROS_PER_SECOND
;
long
windowDurationUs
=
periodCount
*
periodDurationUs
;
Timeline
timeline
=
new
FakeTimeline
(
new
TimelineWindowDefinition
(
periodCount
,
/* id= */
new
Object
(),
/* isSeekable= */
true
,
/* isDynamic= */
false
,
windowDurationUs
));
AtomicReference
<
Player
>
playerReference
=
new
AtomicReference
<>();
AtomicLong
bufferedPositionAtFirstDiscontinuityMs
=
new
AtomicLong
(
C
.
TIME_UNSET
);
EventListener
eventListener
=
new
EventListener
()
{
@Override
public
void
onPositionDiscontinuity
(
@DiscontinuityReason
int
reason
)
{
if
(
reason
==
Player
.
DISCONTINUITY_REASON_PERIOD_TRANSITION
)
{
if
(
bufferedPositionAtFirstDiscontinuityMs
.
get
()
==
C
.
TIME_UNSET
)
{
bufferedPositionAtFirstDiscontinuityMs
.
set
(
playerReference
.
get
().
getBufferedPosition
());
}
}
}
};
ActionSchedule
actionSchedule
=
new
ActionSchedule
.
Builder
(
"periodTransitionReportsCorrectBufferedPosition"
)
.
executeRunnable
(
new
PlayerRunnable
()
{
@Override
public
void
run
(
SimpleExoPlayer
player
)
{
playerReference
.
set
(
player
);
player
.
addListener
(
eventListener
);
}
})
.
pause
()
// Wait until all periods are fully buffered.
.
waitForIsLoading
(
/* targetIsLoading= */
true
)
.
waitForIsLoading
(
/* targetIsLoading= */
false
)
.
play
()
.
build
();
new
Builder
()
.
setTimeline
(
timeline
)
.
setActionSchedule
(
actionSchedule
)
.
build
(
context
)
.
start
()
.
blockUntilEnded
(
TIMEOUT_MS
);
assertThat
(
bufferedPositionAtFirstDiscontinuityMs
.
get
()).
isEqualTo
(
C
.
usToMs
(
windowDurationUs
));
}
// Internal methods.
// Internal methods.
private
static
ActionSchedule
.
Builder
addSurfaceSwitch
(
ActionSchedule
.
Builder
builder
)
{
private
static
ActionSchedule
.
Builder
addSurfaceSwitch
(
ActionSchedule
.
Builder
builder
)
{
...
...
library/core/src/test/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRendererTest.java
View file @
a7ace587
...
@@ -103,6 +103,7 @@ public class SimpleDecoderAudioRendererTest {
...
@@ -103,6 +103,7 @@ public class SimpleDecoderAudioRendererTest {
}
}
verify
(
mockAudioSink
,
times
(
1
)).
playToEndOfStream
();
verify
(
mockAudioSink
,
times
(
1
)).
playToEndOfStream
();
audioRenderer
.
disable
();
audioRenderer
.
disable
();
audioRenderer
.
reset
();
verify
(
mockAudioSink
,
times
(
1
)).
release
();
verify
(
mockAudioSink
,
times
(
1
)).
release
();
}
}
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
View file @
a7ace587
...
@@ -544,7 +544,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
...
@@ -544,7 +544,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
long
endTimeUs
=
representationHolder
.
getSegmentEndTimeUs
(
firstSegmentNum
+
segmentCount
-
1
);
long
endTimeUs
=
representationHolder
.
getSegmentEndTimeUs
(
firstSegmentNum
+
segmentCount
-
1
);
long
periodDurationUs
=
representationHolder
.
periodDurationUs
;
long
periodDurationUs
=
representationHolder
.
periodDurationUs
;
long
clippedEndTimeUs
=
long
clippedEndTimeUs
=
periodDurationUs
!=
C
.
TIME_UNSET
&&
periodDurationUs
<
endTimeUs
periodDurationUs
!=
C
.
TIME_UNSET
&&
periodDurationUs
<
=
endTimeUs
?
periodDurationUs
?
periodDurationUs
:
C
.
TIME_UNSET
;
:
C
.
TIME_UNSET
;
DataSpec
dataSpec
=
new
DataSpec
(
segmentUri
.
resolveUri
(
baseUrl
),
DataSpec
dataSpec
=
new
DataSpec
(
segmentUri
.
resolveUri
(
baseUrl
),
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
View file @
a7ace587
...
@@ -158,6 +158,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -158,6 +158,8 @@ public class DashManifestParser extends DefaultHandler
:
(
period
.
startMs
+
periodDurationMs
);
:
(
period
.
startMs
+
periodDurationMs
);
periods
.
add
(
period
);
periods
.
add
(
period
);
}
}
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"MPD"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"MPD"
));
...
@@ -224,6 +226,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -224,6 +226,8 @@ public class DashManifestParser extends DefaultHandler
segmentBase
=
parseSegmentList
(
xpp
,
null
);
segmentBase
=
parseSegmentList
(
xpp
,
null
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
segmentBase
=
parseSegmentTemplate
(
xpp
,
null
);
segmentBase
=
parseSegmentTemplate
(
xpp
,
null
);
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"Period"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"Period"
));
...
@@ -412,22 +416,26 @@ public class DashManifestParser extends DefaultHandler
...
@@ -412,22 +416,26 @@ public class DashManifestParser extends DefaultHandler
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"widevine:license"
))
{
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"widevine:license"
))
{
String
robustnessLevel
=
xpp
.
getAttributeValue
(
null
,
"robustness_level"
);
String
robustnessLevel
=
xpp
.
getAttributeValue
(
null
,
"robustness_level"
);
requiresSecureDecoder
=
robustnessLevel
!=
null
&&
robustnessLevel
.
startsWith
(
"HW"
);
requiresSecureDecoder
=
robustnessLevel
!=
null
&&
robustnessLevel
.
startsWith
(
"HW"
);
}
else
if
(
data
==
null
)
{
}
else
if
(
data
==
null
if
(
XmlPullParserUtil
.
isStartTagIgnorePrefix
(
xpp
,
"pssh"
)
&&
XmlPullParserUtil
.
isStartTagIgnorePrefix
(
xpp
,
"pssh"
)
&&
xpp
.
next
()
==
XmlPullParser
.
TEXT
)
{
&&
xpp
.
next
()
==
XmlPullParser
.
TEXT
)
{
// The cenc:pssh element is defined in 23001-7:2015.
// The cenc:pssh element is defined in 23001-7:2015.
data
=
Base64
.
decode
(
xpp
.
getText
(),
Base64
.
DEFAULT
);
data
=
Base64
.
decode
(
xpp
.
getText
(),
Base64
.
DEFAULT
);
uuid
=
PsshAtomUtil
.
parseUuid
(
data
);
uuid
=
PsshAtomUtil
.
parseUuid
(
data
);
if
(
uuid
==
null
)
{
if
(
uuid
==
null
)
{
Log
.
w
(
TAG
,
"Skipping malformed cenc:pssh data"
);
Log
.
w
(
TAG
,
"Skipping malformed cenc:pssh data"
);
data
=
null
;
data
=
null
;
}
}
else
if
(
C
.
PLAYREADY_UUID
.
equals
(
uuid
)
&&
XmlPullParserUtil
.
isStartTag
(
xpp
,
"mspr:pro"
)
&&
xpp
.
next
()
==
XmlPullParser
.
TEXT
)
{
// The mspr:pro element is defined in DASH Content Protection using Microsoft PlayReady.
data
=
PsshAtomUtil
.
buildPsshAtom
(
C
.
PLAYREADY_UUID
,
Base64
.
decode
(
xpp
.
getText
(),
Base64
.
DEFAULT
));
}
}
}
else
if
(
data
==
null
&&
C
.
PLAYREADY_UUID
.
equals
(
uuid
)
&&
XmlPullParserUtil
.
isStartTag
(
xpp
,
"mspr:pro"
)
&&
xpp
.
next
()
==
XmlPullParser
.
TEXT
)
{
// The mspr:pro element is defined in DASH Content Protection using Microsoft PlayReady.
data
=
PsshAtomUtil
.
buildPsshAtom
(
C
.
PLAYREADY_UUID
,
Base64
.
decode
(
xpp
.
getText
(),
Base64
.
DEFAULT
));
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"ContentProtection"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"ContentProtection"
));
SchemeData
schemeData
=
SchemeData
schemeData
=
...
@@ -465,7 +473,7 @@ public class DashManifestParser extends DefaultHandler
...
@@ -465,7 +473,7 @@ public class DashManifestParser extends DefaultHandler
*/
*/
protected
void
parseAdaptationSetChild
(
XmlPullParser
xpp
)
protected
void
parseAdaptationSetChild
(
XmlPullParser
xpp
)
throws
XmlPullParserException
,
IOException
{
throws
XmlPullParserException
,
IOException
{
// pass
maybeSkipTag
(
xpp
);
}
}
// Representation parsing.
// Representation parsing.
...
@@ -529,6 +537,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -529,6 +537,8 @@ public class DashManifestParser extends DefaultHandler
inbandEventStreams
.
add
(
parseDescriptor
(
xpp
,
"InbandEventStream"
));
inbandEventStreams
.
add
(
parseDescriptor
(
xpp
,
"InbandEventStream"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SupplementalProperty"
))
{
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SupplementalProperty"
))
{
supplementalProperties
.
add
(
parseDescriptor
(
xpp
,
"SupplementalProperty"
));
supplementalProperties
.
add
(
parseDescriptor
(
xpp
,
"SupplementalProperty"
));
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"Representation"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"Representation"
));
...
@@ -667,6 +677,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -667,6 +677,8 @@ public class DashManifestParser extends DefaultHandler
xpp
.
next
();
xpp
.
next
();
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"Initialization"
))
{
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"Initialization"
))
{
initialization
=
parseInitialization
(
xpp
);
initialization
=
parseInitialization
(
xpp
);
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentBase"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentBase"
));
...
@@ -704,6 +716,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -704,6 +716,8 @@ public class DashManifestParser extends DefaultHandler
segments
=
new
ArrayList
<>();
segments
=
new
ArrayList
<>();
}
}
segments
.
add
(
parseSegmentUrl
(
xpp
));
segments
.
add
(
parseSegmentUrl
(
xpp
));
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentList"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentList"
));
...
@@ -750,6 +764,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -750,6 +764,8 @@ public class DashManifestParser extends DefaultHandler
initialization
=
parseInitialization
(
xpp
);
initialization
=
parseInitialization
(
xpp
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTimeline"
))
{
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTimeline"
))
{
timeline
=
parseSegmentTimeline
(
xpp
);
timeline
=
parseSegmentTimeline
(
xpp
);
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentTemplate"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentTemplate"
));
...
@@ -797,6 +813,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -797,6 +813,8 @@ public class DashManifestParser extends DefaultHandler
EventMessage
event
=
parseEvent
(
xpp
,
schemeIdUri
,
value
,
timescale
,
EventMessage
event
=
parseEvent
(
xpp
,
schemeIdUri
,
value
,
timescale
,
scratchOutputStream
);
scratchOutputStream
);
eventMessages
.
add
(
event
);
eventMessages
.
add
(
event
);
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"EventStream"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"EventStream"
));
...
@@ -935,6 +953,8 @@ public class DashManifestParser extends DefaultHandler
...
@@ -935,6 +953,8 @@ public class DashManifestParser extends DefaultHandler
segmentTimeline
.
add
(
buildSegmentTimelineElement
(
elapsedTime
,
duration
));
segmentTimeline
.
add
(
buildSegmentTimelineElement
(
elapsedTime
,
duration
));
elapsedTime
+=
duration
;
elapsedTime
+=
duration
;
}
}
}
else
{
maybeSkipTag
(
xpp
);
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentTimeline"
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentTimeline"
));
return
segmentTimeline
;
return
segmentTimeline
;
...
@@ -1018,6 +1038,29 @@ public class DashManifestParser extends DefaultHandler
...
@@ -1018,6 +1038,29 @@ public class DashManifestParser extends DefaultHandler
// Utility methods.
// Utility methods.
/**
/**
* If the provided {@link XmlPullParser} is currently positioned at the start of a tag, skips
* forward to the end of that tag.
*
* @param xpp The {@link XmlPullParser}.
* @throws XmlPullParserException If an error occurs parsing the stream.
* @throws IOException If an error occurs reading the stream.
*/
public
static
void
maybeSkipTag
(
XmlPullParser
xpp
)
throws
IOException
,
XmlPullParserException
{
if
(!
XmlPullParserUtil
.
isStartTag
(
xpp
))
{
return
;
}
int
depth
=
1
;
while
(
depth
!=
0
)
{
xpp
.
next
();
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
))
{
depth
++;
}
else
if
(
XmlPullParserUtil
.
isEndTag
(
xpp
))
{
depth
--;
}
}
}
/**
* Removes unnecessary {@link SchemeData}s with null {@link SchemeData#data}.
* Removes unnecessary {@link SchemeData}s with null {@link SchemeData#data}.
*/
*/
private
static
void
filterRedundantIncompleteSchemeDatas
(
ArrayList
<
SchemeData
>
schemeDatas
)
{
private
static
void
filterRedundantIncompleteSchemeDatas
(
ArrayList
<
SchemeData
>
schemeDatas
)
{
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
View file @
a7ace587
...
@@ -1032,6 +1032,12 @@ public class PlayerView extends FrameLayout {
...
@@ -1032,6 +1032,12 @@ public class PlayerView extends FrameLayout {
if
(
ev
.
getActionMasked
()
!=
MotionEvent
.
ACTION_DOWN
)
{
if
(
ev
.
getActionMasked
()
!=
MotionEvent
.
ACTION_DOWN
)
{
return
false
;
return
false
;
}
}
return
performClick
();
}
@Override
public
boolean
performClick
()
{
super
.
performClick
();
return
toggleControllerVisibility
();
return
toggleControllerVisibility
();
}
}
...
...
library/ui/src/main/res/values-mr/strings.xml
View file @
a7ace587
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
<string
name=
"exo_controls_repeat_one_description"
>
एक रीपीट करा
</string>
<string
name=
"exo_controls_repeat_one_description"
>
एक रीपीट करा
</string>
<string
name=
"exo_controls_repeat_all_description"
>
सर्व रीपीट करा
</string>
<string
name=
"exo_controls_repeat_all_description"
>
सर्व रीपीट करा
</string>
<string
name=
"exo_controls_shuffle_description"
>
शफल करा
</string>
<string
name=
"exo_controls_shuffle_description"
>
शफल करा
</string>
<string
name=
"exo_controls_fullscreen_description"
>
पूर्ण
स्क्रीन मोड
</string>
<string
name=
"exo_controls_fullscreen_description"
>
फुल
स्क्रीन मोड
</string>
<string
name=
"exo_download_description"
>
डाउनलोड करा
</string>
<string
name=
"exo_download_description"
>
डाउनलोड करा
</string>
<string
name=
"exo_download_notification_channel_name"
>
डाउनलोड
</string>
<string
name=
"exo_download_notification_channel_name"
>
डाउनलोड
</string>
<string
name=
"exo_download_downloading"
>
डाउनलोड होत आहे
</string>
<string
name=
"exo_download_downloading"
>
डाउनलोड होत आहे
</string>
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java
View file @
a7ace587
...
@@ -687,6 +687,56 @@ public abstract class Action {
...
@@ -687,6 +687,56 @@ public abstract class Action {
}
}
/**
/**
* Waits for a specified loading state, returning either immediately or after a call to {@link
* Player.EventListener#onLoadingChanged(boolean)}.
*/
public
static
final
class
WaitForIsLoading
extends
Action
{
private
final
boolean
targetIsLoading
;
/**
* @param tag A tag to use for logging.
* @param targetIsLoading The loading state to wait for.
*/
public
WaitForIsLoading
(
String
tag
,
boolean
targetIsLoading
)
{
super
(
tag
,
"WaitForIsLoading"
);
this
.
targetIsLoading
=
targetIsLoading
;
}
@Override
protected
void
doActionAndScheduleNextImpl
(
final
SimpleExoPlayer
player
,
final
DefaultTrackSelector
trackSelector
,
final
Surface
surface
,
final
HandlerWrapper
handler
,
final
ActionNode
nextAction
)
{
if
(
nextAction
==
null
)
{
return
;
}
if
(
targetIsLoading
==
player
.
isLoading
())
{
nextAction
.
schedule
(
player
,
trackSelector
,
surface
,
handler
);
}
else
{
player
.
addListener
(
new
Player
.
EventListener
()
{
@Override
public
void
onLoadingChanged
(
boolean
isLoading
)
{
if
(
targetIsLoading
==
isLoading
)
{
player
.
removeListener
(
this
);
nextAction
.
schedule
(
player
,
trackSelector
,
surface
,
handler
);
}
}
});
}
}
@Override
protected
void
doActionImpl
(
SimpleExoPlayer
player
,
DefaultTrackSelector
trackSelector
,
Surface
surface
)
{
// Not triggered.
}
}
/**
* Waits for {@link Player.EventListener#onSeekProcessed()}.
* Waits for {@link Player.EventListener#onSeekProcessed()}.
*/
*/
public
static
final
class
WaitForSeekProcessed
extends
Action
{
public
static
final
class
WaitForSeekProcessed
extends
Action
{
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/ActionSchedule.java
View file @
a7ace587
...
@@ -41,6 +41,7 @@ import com.google.android.exoplayer2.testutil.Action.SetShuffleModeEnabled;
...
@@ -41,6 +41,7 @@ import com.google.android.exoplayer2.testutil.Action.SetShuffleModeEnabled;
import
com.google.android.exoplayer2.testutil.Action.SetVideoSurface
;
import
com.google.android.exoplayer2.testutil.Action.SetVideoSurface
;
import
com.google.android.exoplayer2.testutil.Action.Stop
;
import
com.google.android.exoplayer2.testutil.Action.Stop
;
import
com.google.android.exoplayer2.testutil.Action.ThrowPlaybackException
;
import
com.google.android.exoplayer2.testutil.Action.ThrowPlaybackException
;
import
com.google.android.exoplayer2.testutil.Action.WaitForIsLoading
;
import
com.google.android.exoplayer2.testutil.Action.WaitForPlaybackState
;
import
com.google.android.exoplayer2.testutil.Action.WaitForPlaybackState
;
import
com.google.android.exoplayer2.testutil.Action.WaitForPositionDiscontinuity
;
import
com.google.android.exoplayer2.testutil.Action.WaitForPositionDiscontinuity
;
import
com.google.android.exoplayer2.testutil.Action.WaitForSeekProcessed
;
import
com.google.android.exoplayer2.testutil.Action.WaitForSeekProcessed
;
...
@@ -415,6 +416,16 @@ public final class ActionSchedule {
...
@@ -415,6 +416,16 @@ public final class ActionSchedule {
}
}
/**
/**
* Schedules a delay until {@code player.isLoading()} changes to the specified value.
*
* @param targetIsLoading The target value of {@code player.isLoading()}.
* @return The builder, for convenience.
*/
public
Builder
waitForIsLoading
(
boolean
targetIsLoading
)
{
return
apply
(
new
WaitForIsLoading
(
tag
,
targetIsLoading
));
}
/**
* Schedules a {@link Runnable} to be executed.
* Schedules a {@link Runnable} to be executed.
*
*
* @return The builder, for convenience.
* @return The builder, for convenience.
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/DebugRenderersFactory.java
View file @
a7ace587
...
@@ -105,9 +105,12 @@ public class DebugRenderersFactory extends DefaultRenderersFactory {
...
@@ -105,9 +105,12 @@ public class DebugRenderersFactory extends DefaultRenderersFactory {
}
}
@Override
@Override
protected
void
flushCodec
()
throws
ExoPlaybackException
{
protected
boolean
flushOrReleaseCodec
()
{
super
.
flushCodec
();
try
{
clearTimestamps
();
return
super
.
flushOrReleaseCodec
();
}
finally
{
clearTimestamps
();
}
}
}
@Override
@Override
...
...
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