Search in sources :

Example 6 with AdaptationSet

use of com.google.android.exoplayer2.source.dash.manifest.AdaptationSet in project ExoPlayer by google.

the class DashMediaSource method getAvailableEndTimeInManifestUs.

private static long getAvailableEndTimeInManifestUs(Period period, long periodDurationUs, long nowUnixTimeUs) {
    long periodStartTimeInManifestUs = Util.msToUs(period.startMs);
    long availableEndTimeInManifestUs = Long.MAX_VALUE;
    boolean haveAudioVideoAdaptationSets = hasVideoOrAudioAdaptationSets(period);
    for (int i = 0; i < period.adaptationSets.size(); i++) {
        AdaptationSet adaptationSet = period.adaptationSets.get(i);
        List<Representation> representations = adaptationSet.representations;
        // or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
        if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT) || representations.isEmpty()) {
            continue;
        }
        @Nullable DashSegmentIndex index = representations.get(0).getIndex();
        if (index == null) {
            return periodStartTimeInManifestUs + periodDurationUs;
        }
        long availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
        if (availableSegmentCount == 0) {
            return periodStartTimeInManifestUs;
        }
        long firstAvailableSegmentNum = index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
        long lastAvailableSegmentNum = firstAvailableSegmentNum + availableSegmentCount - 1;
        long adaptationSetAvailableEndTimeInManifestUs = periodStartTimeInManifestUs + index.getTimeUs(lastAvailableSegmentNum) + index.getDurationUs(lastAvailableSegmentNum, periodDurationUs);
        availableEndTimeInManifestUs = min(availableEndTimeInManifestUs, adaptationSetAvailableEndTimeInManifestUs);
    }
    return availableEndTimeInManifestUs;
}
Also used : AdaptationSet(com.google.android.exoplayer2.source.dash.manifest.AdaptationSet) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation) Nullable(androidx.annotation.Nullable)

Example 7 with AdaptationSet

use of com.google.android.exoplayer2.source.dash.manifest.AdaptationSet in project ExoPlayer by google.

the class DashMediaSource method getAvailableStartTimeInManifestUs.

private static long getAvailableStartTimeInManifestUs(Period period, long periodDurationUs, long nowUnixTimeUs) {
    long periodStartTimeInManifestUs = Util.msToUs(period.startMs);
    long availableStartTimeInManifestUs = periodStartTimeInManifestUs;
    boolean haveAudioVideoAdaptationSets = hasVideoOrAudioAdaptationSets(period);
    for (int i = 0; i < period.adaptationSets.size(); i++) {
        AdaptationSet adaptationSet = period.adaptationSets.get(i);
        List<Representation> representations = adaptationSet.representations;
        // or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
        if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT) || representations.isEmpty()) {
            continue;
        }
        @Nullable DashSegmentIndex index = representations.get(0).getIndex();
        if (index == null) {
            return periodStartTimeInManifestUs;
        }
        long availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
        if (availableSegmentCount == 0) {
            return periodStartTimeInManifestUs;
        }
        long firstAvailableSegmentNum = index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
        long adaptationSetAvailableStartTimeInManifestUs = periodStartTimeInManifestUs + index.getTimeUs(firstAvailableSegmentNum);
        availableStartTimeInManifestUs = max(availableStartTimeInManifestUs, adaptationSetAvailableStartTimeInManifestUs);
    }
    return availableStartTimeInManifestUs;
}
Also used : AdaptationSet(com.google.android.exoplayer2.source.dash.manifest.AdaptationSet) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation) Nullable(androidx.annotation.Nullable)

Example 8 with AdaptationSet

use of com.google.android.exoplayer2.source.dash.manifest.AdaptationSet in project ExoPlayer by google.

the class DashMediaPeriod method getGroupedAdaptationSetIndices.

/**
 * Groups adaptation sets. Two adaptations sets belong to the same group if either:
 *
 * <ul>
 *   <li>One is a trick-play adaptation set and uses a {@code
 *       http://dashif.org/guidelines/trickmode} essential or supplemental property to indicate
 *       that the other is the main adaptation set to which it corresponds.
 *   <li>The two adaptation sets are marked as safe for switching using {@code
 *       urn:mpeg:dash:adaptation-set-switching:2016} supplemental properties.
 * </ul>
 *
 * @param adaptationSets The adaptation sets to merge.
 * @return An array of groups, where each group is an array of adaptation set indices.
 */
private static int[][] getGroupedAdaptationSetIndices(List<AdaptationSet> adaptationSets) {
    int adaptationSetCount = adaptationSets.size();
    SparseIntArray adaptationSetIdToIndex = new SparseIntArray(adaptationSetCount);
    List<List<Integer>> adaptationSetGroupedIndices = new ArrayList<>(adaptationSetCount);
    SparseArray<List<Integer>> adaptationSetIndexToGroupedIndices = new SparseArray<>(adaptationSetCount);
    // adaptationSetIdToIndex map.
    for (int i = 0; i < adaptationSetCount; i++) {
        adaptationSetIdToIndex.put(adaptationSets.get(i).id, i);
        List<Integer> initialGroup = new ArrayList<>();
        initialGroup.add(i);
        adaptationSetGroupedIndices.add(initialGroup);
        adaptationSetIndexToGroupedIndices.put(i, initialGroup);
    }
    // Merge adaptation set groups.
    for (int i = 0; i < adaptationSetCount; i++) {
        int mergedGroupIndex = i;
        AdaptationSet adaptationSet = adaptationSets.get(i);
        // Trick-play adaptation sets are merged with their corresponding main adaptation sets.
        @Nullable Descriptor trickPlayProperty = findTrickPlayProperty(adaptationSet.essentialProperties);
        if (trickPlayProperty == null) {
            // Trick-play can also be specified using a supplemental property.
            trickPlayProperty = findTrickPlayProperty(adaptationSet.supplementalProperties);
        }
        if (trickPlayProperty != null) {
            int mainAdaptationSetId = Integer.parseInt(trickPlayProperty.value);
            int mainAdaptationSetIndex = adaptationSetIdToIndex.get(mainAdaptationSetId, /* valueIfKeyNotFound= */
            -1);
            if (mainAdaptationSetIndex != -1) {
                mergedGroupIndex = mainAdaptationSetIndex;
            }
        }
        // merged group.
        if (mergedGroupIndex == i) {
            @Nullable Descriptor adaptationSetSwitchingProperty = findAdaptationSetSwitchingProperty(adaptationSet.supplementalProperties);
            if (adaptationSetSwitchingProperty != null) {
                String[] otherAdaptationSetIds = Util.split(adaptationSetSwitchingProperty.value, ",");
                for (String adaptationSetId : otherAdaptationSetIds) {
                    int otherAdaptationSetId = adaptationSetIdToIndex.get(Integer.parseInt(adaptationSetId), /* valueIfKeyNotFound= */
                    -1);
                    if (otherAdaptationSetId != -1) {
                        mergedGroupIndex = min(mergedGroupIndex, otherAdaptationSetId);
                    }
                }
            }
        }
        // Merge the groups if necessary.
        if (mergedGroupIndex != i) {
            List<Integer> thisGroup = adaptationSetIndexToGroupedIndices.get(i);
            List<Integer> mergedGroup = adaptationSetIndexToGroupedIndices.get(mergedGroupIndex);
            mergedGroup.addAll(thisGroup);
            adaptationSetIndexToGroupedIndices.put(i, mergedGroup);
            adaptationSetGroupedIndices.remove(thisGroup);
        }
    }
    int[][] groupedAdaptationSetIndices = new int[adaptationSetGroupedIndices.size()][];
    for (int i = 0; i < groupedAdaptationSetIndices.length; i++) {
        groupedAdaptationSetIndices[i] = Ints.toArray(adaptationSetGroupedIndices.get(i));
        // Restore the original adaptation set order within each group.
        Arrays.sort(groupedAdaptationSetIndices[i]);
    }
    return groupedAdaptationSetIndices;
}
Also used : ArrayList(java.util.ArrayList) SparseArray(android.util.SparseArray) SparseIntArray(android.util.SparseIntArray) Descriptor(com.google.android.exoplayer2.source.dash.manifest.Descriptor) List(java.util.List) ArrayList(java.util.ArrayList) AdaptationSet(com.google.android.exoplayer2.source.dash.manifest.AdaptationSet) Nullable(androidx.annotation.Nullable)

Example 9 with AdaptationSet

use of com.google.android.exoplayer2.source.dash.manifest.AdaptationSet in project ExoPlayer by google.

the class DashMediaPeriod method buildTrackGroups.

private static Pair<TrackGroupArray, TrackGroupInfo[]> buildTrackGroups(DrmSessionManager drmSessionManager, List<AdaptationSet> adaptationSets, List<EventStream> eventStreams) {
    int[][] groupedAdaptationSetIndices = getGroupedAdaptationSetIndices(adaptationSets);
    int primaryGroupCount = groupedAdaptationSetIndices.length;
    boolean[] primaryGroupHasEventMessageTrackFlags = new boolean[primaryGroupCount];
    Format[][] primaryGroupClosedCaptionTrackFormats = new Format[primaryGroupCount][];
    int totalEmbeddedTrackGroupCount = identifyEmbeddedTracks(primaryGroupCount, adaptationSets, groupedAdaptationSetIndices, primaryGroupHasEventMessageTrackFlags, primaryGroupClosedCaptionTrackFormats);
    int totalGroupCount = primaryGroupCount + totalEmbeddedTrackGroupCount + eventStreams.size();
    TrackGroup[] trackGroups = new TrackGroup[totalGroupCount];
    TrackGroupInfo[] trackGroupInfos = new TrackGroupInfo[totalGroupCount];
    int trackGroupCount = buildPrimaryAndEmbeddedTrackGroupInfos(drmSessionManager, adaptationSets, groupedAdaptationSetIndices, primaryGroupCount, primaryGroupHasEventMessageTrackFlags, primaryGroupClosedCaptionTrackFormats, trackGroups, trackGroupInfos);
    buildManifestEventTrackGroupInfos(eventStreams, trackGroups, trackGroupInfos, trackGroupCount);
    return Pair.create(new TrackGroupArray(trackGroups), trackGroupInfos);
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray)

Example 10 with AdaptationSet

use of com.google.android.exoplayer2.source.dash.manifest.AdaptationSet in project ExoPlayer by google.

the class DashMediaPeriod method buildPrimaryAndEmbeddedTrackGroupInfos.

private static int buildPrimaryAndEmbeddedTrackGroupInfos(DrmSessionManager drmSessionManager, List<AdaptationSet> adaptationSets, int[][] groupedAdaptationSetIndices, int primaryGroupCount, boolean[] primaryGroupHasEventMessageTrackFlags, Format[][] primaryGroupClosedCaptionTrackFormats, TrackGroup[] trackGroups, TrackGroupInfo[] trackGroupInfos) {
    int trackGroupCount = 0;
    for (int i = 0; i < primaryGroupCount; i++) {
        int[] adaptationSetIndices = groupedAdaptationSetIndices[i];
        List<Representation> representations = new ArrayList<>();
        for (int adaptationSetIndex : adaptationSetIndices) {
            representations.addAll(adaptationSets.get(adaptationSetIndex).representations);
        }
        Format[] formats = new Format[representations.size()];
        for (int j = 0; j < formats.length; j++) {
            Format format = representations.get(j).format;
            formats[j] = format.copyWithCryptoType(drmSessionManager.getCryptoType(format));
        }
        AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]);
        String trackGroupId = firstAdaptationSet.id != AdaptationSet.ID_UNSET ? Integer.toString(firstAdaptationSet.id) : ("unset:" + i);
        int primaryTrackGroupIndex = trackGroupCount++;
        int eventMessageTrackGroupIndex = primaryGroupHasEventMessageTrackFlags[i] ? trackGroupCount++ : C.INDEX_UNSET;
        int closedCaptionTrackGroupIndex = primaryGroupClosedCaptionTrackFormats[i].length != 0 ? trackGroupCount++ : C.INDEX_UNSET;
        trackGroups[primaryTrackGroupIndex] = new TrackGroup(trackGroupId, formats);
        trackGroupInfos[primaryTrackGroupIndex] = TrackGroupInfo.primaryTrack(firstAdaptationSet.type, adaptationSetIndices, primaryTrackGroupIndex, eventMessageTrackGroupIndex, closedCaptionTrackGroupIndex);
        if (eventMessageTrackGroupIndex != C.INDEX_UNSET) {
            String eventMessageTrackGroupId = trackGroupId + ":emsg";
            Format format = new Format.Builder().setId(eventMessageTrackGroupId).setSampleMimeType(MimeTypes.APPLICATION_EMSG).build();
            trackGroups[eventMessageTrackGroupIndex] = new TrackGroup(eventMessageTrackGroupId, format);
            trackGroupInfos[eventMessageTrackGroupIndex] = TrackGroupInfo.embeddedEmsgTrack(adaptationSetIndices, primaryTrackGroupIndex);
        }
        if (closedCaptionTrackGroupIndex != C.INDEX_UNSET) {
            String closedCaptionTrackGroupId = trackGroupId + ":cc";
            trackGroups[closedCaptionTrackGroupIndex] = new TrackGroup(closedCaptionTrackGroupId, primaryGroupClosedCaptionTrackFormats[i]);
            trackGroupInfos[closedCaptionTrackGroupIndex] = TrackGroupInfo.embeddedClosedCaptionTrack(adaptationSetIndices, primaryTrackGroupIndex);
        }
    }
    return trackGroupCount;
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) ArrayList(java.util.ArrayList) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation) AdaptationSet(com.google.android.exoplayer2.source.dash.manifest.AdaptationSet)

Aggregations

AdaptationSet (com.google.android.exoplayer2.source.dash.manifest.AdaptationSet)16 Format (com.google.android.exoplayer2.Format)9 ArrayList (java.util.ArrayList)9 Test (org.junit.Test)9 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)8 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)7 Representation (com.google.android.exoplayer2.source.dash.manifest.Representation)7 DashManifest (com.google.android.exoplayer2.source.dash.manifest.DashManifest)6 Nullable (androidx.annotation.Nullable)5 StreamKey (com.google.android.exoplayer2.offline.StreamKey)4 MultiSegmentRepresentation (com.google.android.exoplayer2.source.dash.manifest.Representation.MultiSegmentRepresentation)3 SingleSegmentRepresentation (com.google.android.exoplayer2.source.dash.manifest.Representation.SingleSegmentRepresentation)3 Descriptor (com.google.android.exoplayer2.source.dash.manifest.Descriptor)2 Period (com.google.android.exoplayer2.source.dash.manifest.Period)2 SingleSegmentBase (com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)2 SparseArray (android.util.SparseArray)1 SparseIntArray (android.util.SparseIntArray)1 DownloadException (com.google.android.exoplayer2.offline.DownloadException)1 ChunkSampleStream (com.google.android.exoplayer2.source.chunk.ChunkSampleStream)1 DashSegmentIndex (com.google.android.exoplayer2.source.dash.DashSegmentIndex)1