Commit 9764fe3b authored by Hampton Maxwell's avatar Hampton Maxwell
Browse files

First pass at text track selection, mostly complete

parent 88585744
Loading
Loading
Loading
Loading
+7 −0
Changes for Video.js: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -274,6 +274,13 @@ Video.propTypes = {
  poster: PropTypes.string,
  posterResizeMode: Image.propTypes.resizeMode,
  repeat: 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,
+62 −1
Changes for android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java: 62 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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.uimanager.ThemedReactContext;
import com.google.android.exoplayer2.C;
@@ -45,6 +46,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;
@@ -535,7 +537,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 +568,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 +639,54 @@ class ReactExoplayerView extends FrameLayout implements
        this.repeat = repeat;
    }

    public void setSelectedTextTrack(String type, Dynamic 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("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
@@ -40,6 +40,7 @@ static NSString *const timedMetadata = @"timedMetadata";
  BOOL _muted;
  BOOL _paused;
  BOOL _repeat;
  NSDictionary * _selectedTextTrack;
  BOOL _playbackStalled;
  BOOL _playInBackground;
  BOOL _playWhenInactive;
@@ -625,6 +626,7 @@ static NSString *const timedMetadata = @"timedMetadata";
    [_player setMuted:NO];
  }

  [self setSelectedTextTrack:_selectedTextTrack];
  [self setResizeMode:_resizeMode];
  [self setRepeat:_repeat];
  [self setPaused:_paused];
@@ -635,6 +637,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:@"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.appliesMediaSelectionCriteriaAutomatically = YES;
    return;
  }
  
  // If a match isn't found, option will be nil and text tracks will be disabled
  // _player.appliesMediaSelectionCriteriaAutomatically = NO;
  [_player.currentItem selectMediaOption:option inMediaSelectionGroup:group];
}

- (BOOL)getFullscreen
{
    return _fullscreenPlayerPresented;
+1 −0
Changes for ios/RCTVideoManager.m: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_VIEW_PROPERTY(src, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL);
RCT_EXPORT_VIEW_PROPERTY(selectedTextTrack, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(paused, BOOL);
RCT_EXPORT_VIEW_PROPERTY(muted, BOOL);
RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);