Merge branch 'master' into master

This commit is contained in:
Emrah
2018-06-09 21:36:09 +02:00
committed by GitHub
14 changed files with 461 additions and 70 deletions

View File

@@ -19,6 +19,7 @@ import okhttp3.JavaNetCookieJar;
import okhttp3.OkHttpClient;
import java.util.Map;
public class DataSourceUtil {
private DataSourceUtil() {
@@ -32,14 +33,14 @@ public class DataSourceUtil {
DataSourceUtil.userAgent = userAgent;
}
public static String getUserAgent(Context context) {
public static String getUserAgent(ReactContext context) {
if (userAgent == null) {
userAgent = Util.getUserAgent(context.getApplicationContext(), "ReactNativeVideo");
userAgent = Util.getUserAgent(context, "ReactNativeVideo");
}
return userAgent;
}
public static DataSource.Factory getRawDataSourceFactory(Context context) {
public static DataSource.Factory getRawDataSourceFactory(ReactContext context) {
if (rawDataSourceFactory == null) {
rawDataSourceFactory = buildRawDataSourceFactory(context);
}
@@ -50,6 +51,7 @@ public class DataSourceUtil {
DataSourceUtil.rawDataSourceFactory = factory;
}
public static DataSource.Factory getDefaultDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
if (defaultDataSourceFactory == null || (requestHeaders != null && !requestHeaders.isEmpty())) {
defaultDataSourceFactory = buildDataSourceFactory(context, bandwidthMeter, requestHeaders);
@@ -61,7 +63,7 @@ public class DataSourceUtil {
DataSourceUtil.defaultDataSourceFactory = factory;
}
private static DataSource.Factory buildRawDataSourceFactory(Context context) {
private static DataSource.Factory buildRawDataSourceFactory(ReactContext context) {
return new RawResourceDataSourceFactory(context.getApplicationContext());
}
@@ -75,7 +77,6 @@ public class DataSourceUtil {
CookieJarContainer container = (CookieJarContainer) client.cookieJar();
ForwardingCookieHandler handler = new ForwardingCookieHandler(context);
container.setCookieJar(new JavaNetCookieJar(handler));
OkHttpDataSourceFactory okHttpDataSourceFactory = new OkHttpDataSourceFactory(client, getUserAgent(context), bandwidthMeter);
if (requestHeaders != null)

View File

@@ -18,8 +18,6 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataRenderer;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer;
@@ -27,17 +25,20 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.SubtitleView;
import java.util.List;
import java.lang.Object;
@TargetApi(16)
public final class ExoPlayerView extends FrameLayout {
private final View surfaceView;
private View surfaceView;
private final View shutterView;
private final SubtitleView subtitleLayout;
private final AspectRatioFrameLayout layout;
private final ComponentListener componentListener;
private SimpleExoPlayer player;
private Context context;
private ViewGroup.LayoutParams layoutParams;
private boolean useTextureView = false;
public ExoPlayerView(Context context) {
this(context, null);
@@ -50,9 +51,9 @@ public final class ExoPlayerView extends FrameLayout {
public ExoPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
boolean useTextureView = false;
this.context = context;
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
@@ -66,25 +67,45 @@ public final class ExoPlayerView extends FrameLayout {
layout.setLayoutParams(aspectRatioParams);
shutterView = new View(getContext());
shutterView.setLayoutParams(params);
shutterView.setLayoutParams(layoutParams);
shutterView.setBackgroundColor(ContextCompat.getColor(context, android.R.color.black));
subtitleLayout = new SubtitleView(context);
subtitleLayout.setLayoutParams(params);
subtitleLayout.setLayoutParams(layoutParams);
subtitleLayout.setUserDefaultStyle();
subtitleLayout.setUserDefaultTextSize();
View view = useTextureView ? new TextureView(context) : new SurfaceView(context);
view.setLayoutParams(params);
surfaceView = view;
updateSurfaceView();
layout.addView(surfaceView, 0, params);
layout.addView(shutterView, 1, params);
layout.addView(subtitleLayout, 2, params);
layout.addView(shutterView, 1, layoutParams);
layout.addView(subtitleLayout, 2, layoutParams);
addViewInLayout(layout, 0, aspectRatioParams);
}
private void setVideoView() {
if (surfaceView instanceof TextureView) {
player.setVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SurfaceView) {
player.setVideoSurfaceView((SurfaceView) surfaceView);
}
}
private void updateSurfaceView() {
View view = useTextureView ? new TextureView(context) : new SurfaceView(context);
view.setLayoutParams(layoutParams);
surfaceView = view;
if (layout.getChildAt(0) != null) {
layout.removeViewAt(0);
}
layout.addView(surfaceView, 0, layoutParams);
if (this.player != null) {
setVideoView();
}
}
/**
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
@@ -101,20 +122,14 @@ public final class ExoPlayerView extends FrameLayout {
this.player.setVideoListener(null);
this.player.removeListener(componentListener);
this.player.setVideoSurface(null);
this.player.setMetadataOutput(componentListener);
}
this.player = player;
shutterView.setVisibility(VISIBLE);
if (player != null) {
if (surfaceView instanceof TextureView) {
player.setVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SurfaceView) {
player.setVideoSurfaceView((SurfaceView) surfaceView);
}
setVideoView();
player.setVideoListener(componentListener);
player.addListener(componentListener);
player.setTextOutput(componentListener);
player.setMetadataOutput(componentListener);
}
}
@@ -141,6 +156,11 @@ public final class ExoPlayerView extends FrameLayout {
return surfaceView;
}
public void setUseTextureView(boolean useTextureView) {
this.useTextureView = useTextureView;
updateSurfaceView();
}
private final Runnable measureAndLayout = new Runnable() {
@Override
public void run() {
@@ -168,7 +188,7 @@ public final class ExoPlayerView extends FrameLayout {
}
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
TextRenderer.Output, ExoPlayer.EventListener, MetadataRenderer.Output {
TextRenderer.Output, ExoPlayer.EventListener {
// TextRenderer.Output implementation
@@ -232,11 +252,6 @@ public final class ExoPlayerView extends FrameLayout {
// Do nothing
}
@Override
public void onMetadata(Metadata metadata) {
Log.d("onMetadata", "onMetadata");
}
@Override
public void onSeekProcessed() {
// Do nothing.

View File

@@ -16,6 +16,7 @@ import android.widget.FrameLayout;
import com.brentvatne.react.R;
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
import com.brentvatne.receiver.BecomingNoisyListener;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.ThemedReactContext;
@@ -46,6 +47,7 @@ import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
@@ -101,6 +103,8 @@ class ReactExoplayerView extends FrameLayout implements
private Uri srcUri;
private String extension;
private boolean repeat;
private String textTrackType;
private Dynamic textTrackValue;
private boolean disableFocus;
private float mProgressUpdateInterval = 250.0f;
private boolean playInBackground = false;
@@ -135,9 +139,9 @@ class ReactExoplayerView extends FrameLayout implements
public ReactExoplayerView(ThemedReactContext context) {
super(context);
this.themedReactContext = context;
createViews();
this.eventEmitter = new VideoEventEmitter(context);
this.themedReactContext = context;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
themedReactContext.addLifecycleEventListener(this);
audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext);
@@ -448,6 +452,7 @@ class ReactExoplayerView extends FrameLayout implements
private void videoLoaded() {
if (loadVideoStarted) {
loadVideoStarted = false;
setSelectedTextTrack(textTrackType, textTrackValue);
Format videoFormat = player.getVideoFormat();
int width = videoFormat != null ? videoFormat.width : 0;
int height = videoFormat != null ? videoFormat.height : 0;
@@ -570,6 +575,16 @@ class ReactExoplayerView extends FrameLayout implements
return false;
}
public int getTextTrackRendererIndex() {
int rendererCount = player.getRendererCount();
for (int rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) {
if (player.getRendererType(rendererIndex) == C.TRACK_TYPE_TEXT) {
return rendererIndex;
}
}
return C.INDEX_UNSET;
}
@Override
public void onMetadata(Metadata metadata) {
eventEmitter.timedMetadata(metadata);
@@ -585,7 +600,7 @@ class ReactExoplayerView extends FrameLayout implements
this.srcUri = uri;
this.extension = extension;
this.requestHeaders = headers;
this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, BANDWIDTH_METER, requestHeaders);
this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, BANDWIDTH_METER, this.requestHeaders);
if (!isOriginalSourceNull && !isSourceEqual) {
reloadSource();
@@ -604,7 +619,7 @@ class ReactExoplayerView extends FrameLayout implements
this.srcUri = uri;
this.extension = extension;
this.mediaDataSourceFactory = DataSourceUtil.getRawDataSourceFactory(getContext());
this.mediaDataSourceFactory = DataSourceUtil.getRawDataSourceFactory(this.themedReactContext);
if (!isOriginalSourceNull && !isSourceEqual) {
reloadSource();
@@ -632,6 +647,60 @@ class ReactExoplayerView extends FrameLayout implements
this.repeat = repeat;
}
public void setSelectedTextTrack(String type, Dynamic value) {
textTrackType = type;
textTrackValue = value;
int index = getTextTrackRendererIndex();
if (index == C.INDEX_UNSET) {
return;
}
MappingTrackSelector.MappedTrackInfo info = trackSelector.getCurrentMappedTrackInfo();
if (info == null) {
return;
}
TrackGroupArray groups = info.getTrackGroups(index);
int trackIndex = C.INDEX_UNSET;
if (TextUtils.isEmpty(type)) {
// Do nothing
} else if (type.equals("disabled")) {
trackSelector.setSelectionOverride(index, groups, null);
return;
} else if (type.equals("language")) {
for (int i = 0; i < groups.length; ++i) {
Format format = groups.get(i).getFormat(0);
if (format.language != null && format.language.equals(value.asString())) {
trackIndex = i;
break;
}
}
} else if (type.equals("title")) {
for (int i = 0; i < groups.length; ++i) {
Format format = groups.get(i).getFormat(0);
if (format.id != null && format.id.equals(value.asString())) {
trackIndex = i;
break;
}
}
} else if (type.equals("index")) {
trackIndex = value.asInt();
} else { // default. invalid type or "system"
trackSelector.clearSelectionOverrides(index);
return;
}
if (trackIndex == C.INDEX_UNSET) {
trackSelector.clearSelectionOverrides(trackIndex);
return;
}
MappingTrackSelector.SelectionOverride override
= new MappingTrackSelector.SelectionOverride(
new FixedTrackSelection.Factory(), trackIndex, 0);
trackSelector.setSelectionOverride(index, groups, override);
}
public void setPausedModifier(boolean paused) {
isPaused = paused;
if (player != null) {
@@ -713,4 +782,8 @@ class ReactExoplayerView extends FrameLayout implements
eventEmitter.fullscreenDidDismiss();
}
}
public void setUseTextureView(boolean useTextureView) {
exoPlayerView.setUseTextureView(useTextureView);
}
}

View File

@@ -4,6 +4,7 @@ import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
@@ -26,6 +27,9 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
private static final String PROP_SRC_HEADERS = "requestHeaders";
private static final String PROP_RESIZE_MODE = "resizeMode";
private static final String PROP_REPEAT = "repeat";
private static final String PROP_SELECTED_TEXT_TRACK = "selectedTextTrack";
private static final String PROP_SELECTED_TEXT_TRACK_TYPE = "type";
private static final String PROP_SELECTED_TEXT_TRACK_VALUE = "value";
private static final String PROP_PAUSED = "paused";
private static final String PROP_MUTED = "muted";
private static final String PROP_VOLUME = "volume";
@@ -35,6 +39,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
private static final String PROP_PLAY_IN_BACKGROUND = "playInBackground";
private static final String PROP_DISABLE_FOCUS = "disableFocus";
private static final String PROP_FULLSCREEN = "fullscreen";
private static final String PROP_USE_TEXTURE_VIEW = "useTextureView";
@Override
public String getName() {
@@ -120,6 +125,16 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
videoView.setRepeatModifier(repeat);
}
@ReactProp(name = PROP_SELECTED_TEXT_TRACK)
public void setSelectedTextTrack(final ReactExoplayerView videoView,
@Nullable ReadableMap selectedTextTrack) {
String typeString = selectedTextTrack.hasKey(PROP_SELECTED_TEXT_TRACK_TYPE)
? selectedTextTrack.getString(PROP_SELECTED_TEXT_TRACK_TYPE) : null;
Dynamic value = selectedTextTrack.hasKey(PROP_SELECTED_TEXT_TRACK_VALUE)
? selectedTextTrack.getDynamic(PROP_SELECTED_TEXT_TRACK_VALUE) : null;
videoView.setSelectedTextTrack(typeString, value);
}
@ReactProp(name = PROP_PAUSED, defaultBoolean = false)
public void setPaused(final ReactExoplayerView videoView, final boolean paused) {
videoView.setPausedModifier(paused);
@@ -165,6 +180,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
videoView.setFullscreen(fullscreen);
}
@ReactProp(name = PROP_USE_TEXTURE_VIEW, defaultBoolean = false)
public void setUseTextureView(final ReactExoplayerView videoView, final boolean useTextureView) {
videoView.setUseTextureView(useTextureView);
}
private boolean startsWithValidScheme(String uriString) {
return uriString.startsWith("http://")
|| uriString.startsWith("https://")