@Override public void onTimelineChanged(Timeline timeline, Object manifest) { isTimelineStatic = !timeline.isEmpty() && !timeline.getWindow(timeline.getWindowCount() - 1, window).isDynamic; if (manifest instanceof HlsManifest) { HlsManifest hlsManifest = (HlsManifest) manifest; isHls = !hlsManifest.mediaPlaylist.hasEndTag && hlsManifest.mediaPlaylist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_UNKNOWN; Log.e("time->",stringForTime(hlsManifest.mediaPlaylist.startOffsetUs)); } updateNavigation(); updateProgress(); }
/** * @param baseUri The playlist's base uri. * @param variants The available variants. * @param dataSource A {@link DataSource} suitable for loading the media data. * @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. */ public HlsChunkSource(String baseUri, HlsMasterPlaylist.HlsUrl[] variants, DataSource dataSource, TimestampAdjusterProvider timestampAdjusterProvider) { this.baseUri = baseUri; this.variants = variants; this.dataSource = dataSource; this.timestampAdjusterProvider = timestampAdjusterProvider; playlistParser = new HlsPlaylistParser(); variantPlaylists = new HlsMediaPlaylist[variants.length]; variantLastPlaylistLoadTimesMs = new long[variants.length]; 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; } trackGroup = new TrackGroup(variantFormats); trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection); }
/** * Returns the media sequence number of a chunk in a new variant for a live stream variant switch. * * @param previousChunkIndex The index of the last chunk in the old variant. * @param oldVariantIndex The index of the old variant. * @param newVariantIndex The index of the new variant. * @return Media sequence number of the chunk to switch to in a live stream in the variant that * corresponds to the given {@code newVariantIndex}. */ private int getLiveNextChunkSequenceNumber(int previousChunkIndex, int oldVariantIndex, int newVariantIndex) { if (oldVariantIndex == newVariantIndex) { return previousChunkIndex + 1; } HlsMediaPlaylist oldMediaPlaylist = variantPlaylists[oldVariantIndex]; HlsMediaPlaylist newMediaPlaylist = variantPlaylists[newVariantIndex]; double offsetToLiveInstantSecs = 0; for (int i = previousChunkIndex - oldMediaPlaylist.mediaSequence; i < oldMediaPlaylist.segments.size(); i++) { offsetToLiveInstantSecs += oldMediaPlaylist.segments.get(i).durationSecs; } long currentTimeMs = SystemClock.elapsedRealtime(); offsetToLiveInstantSecs += (double) (currentTimeMs - variantLastPlaylistLoadTimesMs[oldVariantIndex]) / 1000; offsetToLiveInstantSecs += LIVE_VARIANT_SWITCH_SAFETY_EXTRA_SECS; offsetToLiveInstantSecs -= (double) (currentTimeMs - variantLastPlaylistLoadTimesMs[newVariantIndex]) / 1000; if (offsetToLiveInstantSecs < 0) { // The instant we are looking for is not contained in the playlist, we need it to be // refreshed. return newMediaPlaylist.mediaSequence + newMediaPlaylist.segments.size() + 1; } for (int i = newMediaPlaylist.segments.size() - 1; i >= 0; i--) { offsetToLiveInstantSecs -= newMediaPlaylist.segments.get(i).durationSecs; if (offsetToLiveInstantSecs < 0) { return newMediaPlaylist.mediaSequence + i; } } // We have fallen behind the live window. return newMediaPlaylist.mediaSequence - 1; }
private HlsInitializationChunk buildInitializationChunk(HlsMediaPlaylist mediaPlaylist, Extractor extractor, Format format) { Segment initSegment = mediaPlaylist.initializationSegment; // The initialization segment is required before the actual media chunk. Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url); DataSpec initDataSpec = new DataSpec(initSegmentUri, initSegment.byterangeOffset, initSegment.byterangeLength, null); return new HlsInitializationChunk(dataSource, initDataSpec, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), extractor, format); }
private long msToRerequestLiveMediaPlaylist(int variantIndex) { HlsMediaPlaylist mediaPlaylist = variantPlaylists[variantIndex]; long timeSinceLastMediaPlaylistLoadMs = SystemClock.elapsedRealtime() - variantLastPlaylistLoadTimesMs[variantIndex]; // Don't re-request media playlist more often than one-half of the target duration. return (mediaPlaylist.targetDurationSecs * 1000) / 2 - timeSinceLastMediaPlaylistLoadMs; }
private static void addSegment(ArrayList<Segment> segments, HlsMediaPlaylist mediaPlaylist, HlsMediaPlaylist.Segment hlsSegment, HashSet<Uri> encryptionKeyUris) throws IOException, InterruptedException { long startTimeUs = mediaPlaylist.startTimeUs + hlsSegment.relativeStartTimeUs; if (hlsSegment.fullSegmentEncryptionKeyUri != null) { Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, hlsSegment.fullSegmentEncryptionKeyUri); if (encryptionKeyUris.add(keyUri)) { segments.add(new Segment(startTimeUs, new DataSpec(keyUri))); } } Uri resolvedUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, hlsSegment.url); segments.add(new Segment(startTimeUs, new DataSpec(resolvedUri, hlsSegment.byterangeOffset, hlsSegment.byterangeLength, null))); }
/** * @param masterPlaylist The master playlist. * @param mediaPlaylist The media playlist. */ HlsManifest(HlsMasterPlaylist masterPlaylist, HlsMediaPlaylist mediaPlaylist) { this.masterPlaylist = masterPlaylist; this.mediaPlaylist = mediaPlaylist; }
private void setMediaPlaylist(int variantIndex, HlsMediaPlaylist mediaPlaylist) { variantLastPlaylistLoadTimesMs[variantIndex] = SystemClock.elapsedRealtime(); variantPlaylists[variantIndex] = mediaPlaylist; live |= mediaPlaylist.live; durationUs = live ? C.TIME_UNSET : mediaPlaylist.durationUs; }
@Override protected void consume(byte[] data, int limit) throws IOException { result = (HlsMediaPlaylist) playlistParser.parse(playlistUri, new ByteArrayInputStream(data, 0, limit)); }
public HlsMediaPlaylist getResult() { return result; }
private void updateLiveEdgeTimeUs(HlsMediaPlaylist mediaPlaylist) { liveEdgeTimeUs = mediaPlaylist.hasEndTag ? C.TIME_UNSET : mediaPlaylist.getEndTimeUs(); }