Update ExoPlayer to r2.2.0 (#505)

This commit is contained in:
Andrew Jack 2017-03-21 20:25:17 +00:00 committed by Matt Apperson
parent 5a4730cb8c
commit e76936b4fc
3 changed files with 56 additions and 35 deletions

View File

@ -12,8 +12,8 @@ android {
dependencies {
provided 'com.facebook.react:react-native:+'
compile 'com.google.android.exoplayer:exoplayer:r2.1.1'
compile('com.google.android.exoplayer:extension-okhttp:r2.1.1') {
compile 'com.google.android.exoplayer:exoplayer:r2.2.0'
compile('com.google.android.exoplayer:extension-okhttp:r2.2.0') {
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
compile 'com.squareup.okhttp3:okhttp:3.4.2'

View File

@ -28,6 +28,7 @@ import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataRenderer;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.LoopingMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
@ -51,14 +52,12 @@ import java.net.CookieManager;
import java.net.CookiePolicy;
@SuppressLint("ViewConstructor")
class ReactExoplayerView extends FrameLayout implements
LifecycleEventListener,
ExoPlayer.EventListener,
BecomingNoisyListener,
AudioManager.OnAudioFocusChangeListener,
MetadataRenderer.Output
{
MetadataRenderer.Output {
private static final String TAG = "ReactExoplayerView";
@ -74,7 +73,6 @@ class ReactExoplayerView extends FrameLayout implements
private final VideoEventEmitter eventEmitter;
private Handler mainHandler;
private Timeline.Window window;
private ExoPlayerView exoPlayerView;
private DataSource.Factory mediaDataSourceFactory;
@ -82,13 +80,11 @@ class ReactExoplayerView extends FrameLayout implements
private MappingTrackSelector trackSelector;
private boolean playerNeedsSource;
private boolean shouldRestorePosition;
private int playerWindow;
private long playerPosition;
private int resumeWindow;
private long resumePosition;
private boolean loadVideoStarted;
private boolean isPaused = true;
private boolean isBuffering;
private boolean isTimelineStatic;
// Props from React
private Uri srcUri;
@ -129,6 +125,8 @@ class ReactExoplayerView extends FrameLayout implements
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
themedReactContext.addLifecycleEventListener(this);
audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext);
initializePlayer();
}
@ -139,9 +137,9 @@ class ReactExoplayerView extends FrameLayout implements
}
private void createViews() {
clearResumePosition();
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
window = new Timeline.Window();
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
}
@ -199,13 +197,6 @@ class ReactExoplayerView extends FrameLayout implements
player.addListener(this);
player.setMetadataOutput(this);
exoPlayerView.setPlayer(player);
if (isTimelineStatic) {
if (playerPosition == C.TIME_UNSET) {
player.seekToDefaultPosition(playerWindow);
} else {
player.seekTo(playerWindow, playerPosition);
}
}
audioBecomingNoisyReceiver.setListener(this);
setPlayWhenReady(!isPaused);
playerNeedsSource = true;
@ -213,7 +204,11 @@ class ReactExoplayerView extends FrameLayout implements
if (playerNeedsSource && srcUri != null) {
MediaSource mediaSource = buildMediaSource(srcUri, extension);
mediaSource = repeat ? new LoopingMediaSource(mediaSource) : mediaSource;
player.prepare(mediaSource, !shouldRestorePosition, true);
boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
player.seekTo(resumeWindow, resumePosition);
}
player.prepare(mediaSource, !haveResumePosition, false);
playerNeedsSource = false;
eventEmitter.loadStart();
@ -245,13 +240,7 @@ class ReactExoplayerView extends FrameLayout implements
private void releasePlayer() {
if (player != null) {
isPaused = player.getPlayWhenReady();
shouldRestorePosition = false;
playerWindow = player.getCurrentWindowIndex();
playerPosition = C.TIME_UNSET;
Timeline timeline = player.getCurrentTimeline();
if (!timeline.isEmpty() && timeline.getWindow(playerWindow, window).isSeekable) {
playerPosition = player.getCurrentPosition();
}
updateResumePosition();
player.release();
player.setMetadataOutput(null);
player = null;
@ -331,6 +320,17 @@ class ReactExoplayerView extends FrameLayout implements
audioManager.abandonAudioFocus(this);
}
private void updateResumePosition() {
resumeWindow = player.getCurrentWindowIndex();
resumePosition = player.isCurrentWindowSeekable() ? Math.max(0, player.getCurrentPosition())
: C.TIME_UNSET;
}
private void clearResumePosition() {
resumeWindow = C.INDEX_UNSET;
resumePosition = C.TIME_UNSET;
}
/**
* Returns a new DataSource factory.
*
@ -442,13 +442,17 @@ class ReactExoplayerView extends FrameLayout implements
@Override
public void onPositionDiscontinuity() {
// Do nothing.
if (playerNeedsSource) {
// This will only occur if the user has performed a seek whilst in the error state. Update the
// resume position so that if the user then retries, playback will resume from the position to
// which they seeked.
updateResumePosition();
}
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
isTimelineStatic = !timeline.isEmpty()
&& !timeline.getWindow(timeline.getWindowCount() - 1, window).isDynamic;
// Do nothing.
}
@Override
@ -485,6 +489,26 @@ class ReactExoplayerView extends FrameLayout implements
eventEmitter.error(errorString, e);
}
playerNeedsSource = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
initializePlayer();
} else {
updateResumePosition();
}
}
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
return true;
}
cause = cause.getCause();
}
return false;
}
@Override

View File

@ -9,14 +9,11 @@ import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.BinaryFrame;
import com.google.android.exoplayer2.metadata.id3.Id3Frame;
import com.google.android.exoplayer2.metadata.id3.TxxxFrame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;
class VideoEventEmitter {
@ -191,8 +188,8 @@ class VideoEventEmitter {
String value = "";
if (frame instanceof TxxxFrame) {
TxxxFrame txxxFrame = (TxxxFrame) frame;
if (frame instanceof TextInformationFrame) {
TextInformationFrame txxxFrame = (TextInformationFrame) frame;
value = txxxFrame.value;
}