Update exoplayer version to v2.15

Fixes #11547
This commit is contained in:
Leonid Zavodnik
2021-08-22 22:00:43 +02:00
committed by Greyson Parrelli
parent d507df2e7e
commit a6690e1bde
106 changed files with 763 additions and 850 deletions

View File

@@ -26,21 +26,11 @@ import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
@@ -51,6 +41,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.video.exo.AttachmentDataSourceFactory;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
public class VideoPlayer extends FrameLayout {
@@ -87,21 +78,30 @@ public class VideoPlayer extends FrameLayout {
this.exoControls.setShowTimeoutMs(-1);
}
private CreateMediaSource createMediaSource;
private MediaItem mediaItem;
public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay) {
Context context = getContext();
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(context);
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory();
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
Context context = getContext();
if (exoPlayer == null) {
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, renderersFactory, trackSelector, loadControl);
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
MediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(attachmentDataSourceFactory);
exoPlayer = new SimpleExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();
exoPlayer.addListener(new ExoPlayerListener(this, window, playerStateCallback, playerPositionDiscontinuityCallback));
exoPlayer.addListener(new Player.EventListener() {
exoPlayer.addListener(new Player.Listener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
onPlaybackStateChanged(playWhenReady, exoPlayer.getPlaybackState());
}
@Override
public void onPlaybackStateChanged(int playbackState) {
onPlaybackStateChanged(exoPlayer.getPlayWhenReady(), playbackState);
}
private void onPlaybackStateChanged(boolean playWhenReady, int playbackState) {
if (playerCallback != null) {
switch (playbackState) {
case Player.STATE_READY:
@@ -118,15 +118,9 @@ public class VideoPlayer extends FrameLayout {
exoControls.setPlayer(exoPlayer);
}
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
createMediaSource = () -> new ExtractorMediaSource.Factory(attachmentDataSourceFactory)
.setExtractorsFactory(extractorsFactory)
.createMediaSource(videoSource.getUri());
exoPlayer.prepare(createMediaSource.create());
mediaItem = MediaItem.fromUri(Objects.requireNonNull(videoSource.getUri()));
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
exoPlayer.setPlayWhenReady(autoplay);
}
@@ -151,10 +145,7 @@ public class VideoPlayer extends FrameLayout {
}
public @Nullable View getControlView() {
if (this.exoControls != null) {
return this.exoControls;
}
return null;
return this.exoControls;
}
public void cleanup() {
@@ -198,9 +189,13 @@ public class VideoPlayer extends FrameLayout {
}
public void clip(long fromUs, long toUs, boolean playWhenReady) {
if (this.exoPlayer != null && createMediaSource != null) {
MediaSource clippedMediaSource = new ClippingMediaSource(createMediaSource.create(), fromUs, toUs);
exoPlayer.prepare(clippedMediaSource);
if (this.exoPlayer != null && mediaItem != null) {
MediaItem clippedMediaItem = mediaItem.buildUpon()
.setClipStartPositionMs(TimeUnit.MICROSECONDS.toMillis(fromUs))
.setClipEndPositionMs(TimeUnit.MICROSECONDS.toMillis(toUs))
.build();
exoPlayer.setMediaItem(clippedMediaItem);
exoPlayer.prepare();
exoPlayer.setPlayWhenReady(playWhenReady);
clipped = true;
clippedStartUs = fromUs;
@@ -208,9 +203,10 @@ public class VideoPlayer extends FrameLayout {
}
public void removeClip(boolean playWhenReady) {
if (exoPlayer != null && createMediaSource != null) {
if (exoPlayer != null && mediaItem != null) {
if (clipped) {
exoPlayer.prepare(createMediaSource.create());
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
clipped = false;
clippedStartUs = 0;
}
@@ -246,7 +242,7 @@ public class VideoPlayer extends FrameLayout {
}
}
private static class ExoPlayerListener implements Player.EventListener {
private static class ExoPlayerListener implements Player.Listener {
private final VideoPlayer videoPlayer;
private final Window window;
private final PlayerStateCallback playerStateCallback;
@@ -264,7 +260,16 @@ public class VideoPlayer extends FrameLayout {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
onPlaybackStateChanged(playWhenReady, videoPlayer.exoPlayer.getPlaybackState());
}
@Override
public void onPlaybackStateChanged(int playbackState) {
onPlaybackStateChanged(videoPlayer.exoPlayer.getPlayWhenReady(), playbackState);
}
private void onPlaybackStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_IDLE:
case Player.STATE_BUFFERING:
@@ -289,7 +294,10 @@ public class VideoPlayer extends FrameLayout {
}
@Override
public void onPositionDiscontinuity(int reason) {
public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition,
@NonNull Player.PositionInfo newPosition,
int reason)
{
if (playerPositionDiscontinuityCallback != null) {
playerPositionDiscontinuityCallback.onPositionDiscontinuity(videoPlayer, reason);
}
@@ -314,8 +322,4 @@ public class VideoPlayer extends FrameLayout {
void onStopped();
}
private interface CreateMediaSource {
MediaSource create();
}
}

View File

@@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.video.exo;
import android.net.Uri;
import androidx.annotation.NonNull;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
@@ -34,7 +36,7 @@ public class AttachmentDataSource implements DataSource {
}
@Override
public void addTransferListener(TransferListener transferListener) {
public void addTransferListener(@NonNull TransferListener transferListener) {
}
@Override
@@ -47,7 +49,7 @@ public class AttachmentDataSource implements DataSource {
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
return dataSource.read(buffer, offset, readLength);
}
@@ -57,7 +59,7 @@ public class AttachmentDataSource implements DataSource {
}
@Override
public Map<String, List<String>> getResponseHeaders() {
public @NonNull Map<String, List<String>> getResponseHeaders() {
return Collections.emptyMap();
}

View File

@@ -27,7 +27,7 @@ public class AttachmentDataSourceFactory implements DataSource.Factory {
}
@Override
public AttachmentDataSource createDataSource() {
public @NonNull AttachmentDataSource createDataSource() {
return new AttachmentDataSource(defaultDataSourceFactory.createDataSource(),
new PartDataSource(context, listener),
new BlobDataSource(context, listener));

View File

@@ -5,27 +5,38 @@ import android.net.Uri;
import android.support.v4.media.MediaDescriptionCompat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManagerProvider;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import java.util.List;
/**
* This class is responsible for creating a MediaSource object for a given Uri, using AttachmentDataSourceFactory
*/
public final class AttachmentMediaSourceFactory {
@SuppressWarnings("deprecation")
public final class AttachmentMediaSourceFactory implements MediaSourceFactory {
private final ExtractorMediaSource.Factory extractorMediaSourceFactory;
private final ProgressiveMediaSource.Factory progressiveMediaSourceFactory;
public AttachmentMediaSourceFactory(@NonNull Context context) {
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
extractorMediaSourceFactory = new ExtractorMediaSource.Factory(attachmentDataSourceFactory)
.setExtractorsFactory(extractorsFactory);
progressiveMediaSourceFactory = new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory);
}
/**
@@ -36,13 +47,53 @@ public final class AttachmentMediaSourceFactory {
* @return A preparable MediaSource
*/
public @NonNull MediaSource createMediaSource(MediaDescriptionCompat description) {
return createMediaSource(description.getMediaUri());
return progressiveMediaSourceFactory.createMediaSource(
new MediaItem.Builder().setUri(description.getMediaUri()).setTag(description).build()
);
}
/**
* Creates a MediaSource for a given Uri
*/
public @NonNull MediaSource createMediaSource(Uri uri) {
return extractorMediaSourceFactory.createMediaSource(uri);
@Override
public MediaSourceFactory setStreamKeys(@Nullable List<StreamKey> streamKeys) {
return progressiveMediaSourceFactory.setStreamKeys(streamKeys);
}
@Override
public MediaSourceFactory setDrmSessionManagerProvider(@Nullable DrmSessionManagerProvider drmSessionManagerProvider) {
return progressiveMediaSourceFactory.setDrmSessionManagerProvider(drmSessionManagerProvider);
}
@Override
public MediaSourceFactory setDrmSessionManager(@Nullable DrmSessionManager drmSessionManager) {
return progressiveMediaSourceFactory.setDrmSessionManager(drmSessionManager);
}
@Override
public MediaSourceFactory setDrmHttpDataSourceFactory(@Nullable HttpDataSource.Factory drmHttpDataSourceFactory) {
return progressiveMediaSourceFactory.setDrmHttpDataSourceFactory(drmHttpDataSourceFactory);
}
@Override
public MediaSourceFactory setDrmUserAgent(@Nullable String userAgent) {
return progressiveMediaSourceFactory.setDrmUserAgent(userAgent);
}
@Override
public MediaSourceFactory setLoadErrorHandlingPolicy(@Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
return progressiveMediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
}
@Override
public int[] getSupportedTypes() {
return new int[] { C.TYPE_OTHER };
}
@Override
public MediaSource createMediaSource(MediaItem mediaItem) {
return progressiveMediaSourceFactory.createMediaSource(mediaItem);
}
@Override
public MediaSource createMediaSource(Uri uri) {
return progressiveMediaSourceFactory.createMediaSource(uri);
}
}

View File

@@ -25,7 +25,7 @@ public class BlobDataSource implements DataSource {
private final @NonNull Context context;
private final @Nullable TransferListener listener;
private Uri uri;
private DataSpec dataSpec;
private InputStream inputStream;
BlobDataSource(@NonNull Context context, @Nullable TransferListener listener) {
@@ -34,21 +34,21 @@ public class BlobDataSource implements DataSource {
}
@Override
public void addTransferListener(TransferListener transferListener) {
public void addTransferListener(@NonNull TransferListener transferListener) {
}
@Override
public long open(DataSpec dataSpec) throws IOException {
this.uri = dataSpec.uri;
this.inputStream = BlobProvider.getInstance().getStream(context, uri, dataSpec.position);
this.dataSpec = dataSpec;
this.inputStream = BlobProvider.getInstance().getStream(context, dataSpec.uri, dataSpec.position);
if (listener != null) {
listener.onTransferStart(this, dataSpec, false);
}
long size = unwrapLong(BlobProvider.getFileSize(uri));
long size = unwrapLong(BlobProvider.getFileSize(dataSpec.uri));
if (size == 0) {
size = BlobProvider.getInstance().calculateFileSize(context, uri);
size = BlobProvider.getInstance().calculateFileSize(context, dataSpec.uri);
}
if (size - dataSpec.position <= 0) throw new EOFException("No more data");
@@ -61,11 +61,11 @@ public class BlobDataSource implements DataSource {
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
int read = inputStream.read(buffer, offset, readLength);
if (read > 0 && listener != null) {
listener.onBytesTransferred(this, null, false, read);
listener.onBytesTransferred(this, dataSpec, false, read);
}
return read;
@@ -73,11 +73,11 @@ public class BlobDataSource implements DataSource {
@Override
public Uri getUri() {
return uri;
return dataSpec.uri;
}
@Override
public Map<String, List<String>> getResponseHeaders() {
public @NonNull Map<String, List<String>> getResponseHeaders() {
return Collections.emptyMap();
}

View File

@@ -28,7 +28,7 @@ public class ChunkedDataSource implements DataSource {
private final OkHttpClient okHttpClient;
private final TransferListener transferListener;
private Uri uri;
private DataSpec dataSpec;
private volatile InputStream inputStream;
private volatile Exception exception;
@@ -38,12 +38,12 @@ public class ChunkedDataSource implements DataSource {
}
@Override
public void addTransferListener(TransferListener transferListener) {
public void addTransferListener(@NonNull TransferListener transferListener) {
}
@Override
public long open(DataSpec dataSpec) throws IOException {
this.uri = dataSpec.uri;
public long open(@NonNull DataSpec dataSpec) throws IOException {
this.dataSpec = dataSpec;
this.exception = null;
if (inputStream != null) {
@@ -55,7 +55,7 @@ public class ChunkedDataSource implements DataSource {
CountDownLatch countDownLatch = new CountDownLatch(1);
ChunkedDataFetcher fetcher = new ChunkedDataFetcher(okHttpClient);
fetcher.fetch(this.uri.toString(), dataSpec.length, new ChunkedDataFetcher.Callback() {
fetcher.fetch(this.dataSpec.uri.toString(), dataSpec.length, new ChunkedDataFetcher.Callback() {
@Override
public void onSuccess(InputStream stream) {
inputStream = stream;
@@ -87,7 +87,7 @@ public class ChunkedDataSource implements DataSource {
transferListener.onTransferStart(this, dataSpec, false);
}
if ( dataSpec.length != C.LENGTH_UNSET && dataSpec.length - dataSpec.position <= 0) {
if (dataSpec.length != C.LENGTH_UNSET && dataSpec.length - dataSpec.position <= 0) {
throw new EOFException("No more data");
}
@@ -95,11 +95,11 @@ public class ChunkedDataSource implements DataSource {
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
int read = inputStream.read(buffer, offset, readLength);
if (read > 0 && transferListener != null) {
transferListener.onBytesTransferred(this, null, false, read);
transferListener.onBytesTransferred(this, dataSpec, false, read);
}
return read;
@@ -107,7 +107,7 @@ public class ChunkedDataSource implements DataSource {
@Override
public @Nullable Uri getUri() {
return uri;
return dataSpec.uri;
}
@Override

View File

@@ -20,7 +20,7 @@ public class ChunkedDataSourceFactory implements DataSource.Factory {
@Override
public DataSource createDataSource() {
public @NonNull DataSource createDataSource() {
return new ChunkedDataSource(okHttpClient, listener);
}
}

View File

@@ -37,7 +37,7 @@ public class PartDataSource implements DataSource {
}
@Override
public void addTransferListener(TransferListener transferListener) {
public void addTransferListener(@NonNull TransferListener transferListener) {
}
@Override
@@ -62,7 +62,7 @@ public class PartDataSource implements DataSource {
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
int read = inputSteam.read(buffer, offset, readLength);
if (read > 0 && listener != null) {
@@ -78,7 +78,7 @@ public class PartDataSource implements DataSource {
}
@Override
public Map<String, List<String>> getResponseHeaders() {
public @NonNull Map<String, List<String>> getResponseHeaders() {
return Collections.emptyMap();
}