mirror of
https://github.com/androidx/media.git
synced 2025-05-05 06:30:24 +08:00
commit
2f8c31d173
@ -1,5 +1,12 @@
|
|||||||
# Release notes #
|
# Release notes #
|
||||||
|
|
||||||
|
### r2.5.1 ###
|
||||||
|
|
||||||
|
* Fix an issue that could cause the reported playback position to stop advancing
|
||||||
|
in some cases.
|
||||||
|
* Fix an issue where a Surface could be released whilst still in use by the
|
||||||
|
player.
|
||||||
|
|
||||||
### r2.5.0 ###
|
### r2.5.0 ###
|
||||||
|
|
||||||
* IMA extension: Wraps the Google Interactive Media Ads (IMA) SDK to provide an
|
* IMA extension: Wraps the Google Interactive Media Ads (IMA) SDK to provide an
|
||||||
|
@ -24,7 +24,7 @@ project.ext {
|
|||||||
supportLibraryVersion = '25.4.0'
|
supportLibraryVersion = '25.4.0'
|
||||||
dexmakerVersion = '1.2'
|
dexmakerVersion = '1.2'
|
||||||
mockitoVersion = '1.9.5'
|
mockitoVersion = '1.9.5'
|
||||||
releaseVersion = 'r2.5.0'
|
releaseVersion = 'r2.5.1'
|
||||||
modulePrefix = ':'
|
modulePrefix = ':'
|
||||||
if (gradle.ext.has('exoplayerModulePrefix')) {
|
if (gradle.ext.has('exoplayerModulePrefix')) {
|
||||||
modulePrefix += gradle.ext.exoplayerModulePrefix
|
modulePrefix += gradle.ext.exoplayerModulePrefix
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.google.android.exoplayer2.demo"
|
package="com.google.android.exoplayer2.demo"
|
||||||
android:versionCode="2500"
|
android:versionCode="2501"
|
||||||
android:versionName="2.5.0">
|
android:versionName="2.5.1">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
@ -975,11 +975,10 @@ import java.io.IOException;
|
|||||||
mediaPeriodInfoSequence.setTimeline(timeline);
|
mediaPeriodInfoSequence.setTimeline(timeline);
|
||||||
Object manifest = timelineAndManifest.second;
|
Object manifest = timelineAndManifest.second;
|
||||||
|
|
||||||
int processedInitialSeekCount = 0;
|
|
||||||
if (oldTimeline == null) {
|
if (oldTimeline == null) {
|
||||||
if (pendingInitialSeekCount > 0) {
|
if (pendingInitialSeekCount > 0) {
|
||||||
Pair<Integer, Long> periodPosition = resolveSeekPosition(pendingSeekPosition);
|
Pair<Integer, Long> periodPosition = resolveSeekPosition(pendingSeekPosition);
|
||||||
processedInitialSeekCount = pendingInitialSeekCount;
|
int processedInitialSeekCount = pendingInitialSeekCount;
|
||||||
pendingInitialSeekCount = 0;
|
pendingInitialSeekCount = 0;
|
||||||
pendingSeekPosition = null;
|
pendingSeekPosition = null;
|
||||||
if (periodPosition == null) {
|
if (periodPosition == null) {
|
||||||
@ -996,7 +995,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
} else if (playbackInfo.startPositionUs == C.TIME_UNSET) {
|
} else if (playbackInfo.startPositionUs == C.TIME_UNSET) {
|
||||||
if (timeline.isEmpty()) {
|
if (timeline.isEmpty()) {
|
||||||
handleSourceInfoRefreshEndedPlayback(manifest, processedInitialSeekCount);
|
handleSourceInfoRefreshEndedPlayback(manifest);
|
||||||
} else {
|
} else {
|
||||||
Pair<Integer, Long> defaultPosition = getPeriodPosition(0, C.TIME_UNSET);
|
Pair<Integer, Long> defaultPosition = getPeriodPosition(0, C.TIME_UNSET);
|
||||||
int periodIndex = defaultPosition.first;
|
int periodIndex = defaultPosition.first;
|
||||||
@ -1005,8 +1004,10 @@ import java.io.IOException;
|
|||||||
startPositionUs);
|
startPositionUs);
|
||||||
playbackInfo = new PlaybackInfo(periodId, periodId.isAd() ? 0 : startPositionUs,
|
playbackInfo = new PlaybackInfo(periodId, periodId.isAd() ? 0 : startPositionUs,
|
||||||
startPositionUs);
|
startPositionUs);
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
notifySourceInfoRefresh(manifest);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1015,7 +1016,7 @@ import java.io.IOException;
|
|||||||
MediaPeriodHolder periodHolder = playingPeriodHolder != null ? playingPeriodHolder
|
MediaPeriodHolder periodHolder = playingPeriodHolder != null ? playingPeriodHolder
|
||||||
: loadingPeriodHolder;
|
: loadingPeriodHolder;
|
||||||
if (periodHolder == null && playingPeriodIndex >= oldTimeline.getPeriodCount()) {
|
if (periodHolder == null && playingPeriodIndex >= oldTimeline.getPeriodCount()) {
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Object playingPeriodUid = periodHolder == null
|
Object playingPeriodUid = periodHolder == null
|
||||||
@ -1027,7 +1028,7 @@ import java.io.IOException;
|
|||||||
int newPeriodIndex = resolveSubsequentPeriod(playingPeriodIndex, oldTimeline, timeline);
|
int newPeriodIndex = resolveSubsequentPeriod(playingPeriodIndex, oldTimeline, timeline);
|
||||||
if (newPeriodIndex == C.INDEX_UNSET) {
|
if (newPeriodIndex == C.INDEX_UNSET) {
|
||||||
// We failed to resolve a suitable restart position.
|
// We failed to resolve a suitable restart position.
|
||||||
handleSourceInfoRefreshEndedPlayback(manifest, processedInitialSeekCount);
|
handleSourceInfoRefreshEndedPlayback(manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We resolved a subsequent period. Seek to the default position in the corresponding window.
|
// We resolved a subsequent period. Seek to the default position in the corresponding window.
|
||||||
@ -1055,7 +1056,7 @@ import java.io.IOException;
|
|||||||
MediaPeriodId periodId = new MediaPeriodId(newPeriodIndex);
|
MediaPeriodId periodId = new MediaPeriodId(newPeriodIndex);
|
||||||
newPositionUs = seekToPeriodPosition(periodId, newPositionUs);
|
newPositionUs = seekToPeriodPosition(periodId, newPositionUs);
|
||||||
playbackInfo = new PlaybackInfo(periodId, newPositionUs);
|
playbackInfo = new PlaybackInfo(periodId, newPositionUs);
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,14 +1073,14 @@ import java.io.IOException;
|
|||||||
long newPositionUs = seekToPeriodPosition(periodId, playbackInfo.contentPositionUs);
|
long newPositionUs = seekToPeriodPosition(periodId, playbackInfo.contentPositionUs);
|
||||||
long contentPositionUs = periodId.isAd() ? playbackInfo.contentPositionUs : C.TIME_UNSET;
|
long contentPositionUs = periodId.isAd() ? playbackInfo.contentPositionUs : C.TIME_UNSET;
|
||||||
playbackInfo = new PlaybackInfo(periodId, newPositionUs, contentPositionUs);
|
playbackInfo = new PlaybackInfo(periodId, newPositionUs, contentPositionUs);
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (periodHolder == null) {
|
if (periodHolder == null) {
|
||||||
// We don't have any period holders, so we're done.
|
// We don't have any period holders, so we're done.
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,7 +1118,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaPeriodHolder updatePeriodInfo(MediaPeriodHolder periodHolder, int periodIndex) {
|
private MediaPeriodHolder updatePeriodInfo(MediaPeriodHolder periodHolder, int periodIndex) {
|
||||||
@ -1131,6 +1132,10 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleSourceInfoRefreshEndedPlayback(Object manifest) {
|
||||||
|
handleSourceInfoRefreshEndedPlayback(manifest, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleSourceInfoRefreshEndedPlayback(Object manifest,
|
private void handleSourceInfoRefreshEndedPlayback(Object manifest,
|
||||||
int processedInitialSeekCount) {
|
int processedInitialSeekCount) {
|
||||||
// Set the playback position to (0,0) for notifying the eventHandler.
|
// Set the playback position to (0,0) for notifying the eventHandler.
|
||||||
@ -1143,6 +1148,10 @@ import java.io.IOException;
|
|||||||
resetInternal(false);
|
resetInternal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifySourceInfoRefresh(Object manifest) {
|
||||||
|
notifySourceInfoRefresh(manifest, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private void notifySourceInfoRefresh(Object manifest, int processedInitialSeekCount) {
|
private void notifySourceInfoRefresh(Object manifest, int processedInitialSeekCount) {
|
||||||
eventHandler.obtainMessage(MSG_SOURCE_INFO_REFRESHED,
|
eventHandler.obtainMessage(MSG_SOURCE_INFO_REFRESHED,
|
||||||
new SourceInfo(timeline, manifest, playbackInfo, processedInitialSeekCount)).sendToTarget();
|
new SourceInfo(timeline, manifest, playbackInfo, processedInitialSeekCount)).sendToTarget();
|
||||||
|
@ -31,13 +31,13 @@ public final class ExoPlayerLibraryInfo {
|
|||||||
* The version of the library expressed as a string, for example "1.2.3".
|
* The version of the library expressed as a string, for example "1.2.3".
|
||||||
*/
|
*/
|
||||||
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
|
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
|
||||||
public static final String VERSION = "2.5.0";
|
public static final String VERSION = "2.5.1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}.
|
* The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}.
|
||||||
*/
|
*/
|
||||||
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
||||||
public static final String VERSION_SLASHY = "ExoPlayerLib/2.5.0";
|
public static final String VERSION_SLASHY = "ExoPlayerLib/2.5.1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The version of the library expressed as an integer, for example 1002003.
|
* The version of the library expressed as an integer, for example 1002003.
|
||||||
@ -47,7 +47,7 @@ public final class ExoPlayerLibraryInfo {
|
|||||||
* integer version 123045006 (123-045-006).
|
* integer version 123045006 (123-045-006).
|
||||||
*/
|
*/
|
||||||
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
||||||
public static final int VERSION_INT = 2005000;
|
public static final int VERSION_INT = 2005001;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
|
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
|
||||||
|
@ -749,12 +749,12 @@ public class SimpleExoPlayer implements ExoPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.surface != null && this.surface != surface) {
|
if (this.surface != null && this.surface != surface) {
|
||||||
// If we created this surface, we are responsible for releasing it.
|
// We're replacing a surface. Block to ensure that it's not accessed after the method returns.
|
||||||
|
player.blockingSendMessages(messages);
|
||||||
|
// If we created the previous surface, we are responsible for releasing it.
|
||||||
if (this.ownsSurface) {
|
if (this.ownsSurface) {
|
||||||
this.surface.release();
|
this.surface.release();
|
||||||
}
|
}
|
||||||
// We're replacing a surface. Block to ensure that it's not accessed after the method returns.
|
|
||||||
player.blockingSendMessages(messages);
|
|
||||||
} else {
|
} else {
|
||||||
player.sendMessages(messages);
|
player.sendMessages(messages);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,9 @@ public final class ClippingMediaSource implements MediaSource, MediaSource.Liste
|
|||||||
* start providing samples, in microseconds.
|
* start providing samples, in microseconds.
|
||||||
* @param endPositionUs The end position within {@code mediaSource}'s timeline at which to stop
|
* @param endPositionUs The end position within {@code mediaSource}'s timeline at which to stop
|
||||||
* providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples
|
* providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples
|
||||||
* from the specified start point up to the end of the source.
|
* from the specified start point up to the end of the source. Specifying a position that
|
||||||
|
* exceeds the {@code mediaSource}'s duration will also result in the end of the source not
|
||||||
|
* being clipped.
|
||||||
*/
|
*/
|
||||||
public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs) {
|
public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs) {
|
||||||
this(mediaSource, startPositionUs, endPositionUs, true);
|
this(mediaSource, startPositionUs, endPositionUs, true);
|
||||||
@ -66,7 +68,9 @@ public final class ClippingMediaSource implements MediaSource, MediaSource.Liste
|
|||||||
* start providing samples, in microseconds.
|
* start providing samples, in microseconds.
|
||||||
* @param endPositionUs The end position within {@code mediaSource}'s timeline at which to stop
|
* @param endPositionUs The end position within {@code mediaSource}'s timeline at which to stop
|
||||||
* providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples
|
* providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples
|
||||||
* from the specified start point up to the end of the source.
|
* from the specified start point up to the end of the source. Specifying a position that
|
||||||
|
* exceeds the {@code mediaSource}'s duration will also result in the end of the source not
|
||||||
|
* being clipped.
|
||||||
* @param enableInitialDiscontinuity Whether the initial discontinuity should be enabled.
|
* @param enableInitialDiscontinuity Whether the initial discontinuity should be enabled.
|
||||||
*/
|
*/
|
||||||
public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs,
|
public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs,
|
||||||
@ -149,8 +153,10 @@ public final class ClippingMediaSource implements MediaSource, MediaSource.Liste
|
|||||||
Assertions.checkArgument(!window.isDynamic);
|
Assertions.checkArgument(!window.isDynamic);
|
||||||
long resolvedEndUs = endUs == C.TIME_END_OF_SOURCE ? window.durationUs : endUs;
|
long resolvedEndUs = endUs == C.TIME_END_OF_SOURCE ? window.durationUs : endUs;
|
||||||
if (window.durationUs != C.TIME_UNSET) {
|
if (window.durationUs != C.TIME_UNSET) {
|
||||||
|
if (resolvedEndUs > window.durationUs) {
|
||||||
|
resolvedEndUs = window.durationUs;
|
||||||
|
}
|
||||||
Assertions.checkArgument(startUs == 0 || window.isSeekable);
|
Assertions.checkArgument(startUs == 0 || window.isSeekable);
|
||||||
Assertions.checkArgument(resolvedEndUs <= window.durationUs);
|
|
||||||
Assertions.checkArgument(startUs <= resolvedEndUs);
|
Assertions.checkArgument(startUs <= resolvedEndUs);
|
||||||
}
|
}
|
||||||
Period period = timeline.getPeriod(0, new Period());
|
Period period = timeline.getPeriod(0, new Period());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user