Java 类com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl 实例源码

项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
/**
 * Called by the bundles when a snapshot changes.
 *
 * @param url The url of the playlist.
 * @param newSnapshot The new snapshot.
 * @return True if a refresh should be scheduled.
 */
private boolean onPlaylistUpdated(HlsUrl url, HlsMediaPlaylist newSnapshot) {
  if (url == primaryHlsUrl) {
    if (primaryUrlSnapshot == null) {
      // This is the first primary url snapshot.
      isLive = !newSnapshot.hasEndTag;
    }
    primaryUrlSnapshot = newSnapshot;
    primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot);
  }
  int listenersSize = listeners.size();
  for (int i = 0; i < listenersSize; i++) {
    listeners.get(i).onPlaylistChanged();
  }
  // If the primary playlist is not the final one, we should schedule a refresh.
  return url == primaryHlsUrl && !newSnapshot.hasEndTag;
}
项目:Exoplayer2Radio    文件:HlsChunkSource.java   
/**
 * @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists.
 * @param variants The available variants.
 * @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the
 *     chunks.
 * @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If
 *     multiple {@link HlsChunkSource}s are used for a single playback, they should all share the
 *     same provider.
 * @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
 *     information is available in the master playlist.
 */
public HlsChunkSource(HlsPlaylistTracker playlistTracker, HlsUrl[] variants,
    HlsDataSourceFactory dataSourceFactory, TimestampAdjusterProvider timestampAdjusterProvider,
    List<Format> muxedCaptionFormats) {
  this.playlistTracker = playlistTracker;
  this.variants = variants;
  this.timestampAdjusterProvider = timestampAdjusterProvider;
  this.muxedCaptionFormats = muxedCaptionFormats;
  Format[] variantFormats = new Format[variants.length];
  int[] initialTrackSelection = new int[variants.length];
  for (int i = 0; i < variants.length; i++) {
    variantFormats[i] = variants[i].format;
    initialTrackSelection[i] = i;
  }
  mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
  encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
  trackGroup = new TrackGroup(variantFormats);
  trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection);
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
/**
 * Called by the bundles when a snapshot changes.
 *
 * @param url The url of the playlist.
 * @param newSnapshot The new snapshot.
 * @return True if a refresh should be scheduled.
 */
private boolean onPlaylistUpdated(HlsUrl url, HlsMediaPlaylist newSnapshot) {
  if (url == primaryHlsUrl) {
    if (primaryUrlSnapshot == null) {
      // This is the first primary url snapshot.
      isLive = !newSnapshot.hasEndTag;
    }
    primaryUrlSnapshot = newSnapshot;
    primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot);
  }
  int listenersSize = listeners.size();
  for (int i = 0; i < listenersSize; i++) {
    listeners.get(i).onPlaylistChanged();
  }
  // If the primary playlist is not the final one, we should schedule a refresh.
  return url == primaryHlsUrl && !newSnapshot.hasEndTag;
}
项目:K-Sonic    文件:HlsChunkSource.java   
/**
 * @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists.
 * @param variants The available variants.
 * @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the
 *     chunks.
 * @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If
 *     multiple {@link HlsChunkSource}s are used for a single playback, they should all share the
 *     same provider.
 * @param muxedCaptionFormats List of muxed caption {@link Format}s.
 */
public HlsChunkSource(HlsPlaylistTracker playlistTracker, HlsUrl[] variants,
    HlsDataSourceFactory dataSourceFactory, TimestampAdjusterProvider timestampAdjusterProvider,
    List<Format> muxedCaptionFormats) {
  this.playlistTracker = playlistTracker;
  this.variants = variants;
  this.timestampAdjusterProvider = timestampAdjusterProvider;
  this.muxedCaptionFormats = muxedCaptionFormats;
  Format[] variantFormats = new Format[variants.length];
  int[] initialTrackSelection = new int[variants.length];
  for (int i = 0; i < variants.length; i++) {
    variantFormats[i] = variants[i].format;
    initialTrackSelection[i] = i;
  }
  mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
  encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
  trackGroup = new TrackGroup(variantFormats);
  trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection);
}
项目:transistor    文件:HlsChunkSource.java   
/**
 * @param extractorFactory An {@link HlsExtractorFactory} from which to obtain the extractors for
 *     media chunks.
 * @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists.
 * @param variants The available variants.
 * @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the
 *     chunks.
 * @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If
 *     multiple {@link HlsChunkSource}s are used for a single playback, they should all share the
 *     same provider.
 * @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
 *     information is available in the master playlist.
 */
public HlsChunkSource(HlsExtractorFactory extractorFactory, HlsPlaylistTracker playlistTracker,
    HlsUrl[] variants, HlsDataSourceFactory dataSourceFactory,
    TimestampAdjusterProvider timestampAdjusterProvider, List<Format> muxedCaptionFormats) {
  this.extractorFactory = extractorFactory;
  this.playlistTracker = playlistTracker;
  this.variants = variants;
  this.timestampAdjusterProvider = timestampAdjusterProvider;
  this.muxedCaptionFormats = muxedCaptionFormats;
  liveEdgeTimeUs = C.TIME_UNSET;
  Format[] variantFormats = new Format[variants.length];
  int[] initialTrackSelection = new int[variants.length];
  for (int i = 0; i < variants.length; i++) {
    variantFormats[i] = variants[i].format;
    initialTrackSelection[i] = i;
  }
  mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
  encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
  trackGroup = new TrackGroup(variantFormats);
  trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection);
}
项目:Exoplayer2Radio    文件:HlsMediaChunk.java   
/**
 * @param dataSource The source from which the data should be loaded.
 * @param dataSpec Defines the data to be loaded.
 * @param initDataSpec Defines the initialization data to be fed to new extractors. May be null.
 * @param hlsUrl The url of the playlist from which this chunk was obtained.
 * @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
 *     information is available in the master playlist.
 * @param trackSelectionReason See {@link #trackSelectionReason}.
 * @param trackSelectionData See {@link #trackSelectionData}.
 * @param startTimeUs The start time of the chunk in microseconds.
 * @param endTimeUs The end time of the chunk in microseconds.
 * @param chunkIndex The media sequence number of the chunk.
 * @param discontinuitySequenceNumber The discontinuity sequence number of the chunk.
 * @param isMasterTimestampSource True if the chunk can initialize the timestamp adjuster.
 * @param timestampAdjuster Adjuster corresponding to the provided discontinuity sequence number.
 * @param previousChunk The {@link HlsMediaChunk} that preceded this one. May be null.
 * @param encryptionKey For AES encryption chunks, the encryption key.
 * @param encryptionIv For AES encryption chunks, the encryption initialization vector.
 */
public HlsMediaChunk(DataSource dataSource, DataSpec dataSpec, DataSpec initDataSpec,
    HlsUrl hlsUrl, List<Format> muxedCaptionFormats, int trackSelectionReason,
    Object trackSelectionData, long startTimeUs, long endTimeUs, int chunkIndex,
    int discontinuitySequenceNumber, boolean isMasterTimestampSource,
    TimestampAdjuster timestampAdjuster, HlsMediaChunk previousChunk, byte[] encryptionKey,
    byte[] encryptionIv) {
  super(buildDataSource(dataSource, encryptionKey, encryptionIv), dataSpec, hlsUrl.format,
      trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, chunkIndex);
  this.discontinuitySequenceNumber = discontinuitySequenceNumber;
  this.initDataSpec = initDataSpec;
  this.hlsUrl = hlsUrl;
  this.muxedCaptionFormats = muxedCaptionFormats;
  this.isMasterTimestampSource = isMasterTimestampSource;
  this.timestampAdjuster = timestampAdjuster;
  // Note: this.dataSource and dataSource may be different.
  this.isEncrypted = this.dataSource instanceof Aes128DataSource;
  lastPathSegment = dataSpec.uri.getLastPathSegment();
  isPackedAudio = lastPathSegment.endsWith(AAC_FILE_EXTENSION)
      || lastPathSegment.endsWith(AC3_FILE_EXTENSION)
      || lastPathSegment.endsWith(EC3_FILE_EXTENSION)
      || lastPathSegment.endsWith(MP3_FILE_EXTENSION);
  if (previousChunk != null) {
    id3Decoder = previousChunk.id3Decoder;
    id3Data = previousChunk.id3Data;
    previousExtractor = previousChunk.extractor;
    shouldSpliceIn = previousChunk.hlsUrl != hlsUrl;
    needNewExtractor = previousChunk.discontinuitySequenceNumber != discontinuitySequenceNumber
        || shouldSpliceIn;
  } else {
    id3Decoder = isPackedAudio ? new Id3Decoder() : null;
    id3Data = isPackedAudio ? new ParsableByteArray(Id3Decoder.ID3_HEADER_LENGTH) : null;
    previousExtractor = null;
    shouldSpliceIn = false;
    needNewExtractor = true;
  }
  initDataSource = dataSource;
  uid = UID_SOURCE.getAndIncrement();
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
@Override
public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs) {
  HlsPlaylist result = loadable.getResult();
  HlsMasterPlaylist masterPlaylist;
  boolean isMediaPlaylist = result instanceof HlsMediaPlaylist;
  if (isMediaPlaylist) {
    masterPlaylist = HlsMasterPlaylist.createSingleVariantMasterPlaylist(result.baseUri);
  } else /* result instanceof HlsMasterPlaylist */ {
    masterPlaylist = (HlsMasterPlaylist) result;
  }
  this.masterPlaylist = masterPlaylist;
  primaryHlsUrl = masterPlaylist.variants.get(0);
  ArrayList<HlsUrl> urls = new ArrayList<>();
  urls.addAll(masterPlaylist.variants);
  urls.addAll(masterPlaylist.audios);
  urls.addAll(masterPlaylist.subtitles);
  createBundles(urls);
  MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl);
  if (isMediaPlaylist) {
    // We don't need to load the playlist again. We can use the same result.
    primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result);
  } else {
    primaryBundle.loadPlaylist();
  }
  eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
      loadDurationMs, loadable.bytesLoaded());
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
private boolean maybeSelectNewPrimaryUrl() {
  List<HlsUrl> variants = masterPlaylist.variants;
  int variantsSize = variants.size();
  long currentTimeMs = SystemClock.elapsedRealtime();
  for (int i = 0; i < variantsSize; i++) {
    MediaPlaylistBundle bundle = playlistBundles.get(variants.get(i));
    if (currentTimeMs > bundle.blacklistUntilMs) {
      primaryHlsUrl = bundle.playlistUrl;
      bundle.loadPlaylist();
      return true;
    }
  }
  return false;
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
private void maybeSetPrimaryUrl(HlsUrl url) {
  if (!masterPlaylist.variants.contains(url)
      || (primaryUrlSnapshot != null && primaryUrlSnapshot.hasEndTag)) {
    // Only allow variant urls to be chosen as primary. Also prevent changing the primary url if
    // the last primary snapshot contains an end tag.
    return;
  }
  MediaPlaylistBundle currentPrimaryBundle = playlistBundles.get(primaryHlsUrl);
  long primarySnapshotAccessAgeMs =
      currentPrimaryBundle.lastSnapshotAccessTimeMs - SystemClock.elapsedRealtime();
  if (primarySnapshotAccessAgeMs > PRIMARY_URL_KEEPALIVE_MS) {
    primaryHlsUrl = url;
    playlistBundles.get(primaryHlsUrl).loadPlaylist();
  }
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
private void createBundles(List<HlsUrl> urls) {
  int listSize = urls.size();
  long currentTimeMs = SystemClock.elapsedRealtime();
  for (int i = 0; i < listSize; i++) {
    HlsUrl url = urls.get(i);
    MediaPlaylistBundle bundle = new MediaPlaylistBundle(url, currentTimeMs);
    playlistBundles.put(url, bundle);
  }
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
public MediaPlaylistBundle(HlsUrl playlistUrl, long initialLastSnapshotAccessTimeMs) {
  this.playlistUrl = playlistUrl;
  lastSnapshotAccessTimeMs = initialLastSnapshotAccessTimeMs;
  mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist");
  mediaPlaylistLoadable = new ParsingLoadable<>(
      dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
      UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST,
      playlistParser);
}
项目:Exoplayer2Radio    文件:HlsMediaPeriod.java   
@Override
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) {
    streamWrapper.onPlaylistBlacklisted(url, blacklistMs);
  }
  continuePreparingOrLoading();
}
项目:Exoplayer2Radio    文件:HlsMediaPeriod.java   
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
    Format muxedAudioFormat, List<Format> muxedCaptionFormats) {
  HlsChunkSource defaultChunkSource = new HlsChunkSource(playlistTracker, variants,
      dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats);
  return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator,
      preparePositionUs, muxedAudioFormat, minLoadableRetryCount, eventDispatcher);
}
项目:Exoplayer2Radio    文件:HlsMediaPeriod.java   
private static boolean variantHasExplicitCodecWithPrefix(HlsUrl variant, String prefix) {
  String codecs = variant.format.codecs;
  if (TextUtils.isEmpty(codecs)) {
    return false;
  }
  String[] codecArray = codecs.split("(\\s*,\\s*)|(\\s*$)");
  for (String codec : codecArray) {
    if (codec.startsWith(prefix)) {
      return true;
    }
  }
  return false;
}
项目:Exoplayer2Radio    文件:HlsChunkSource.java   
/**
 * Called when a playlist is blacklisted.
 *
 * @param url The url that references the blacklisted playlist.
 * @param blacklistMs The amount of milliseconds for which the playlist was blacklisted.
 */
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  int trackGroupIndex = trackGroup.indexOf(url.format);
  if (trackGroupIndex != C.INDEX_UNSET) {
    int trackSelectionIndex = trackSelection.indexOf(trackGroupIndex);
    if (trackSelectionIndex != C.INDEX_UNSET) {
      trackSelection.blacklist(trackSelectionIndex, blacklistMs);
    }
  }
}
项目:Exoplayer2Radio    文件:HlsSampleStreamWrapper.java   
@Override
public boolean continueLoading(long positionUs) {
  if (loadingFinished || loader.isLoading()) {
    return false;
  }

  chunkSource.getNextChunk(mediaChunks.isEmpty() ? null : mediaChunks.getLast(),
      pendingResetPositionUs != C.TIME_UNSET ? pendingResetPositionUs : positionUs,
      nextChunkHolder);
  boolean endOfStream = nextChunkHolder.endOfStream;
  Chunk loadable = nextChunkHolder.chunk;
  HlsMasterPlaylist.HlsUrl playlistToLoad = nextChunkHolder.playlist;
  nextChunkHolder.clear();

  if (endOfStream) {
    loadingFinished = true;
    return true;
  }

  if (loadable == null) {
    if (playlistToLoad != null) {
      callback.onPlaylistRefreshRequired(playlistToLoad);
    }
    return false;
  }

  if (isMediaChunk(loadable)) {
    pendingResetPositionUs = C.TIME_UNSET;
    HlsMediaChunk mediaChunk = (HlsMediaChunk) loadable;
    mediaChunk.init(this);
    mediaChunks.add(mediaChunk);
  }
  long elapsedRealtimeMs = loader.startLoading(loadable, this, minLoadableRetryCount);
  eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, trackType, loadable.trackFormat,
      loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs,
      loadable.endTimeUs, elapsedRealtimeMs);
  return true;
}
项目:K-Sonic    文件:HlsMediaChunk.java   
/**
 * @param dataSource The source from which the data should be loaded.
 * @param dataSpec Defines the data to be loaded.
 * @param initDataSpec Defines the initialization data to be fed to new extractors. May be null.
 * @param hlsUrl The url of the playlist from which this chunk was obtained.
 * @param muxedCaptionFormats List of muxed caption {@link Format}s.
 * @param trackSelectionReason See {@link #trackSelectionReason}.
 * @param trackSelectionData See {@link #trackSelectionData}.
 * @param startTimeUs The start time of the chunk in microseconds.
 * @param endTimeUs The end time of the chunk in microseconds.
 * @param chunkIndex The media sequence number of the chunk.
 * @param discontinuitySequenceNumber The discontinuity sequence number of the chunk.
 * @param isMasterTimestampSource True if the chunk can initialize the timestamp adjuster.
 * @param timestampAdjuster Adjuster corresponding to the provided discontinuity sequence number.
 * @param previousChunk The {@link HlsMediaChunk} that preceded this one. May be null.
 * @param encryptionKey For AES encryption chunks, the encryption key.
 * @param encryptionIv For AES encryption chunks, the encryption initialization vector.
 */
public HlsMediaChunk(DataSource dataSource, DataSpec dataSpec, DataSpec initDataSpec,
    HlsUrl hlsUrl, List<Format> muxedCaptionFormats, int trackSelectionReason,
    Object trackSelectionData, long startTimeUs, long endTimeUs, int chunkIndex,
    int discontinuitySequenceNumber, boolean isMasterTimestampSource,
    TimestampAdjuster timestampAdjuster, HlsMediaChunk previousChunk, byte[] encryptionKey,
    byte[] encryptionIv) {
  super(buildDataSource(dataSource, encryptionKey, encryptionIv), dataSpec, hlsUrl.format,
      trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, chunkIndex);
  this.discontinuitySequenceNumber = discontinuitySequenceNumber;
  this.initDataSpec = initDataSpec;
  this.hlsUrl = hlsUrl;
  this.muxedCaptionFormats = muxedCaptionFormats;
  this.isMasterTimestampSource = isMasterTimestampSource;
  this.timestampAdjuster = timestampAdjuster;
  // Note: this.dataSource and dataSource may be different.
  this.isEncrypted = this.dataSource instanceof Aes128DataSource;
  lastPathSegment = dataSpec.uri.getLastPathSegment();
  isPackedAudio = lastPathSegment.endsWith(AAC_FILE_EXTENSION)
      || lastPathSegment.endsWith(AC3_FILE_EXTENSION)
      || lastPathSegment.endsWith(EC3_FILE_EXTENSION)
      || lastPathSegment.endsWith(MP3_FILE_EXTENSION);
  if (previousChunk != null) {
    id3Decoder = previousChunk.id3Decoder;
    id3Data = previousChunk.id3Data;
    previousExtractor = previousChunk.extractor;
    shouldSpliceIn = previousChunk.hlsUrl != hlsUrl;
    needNewExtractor = previousChunk.discontinuitySequenceNumber != discontinuitySequenceNumber
        || shouldSpliceIn;
  } else {
    id3Decoder = isPackedAudio ? new Id3Decoder() : null;
    id3Data = isPackedAudio ? new ParsableByteArray(Id3Decoder.ID3_HEADER_LENGTH) : null;
    previousExtractor = null;
    shouldSpliceIn = false;
    needNewExtractor = true;
  }
  initDataSource = dataSource;
  uid = UID_SOURCE.getAndIncrement();
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
@Override
public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs) {
  HlsPlaylist result = loadable.getResult();
  HlsMasterPlaylist masterPlaylist;
  boolean isMediaPlaylist = result instanceof HlsMediaPlaylist;
  if (isMediaPlaylist) {
    masterPlaylist = HlsMasterPlaylist.createSingleVariantMasterPlaylist(result.baseUri);
  } else /* result instanceof HlsMasterPlaylist */ {
    masterPlaylist = (HlsMasterPlaylist) result;
  }
  this.masterPlaylist = masterPlaylist;
  primaryHlsUrl = masterPlaylist.variants.get(0);
  ArrayList<HlsUrl> urls = new ArrayList<>();
  urls.addAll(masterPlaylist.variants);
  urls.addAll(masterPlaylist.audios);
  urls.addAll(masterPlaylist.subtitles);
  createBundles(urls);
  MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl);
  if (isMediaPlaylist) {
    // We don't need to load the playlist again. We can use the same result.
    primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result);
  } else {
    primaryBundle.loadPlaylist();
  }
  eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
      loadDurationMs, loadable.bytesLoaded());
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
private boolean maybeSelectNewPrimaryUrl() {
  List<HlsUrl> variants = masterPlaylist.variants;
  int variantsSize = variants.size();
  long currentTimeMs = SystemClock.elapsedRealtime();
  for (int i = 0; i < variantsSize; i++) {
    MediaPlaylistBundle bundle = playlistBundles.get(variants.get(i));
    if (currentTimeMs > bundle.blacklistUntilMs) {
      primaryHlsUrl = bundle.playlistUrl;
      bundle.loadPlaylist();
      return true;
    }
  }
  return false;
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
private void maybeSetPrimaryUrl(HlsUrl url) {
  if (!masterPlaylist.variants.contains(url)
      || (primaryUrlSnapshot != null && primaryUrlSnapshot.hasEndTag)) {
    // Only allow variant urls to be chosen as primary. Also prevent changing the primary url if
    // the last primary snapshot contains an end tag.
    return;
  }
  MediaPlaylistBundle currentPrimaryBundle = playlistBundles.get(primaryHlsUrl);
  long primarySnapshotAccessAgeMs =
      currentPrimaryBundle.lastSnapshotAccessTimeMs - SystemClock.elapsedRealtime();
  if (primarySnapshotAccessAgeMs > PRIMARY_URL_KEEPALIVE_MS) {
    primaryHlsUrl = url;
    playlistBundles.get(primaryHlsUrl).loadPlaylist();
  }
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
private void createBundles(List<HlsUrl> urls) {
  int listSize = urls.size();
  long currentTimeMs = SystemClock.elapsedRealtime();
  for (int i = 0; i < listSize; i++) {
    HlsUrl url = urls.get(i);
    MediaPlaylistBundle bundle = new MediaPlaylistBundle(url, currentTimeMs);
    playlistBundles.put(url, bundle);
  }
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
public MediaPlaylistBundle(HlsUrl playlistUrl, long initialLastSnapshotAccessTimeMs) {
  this.playlistUrl = playlistUrl;
  lastSnapshotAccessTimeMs = initialLastSnapshotAccessTimeMs;
  mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist");
  mediaPlaylistLoadable = new ParsingLoadable<>(
      dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
      UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST,
      playlistParser);
}
项目:K-Sonic    文件:HlsMediaPeriod.java   
@Override
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) {
    streamWrapper.onPlaylistBlacklisted(url, blacklistMs);
  }
  continuePreparingOrLoading();
}
项目:K-Sonic    文件:HlsMediaPeriod.java   
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
    Format muxedAudioFormat, List<Format> muxedCaptionFormats) {
  HlsChunkSource defaultChunkSource = new HlsChunkSource(playlistTracker, variants,
      dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats);
  return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator,
      preparePositionUs, muxedAudioFormat, minLoadableRetryCount, eventDispatcher);
}
项目:K-Sonic    文件:HlsMediaPeriod.java   
private static boolean variantHasExplicitCodecWithPrefix(HlsUrl variant, String prefix) {
  String codecs = variant.format.codecs;
  if (TextUtils.isEmpty(codecs)) {
    return false;
  }
  String[] codecArray = codecs.split("(\\s*,\\s*)|(\\s*$)");
  for (String codec : codecArray) {
    if (codec.startsWith(prefix)) {
      return true;
    }
  }
  return false;
}
项目:K-Sonic    文件:HlsChunkSource.java   
/**
 * Called when a playlist is blacklisted.
 *
 * @param url The url that references the blacklisted playlist.
 * @param blacklistMs The amount of milliseconds for which the playlist was blacklisted.
 */
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  int trackGroupIndex = trackGroup.indexOf(url.format);
  if (trackGroupIndex != C.INDEX_UNSET) {
    int trackSelectionIndex = trackSelection.indexOf(trackGroupIndex);
    if (trackSelectionIndex != C.INDEX_UNSET) {
      trackSelection.blacklist(trackSelectionIndex, blacklistMs);
    }
  }
}
项目:K-Sonic    文件:HlsSampleStreamWrapper.java   
@Override
public boolean continueLoading(long positionUs) {
  if (loadingFinished || loader.isLoading()) {
    return false;
  }

  chunkSource.getNextChunk(mediaChunks.isEmpty() ? null : mediaChunks.getLast(),
      pendingResetPositionUs != C.TIME_UNSET ? pendingResetPositionUs : positionUs,
      nextChunkHolder);
  boolean endOfStream = nextChunkHolder.endOfStream;
  Chunk loadable = nextChunkHolder.chunk;
  HlsMasterPlaylist.HlsUrl playlistToLoad = nextChunkHolder.playlist;
  nextChunkHolder.clear();

  if (endOfStream) {
    loadingFinished = true;
    return true;
  }

  if (loadable == null) {
    if (playlistToLoad != null) {
      callback.onPlaylistRefreshRequired(playlistToLoad);
    }
    return false;
  }

  if (isMediaChunk(loadable)) {
    pendingResetPositionUs = C.TIME_UNSET;
    HlsMediaChunk mediaChunk = (HlsMediaChunk) loadable;
    mediaChunk.init(this);
    mediaChunks.add(mediaChunk);
  }
  long elapsedRealtimeMs = loader.startLoading(loadable, this, minLoadableRetryCount);
  eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, trackType, loadable.trackFormat,
      loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs,
      loadable.endTimeUs, elapsedRealtimeMs);
  return true;
}
项目:transistor    文件:HlsPlaylistTracker.java   
@Override
public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs) {
  HlsPlaylist result = loadable.getResult();
  HlsMasterPlaylist masterPlaylist;
  boolean isMediaPlaylist = result instanceof HlsMediaPlaylist;
  if (isMediaPlaylist) {
    masterPlaylist = HlsMasterPlaylist.createSingleVariantMasterPlaylist(result.baseUri);
  } else /* result instanceof HlsMasterPlaylist */ {
    masterPlaylist = (HlsMasterPlaylist) result;
  }
  this.masterPlaylist = masterPlaylist;
  primaryHlsUrl = masterPlaylist.variants.get(0);
  ArrayList<HlsUrl> urls = new ArrayList<>();
  urls.addAll(masterPlaylist.variants);
  urls.addAll(masterPlaylist.audios);
  urls.addAll(masterPlaylist.subtitles);
  createBundles(urls);
  MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl);
  if (isMediaPlaylist) {
    // We don't need to load the playlist again. We can use the same result.
    primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result);
  } else {
    primaryBundle.loadPlaylist();
  }
  eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
      loadDurationMs, loadable.bytesLoaded());
}
项目:transistor    文件:HlsPlaylistTracker.java   
private boolean maybeSelectNewPrimaryUrl() {
  List<HlsUrl> variants = masterPlaylist.variants;
  int variantsSize = variants.size();
  long currentTimeMs = SystemClock.elapsedRealtime();
  for (int i = 0; i < variantsSize; i++) {
    MediaPlaylistBundle bundle = playlistBundles.get(variants.get(i));
    if (currentTimeMs > bundle.blacklistUntilMs) {
      primaryHlsUrl = bundle.playlistUrl;
      bundle.loadPlaylist();
      return true;
    }
  }
  return false;
}
项目:transistor    文件:HlsPlaylistTracker.java   
private void maybeSetPrimaryUrl(HlsUrl url) {
  if (url == primaryHlsUrl
      || !masterPlaylist.variants.contains(url)
      || (primaryUrlSnapshot != null && primaryUrlSnapshot.hasEndTag)) {
    // Ignore if the primary url is unchanged, if the url is not a variant url, or if the last
    // primary snapshot contains an end tag.
    return;
  }
  primaryHlsUrl = url;
  playlistBundles.get(primaryHlsUrl).loadPlaylist();
}
项目:transistor    文件:HlsPlaylistTracker.java   
private void createBundles(List<HlsUrl> urls) {
  int listSize = urls.size();
  for (int i = 0; i < listSize; i++) {
    HlsUrl url = urls.get(i);
    MediaPlaylistBundle bundle = new MediaPlaylistBundle(url);
    playlistBundles.put(url, bundle);
  }
}
项目:transistor    文件:HlsPlaylistTracker.java   
/**
 * Called by the bundles when a snapshot changes.
 *
 * @param url The url of the playlist.
 * @param newSnapshot The new snapshot.
 */
private void onPlaylistUpdated(HlsUrl url, HlsMediaPlaylist newSnapshot) {
  if (url == primaryHlsUrl) {
    if (primaryUrlSnapshot == null) {
      // This is the first primary url snapshot.
      isLive = !newSnapshot.hasEndTag;
    }
    primaryUrlSnapshot = newSnapshot;
    primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot);
  }
  int listenersSize = listeners.size();
  for (int i = 0; i < listenersSize; i++) {
    listeners.get(i).onPlaylistChanged();
  }
}
项目:transistor    文件:HlsPlaylistTracker.java   
public MediaPlaylistBundle(HlsUrl playlistUrl) {
  this.playlistUrl = playlistUrl;
  mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist");
  mediaPlaylistLoadable = new ParsingLoadable<>(
      dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
      UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST,
      playlistParser);
}
项目:transistor    文件:HlsMediaPeriod.java   
@Override
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) {
    streamWrapper.onPlaylistBlacklisted(url, blacklistMs);
  }
  continuePreparingOrLoading();
}
项目:transistor    文件:HlsMediaPeriod.java   
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
    Format muxedAudioFormat, List<Format> muxedCaptionFormats, long positionUs) {
  HlsChunkSource defaultChunkSource = new HlsChunkSource(extractorFactory, playlistTracker,
      variants, dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats);
  return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator, positionUs,
      muxedAudioFormat, minLoadableRetryCount, eventDispatcher);
}
项目:transistor    文件:HlsMediaPeriod.java   
private static boolean variantHasExplicitCodecWithPrefix(HlsUrl variant, String prefix) {
  String codecs = variant.format.codecs;
  if (TextUtils.isEmpty(codecs)) {
    return false;
  }
  String[] codecArray = codecs.split("(\\s*,\\s*)|(\\s*$)");
  for (String codec : codecArray) {
    if (codec.startsWith(prefix)) {
      return true;
    }
  }
  return false;
}
项目:transistor    文件:HlsChunkSource.java   
/**
 * Called when a playlist is blacklisted.
 *
 * @param url The url that references the blacklisted playlist.
 * @param blacklistMs The amount of milliseconds for which the playlist was blacklisted.
 */
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  int trackGroupIndex = trackGroup.indexOf(url.format);
  if (trackGroupIndex != C.INDEX_UNSET) {
    int trackSelectionIndex = trackSelection.indexOf(trackGroupIndex);
    if (trackSelectionIndex != C.INDEX_UNSET) {
      trackSelection.blacklist(trackSelectionIndex, blacklistMs);
    }
  }
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
private void notifyPlaylistBlacklisting(HlsUrl url, long blacklistMs) {
  int listenersSize = listeners.size();
  for (int i = 0; i < listenersSize; i++) {
    listeners.get(i).onPlaylistBlacklisted(url, blacklistMs);
  }
}
项目:Exoplayer2Radio    文件:HlsMediaPeriod.java   
@Override
public void onPlaylistRefreshRequired(HlsUrl url) {
  playlistTracker.refreshPlaylist(url);
}
项目:Exoplayer2Radio    文件:HlsSampleStreamWrapper.java   
public void onPlaylistBlacklisted(HlsUrl url, long blacklistMs) {
  chunkSource.onPlaylistBlacklisted(url, blacklistMs);
}