Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor exoplayer deprecations #1653

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Changelog

### next
### Version 4.4.4
* Handle racing conditions when props are setted on exoplayer

### Version 4.4.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@
import com.facebook.react.uimanager.ThemedReactContext;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
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.metadata.MetadataOutput;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
Expand Down Expand Up @@ -78,11 +78,11 @@
@SuppressLint("ViewConstructor")
class ReactExoplayerView extends FrameLayout implements
LifecycleEventListener,
ExoPlayer.EventListener,
Player.EventListener,
BandwidthMeter.EventListener,
BecomingNoisyListener,
AudioManager.OnAudioFocusChangeListener,
MetadataRenderer.Output {
MetadataOutput {

private static final String TAG = "ReactExoplayerView";

Expand Down Expand Up @@ -158,7 +158,7 @@ public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_PROGRESS:
if (player != null
&& player.getPlaybackState() == ExoPlayer.STATE_READY
&& player.getPlaybackState() == Player.STATE_READY
&& player.getPlayWhenReady()
) {
long pos = player.getCurrentPosition();
Expand Down Expand Up @@ -346,16 +346,23 @@ private void initializePlayer() {
@Override
public void run() {
if (player == null) {
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory();
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(trackSelector.buildUponParameters()
.setMaxVideoBitrate(maxBitRate == 0 ? Integer.MAX_VALUE : maxBitRate));
.setMaxVideoBitrate(maxBitRate == 0 ? Integer.MAX_VALUE : maxBitRate));

DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(allocator, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, -1, true);
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, defaultLoadControl);
DefaultLoadControl.Builder defaultLoadControlBuilder = new DefaultLoadControl.Builder();
defaultLoadControlBuilder.setAllocator(allocator);
defaultLoadControlBuilder.setBufferDurationsMs(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs);
defaultLoadControlBuilder.setTargetBufferBytes(-1);
defaultLoadControlBuilder.setPrioritizeTimeOverSizeThresholds(true);
DefaultLoadControl defaultLoadControl = defaultLoadControlBuilder.createDefaultLoadControl();
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(getContext(), DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);
// TODO: Add drmSessionManager to 5th param from: https://github.com/react-native-community/react-native-video/pull/1445
player = ExoPlayerFactory.newSimpleInstance(getContext(), renderersFactory, trackSelector, defaultLoadControl, null, BANDWIDTH_METER);
Copy link
Collaborator

@benoitdion benoitdion Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also update how the bandwidth meter is created. Looks like new DefaultBandwidthMeter() misses a lot of the smart defaults we get when using the builder that takes a context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://medium.com/google-exoplayer/https-medium-com-google-exoplayer-simplified-bandwidth-meter-usage-17d8189f978b

Sth like this?

SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);

DataSource.Factory dataSourceFactory = 
    new DefaultDataSourceFactory(context, userAgent);
MediaSource mediaSource = 
    new DashMediaSource.Factory(dataSourceFactory)
        .createMediaSource(uri);

player.prepare(mediaSource);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks right although it'd be nice to reuse the bandwidth meter between plays. I believe that's why it's currently a static variable.

Maybe outside the scope of this PR but what do you think about creating a ReactVideoPackageConfig class that exposes the exoplayer configuration. There would be a default implementation that uses the exo defaults and each application could override the config by passing a config object when instantiating ReactVideoPackage.

player.addListener(self);
player.setMetadataOutput(self);
player.addMetadataOutput(self);
exoPlayerView.setPlayer(player);
audioBecomingNoisyReceiver.setListener(self);
BANDWIDTH_METER.addEventListener(new Handler(), self);
Expand Down Expand Up @@ -403,21 +410,31 @@ private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
: uri.getLastPathSegment());
switch (type) {
case C.TYPE_SS:
return new SsMediaSource(uri, buildDataSourceFactory(false),
new DefaultSsChunkSource.Factory(mediaDataSourceFactory),
minLoadRetryCount, SsMediaSource.DEFAULT_LIVE_PRESENTATION_DELAY_MS,
mainHandler, null);
return new SsMediaSource.Factory(
new DefaultSsChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)
).setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(uri);
case C.TYPE_DASH:
return new DashMediaSource(uri, buildDataSourceFactory(false),
new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
minLoadRetryCount, DashMediaSource.DEFAULT_LIVE_PRESENTATION_DELAY_MS,
mainHandler, null);
return new DashMediaSource.Factory(
new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)
).setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(uri);
case C.TYPE_HLS:
return new HlsMediaSource(uri, mediaDataSourceFactory,
minLoadRetryCount, mainHandler, null);
return new HlsMediaSource.Factory(
mediaDataSourceFactory
).setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(uri);
case C.TYPE_OTHER:
return new ExtractorMediaSource(uri, mediaDataSourceFactory, new DefaultExtractorsFactory(),
mainHandler, null);
return new ExtractorMediaSource.Factory(
mediaDataSourceFactory
).setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(uri);
default: {
throw new IllegalStateException("Unsupported type: " + type);
}
Expand Down Expand Up @@ -447,14 +464,15 @@ private ArrayList<MediaSource> buildTextSources() {

private MediaSource buildTextSource(String title, Uri uri, String mimeType, String language) {
Format textFormat = Format.createTextSampleFormat(title, mimeType, Format.NO_VALUE, language);
return new SingleSampleMediaSource(uri, mediaDataSourceFactory, textFormat, C.TIME_UNSET);
return new SingleSampleMediaSource.Factory(mediaDataSourceFactory)
.createMediaSource(uri, textFormat, C.TIME_UNSET);
}

private void releasePlayer() {
if (player != null) {
updateResumePosition();
player.release();
player.setMetadataOutput(null);
player.removeMetadataOutput(this);
trackSelector = null;
player = null;
}
Expand Down Expand Up @@ -492,12 +510,12 @@ private void setPlayWhenReady(boolean playWhenReady) {
private void startPlayback() {
if (player != null) {
switch (player.getPlaybackState()) {
case ExoPlayer.STATE_IDLE:
case ExoPlayer.STATE_ENDED:
case Player.STATE_IDLE:
case Player.STATE_ENDED:
initializePlayer();
break;
case ExoPlayer.STATE_BUFFERING:
case ExoPlayer.STATE_READY:
case Player.STATE_BUFFERING:
case Player.STATE_READY:
if (!player.getPlayWhenReady()) {
setPlayWhenReady(true);
}
Expand Down Expand Up @@ -591,7 +609,7 @@ public void onAudioBecomingNoisy() {
eventEmitter.audioBecomingNoisy();
}

// ExoPlayer.EventListener implementation
// Player.EventListener implementation

@Override
public void onLoadingChanged(boolean isLoading) {
Expand All @@ -602,15 +620,15 @@ public void onLoadingChanged(boolean isLoading) {
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
String text = "onStateChanged: playWhenReady=" + playWhenReady + ", playbackState=";
switch (playbackState) {
case ExoPlayer.STATE_IDLE:
case Player.STATE_IDLE:
text += "idle";
eventEmitter.idle();
break;
case ExoPlayer.STATE_BUFFERING:
case Player.STATE_BUFFERING:
text += "buffering";
onBuffering(true);
break;
case ExoPlayer.STATE_READY:
case Player.STATE_READY:
text += "ready";
eventEmitter.ready();
onBuffering(false);
Expand All @@ -621,7 +639,7 @@ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
playerControlView.show();
}
break;
case ExoPlayer.STATE_ENDED:
case Player.STATE_ENDED:
text += "ended";
eventEmitter.end();
onStopPlayback();
Expand Down Expand Up @@ -747,7 +765,7 @@ public void onPositionDiscontinuity(int reason) {
}
// When repeat is turned on, reaching the end of the video will not cause a state change
// so we need to explicitly detect it.
if (reason == ExoPlayer.DISCONTINUITY_REASON_PERIOD_TRANSITION
if (reason == Player.DISCONTINUITY_REASON_PERIOD_TRANSITION
&& player.getRepeatMode() == Player.REPEAT_MODE_ONE) {
eventEmitter.end();
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-video",
"version": "4.4.3",
"version": "4.4.4",
"description": "A <Video /> element for react-native",
"main": "Video.js",
"license": "MIT",
Expand Down