Unverified Commit 7460df9e authored by genglei01's avatar genglei01 Committed by GitHub
Browse files

Merge branch 'master' into master

parents b83fda98 72dd6e44
Loading
Loading
Loading
Loading
+34 −1
Changes for README.md: 34 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -229,7 +229,8 @@ var styles = StyleSheet.create({
* [progressUpdateInterval](#progressupdateinterval)
* [rate](#rate)
* [repeat](#repeat)
* [resizeMode](#resize-mode)
* [resizeMode](#resizemode)
* [selectedTextTrack](#selectedtexttrack)
* [volume](#volume)

#### ignoreSilentSwitch
@@ -304,6 +305,38 @@ Determines how to resize the video when the frame doesn't match the raw video di

Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Windows UWP

#### selectedTextTrack
Configure which text track (caption or subtitle), if any, is shown.

```
selectedTextTrack={{
  type: Type,
  value: Value
}}
```

Example:
```
selectedTextTrack={{
  type: "title",
  value: "English Subtitles"
}}
```

Type | Value | Description
--- | --- | ---
"system" (default) | N/A | Display captions only if the system preference for captions is enabled
"disabled" | N/A | Don't display a text track
"title" | string | Display the text track with the title specified as the Value, e.g. "French 1"
"language" | string | Display the text track with the language specified as the Value, e.g. "fr"
"index" | number | Display the text track with the index specified as the value, e.g. 0

Both iOS & Android offer Settings to enable Captions for hearing impaired people. If "system" is selected and the Captions Setting is enabled, iOS/Android will look for a caption that matches that customer's language and display it.

If a track matching the specified Type (and Value if appropriate) is unavailable, no text track will be displayed. If multiple tracks match the criteria, the first match will be used.

Platforms: Android ExoPlayer, iOS

#### volume
Adjust the volume.
* **1.0 (default)** - Play at full volume
+7 −0
Changes for Video.js: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -275,6 +275,13 @@ Video.propTypes = {
  posterResizeMode: Image.propTypes.resizeMode,
  repeat: PropTypes.bool,
  allowsExternalPlayback: PropTypes.bool,
  selectedTextTrack: PropTypes.shape({
    type: PropTypes.string.isRequired,
    value: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number
    ])
  }),
  paused: PropTypes.bool,
  muted: PropTypes.bool,
  volume: PropTypes.number,
+74 −1
Changes for android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java: 74 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -5,17 +5,20 @@ import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.accessibility.CaptioningManager;
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.uimanager.ThemedReactContext;
import com.google.android.exoplayer2.C;
@@ -45,6 +48,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;
@@ -57,6 +61,7 @@ import java.net.CookieManager;
import java.net.CookiePolicy;
import java.lang.Math;
import java.lang.Object;
import java.util.Locale;

@SuppressLint("ViewConstructor")
class ReactExoplayerView extends FrameLayout implements
@@ -99,6 +104,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;
@@ -444,6 +451,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;
@@ -535,7 +543,8 @@ class ReactExoplayerView extends FrameLayout implements
                            decoderInitializationException.decoderName);
                }
            }
        } else if (e.type == ExoPlaybackException.TYPE_SOURCE) {
        }
        else if (e.type == ExoPlaybackException.TYPE_SOURCE) {
            ex = e.getSourceException();
            errorString = getResources().getString(R.string.unrecognized_media_format);
        }
@@ -565,6 +574,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);
@@ -626,6 +645,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) {
+14 −0
Changes for android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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;
@@ -24,6 +25,9 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
    private static final String PROP_SRC_TYPE = "type";
    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";
@@ -116,6 +120,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);
+46 −0
Changes for ios/RCTVideo.m: 46 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ static NSString *const timedMetadata = @"timedMetadata";
  BOOL _paused;
  BOOL _repeat;
  BOOL _allowsExternalPlayback;
  NSDictionary * _selectedTextTrack;
  BOOL _playbackStalled;
  BOOL _playInBackground;
  BOOL _playWhenInactive;
@@ -637,6 +638,7 @@ static NSString *const timedMetadata = @"timedMetadata";
    [_player setMuted:NO];
  }

  [self setSelectedTextTrack:_selectedTextTrack];
  [self setResizeMode:_resizeMode];
  [self setRepeat:_repeat];
  [self setPaused:_paused];
@@ -648,6 +650,50 @@ static NSString *const timedMetadata = @"timedMetadata";
  _repeat = repeat;
}

- (void)setSelectedTextTrack:(NSDictionary *)selectedTextTrack {
  _selectedTextTrack = selectedTextTrack;
  NSString *type = selectedTextTrack[@"type"];
  AVMediaSelectionGroup *group = [_player.currentItem.asset
                                  mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
  AVMediaSelectionOption *option;

  if ([type isEqualToString:@"disabled"]) {
    // Do nothing. We want to ensure option is nil
  } else if ([type isEqualToString:@"language"] || [type isEqualToString:@"title"]) {
    NSString *value = selectedTextTrack[@"value"];
    for (int i = 0; i < group.options.count; ++i) {
      AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i];
      NSString *optionValue;
      if ([type isEqualToString:@"language"]) {
        optionValue = [currentOption extendedLanguageTag];
      } else {
        optionValue = [[[currentOption commonMetadata]
                        valueForKey:@"value"]
                       objectAtIndex:0];
      }
      if ([value isEqualToString:optionValue]) {
        option = currentOption;
        break;
      }
    }
  //} else if ([type isEqualToString:@"default"]) {
  //  option = group.defaultOption; */
  } else if ([type isEqualToString:@"index"]) {
    if ([selectedTextTrack[@"value"] isKindOfClass:[NSNumber class]]) {
      int index = [selectedTextTrack[@"value"] intValue];
      if (group.options.count > index) {
        option = [group.options objectAtIndex:index];
      }
    }
  } else { // default. invalid type or "system"
    [_player.currentItem selectMediaOptionAutomaticallyInMediaSelectionGroup:group];
    return;
  }
  
  // If a match isn't found, option will be nil and text tracks will be disabled
  [_player.currentItem selectMediaOption:option inMediaSelectionGroup:group];
}

- (BOOL)getFullscreen
{
    return _fullscreenPlayerPresented;
Loading