Java Code Examples for com.google.android.exoplayer2.trackselection.TrackSelection#length()

The following examples show how to use com.google.android.exoplayer2.trackselection.TrackSelection#length() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: PlaybackStatsListener.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Notifies the tracker that the track selection for the current playback changed.
 *
 * @param eventTime The {@link EventTime}.
 * @param trackSelections The new {@link TrackSelectionArray}.
 */
public void onTracksChanged(EventTime eventTime, TrackSelectionArray trackSelections) {
  boolean videoEnabled = false;
  boolean audioEnabled = false;
  for (TrackSelection trackSelection : trackSelections.getAll()) {
    if (trackSelection != null && trackSelection.length() > 0) {
      int trackType = MimeTypes.getTrackType(trackSelection.getFormat(0).sampleMimeType);
      if (trackType == C.TRACK_TYPE_VIDEO) {
        videoEnabled = true;
      } else if (trackType == C.TRACK_TYPE_AUDIO) {
        audioEnabled = true;
      }
    }
  }
  if (!videoEnabled) {
    maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
  }
  if (!audioEnabled) {
    maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
  }
}
 
Example 2
Source File: DefaultSsChunkSource.java    From K-Sonic with MIT License 6 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param elementIndex The index of the stream element in the manifest.
 * @param trackSelection The track selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param trackEncryptionBoxes Track encryption boxes for the stream.
 */
public DefaultSsChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, SsManifest manifest,
    int elementIndex, TrackSelection trackSelection, DataSource dataSource,
    TrackEncryptionBox[] trackEncryptionBoxes) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.elementIndex = elementIndex;
  this.trackSelection = trackSelection;
  this.dataSource = dataSource;

  StreamElement streamElement = manifest.streamElements[elementIndex];

  extractorWrappers = new ChunkExtractorWrapper[trackSelection.length()];
  for (int i = 0; i < extractorWrappers.length; i++) {
    int manifestTrackIndex = trackSelection.getIndexInTrackGroup(i);
    Format format = streamElement.formats[manifestTrackIndex];
    int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0;
    Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale,
        C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE,
        trackEncryptionBoxes, nalUnitLengthFieldLength, null, null);
    FragmentedMp4Extractor extractor = new FragmentedMp4Extractor(
        FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
        | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track);
    extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format);
  }
}
 
Example 3
Source File: ExoPlayerImplInternal.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
private static Format[] getFormats(TrackSelection newSelection) {
  // Build an array of formats contained by the selection.
  int length = newSelection != null ? newSelection.length() : 0;
  Format[] formats = new Format[length];
  for (int i = 0; i < length; i++) {
    formats[i] = newSelection.getFormat(i);
  }
  return formats;
}
 
Example 4
Source File: SsMediaPeriod.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
  List<StreamKey> streamKeys = new ArrayList<>();
  for (int selectionIndex = 0; selectionIndex < trackSelections.size(); selectionIndex++) {
    TrackSelection trackSelection = trackSelections.get(selectionIndex);
    int streamElementIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
    for (int i = 0; i < trackSelection.length(); i++) {
      streamKeys.add(new StreamKey(streamElementIndex, trackSelection.getIndexInTrackGroup(i)));
    }
  }
  return streamKeys;
}
 
Example 5
Source File: SimpleExoPlayerView.java    From K-Sonic with MIT License 5 votes vote down vote up
private void updateForCurrentTrackSelections() {
  if (player == null) {
    return;
  }
  TrackSelectionArray selections = player.getCurrentTrackSelections();
  for (int i = 0; i < selections.length; i++) {
    if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
      // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in
      // onRenderedFirstFrame().
      hideArtwork();
      return;
    }
  }
  // Video disabled so the shutter must be closed.
  if (shutterView != null) {
    shutterView.setVisibility(VISIBLE);
  }
  // Display artwork if enabled and available, else hide it.
  if (useArtwork) {
    for (int i = 0; i < selections.length; i++) {
      TrackSelection selection = selections.get(i);
      if (selection != null) {
        for (int j = 0; j < selection.length(); j++) {
          Metadata metadata = selection.getFormat(j).metadata;
          if (metadata != null && setArtworkFromMetadata(metadata)) {
            return;
          }
        }
      }
    }
    if (setArtworkFromBitmap(defaultArtwork)) {
      return;
    }
  }
  // Artwork disabled or unavailable.
  hideArtwork();
}
 
Example 6
Source File: ExoVideoView.java    From ExoVideoView with Apache License 2.0 5 votes vote down vote up
private void updateForCurrentTrackSelections() {
    if (player == null) {
        return;
    }
    TrackSelectionArray selections = player.getCurrentTrackSelections();
    for (int i = 0; i < selections.length; i++) {
        if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
            // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in
            // onRenderedFirstFrame().
            hideArtwork();
            return;
        }
    }
    // Video disabled so the shutter must be closed.
    if (shutterView != null) {
        shutterView.setVisibility(VISIBLE);
    }
    // Display artwork if enabled and available, else hide it.
    if (useArtwork) {
        for (int i = 0; i < selections.length; i++) {
            TrackSelection selection = selections.get(i);
            if (selection != null) {
                for (int j = 0; j < selection.length(); j++) {
                    Metadata metadata = selection.getFormat(j).metadata;
                    if (metadata != null && setArtworkFromMetadata(metadata)) {
                        return;
                    }
                }
            }
        }
        if (setArtworkFromBitmap(defaultArtwork)) {
            return;
        }
    }
    // Artwork disabled or unavailable.
    hideArtwork();
}
 
Example 7
Source File: ExoPlayerImplInternal.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@NonNull
private static Format[] getFormats(TrackSelection newSelection) {
  // Build an array of formats contained by the selection.
  int length = newSelection != null ? newSelection.length() : 0;
  Format[] formats = new Format[length];
  for (int i = 0; i < length; i++) {
    formats[i] = newSelection.getFormat(i);
  }
  return formats;
}
 
Example 8
Source File: DefaultSsChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param streamElementIndex The index of the stream element in the manifest.
 * @param trackSelection The track selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param trackEncryptionBoxes Track encryption boxes for the stream.
 */
public DefaultSsChunkSource(
    LoaderErrorThrower manifestLoaderErrorThrower,
    SsManifest manifest,
    int streamElementIndex,
    TrackSelection trackSelection,
    DataSource dataSource,
    TrackEncryptionBox[] trackEncryptionBoxes) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.streamElementIndex = streamElementIndex;
  this.trackSelection = trackSelection;
  this.dataSource = dataSource;

  StreamElement streamElement = manifest.streamElements[streamElementIndex];
  extractorWrappers = new ChunkExtractorWrapper[trackSelection.length()];
  for (int i = 0; i < extractorWrappers.length; i++) {
    int manifestTrackIndex = trackSelection.getIndexInTrackGroup(i);
    Format format = streamElement.formats[manifestTrackIndex];
    int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0;
    Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale,
        C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE,
        trackEncryptionBoxes, nalUnitLengthFieldLength, null, null);
    FragmentedMp4Extractor extractor = new FragmentedMp4Extractor(
        FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
        | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track, null);
    extractorWrappers[i] = new ChunkExtractorWrapper(extractor, streamElement.type, format);
  }
}
 
Example 9
Source File: ExoPlayerImplInternal.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
private static Format[] getFormats(TrackSelection newSelection) {
  // Build an array of formats contained by the selection.
  int length = newSelection != null ? newSelection.length() : 0;
  Format[] formats = new Format[length];
  for (int i = 0; i < length; i++) {
    formats[i] = newSelection.getFormat(i);
  }
  return formats;
}
 
Example 10
Source File: DefaultSsChunkSource.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param streamElementIndex The index of the stream element in the manifest.
 * @param trackSelection The track selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 */
public DefaultSsChunkSource(
    LoaderErrorThrower manifestLoaderErrorThrower,
    SsManifest manifest,
    int streamElementIndex,
    TrackSelection trackSelection,
    DataSource dataSource) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.streamElementIndex = streamElementIndex;
  this.trackSelection = trackSelection;
  this.dataSource = dataSource;

  StreamElement streamElement = manifest.streamElements[streamElementIndex];
  extractorWrappers = new ChunkExtractorWrapper[trackSelection.length()];
  for (int i = 0; i < extractorWrappers.length; i++) {
    int manifestTrackIndex = trackSelection.getIndexInTrackGroup(i);
    Format format = streamElement.formats[manifestTrackIndex];
    TrackEncryptionBox[] trackEncryptionBoxes =
        format.drmInitData != null ? manifest.protectionElement.trackEncryptionBoxes : null;
    int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0;
    Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale,
        C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE,
        trackEncryptionBoxes, nalUnitLengthFieldLength, null, null);
    FragmentedMp4Extractor extractor = new FragmentedMp4Extractor(
        FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
        | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track, null);
    extractorWrappers[i] = new ChunkExtractorWrapper(extractor, streamElement.type, format);
  }
}
 
Example 11
Source File: DownloadHelper.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Runs the track selection for a given period index with the current parameters. The selected
 * tracks will be added to {@link #trackSelectionsByPeriodAndRenderer}.
 */
// Intentional reference comparison of track group instances.
@SuppressWarnings("ReferenceEquality")
@RequiresNonNull({
  "trackGroupArrays",
  "trackSelectionsByPeriodAndRenderer",
  "mediaPreparer",
  "mediaPreparer.timeline"
})
private TrackSelectorResult runTrackSelection(int periodIndex) {
  try {
    TrackSelectorResult trackSelectorResult =
        trackSelector.selectTracks(
            rendererCapabilities,
            trackGroupArrays[periodIndex],
            new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)),
            mediaPreparer.timeline);
    for (int i = 0; i < trackSelectorResult.length; i++) {
      TrackSelection newSelection = trackSelectorResult.selections.get(i);
      if (newSelection == null) {
        continue;
      }
      List<TrackSelection> existingSelectionList =
          trackSelectionsByPeriodAndRenderer[periodIndex][i];
      boolean mergedWithExistingSelection = false;
      for (int j = 0; j < existingSelectionList.size(); j++) {
        TrackSelection existingSelection = existingSelectionList.get(j);
        if (existingSelection.getTrackGroup() == newSelection.getTrackGroup()) {
          // Merge with existing selection.
          scratchSet.clear();
          for (int k = 0; k < existingSelection.length(); k++) {
            scratchSet.put(existingSelection.getIndexInTrackGroup(k), 0);
          }
          for (int k = 0; k < newSelection.length(); k++) {
            scratchSet.put(newSelection.getIndexInTrackGroup(k), 0);
          }
          int[] mergedTracks = new int[scratchSet.size()];
          for (int k = 0; k < scratchSet.size(); k++) {
            mergedTracks[k] = scratchSet.keyAt(k);
          }
          existingSelectionList.set(
              j, new DownloadTrackSelection(existingSelection.getTrackGroup(), mergedTracks));
          mergedWithExistingSelection = true;
          break;
        }
      }
      if (!mergedWithExistingSelection) {
        existingSelectionList.add(newSelection);
      }
    }
    return trackSelectorResult;
  } catch (ExoPlaybackException e) {
    // DefaultTrackSelector does not throw exceptions during track selection.
    throw new UnsupportedOperationException(e);
  }
}
 
Example 12
Source File: DashMediaPeriod.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
  List<AdaptationSet> manifestAdaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
  List<StreamKey> streamKeys = new ArrayList<>();
  for (TrackSelection trackSelection : trackSelections) {
    int trackGroupIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
    TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
    if (trackGroupInfo.trackGroupCategory != TrackGroupInfo.CATEGORY_PRIMARY) {
      // Ignore non-primary tracks.
      continue;
    }
    int[] adaptationSetIndices = trackGroupInfo.adaptationSetIndices;
    int[] trackIndices = new int[trackSelection.length()];
    for (int i = 0; i < trackSelection.length(); i++) {
      trackIndices[i] = trackSelection.getIndexInTrackGroup(i);
    }
    Arrays.sort(trackIndices);

    int currentAdaptationSetIndex = 0;
    int totalTracksInPreviousAdaptationSets = 0;
    int tracksInCurrentAdaptationSet =
        manifestAdaptationSets.get(adaptationSetIndices[0]).representations.size();
    for (int i = 0; i < trackIndices.length; i++) {
      while (trackIndices[i]
          >= totalTracksInPreviousAdaptationSets + tracksInCurrentAdaptationSet) {
        currentAdaptationSetIndex++;
        totalTracksInPreviousAdaptationSets += tracksInCurrentAdaptationSet;
        tracksInCurrentAdaptationSet =
            manifestAdaptationSets
                .get(adaptationSetIndices[currentAdaptationSetIndex])
                .representations
                .size();
      }
      streamKeys.add(
          new StreamKey(
              periodIndex,
              adaptationSetIndices[currentAdaptationSetIndex],
              trackIndices[i] - totalTracksInPreviousAdaptationSets));
    }
  }
  return streamKeys;
}
 
Example 13
Source File: DefaultDashChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param periodIndex The index of the period in the manifest.
 * @param adaptationSetIndices The indices of the adaptation sets in the period.
 * @param trackSelection The track selection.
 * @param trackType The type of the tracks in the selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
 *     server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
 *     as the server's unix time minus the local elapsed time. If unknown, set to 0.
 * @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. Note
 *     that segments will only be combined if their {@link Uri}s are the same and if their data
 *     ranges are adjacent.
 * @param enableEventMessageTrack Whether the chunks generated by the source may output an event
 *     message track.
 * @param enableCea608Track Whether the chunks generated by the source may output a CEA-608 track.
 * @param playerTrackEmsgHandler The {@link PlayerTrackEmsgHandler} instance to handle emsg
 *     messages targeting the player. Maybe null if this is not necessary.
 */
public DefaultDashChunkSource(
    LoaderErrorThrower manifestLoaderErrorThrower,
    DashManifest manifest,
    int periodIndex,
    int[] adaptationSetIndices,
    TrackSelection trackSelection,
    int trackType,
    DataSource dataSource,
    long elapsedRealtimeOffsetMs,
    int maxSegmentsPerLoad,
    boolean enableEventMessageTrack,
    boolean enableCea608Track,
    @Nullable PlayerTrackEmsgHandler playerTrackEmsgHandler) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.adaptationSetIndices = adaptationSetIndices;
  this.trackSelection = trackSelection;
  this.trackType = trackType;
  this.dataSource = dataSource;
  this.periodIndex = periodIndex;
  this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
  this.maxSegmentsPerLoad = maxSegmentsPerLoad;
  this.playerTrackEmsgHandler = playerTrackEmsgHandler;

  long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
  liveEdgeTimeUs = C.TIME_UNSET;

  List<Representation> representations = getRepresentations();
  representationHolders = new RepresentationHolder[trackSelection.length()];
  for (int i = 0; i < representationHolders.length; i++) {
    Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
    representationHolders[i] =
        new RepresentationHolder(
            periodDurationUs,
            trackType,
            representation,
            enableEventMessageTrack,
            enableCea608Track,
            playerTrackEmsgHandler);
  }
}
 
Example 14
Source File: DownloadHelper.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Runs the track selection for a given period index with the current parameters. The selected
 * tracks will be added to {@link #trackSelectionsByPeriodAndRenderer}.
 */
// Intentional reference comparison of track group instances.
@SuppressWarnings("ReferenceEquality")
@RequiresNonNull({
  "trackGroupArrays",
  "trackSelectionsByPeriodAndRenderer",
  "mediaPreparer",
  "mediaPreparer.timeline"
})
private TrackSelectorResult runTrackSelection(int periodIndex) {
  try {
    TrackSelectorResult trackSelectorResult =
        trackSelector.selectTracks(
            rendererCapabilities,
            trackGroupArrays[periodIndex],
            new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)),
            mediaPreparer.timeline);
    for (int i = 0; i < trackSelectorResult.length; i++) {
      @Nullable TrackSelection newSelection = trackSelectorResult.selections.get(i);
      if (newSelection == null) {
        continue;
      }
      List<TrackSelection> existingSelectionList =
          trackSelectionsByPeriodAndRenderer[periodIndex][i];
      boolean mergedWithExistingSelection = false;
      for (int j = 0; j < existingSelectionList.size(); j++) {
        TrackSelection existingSelection = existingSelectionList.get(j);
        if (existingSelection.getTrackGroup() == newSelection.getTrackGroup()) {
          // Merge with existing selection.
          scratchSet.clear();
          for (int k = 0; k < existingSelection.length(); k++) {
            scratchSet.put(existingSelection.getIndexInTrackGroup(k), 0);
          }
          for (int k = 0; k < newSelection.length(); k++) {
            scratchSet.put(newSelection.getIndexInTrackGroup(k), 0);
          }
          int[] mergedTracks = new int[scratchSet.size()];
          for (int k = 0; k < scratchSet.size(); k++) {
            mergedTracks[k] = scratchSet.keyAt(k);
          }
          existingSelectionList.set(
              j, new DownloadTrackSelection(existingSelection.getTrackGroup(), mergedTracks));
          mergedWithExistingSelection = true;
          break;
        }
      }
      if (!mergedWithExistingSelection) {
        existingSelectionList.add(newSelection);
      }
    }
    return trackSelectorResult;
  } catch (ExoPlaybackException e) {
    // DefaultTrackSelector does not throw exceptions during track selection.
    throw new UnsupportedOperationException(e);
  }
}
 
Example 15
Source File: DefaultDashChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param periodIndex The index of the period in the manifest.
 * @param adaptationSetIndices The indices of the adaptation sets in the period.
 * @param trackSelection The track selection.
 * @param trackType The type of the tracks in the selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
 *     server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
 *     as the server's unix time minus the local elapsed time. If unknown, set to 0.
 * @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. Note
 *     that segments will only be combined if their {@link Uri}s are the same and if their data
 *     ranges are adjacent.
 * @param enableEventMessageTrack Whether the chunks generated by the source may output an event
 *     message track.
 * @param enableCea608Track Whether the chunks generated by the source may output a CEA-608 track.
 * @param playerTrackEmsgHandler The {@link PlayerTrackEmsgHandler} instance to handle emsg
 *     messages targeting the player. Maybe null if this is not necessary.
 */
public DefaultDashChunkSource(
    LoaderErrorThrower manifestLoaderErrorThrower,
    DashManifest manifest,
    int periodIndex,
    int[] adaptationSetIndices,
    TrackSelection trackSelection,
    int trackType,
    DataSource dataSource,
    long elapsedRealtimeOffsetMs,
    int maxSegmentsPerLoad,
    boolean enableEventMessageTrack,
    boolean enableCea608Track,
    @Nullable PlayerTrackEmsgHandler playerTrackEmsgHandler) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.adaptationSetIndices = adaptationSetIndices;
  this.trackSelection = trackSelection;
  this.trackType = trackType;
  this.dataSource = dataSource;
  this.periodIndex = periodIndex;
  this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
  this.maxSegmentsPerLoad = maxSegmentsPerLoad;
  this.playerTrackEmsgHandler = playerTrackEmsgHandler;

  long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
  liveEdgeTimeUs = C.TIME_UNSET;

  List<Representation> representations = getRepresentations();
  representationHolders = new RepresentationHolder[trackSelection.length()];
  for (int i = 0; i < representationHolders.length; i++) {
    Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
    representationHolders[i] =
        new RepresentationHolder(
            periodDurationUs,
            trackType,
            representation,
            enableEventMessageTrack,
            enableCea608Track,
            playerTrackEmsgHandler);
  }
}
 
Example 16
Source File: DefaultDashChunkSource.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param periodIndex The index of the period in the manifest.
 * @param adaptationSetIndices The indices of the adaptation sets in the period.
 * @param trackSelection The track selection.
 * @param trackType The type of the tracks in the selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
 *     server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
 *     as the server's unix time minus the local elapsed time. If unknown, set to 0.
 * @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. Note
 *     that segments will only be combined if their {@link Uri}s are the same and if their data
 *     ranges are adjacent.
 * @param enableEventMessageTrack Whether to output an event message track.
 * @param closedCaptionFormats The {@link Format Formats} of closed caption tracks to be output.
 * @param playerTrackEmsgHandler The {@link PlayerTrackEmsgHandler} instance to handle emsg
 *     messages targeting the player. Maybe null if this is not necessary.
 */
public DefaultDashChunkSource(
    LoaderErrorThrower manifestLoaderErrorThrower,
    DashManifest manifest,
    int periodIndex,
    int[] adaptationSetIndices,
    TrackSelection trackSelection,
    int trackType,
    DataSource dataSource,
    long elapsedRealtimeOffsetMs,
    int maxSegmentsPerLoad,
    boolean enableEventMessageTrack,
    List<Format> closedCaptionFormats,
    @Nullable PlayerTrackEmsgHandler playerTrackEmsgHandler) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.adaptationSetIndices = adaptationSetIndices;
  this.trackSelection = trackSelection;
  this.trackType = trackType;
  this.dataSource = dataSource;
  this.periodIndex = periodIndex;
  this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
  this.maxSegmentsPerLoad = maxSegmentsPerLoad;
  this.playerTrackEmsgHandler = playerTrackEmsgHandler;

  long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
  liveEdgeTimeUs = C.TIME_UNSET;

  List<Representation> representations = getRepresentations();
  representationHolders = new RepresentationHolder[trackSelection.length()];
  for (int i = 0; i < representationHolders.length; i++) {
    Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
    representationHolders[i] =
        new RepresentationHolder(
            periodDurationUs,
            trackType,
            representation,
            enableEventMessageTrack,
            closedCaptionFormats,
            playerTrackEmsgHandler);
  }
}
 
Example 17
Source File: ExoPlayerImplInternal.java    From K-Sonic with MIT License 4 votes vote down vote up
private void enableRenderers(boolean[] rendererWasEnabledFlags, int enabledRendererCount)
    throws ExoPlaybackException {
  enabledRenderers = new Renderer[enabledRendererCount];
  enabledRendererCount = 0;
  for (int i = 0; i < renderers.length; i++) {
    Renderer renderer = renderers[i];
    TrackSelection newSelection = playingPeriodHolder.trackSelectorResult.selections.get(i);
    if (newSelection != null) {
      enabledRenderers[enabledRendererCount++] = renderer;
      if (renderer.getState() == Renderer.STATE_DISABLED) {
        RendererConfiguration rendererConfiguration =
            playingPeriodHolder.trackSelectorResult.rendererConfigurations[i];
        // The renderer needs enabling with its new track selection.
        boolean playing = playWhenReady && state == ExoPlayer.STATE_READY;
        // Consider as joining only if the renderer was previously disabled.
        boolean joining = !rendererWasEnabledFlags[i] && playing;
        // Build an array of formats contained by the selection.
        Format[] formats = new Format[newSelection.length()];
        for (int j = 0; j < formats.length; j++) {
          formats[j] = newSelection.getFormat(j);
        }
        // Enable the renderer.
        renderer.enable(rendererConfiguration, formats, playingPeriodHolder.sampleStreams[i],
            rendererPositionUs, joining, playingPeriodHolder.getRendererOffset());
        MediaClock mediaClock = renderer.getMediaClock();
        if (mediaClock != null) {
          if (rendererMediaClock != null) {
            throw ExoPlaybackException.createForUnexpected(
                new IllegalStateException("Multiple renderer media clocks enabled."));
          }
          rendererMediaClock = mediaClock;
          rendererMediaClockSource = renderer;
        }
        // Start the renderer if playing.
        if (playing) {
          renderer.start();
        }
      }
    }
  }
}
 
Example 18
Source File: DownloadHelper.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Runs the track selection for a given period index with the current parameters. The selected
 * tracks will be added to {@link #trackSelectionsByPeriodAndRenderer}.
 */
// Intentional reference comparison of track group instances.
@SuppressWarnings("ReferenceEquality")
@RequiresNonNull({
  "trackGroupArrays",
  "trackSelectionsByPeriodAndRenderer",
  "mediaPreparer",
  "mediaPreparer.timeline"
})
private TrackSelectorResult runTrackSelection(int periodIndex) {
  try {
    TrackSelectorResult trackSelectorResult =
        trackSelector.selectTracks(
            rendererCapabilities,
            trackGroupArrays[periodIndex],
            new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)),
            mediaPreparer.timeline);
    for (int i = 0; i < trackSelectorResult.length; i++) {
      TrackSelection newSelection = trackSelectorResult.selections.get(i);
      if (newSelection == null) {
        continue;
      }
      List<TrackSelection> existingSelectionList =
          trackSelectionsByPeriodAndRenderer[periodIndex][i];
      boolean mergedWithExistingSelection = false;
      for (int j = 0; j < existingSelectionList.size(); j++) {
        TrackSelection existingSelection = existingSelectionList.get(j);
        if (existingSelection.getTrackGroup() == newSelection.getTrackGroup()) {
          // Merge with existing selection.
          scratchSet.clear();
          for (int k = 0; k < existingSelection.length(); k++) {
            scratchSet.put(existingSelection.getIndexInTrackGroup(k), 0);
          }
          for (int k = 0; k < newSelection.length(); k++) {
            scratchSet.put(newSelection.getIndexInTrackGroup(k), 0);
          }
          int[] mergedTracks = new int[scratchSet.size()];
          for (int k = 0; k < scratchSet.size(); k++) {
            mergedTracks[k] = scratchSet.keyAt(k);
          }
          existingSelectionList.set(
              j, new DownloadTrackSelection(existingSelection.getTrackGroup(), mergedTracks));
          mergedWithExistingSelection = true;
          break;
        }
      }
      if (!mergedWithExistingSelection) {
        existingSelectionList.add(newSelection);
      }
    }
    return trackSelectorResult;
  } catch (ExoPlaybackException e) {
    // DefaultTrackSelector does not throw exceptions during track selection.
    throw new UnsupportedOperationException(e);
  }
}
 
Example 19
Source File: DefaultDashChunkSource.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
 * @param manifest The initial manifest.
 * @param periodIndex The index of the period in the manifest.
 * @param adaptationSetIndices The indices of the adaptation sets in the period.
 * @param trackSelection The track selection.
 * @param trackType The type of the tracks in the selection.
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
 *     server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
 *     as the server's unix time minus the local elapsed time. If unknown, set to 0.
 * @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. Note
 *     that segments will only be combined if their {@link Uri}s are the same and if their data
 *     ranges are adjacent.
 * @param enableEventMessageTrack Whether to output an event message track.
 * @param closedCaptionFormats The {@link Format Formats} of closed caption tracks to be output.
 * @param playerTrackEmsgHandler The {@link PlayerTrackEmsgHandler} instance to handle emsg
 *     messages targeting the player. Maybe null if this is not necessary.
 */
public DefaultDashChunkSource(
    LoaderErrorThrower manifestLoaderErrorThrower,
    DashManifest manifest,
    int periodIndex,
    int[] adaptationSetIndices,
    TrackSelection trackSelection,
    int trackType,
    DataSource dataSource,
    long elapsedRealtimeOffsetMs,
    int maxSegmentsPerLoad,
    boolean enableEventMessageTrack,
    List<Format> closedCaptionFormats,
    @Nullable PlayerTrackEmsgHandler playerTrackEmsgHandler) {
  this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
  this.manifest = manifest;
  this.adaptationSetIndices = adaptationSetIndices;
  this.trackSelection = trackSelection;
  this.trackType = trackType;
  this.dataSource = dataSource;
  this.periodIndex = periodIndex;
  this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
  this.maxSegmentsPerLoad = maxSegmentsPerLoad;
  this.playerTrackEmsgHandler = playerTrackEmsgHandler;

  long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
  liveEdgeTimeUs = C.TIME_UNSET;

  List<Representation> representations = getRepresentations();
  representationHolders = new RepresentationHolder[trackSelection.length()];
  for (int i = 0; i < representationHolders.length; i++) {
    Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
    representationHolders[i] =
        new RepresentationHolder(
            periodDurationUs,
            trackType,
            representation,
            enableEventMessageTrack,
            closedCaptionFormats,
            playerTrackEmsgHandler);
  }
}
 
Example 20
Source File: HlsMediaPeriod.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
  // See HlsMasterPlaylist.copy for interpretation of StreamKeys.
  HlsMasterPlaylist masterPlaylist = Assertions.checkNotNull(playlistTracker.getMasterPlaylist());
  boolean hasVariants = !masterPlaylist.variants.isEmpty();
  int audioWrapperOffset = hasVariants ? 1 : 0;
  // Subtitle sample stream wrappers are held last.
  int subtitleWrapperOffset = sampleStreamWrappers.length - masterPlaylist.subtitles.size();

  TrackGroupArray mainWrapperTrackGroups;
  int mainWrapperPrimaryGroupIndex;
  int[] mainWrapperVariantIndices;
  if (hasVariants) {
    HlsSampleStreamWrapper mainWrapper = sampleStreamWrappers[0];
    mainWrapperVariantIndices = manifestUrlIndicesPerWrapper[0];
    mainWrapperTrackGroups = mainWrapper.getTrackGroups();
    mainWrapperPrimaryGroupIndex = mainWrapper.getPrimaryTrackGroupIndex();
  } else {
    mainWrapperVariantIndices = new int[0];
    mainWrapperTrackGroups = TrackGroupArray.EMPTY;
    mainWrapperPrimaryGroupIndex = 0;
  }

  List<StreamKey> streamKeys = new ArrayList<>();
  boolean needsPrimaryTrackGroupSelection = false;
  boolean hasPrimaryTrackGroupSelection = false;
  for (TrackSelection trackSelection : trackSelections) {
    TrackGroup trackSelectionGroup = trackSelection.getTrackGroup();
    int mainWrapperTrackGroupIndex = mainWrapperTrackGroups.indexOf(trackSelectionGroup);
    if (mainWrapperTrackGroupIndex != C.INDEX_UNSET) {
      if (mainWrapperTrackGroupIndex == mainWrapperPrimaryGroupIndex) {
        // Primary group in main wrapper.
        hasPrimaryTrackGroupSelection = true;
        for (int i = 0; i < trackSelection.length(); i++) {
          int variantIndex = mainWrapperVariantIndices[trackSelection.getIndexInTrackGroup(i)];
          streamKeys.add(new StreamKey(HlsMasterPlaylist.GROUP_INDEX_VARIANT, variantIndex));
        }
      } else {
        // Embedded group in main wrapper.
        needsPrimaryTrackGroupSelection = true;
      }
    } else {
      // Audio or subtitle group.
      for (int i = audioWrapperOffset; i < sampleStreamWrappers.length; i++) {
        TrackGroupArray wrapperTrackGroups = sampleStreamWrappers[i].getTrackGroups();
        int selectedTrackGroupIndex = wrapperTrackGroups.indexOf(trackSelectionGroup);
        if (selectedTrackGroupIndex != C.INDEX_UNSET) {
          int groupIndexType =
              i < subtitleWrapperOffset
                  ? HlsMasterPlaylist.GROUP_INDEX_AUDIO
                  : HlsMasterPlaylist.GROUP_INDEX_SUBTITLE;
          int[] selectedWrapperUrlIndices = manifestUrlIndicesPerWrapper[i];
          for (int trackIndex = 0; trackIndex < trackSelection.length(); trackIndex++) {
            int renditionIndex =
                selectedWrapperUrlIndices[trackSelection.getIndexInTrackGroup(trackIndex)];
            streamKeys.add(new StreamKey(groupIndexType, renditionIndex));
          }
          break;
        }
      }
    }
  }
  if (needsPrimaryTrackGroupSelection && !hasPrimaryTrackGroupSelection) {
    // A track selection includes a variant-embedded track, but no variant is added yet. We use
    // the valid variant with the lowest bitrate to reduce overhead.
    int lowestBitrateIndex = mainWrapperVariantIndices[0];
    int lowestBitrate = masterPlaylist.variants.get(mainWrapperVariantIndices[0]).format.bitrate;
    for (int i = 1; i < mainWrapperVariantIndices.length; i++) {
      int variantBitrate =
          masterPlaylist.variants.get(mainWrapperVariantIndices[i]).format.bitrate;
      if (variantBitrate < lowestBitrate) {
        lowestBitrate = variantBitrate;
        lowestBitrateIndex = mainWrapperVariantIndices[i];
      }
    }
    streamKeys.add(new StreamKey(HlsMasterPlaylist.GROUP_INDEX_VARIANT, lowestBitrateIndex));
  }
  return streamKeys;
}