Search in sources :

Example 16 with DashManifest

use of androidx.media3.exoplayer.dash.manifest.DashManifest in project media by androidx.

the class DashManifestParserTest method parseMediaPresentationDescription_text.

@Test
public void parseMediaPresentationDescription_text() throws IOException {
    DashManifestParser parser = new DashManifestParser();
    DashManifest manifest = parser.parse(Uri.parse("https://example.com/test.mpd"), TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_MPD_TEXT));
    List<AdaptationSet> adaptationSets = manifest.getPeriod(0).adaptationSets;
    Format format = adaptationSets.get(0).representations.get(0).format;
    assertThat(format.containerMimeType).isEqualTo(MimeTypes.APPLICATION_RAWCC);
    assertThat(format.sampleMimeType).isEqualTo(MimeTypes.APPLICATION_CEA608);
    assertThat(format.codecs).isEqualTo("cea608");
    assertThat(format.roleFlags).isEqualTo(C.ROLE_FLAG_SUBTITLE | C.ROLE_FLAG_MAIN);
    assertThat(format.selectionFlags).isEqualTo(0);
    assertThat(adaptationSets.get(0).type).isEqualTo(C.TRACK_TYPE_TEXT);
    format = adaptationSets.get(1).representations.get(0).format;
    assertThat(format.containerMimeType).isEqualTo(MimeTypes.APPLICATION_MP4);
    assertThat(format.sampleMimeType).isEqualTo(MimeTypes.APPLICATION_TTML);
    assertThat(format.codecs).isEqualTo("stpp.ttml.im1t");
    assertThat(format.roleFlags).isEqualTo(C.ROLE_FLAG_SUBTITLE);
    assertThat(format.selectionFlags).isEqualTo(C.SELECTION_FLAG_FORCED);
    assertThat(adaptationSets.get(1).type).isEqualTo(C.TRACK_TYPE_TEXT);
    // Ensure that forced-subtitle and forced_subtitle are both parsed as a 'forced' text track.
    // https://github.com/google/ExoPlayer/issues/9727
    format = adaptationSets.get(2).representations.get(0).format;
    assertThat(format.roleFlags).isEqualTo(C.ROLE_FLAG_SUBTITLE);
    assertThat(format.selectionFlags).isEqualTo(C.SELECTION_FLAG_FORCED);
    format = adaptationSets.get(3).representations.get(0).format;
    assertThat(format.containerMimeType).isEqualTo(MimeTypes.APPLICATION_TTML);
    assertThat(format.sampleMimeType).isEqualTo(MimeTypes.APPLICATION_TTML);
    assertThat(format.codecs).isNull();
    assertThat(format.roleFlags).isEqualTo(0);
    assertThat(adaptationSets.get(2).type).isEqualTo(C.TRACK_TYPE_TEXT);
}
Also used : Format(androidx.media3.common.Format) Test(org.junit.Test)

Example 17 with DashManifest

use of androidx.media3.exoplayer.dash.manifest.DashManifest in project media by androidx.

the class DashManifestParserTest method parseEssentialAndSupplementalProperties.

@Test
public void parseEssentialAndSupplementalProperties() throws IOException {
    DashManifestParser parser = new DashManifestParser();
    DashManifest manifest = parser.parse(Uri.parse("https://example.com/test.mpd"), TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_MPD_ESSENTIAL_SUPPLEMENTAL_PROPERTIES));
    // Verify test setup.
    assertThat(manifest.getPeriodCount()).isEqualTo(1);
    assertThat(manifest.getPeriod(0).adaptationSets).hasSize(1);
    AdaptationSet adaptationSet = manifest.getPeriod(0).adaptationSets.get(0);
    assertThat(adaptationSet.representations).hasSize(2);
    Representation representation0 = adaptationSet.representations.get(0);
    Representation representation1 = adaptationSet.representations.get(1);
    assertThat(representation0).isInstanceOf(SingleSegmentRepresentation.class);
    assertThat(representation1).isInstanceOf(MultiSegmentRepresentation.class);
    // Verify parsed properties.
    assertThat(adaptationSet.essentialProperties).hasSize(1);
    assertThat(adaptationSet.essentialProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
    assertThat(adaptationSet.essentialProperties.get(0).value).isEqualTo("adaptationEssential");
    assertThat(adaptationSet.supplementalProperties).hasSize(1);
    assertThat(adaptationSet.supplementalProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
    assertThat(adaptationSet.supplementalProperties.get(0).value).isEqualTo("adaptationSupplemental");
    assertThat(representation0.essentialProperties).hasSize(2);
    assertThat(representation0.essentialProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
    assertThat(representation0.essentialProperties.get(0).value).isEqualTo("adaptationEssential");
    assertThat(representation0.essentialProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
    assertThat(representation0.essentialProperties.get(1).value).isEqualTo("representationEssential");
    assertThat(representation0.supplementalProperties).hasSize(2);
    assertThat(representation0.supplementalProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
    assertThat(representation0.supplementalProperties.get(0).value).isEqualTo("adaptationSupplemental");
    assertThat(representation0.supplementalProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
    assertThat(representation0.supplementalProperties.get(1).value).isEqualTo("representationSupplemental");
    assertThat(representation1.essentialProperties).hasSize(2);
    assertThat(representation0.essentialProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
    assertThat(representation0.essentialProperties.get(0).value).isEqualTo("adaptationEssential");
    assertThat(representation1.essentialProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
    assertThat(representation1.essentialProperties.get(1).value).isEqualTo("representationEssential");
    assertThat(representation1.supplementalProperties).hasSize(2);
    assertThat(representation0.supplementalProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
    assertThat(representation0.supplementalProperties.get(0).value).isEqualTo("adaptationSupplemental");
    assertThat(representation1.supplementalProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
    assertThat(representation1.supplementalProperties.get(1).value).isEqualTo("representationSupplemental");
}
Also used : MultiSegmentRepresentation(androidx.media3.exoplayer.dash.manifest.Representation.MultiSegmentRepresentation) SingleSegmentRepresentation(androidx.media3.exoplayer.dash.manifest.Representation.SingleSegmentRepresentation) Test(org.junit.Test)

Example 18 with DashManifest

use of androidx.media3.exoplayer.dash.manifest.DashManifest in project media by androidx.

the class DashMediaSource method getIntervalUntilNextManifestRefreshMs.

private static long getIntervalUntilNextManifestRefreshMs(DashManifest manifest, long nowUnixTimeMs) {
    int periodIndex = manifest.getPeriodCount() - 1;
    Period period = manifest.getPeriod(periodIndex);
    long periodStartUs = Util.msToUs(period.startMs);
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    long nowUnixTimeUs = Util.msToUs(nowUnixTimeMs);
    long availabilityStartTimeUs = Util.msToUs(manifest.availabilityStartTimeMs);
    long intervalUs = Util.msToUs(DEFAULT_NOTIFY_MANIFEST_INTERVAL_MS);
    for (int i = 0; i < period.adaptationSets.size(); i++) {
        List<Representation> representations = period.adaptationSets.get(i).representations;
        if (representations.isEmpty()) {
            continue;
        }
        @Nullable DashSegmentIndex index = representations.get(0).getIndex();
        if (index != null) {
            long nextSegmentShiftUnixTimeUs = availabilityStartTimeUs + periodStartUs + index.getNextSegmentAvailableTimeUs(periodDurationUs, nowUnixTimeUs);
            long requiredIntervalUs = nextSegmentShiftUnixTimeUs - nowUnixTimeUs;
            // Avoid multiple refreshes within a very small amount of time.
            if (requiredIntervalUs < intervalUs - 100_000 || (requiredIntervalUs > intervalUs && requiredIntervalUs < intervalUs + 100_000)) {
                intervalUs = requiredIntervalUs;
            }
        }
    }
    // Round up to compensate for a potential loss in the us to ms conversion.
    return LongMath.divide(intervalUs, 1000, RoundingMode.CEILING);
}
Also used : Period(androidx.media3.exoplayer.dash.manifest.Period) MediaPeriod(androidx.media3.exoplayer.source.MediaPeriod) Representation(androidx.media3.exoplayer.dash.manifest.Representation) Nullable(androidx.annotation.Nullable)

Example 19 with DashManifest

use of androidx.media3.exoplayer.dash.manifest.DashManifest in project media by androidx.

the class DefaultDashChunkSource method updateManifest.

@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
    try {
        manifest = newManifest;
        periodIndex = newPeriodIndex;
        long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
        List<Representation> representations = getRepresentations();
        for (int i = 0; i < representationHolders.length; i++) {
            Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
            representationHolders[i] = representationHolders[i].copyWithNewRepresentation(periodDurationUs, representation);
        }
    } catch (BehindLiveWindowException e) {
        fatalError = e;
    }
}
Also used : BehindLiveWindowException(androidx.media3.exoplayer.source.BehindLiveWindowException) Representation(androidx.media3.exoplayer.dash.manifest.Representation)

Example 20 with DashManifest

use of androidx.media3.exoplayer.dash.manifest.DashManifest in project media by androidx.

the class DashManifest method copy.

@Override
public final DashManifest copy(List<StreamKey> streamKeys) {
    LinkedList<StreamKey> keys = new LinkedList<>(streamKeys);
    Collections.sort(keys);
    // Add a stopper key to the end
    keys.add(new StreamKey(-1, -1, -1));
    ArrayList<Period> copyPeriods = new ArrayList<>();
    long shiftMs = 0;
    for (int periodIndex = 0; periodIndex < getPeriodCount(); periodIndex++) {
        if (keys.peek().periodIndex != periodIndex) {
            // No representations selected in this period.
            long periodDurationMs = getPeriodDurationMs(periodIndex);
            if (periodDurationMs != C.TIME_UNSET) {
                shiftMs += periodDurationMs;
            }
        } else {
            Period period = getPeriod(periodIndex);
            ArrayList<AdaptationSet> copyAdaptationSets = copyAdaptationSets(period.adaptationSets, keys);
            Period copiedPeriod = new Period(period.id, period.startMs - shiftMs, copyAdaptationSets, period.eventStreams);
            copyPeriods.add(copiedPeriod);
        }
    }
    long newDuration = durationMs != C.TIME_UNSET ? durationMs - shiftMs : C.TIME_UNSET;
    return new DashManifest(availabilityStartTimeMs, newDuration, minBufferTimeMs, dynamic, minUpdatePeriodMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, publishTimeMs, programInformation, utcTiming, serviceDescription, location, copyPeriods);
}
Also used : ArrayList(java.util.ArrayList) StreamKey(androidx.media3.common.StreamKey) LinkedList(java.util.LinkedList)

Aggregations

Test (org.junit.Test)14 DashManifest (androidx.media3.exoplayer.dash.manifest.DashManifest)12 TrackGroup (androidx.media3.common.TrackGroup)8 AdaptationSet (androidx.media3.exoplayer.dash.manifest.AdaptationSet)7 Format (androidx.media3.common.Format)6 TrackGroupArray (androidx.media3.common.TrackGroupArray)5 StreamKey (androidx.media3.common.StreamKey)3 DashManifestParser (androidx.media3.exoplayer.dash.manifest.DashManifestParser)3 Representation (androidx.media3.exoplayer.dash.manifest.Representation)3 LoaderErrorThrower (androidx.media3.exoplayer.upstream.LoaderErrorThrower)3 FakeDataSource (androidx.media3.test.utils.FakeDataSource)3 ArrayList (java.util.ArrayList)3 Period (androidx.media3.exoplayer.dash.manifest.Period)2 MultiSegmentRepresentation (androidx.media3.exoplayer.dash.manifest.Representation.MultiSegmentRepresentation)2 SingleSegmentRepresentation (androidx.media3.exoplayer.dash.manifest.Representation.SingleSegmentRepresentation)2 LoadEventInfo (androidx.media3.exoplayer.source.LoadEventInfo)2 ChunkHolder (androidx.media3.exoplayer.source.chunk.ChunkHolder)2 FixedTrackSelection (androidx.media3.exoplayer.trackselection.FixedTrackSelection)2 Random (java.util.Random)2 Nullable (androidx.annotation.Nullable)1