mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Some brevity/consistency renaming in source package
SmoothStreaming -> Ss MediaPresentationDescription -> DashManifest DashSingleSegmentIndex -> SingleSegmentIndex Moved DASH and Ss manifest classes to matching manifest packages for consistency. For Hls the package is called playlist still, since that's what they're widely known as. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=127925961
This commit is contained in:
parent
fc457e4c1b
commit
722e05b8ba
@ -43,8 +43,8 @@ import com.google.android.exoplayer2.source.chunk.FormatEvaluator.AdaptiveEvalua
|
|||||||
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
||||||
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
|
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
|
||||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSmoothStreamingChunkSource;
|
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingMediaSource;
|
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
|
||||||
import com.google.android.exoplayer2.text.CaptionStyleCompat;
|
import com.google.android.exoplayer2.text.CaptionStyleCompat;
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.text.SubtitleLayout;
|
import com.google.android.exoplayer2.text.SubtitleLayout;
|
||||||
@ -349,16 +349,13 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
int type = Util.inferContentType(lastPathSegment);
|
int type = Util.inferContentType(lastPathSegment);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Util.TYPE_SS:
|
case Util.TYPE_SS:
|
||||||
DefaultSmoothStreamingChunkSource.Factory factory =
|
DefaultSsChunkSource.Factory factory = new DefaultSsChunkSource.Factory(
|
||||||
new DefaultSmoothStreamingChunkSource.Factory(mediaDataSourceFactory,
|
mediaDataSourceFactory, formatEvaluatorFactory);
|
||||||
formatEvaluatorFactory);
|
return new SsMediaSource(uri, manifestDataSourceFactory, factory, mainHandler, eventLogger);
|
||||||
return new SmoothStreamingMediaSource(uri, manifestDataSourceFactory, factory, mainHandler,
|
|
||||||
eventLogger);
|
|
||||||
case Util.TYPE_DASH:
|
case Util.TYPE_DASH:
|
||||||
DefaultDashChunkSource.Factory factory2 = new DefaultDashChunkSource.Factory(
|
DefaultDashChunkSource.Factory factory2 = new DefaultDashChunkSource.Factory(
|
||||||
mediaDataSourceFactory, formatEvaluatorFactory);
|
mediaDataSourceFactory, formatEvaluatorFactory);
|
||||||
return new DashMediaSource(uri, mediaDataSourceFactory, factory2, mainHandler,
|
return new DashMediaSource(uri, mediaDataSourceFactory, factory2, mainHandler, eventLogger);
|
||||||
eventLogger);
|
|
||||||
case Util.TYPE_HLS:
|
case Util.TYPE_HLS:
|
||||||
return new HlsMediaSource(uri, mediaDataSourceFactory, formatEvaluatorFactory, mainHandler,
|
return new HlsMediaSource(uri, mediaDataSourceFactory, formatEvaluatorFactory, mainHandler,
|
||||||
eventLogger);
|
eventLogger);
|
||||||
|
@ -74,7 +74,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testGetAvailableRangeOnLiveWithTimeline() {
|
public void testGetAvailableRangeOnLiveWithTimeline() {
|
||||||
MediaPresentationDescription mpd = buildLiveMpdWithTimeline(LIVE_DURATION_MS, 0);
|
DashManifest mpd = buildLiveMpdWithTimeline(LIVE_DURATION_MS, 0);
|
||||||
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
||||||
TimeRange availableRange = chunkSource.getAvailableRange();
|
TimeRange availableRange = chunkSource.getAvailableRange();
|
||||||
checkAvailableRange(availableRange, 0, LIVE_DURATION_MS * 1000);
|
checkAvailableRange(availableRange, 0, LIVE_DURATION_MS * 1000);
|
||||||
@ -90,7 +90,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testGetSeekRangeOnMultiPeriodLiveWithTimeline() {
|
public void testGetSeekRangeOnMultiPeriodLiveWithTimeline() {
|
||||||
MediaPresentationDescription mpd = buildMultiPeriodLiveMpdWithTimeline();
|
DashManifest mpd = buildMultiPeriodLiveMpdWithTimeline();
|
||||||
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
||||||
TimeRange availableRange = chunkSource.getAvailableRange();
|
TimeRange availableRange = chunkSource.getAvailableRange();
|
||||||
checkAvailableRange(availableRange, 0, MULTI_PERIOD_LIVE_DURATION_MS * 1000);
|
checkAvailableRange(availableRange, 0, MULTI_PERIOD_LIVE_DURATION_MS * 1000);
|
||||||
@ -113,13 +113,13 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testSegmentRequestSequenceOnMultiPeriodLiveWithTimeline() {
|
public void testSegmentRequestSequenceOnMultiPeriodLiveWithTimeline() {
|
||||||
MediaPresentationDescription mpd = buildMultiPeriodLiveMpdWithTimeline();
|
DashManifest mpd = buildMultiPeriodLiveMpdWithTimeline();
|
||||||
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
||||||
checkSegmentRequestSequenceOnMultiPeriodLive(chunkSource);
|
checkSegmentRequestSequenceOnMultiPeriodLive(chunkSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSegmentRequestSequenceOnMultiPeriodLiveWithTemplate() {
|
public void testSegmentRequestSequenceOnMultiPeriodLiveWithTemplate() {
|
||||||
MediaPresentationDescription mpd = buildMultiPeriodLiveMpdWithTemplate();
|
DashManifest mpd = buildMultiPeriodLiveMpdWithTemplate();
|
||||||
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
DashChunkSource chunkSource = buildDashChunkSource(mpd);
|
||||||
checkSegmentRequestSequenceOnMultiPeriodLive(chunkSource);
|
checkSegmentRequestSequenceOnMultiPeriodLive(chunkSource);
|
||||||
}
|
}
|
||||||
@ -208,30 +208,30 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
return Representation.newInstance(null, 0, REGULAR_VIDEO, segmentBase);
|
return Representation.newInstance(null, 0, REGULAR_VIDEO, segmentBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildMpd(long durationMs,
|
private static DashManifest buildMpd(long durationMs,
|
||||||
List<Representation> representations, boolean live, boolean limitTimeshiftBuffer) {
|
List<Representation> representations, boolean live, boolean limitTimeshiftBuffer) {
|
||||||
AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_VIDEO, representations);
|
AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_VIDEO, representations);
|
||||||
Period period = new Period(null, 0, Collections.singletonList(adaptationSet));
|
Period period = new Period(null, 0, Collections.singletonList(adaptationSet));
|
||||||
return new MediaPresentationDescription(AVAILABILITY_START_TIME_MS, durationMs, -1, live, -1,
|
return new DashManifest(AVAILABILITY_START_TIME_MS, durationMs, -1, live, -1,
|
||||||
(limitTimeshiftBuffer) ? LIVE_TIMESHIFT_BUFFER_DEPTH_MS : -1, null, null,
|
(limitTimeshiftBuffer) ? LIVE_TIMESHIFT_BUFFER_DEPTH_MS : -1, null, null,
|
||||||
Collections.singletonList(period));
|
Collections.singletonList(period));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildMultiPeriodMpd(long durationMs,
|
private static DashManifest buildMultiPeriodMpd(long durationMs,
|
||||||
List<Period> periods, boolean live, boolean limitTimeshiftBuffer) {
|
List<Period> periods, boolean live, boolean limitTimeshiftBuffer) {
|
||||||
return new MediaPresentationDescription(AVAILABILITY_START_TIME_MS, durationMs, -1, live, -1,
|
return new DashManifest(AVAILABILITY_START_TIME_MS, durationMs, -1, live, -1,
|
||||||
(limitTimeshiftBuffer) ? LIVE_TIMESHIFT_BUFFER_DEPTH_MS : -1,
|
(limitTimeshiftBuffer) ? LIVE_TIMESHIFT_BUFFER_DEPTH_MS : -1,
|
||||||
null, null, periods);
|
null, null, periods);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildVodMpd() {
|
private static DashManifest buildVodMpd() {
|
||||||
List<Representation> representations = new ArrayList<>();
|
List<Representation> representations = new ArrayList<>();
|
||||||
representations.add(buildVodRepresentation(TALL_VIDEO));
|
representations.add(buildVodRepresentation(TALL_VIDEO));
|
||||||
representations.add(buildVodRepresentation(WIDE_VIDEO));
|
representations.add(buildVodRepresentation(WIDE_VIDEO));
|
||||||
return buildMpd(VOD_DURATION_MS, representations, false, false);
|
return buildMpd(VOD_DURATION_MS, representations, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildMultiPeriodVodMpd() {
|
private static DashManifest buildMultiPeriodVodMpd() {
|
||||||
List<Period> periods = new ArrayList<>();
|
List<Period> periods = new ArrayList<>();
|
||||||
long timeMs = 0;
|
long timeMs = 0;
|
||||||
long periodDurationMs = VOD_DURATION_MS;
|
long periodDurationMs = VOD_DURATION_MS;
|
||||||
@ -246,21 +246,21 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
return buildMultiPeriodMpd(timeMs, periods, false, false);
|
return buildMultiPeriodMpd(timeMs, periods, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildLiveMpdWithTimeline(long durationMs,
|
private static DashManifest buildLiveMpdWithTimeline(long durationMs,
|
||||||
long timelineStartTimeMs) {
|
long timelineStartTimeMs) {
|
||||||
Representation representation = buildSegmentTimelineRepresentation(
|
Representation representation = buildSegmentTimelineRepresentation(
|
||||||
durationMs - timelineStartTimeMs, timelineStartTimeMs);
|
durationMs - timelineStartTimeMs, timelineStartTimeMs);
|
||||||
return buildMpd(durationMs, Collections.singletonList(representation), true, false);
|
return buildMpd(durationMs, Collections.singletonList(representation), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildLiveMpdWithTemplate(long durationMs,
|
private static DashManifest buildLiveMpdWithTemplate(long durationMs,
|
||||||
boolean limitTimeshiftBuffer) {
|
boolean limitTimeshiftBuffer) {
|
||||||
Representation representation = buildSegmentTemplateRepresentation();
|
Representation representation = buildSegmentTemplateRepresentation();
|
||||||
return buildMpd(durationMs, Collections.singletonList(representation), true,
|
return buildMpd(durationMs, Collections.singletonList(representation), true,
|
||||||
limitTimeshiftBuffer);
|
limitTimeshiftBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildMultiPeriodLiveMpdWithTimeline() {
|
private static DashManifest buildMultiPeriodLiveMpdWithTimeline() {
|
||||||
List<Period> periods = new ArrayList<>();
|
List<Period> periods = new ArrayList<>();
|
||||||
long periodStartTimeMs = 0;
|
long periodStartTimeMs = 0;
|
||||||
long periodDurationMs = LIVE_DURATION_MS;
|
long periodDurationMs = LIVE_DURATION_MS;
|
||||||
@ -275,7 +275,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
return buildMultiPeriodMpd(periodDurationMs, periods, true, false);
|
return buildMultiPeriodMpd(periodDurationMs, periods, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription buildMultiPeriodLiveMpdWithTemplate() {
|
private static DashManifest buildMultiPeriodLiveMpdWithTemplate() {
|
||||||
List<Period> periods = new ArrayList<>();
|
List<Period> periods = new ArrayList<>();
|
||||||
long periodStartTimeMs = 0;
|
long periodStartTimeMs = 0;
|
||||||
long periodDurationMs = LIVE_DURATION_MS;
|
long periodDurationMs = LIVE_DURATION_MS;
|
||||||
@ -290,14 +290,14 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
return buildMultiPeriodMpd(MULTI_PERIOD_LIVE_DURATION_MS, periods, true, false);
|
return buildMultiPeriodMpd(MULTI_PERIOD_LIVE_DURATION_MS, periods, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DashChunkSource buildDashChunkSource(MediaPresentationDescription mpd) {
|
private static DashChunkSource buildDashChunkSource(DashManifest mpd) {
|
||||||
return buildDashChunkSource(mpd, false, 0);
|
return buildDashChunkSource(mpd, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DashChunkSource buildDashChunkSource(MediaPresentationDescription mpd,
|
private static DashChunkSource buildDashChunkSource(DashManifest mpd,
|
||||||
boolean startAtLiveEdge, long liveEdgeLatencyMs) {
|
boolean startAtLiveEdge, long liveEdgeLatencyMs) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ManifestFetcher<MediaPresentationDescription> manifestFetcher = mock(ManifestFetcher.class);
|
ManifestFetcher<DashManifest> manifestFetcher = mock(ManifestFetcher.class);
|
||||||
when(manifestFetcher.getManifest()).thenReturn(mpd);
|
when(manifestFetcher.getManifest()).thenReturn(mpd);
|
||||||
DashChunkSource chunkSource = new DashChunkSource(manifestFetcher, mpd,
|
DashChunkSource chunkSource = new DashChunkSource(manifestFetcher, mpd,
|
||||||
AdaptationSet.TYPE_VIDEO, mock(DataSource.class), null,
|
AdaptationSet.TYPE_VIDEO, mock(DataSource.class), null,
|
||||||
@ -331,7 +331,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
private static void checkLiveEdgeConsistencyWithTimeline(long durationMs, long timelineStartMs,
|
private static void checkLiveEdgeConsistencyWithTimeline(long durationMs, long timelineStartMs,
|
||||||
long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs,
|
long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs,
|
||||||
long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) {
|
long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) {
|
||||||
MediaPresentationDescription mpd = buildLiveMpdWithTimeline(durationMs, timelineStartMs);
|
DashManifest mpd = buildLiveMpdWithTimeline(durationMs, timelineStartMs);
|
||||||
checkLiveEdgeConsistency(mpd, liveEdgeLatencyMs, seekPositionMs,
|
checkLiveEdgeConsistency(mpd, liveEdgeLatencyMs, seekPositionMs,
|
||||||
availableRangeStartMs, availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs);
|
availableRangeStartMs, availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs);
|
||||||
}
|
}
|
||||||
@ -339,7 +339,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
private static void checkLiveEdgeConsistencyWithTemplateAndUnlimitedTimeshift(long durationMs,
|
private static void checkLiveEdgeConsistencyWithTemplateAndUnlimitedTimeshift(long durationMs,
|
||||||
long liveEdgeLatencyMs, long availablePositionMs, long availableRangeEndMs,
|
long liveEdgeLatencyMs, long availablePositionMs, long availableRangeEndMs,
|
||||||
long chunkStartTimeMs, long chunkEndTimeMs) {
|
long chunkStartTimeMs, long chunkEndTimeMs) {
|
||||||
MediaPresentationDescription mpd = buildLiveMpdWithTemplate(durationMs, false);
|
DashManifest mpd = buildLiveMpdWithTemplate(durationMs, false);
|
||||||
checkLiveEdgeConsistency(mpd, liveEdgeLatencyMs, availablePositionMs, 0,
|
checkLiveEdgeConsistency(mpd, liveEdgeLatencyMs, availablePositionMs, 0,
|
||||||
availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs);
|
availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs);
|
||||||
}
|
}
|
||||||
@ -347,12 +347,12 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
private static void checkLiveEdgeConsistencyWithTemplateAndLimitedTimeshift(long durationMs,
|
private static void checkLiveEdgeConsistencyWithTemplateAndLimitedTimeshift(long durationMs,
|
||||||
long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs,
|
long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs,
|
||||||
long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) {
|
long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) {
|
||||||
MediaPresentationDescription mpd = buildLiveMpdWithTemplate(durationMs, true);
|
DashManifest mpd = buildLiveMpdWithTemplate(durationMs, true);
|
||||||
checkLiveEdgeConsistency(mpd, liveEdgeLatencyMs, seekPositionMs, availableRangeStartMs,
|
checkLiveEdgeConsistency(mpd, liveEdgeLatencyMs, seekPositionMs, availableRangeStartMs,
|
||||||
availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs);
|
availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkLiveEdgeConsistency(MediaPresentationDescription mpd,
|
private static void checkLiveEdgeConsistency(DashManifest mpd,
|
||||||
long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs,
|
long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs,
|
||||||
long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) {
|
long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) {
|
||||||
DashChunkSource chunkSource = buildDashChunkSource(mpd, true, liveEdgeLatencyMs);
|
DashChunkSource chunkSource = buildDashChunkSource(mpd, true, liveEdgeLatencyMs);
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.test.InstrumentationTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link DashManifestParser}.
|
||||||
|
*/
|
||||||
|
public class DashManifestParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
|
private static final String SAMPLE_MPD_1 = "dash/sample_mpd_1";
|
||||||
|
private static final String SAMPLE_MPD_2_UNKNOWN_MIME_TYPE =
|
||||||
|
"dash/sample_mpd_2_unknown_mime_type";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple test to ensure the sample manifests parse without any exceptions being thrown.
|
||||||
|
*/
|
||||||
|
public void testParseMediaPresentationDescription() throws IOException {
|
||||||
|
DashManifestParser parser = new DashManifestParser();
|
||||||
|
parser.parse(Uri.parse("https://example.com/test.mpd"),
|
||||||
|
TestUtil.getInputStream(getInstrumentation(), SAMPLE_MPD_1));
|
||||||
|
parser.parse(Uri.parse("https://example.com/test.mpd"),
|
||||||
|
TestUtil.getInputStream(getInstrumentation(), SAMPLE_MPD_2_UNKNOWN_MIME_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
@ -13,10 +13,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.SingleSegmentBase;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.test.InstrumentationTestCase;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for {@link MediaPresentationDescriptionParser}.
|
|
||||||
*/
|
|
||||||
public class MediaPresentationDescriptionParserTest extends InstrumentationTestCase {
|
|
||||||
|
|
||||||
private static final String SAMPLE_MPD_1 = "dash/sample_mpd_1";
|
|
||||||
private static final String SAMPLE_MPD_2_UNKNOWN_MIME_TYPE =
|
|
||||||
"dash/sample_mpd_2_unknown_mime_type";
|
|
||||||
|
|
||||||
public void testParseMediaPresentationDescription() throws IOException {
|
|
||||||
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
|
|
||||||
InputStream inputStream =
|
|
||||||
getInstrumentation().getContext().getResources().getAssets().open(SAMPLE_MPD_1);
|
|
||||||
// Simple test to ensure that the sample manifest parses without throwing any exceptions.
|
|
||||||
parser.parse(Uri.parse("https://example.com/test.mpd"), inputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testParseMediaPresentationDescriptionWithUnknownMimeType() throws IOException {
|
|
||||||
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
|
|
||||||
InputStream inputStream = getInstrumentation().getContext().getResources().getAssets()
|
|
||||||
.open(SAMPLE_MPD_2_UNKNOWN_MIME_TYPE);
|
|
||||||
// Simple test to ensure that the sample manifest with an unknown mime type parses without
|
|
||||||
// throwing any exceptions.
|
|
||||||
parser.parse(Uri.parse("https://example.com/test.mpd"), inputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.exoplayer2.source.smoothstreaming;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.test.InstrumentationTestCase;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for {@link SmoothStreamingManifestParser}.
|
|
||||||
*/
|
|
||||||
public class SmoothStreamingManifestParserTest extends InstrumentationTestCase {
|
|
||||||
|
|
||||||
private static final String SAMPLE_ISMC_1 = "smoothstreaming/sample_ismc_1";
|
|
||||||
private static final String SAMPLE_ISMC_2 = "smoothstreaming/sample_ismc_2";
|
|
||||||
|
|
||||||
public void testParseSmoothStreamingManifest() throws IOException {
|
|
||||||
SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser();
|
|
||||||
// Simple test to ensure that the sample manifest parses without throwing any exceptions.
|
|
||||||
// SystemID UUID in the manifest is not wrapped in braces.
|
|
||||||
InputStream inputStream1 =
|
|
||||||
getInstrumentation().getContext().getResources().getAssets().open(SAMPLE_ISMC_1);
|
|
||||||
parser.parse(Uri.parse("https://example.com/test.ismc"), inputStream1);
|
|
||||||
// Simple test to ensure that the sample manifest parses without throwing any exceptions.
|
|
||||||
// SystemID UUID in the manifest is wrapped in braces.
|
|
||||||
InputStream inputStream2 =
|
|
||||||
getInstrumentation().getContext().getResources().getAssets().open(SAMPLE_ISMC_2);
|
|
||||||
parser.parse(Uri.parse("https://example.com/test.ismc"), inputStream2);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.source.smoothstreaming.manifest;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.test.InstrumentationTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link SsManifestParser}.
|
||||||
|
*/
|
||||||
|
public final class SsManifestParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
|
private static final String SAMPLE_ISMC_1 = "smoothstreaming/sample_ismc_1";
|
||||||
|
private static final String SAMPLE_ISMC_2 = "smoothstreaming/sample_ismc_2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple test to ensure the sample manifests parse without any exceptions being thrown.
|
||||||
|
*/
|
||||||
|
public void testParseSmoothStreamingManifest() throws IOException {
|
||||||
|
SsManifestParser parser = new SsManifestParser();
|
||||||
|
parser.parse(Uri.parse("https://example.com/test.ismc"),
|
||||||
|
TestUtil.getInputStream(getInstrumentation(), SAMPLE_ISMC_1));
|
||||||
|
parser.parse(Uri.parse("https://example.com/test.ismc"),
|
||||||
|
TestUtil.getInputStream(getInstrumentation(), SAMPLE_ISMC_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source.dash;
|
|||||||
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.chunk.ChunkSource;
|
import com.google.android.exoplayer2.source.chunk.ChunkSource;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescription;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,12 +27,12 @@ public interface DashChunkSource extends ChunkSource {
|
|||||||
|
|
||||||
interface Factory {
|
interface Factory {
|
||||||
|
|
||||||
DashChunkSource createDashChunkSource(Loader manifestLoader,
|
DashChunkSource createDashChunkSource(Loader manifestLoader, DashManifest manifest,
|
||||||
MediaPresentationDescription manifest, int periodIndex, int adaptationSetIndex,
|
int periodIndex, int adaptationSetIndex, TrackGroup trackGroup, int[] tracks,
|
||||||
TrackGroup trackGroup, int[] tracks, long elapsedRealtimeOffsetMs);
|
long elapsedRealtimeOffsetMs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateManifest(MediaPresentationDescription newManifest, int periodIndex);
|
void updateManifest(DashManifest newManifest, int periodIndex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@ import com.google.android.exoplayer2.source.SequenceableLoader;
|
|||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
|
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.AdaptationSet;
|
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescription;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.Period;
|
import com.google.android.exoplayer2.source.dash.manifest.Period;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.Representation;
|
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
@ -58,11 +58,11 @@ import java.util.List;
|
|||||||
private CompositeSequenceableLoader sequenceableLoader;
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private Allocator allocator;
|
private Allocator allocator;
|
||||||
private MediaPresentationDescription manifest;
|
private DashManifest manifest;
|
||||||
private int index;
|
private int index;
|
||||||
private Period period;
|
private Period period;
|
||||||
|
|
||||||
public DashMediaPeriod(MediaPresentationDescription manifest, int index,
|
public DashMediaPeriod(DashManifest manifest, int index,
|
||||||
DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount,
|
DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount,
|
||||||
EventDispatcher eventDispatcher, long elapsedRealtimeOffset, Loader loader) {
|
EventDispatcher eventDispatcher, long elapsedRealtimeOffset, Loader loader) {
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
@ -79,7 +79,7 @@ import java.util.List;
|
|||||||
trackGroupAdaptationSetIndices = trackGroupsAndAdaptationSetIndices.second;
|
trackGroupAdaptationSetIndices = trackGroupsAndAdaptationSetIndices.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateManifest(MediaPresentationDescription manifest, int index) {
|
public void updateManifest(DashManifest manifest, int index) {
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
period = manifest.getPeriod(index);
|
period = manifest.getPeriod(index);
|
||||||
|
@ -21,9 +21,9 @@ import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
|||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescription;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescriptionParser;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.UtcTimingElement;
|
import com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||||
@ -59,7 +59,7 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
private final DashChunkSource.Factory chunkSourceFactory;
|
private final DashChunkSource.Factory chunkSourceFactory;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final MediaPresentationDescriptionParser manifestParser;
|
private final DashManifestParser manifestParser;
|
||||||
private final ManifestCallback manifestCallback;
|
private final ManifestCallback manifestCallback;
|
||||||
|
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
@ -68,7 +68,7 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
private Uri manifestUri;
|
private Uri manifestUri;
|
||||||
private long manifestLoadStartTimestamp;
|
private long manifestLoadStartTimestamp;
|
||||||
private long manifestLoadEndTimestamp;
|
private long manifestLoadEndTimestamp;
|
||||||
private MediaPresentationDescription manifest;
|
private DashManifest manifest;
|
||||||
private Handler manifestRefreshHandler;
|
private Handler manifestRefreshHandler;
|
||||||
private DashMediaPeriod[] periods;
|
private DashMediaPeriod[] periods;
|
||||||
private long elapsedRealtimeOffset;
|
private long elapsedRealtimeOffset;
|
||||||
@ -88,7 +88,7 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
this.chunkSourceFactory = chunkSourceFactory;
|
this.chunkSourceFactory = chunkSourceFactory;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
manifestParser = new MediaPresentationDescriptionParser();
|
manifestParser = new DashManifestParser();
|
||||||
manifestCallback = new ManifestCallback();
|
manifestCallback = new ManifestCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
|
|
||||||
// Loadable callbacks.
|
// Loadable callbacks.
|
||||||
|
|
||||||
/* package */ void onManifestLoadCompleted(ParsingLoadable<MediaPresentationDescription> loadable,
|
/* package */ void onManifestLoadCompleted(ParsingLoadable<DashManifest> loadable,
|
||||||
long elapsedRealtimeMs, long loadDurationMs) {
|
long elapsedRealtimeMs, long loadDurationMs) {
|
||||||
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
||||||
loadDurationMs, loadable.bytesLoaded());
|
loadDurationMs, loadable.bytesLoaded());
|
||||||
@ -162,7 +162,7 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ int onManifestLoadError(ParsingLoadable<MediaPresentationDescription> loadable,
|
/* package */ int onManifestLoadError(ParsingLoadable<DashManifest> loadable,
|
||||||
long elapsedRealtimeMs, long loadDurationMs, IOException error) {
|
long elapsedRealtimeMs, long loadDurationMs, IOException error) {
|
||||||
boolean isFatal = error instanceof ParserException;
|
boolean isFatal = error instanceof ParserException;
|
||||||
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs,
|
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs,
|
||||||
@ -278,22 +278,22 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class ManifestCallback implements
|
private final class ManifestCallback implements
|
||||||
Loader.Callback<ParsingLoadable<MediaPresentationDescription>> {
|
Loader.Callback<ParsingLoadable<DashManifest>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadCompleted(ParsingLoadable<MediaPresentationDescription> loadable,
|
public void onLoadCompleted(ParsingLoadable<DashManifest> loadable,
|
||||||
long elapsedRealtimeMs, long loadDurationMs) {
|
long elapsedRealtimeMs, long loadDurationMs) {
|
||||||
onManifestLoadCompleted(loadable, elapsedRealtimeMs, loadDurationMs);
|
onManifestLoadCompleted(loadable, elapsedRealtimeMs, loadDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadCanceled(ParsingLoadable<MediaPresentationDescription> loadable,
|
public void onLoadCanceled(ParsingLoadable<DashManifest> loadable,
|
||||||
long elapsedRealtimeMs, long loadDurationMs, boolean released) {
|
long elapsedRealtimeMs, long loadDurationMs, boolean released) {
|
||||||
DashMediaSource.this.onLoadCanceled(loadable, elapsedRealtimeMs, loadDurationMs);
|
DashMediaSource.this.onLoadCanceled(loadable, elapsedRealtimeMs, loadDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onLoadError(ParsingLoadable<MediaPresentationDescription> loadable,
|
public int onLoadError(ParsingLoadable<DashManifest> loadable,
|
||||||
long elapsedRealtimeMs, long loadDurationMs, IOException error) {
|
long elapsedRealtimeMs, long loadDurationMs, IOException error) {
|
||||||
return onManifestLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error);
|
return onManifestLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.source.dash;
|
package com.google.android.exoplayer2.source.dash;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.RangedUri;
|
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indexes the segments within a media stream.
|
* Indexes the segments within a media stream.
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.source.dash;
|
package com.google.android.exoplayer2.source.dash;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.extractor.ChunkIndex;
|
import com.google.android.exoplayer2.extractor.ChunkIndex;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.RangedUri;
|
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of {@link DashSegmentIndex} that wraps a {@link ChunkIndex} parsed from a
|
* An implementation of {@link DashSegmentIndex} that wraps a {@link ChunkIndex} parsed from a
|
||||||
|
@ -33,9 +33,9 @@ import com.google.android.exoplayer2.source.chunk.FormatEvaluator.Evaluation;
|
|||||||
import com.google.android.exoplayer2.source.chunk.InitializationChunk;
|
import com.google.android.exoplayer2.source.chunk.InitializationChunk;
|
||||||
import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
||||||
import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk;
|
import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescription;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.RangedUri;
|
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.Representation;
|
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
|
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
|
||||||
@ -66,9 +66,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DashChunkSource createDashChunkSource(Loader manifestLoader,
|
public DashChunkSource createDashChunkSource(Loader manifestLoader, DashManifest manifest,
|
||||||
MediaPresentationDescription manifest, int periodIndex, int adaptationSetIndex,
|
int periodIndex, int adaptationSetIndex, TrackGroup trackGroup, int[] tracks,
|
||||||
TrackGroup trackGroup, int[] tracks, long elapsedRealtimeOffsetMs) {
|
long elapsedRealtimeOffsetMs) {
|
||||||
FormatEvaluator adaptiveEvaluator = tracks.length > 1
|
FormatEvaluator adaptiveEvaluator = tracks.length > 1
|
||||||
? formatEvaluatorFactory.createFormatEvaluator() : null;
|
? formatEvaluatorFactory.createFormatEvaluator() : null;
|
||||||
DataSource dataSource = dataSourceFactory.createDataSource();
|
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||||
@ -89,7 +89,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
private final long elapsedRealtimeOffsetUs;
|
private final long elapsedRealtimeOffsetUs;
|
||||||
private final Evaluation evaluation;
|
private final Evaluation evaluation;
|
||||||
|
|
||||||
private MediaPresentationDescription manifest;
|
private DashManifest manifest;
|
||||||
|
|
||||||
private boolean lastChunkWasInitialization;
|
private boolean lastChunkWasInitialization;
|
||||||
private IOException fatalError;
|
private IOException fatalError;
|
||||||
@ -108,10 +108,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
|
* 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.
|
* as the server's unix time minus the local elapsed time. If unknown, set to 0.
|
||||||
*/
|
*/
|
||||||
public DefaultDashChunkSource(Loader manifestLoader, MediaPresentationDescription manifest,
|
public DefaultDashChunkSource(Loader manifestLoader, DashManifest manifest, int periodIndex,
|
||||||
int periodIndex, int adaptationSetIndex, TrackGroup trackGroup, int[] tracks,
|
int adaptationSetIndex, TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
||||||
DataSource dataSource, FormatEvaluator adaptiveFormatEvaluator,
|
FormatEvaluator adaptiveFormatEvaluator, long elapsedRealtimeOffsetMs) {
|
||||||
long elapsedRealtimeOffsetMs) {
|
|
||||||
this.manifestLoader = manifestLoader;
|
this.manifestLoader = manifestLoader;
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
this.adaptationSetIndex = adaptationSetIndex;
|
this.adaptationSetIndex = adaptationSetIndex;
|
||||||
@ -143,7 +142,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateManifest(MediaPresentationDescription newManifest, int periodIndex) {
|
public void updateManifest(DashManifest newManifest, int periodIndex) {
|
||||||
try {
|
try {
|
||||||
manifest = newManifest;
|
manifest = newManifest;
|
||||||
long periodDurationUs = getPeriodDurationUs(periodIndex);
|
long periodDurationUs = getPeriodDurationUs(periodIndex);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Represents a DASH media presentation description (mpd).
|
* Represents a DASH media presentation description (mpd).
|
||||||
*/
|
*/
|
||||||
public class MediaPresentationDescription {
|
public class DashManifest {
|
||||||
|
|
||||||
public final long availabilityStartTime;
|
public final long availabilityStartTime;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ public class MediaPresentationDescription {
|
|||||||
|
|
||||||
private final List<Period> periods;
|
private final List<Period> periods;
|
||||||
|
|
||||||
public MediaPresentationDescription(long availabilityStartTime, long duration, long minBufferTime,
|
public DashManifest(long availabilityStartTime, long duration, long minBufferTime,
|
||||||
boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth, UtcTimingElement utcTiming,
|
boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth, UtcTimingElement utcTiming,
|
||||||
Uri location, List<Period> periods) {
|
Uri location, List<Period> periods) {
|
||||||
this.availabilityStartTime = availabilityStartTime;
|
this.availabilityStartTime = availabilityStartTime;
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
@ -21,10 +21,10 @@ import com.google.android.exoplayer2.ParserException;
|
|||||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
|
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil;
|
import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.SegmentList;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentList;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.SegmentTemplate;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentTemplate;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.SegmentTimelineElement;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentTimelineElement;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.SingleSegmentBase;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
|
||||||
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
@ -55,8 +55,8 @@ import java.util.regex.Pattern;
|
|||||||
/**
|
/**
|
||||||
* A parser of media presentation description files.
|
* A parser of media presentation description files.
|
||||||
*/
|
*/
|
||||||
public class MediaPresentationDescriptionParser extends DefaultHandler
|
public class DashManifestParser extends DefaultHandler
|
||||||
implements ParsingLoadable.Parser<MediaPresentationDescription> {
|
implements ParsingLoadable.Parser<DashManifest> {
|
||||||
|
|
||||||
private static final String TAG = "MpdParser";
|
private static final String TAG = "MpdParser";
|
||||||
|
|
||||||
@ -66,16 +66,16 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||||||
private final XmlPullParserFactory xmlParserFactory;
|
private final XmlPullParserFactory xmlParserFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent to calling {@code new MediaPresentationDescriptionParser(null)}.
|
* Equivalent to calling {@code new DashManifestParser(null)}.
|
||||||
*/
|
*/
|
||||||
public MediaPresentationDescriptionParser() {
|
public DashManifestParser() {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param contentId An optional content identifier to include in the parsed manifest.
|
* @param contentId An optional content identifier to include in the parsed manifest.
|
||||||
*/
|
*/
|
||||||
public MediaPresentationDescriptionParser(String contentId) {
|
public DashManifestParser(String contentId) {
|
||||||
this.contentId = contentId;
|
this.contentId = contentId;
|
||||||
try {
|
try {
|
||||||
xmlParserFactory = XmlPullParserFactory.newInstance();
|
xmlParserFactory = XmlPullParserFactory.newInstance();
|
||||||
@ -87,7 +87,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||||||
// MPD parsing.
|
// MPD parsing.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaPresentationDescription parse(Uri uri, InputStream inputStream) throws IOException {
|
public DashManifest parse(Uri uri, InputStream inputStream) throws IOException {
|
||||||
try {
|
try {
|
||||||
XmlPullParser xpp = xmlParserFactory.newPullParser();
|
XmlPullParser xpp = xmlParserFactory.newPullParser();
|
||||||
xpp.setInput(inputStream, null);
|
xpp.setInput(inputStream, null);
|
||||||
@ -102,7 +102,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MediaPresentationDescription parseMediaPresentationDescription(XmlPullParser xpp,
|
protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp,
|
||||||
String baseUrl) throws XmlPullParserException, IOException, ParseException {
|
String baseUrl) throws XmlPullParserException, IOException, ParseException {
|
||||||
long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", -1);
|
long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", -1);
|
||||||
long durationMs = parseDuration(xpp, "mediaPresentationDuration", -1);
|
long durationMs = parseDuration(xpp, "mediaPresentationDuration", -1);
|
||||||
@ -165,11 +165,10 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||||||
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods);
|
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MediaPresentationDescription buildMediaPresentationDescription(
|
protected DashManifest buildMediaPresentationDescription(long availabilityStartTime,
|
||||||
long availabilityStartTime, long durationMs, long minBufferTimeMs, boolean dynamic,
|
long durationMs, long minBufferTimeMs, boolean dynamic, long minUpdateTimeMs,
|
||||||
long minUpdateTimeMs, long timeShiftBufferDepthMs, UtcTimingElement utcTiming,
|
long timeShiftBufferDepthMs, UtcTimingElement utcTiming, Uri location, List<Period> periods) {
|
||||||
Uri location, List<Period> periods) {
|
return new DashManifest(availabilityStartTime, durationMs, minBufferTimeMs,
|
||||||
return new MediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
|
|
||||||
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods);
|
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods);
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.UriUtil;
|
import com.google.android.exoplayer2.util.UriUtil;
|
@ -13,12 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.MultiSegmentBase;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.MultiSegmentBase;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.SegmentBase.SingleSegmentBase;
|
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ public abstract class Representation {
|
|||||||
public final long contentLength;
|
public final long contentLength;
|
||||||
|
|
||||||
private final RangedUri indexUri;
|
private final RangedUri indexUri;
|
||||||
private final DashSingleSegmentIndex segmentIndex;
|
private final SingleSegmentIndex segmentIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param contentId Identifies the piece of content to which this representation belongs.
|
* @param contentId Identifies the piece of content to which this representation belongs.
|
||||||
@ -198,7 +198,7 @@ public abstract class Representation {
|
|||||||
// If we have an index uri then the index is defined externally, and we shouldn't return one
|
// If we have an index uri then the index is defined externally, and we shouldn't return one
|
||||||
// directly. If we don't, then we can't do better than an index defining a single segment.
|
// directly. If we don't, then we can't do better than an index defining a single segment.
|
||||||
segmentIndex = indexUri != null ? null
|
segmentIndex = indexUri != null ? null
|
||||||
: new DashSingleSegmentIndex(new RangedUri(segmentBase.uri, null, 0, contentLength));
|
: new SingleSegmentIndex(new RangedUri(segmentBase.uri, null, 0, contentLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
@ -13,21 +13,21 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link DashSegmentIndex} that defines a single segment.
|
* A {@link DashSegmentIndex} that defines a single segment.
|
||||||
*/
|
*/
|
||||||
/* package */ final class DashSingleSegmentIndex implements DashSegmentIndex {
|
/* package */ final class SingleSegmentIndex implements DashSegmentIndex {
|
||||||
|
|
||||||
private final RangedUri uri;
|
private final RangedUri uri;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param uri A {@link RangedUri} defining the location of the segment data.
|
* @param uri A {@link RangedUri} defining the location of the segment data.
|
||||||
*/
|
*/
|
||||||
public DashSingleSegmentIndex(RangedUri uri) {
|
public SingleSegmentIndex(RangedUri uri) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.dash.mpd;
|
package com.google.android.exoplayer2.source.dash.manifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a UTCTiming element.
|
* Represents a UTCTiming element.
|
@ -30,7 +30,8 @@ import com.google.android.exoplayer2.source.chunk.ContainerMediaChunk;
|
|||||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
|
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
|
||||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.Evaluation;
|
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.Evaluation;
|
||||||
import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
|
||||||
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
@ -43,11 +44,11 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A default {@link SmoothStreamingChunkSource} implementation.
|
* A default {@link SsChunkSource} implementation.
|
||||||
*/
|
*/
|
||||||
public class DefaultSmoothStreamingChunkSource implements SmoothStreamingChunkSource {
|
public class DefaultSsChunkSource implements SsChunkSource {
|
||||||
|
|
||||||
public static final class Factory implements SmoothStreamingChunkSource.Factory {
|
public static final class Factory implements SsChunkSource.Factory {
|
||||||
|
|
||||||
private final FormatEvaluator.Factory formatEvaluatorFactory;
|
private final FormatEvaluator.Factory formatEvaluatorFactory;
|
||||||
private final DataSource.Factory dataSourceFactory;
|
private final DataSource.Factory dataSourceFactory;
|
||||||
@ -59,13 +60,13 @@ public class DefaultSmoothStreamingChunkSource implements SmoothStreamingChunkSo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SmoothStreamingChunkSource createChunkSource(Loader manifestLoader,
|
public SsChunkSource createChunkSource(Loader manifestLoader, SsManifest manifest,
|
||||||
SmoothStreamingManifest manifest, int elementIndex, TrackGroup trackGroup, int[] tracks,
|
int elementIndex, TrackGroup trackGroup, int[] tracks,
|
||||||
TrackEncryptionBox[] trackEncryptionBoxes) {
|
TrackEncryptionBox[] trackEncryptionBoxes) {
|
||||||
FormatEvaluator adaptiveEvaluator = tracks.length > 1
|
FormatEvaluator adaptiveEvaluator = tracks.length > 1
|
||||||
? formatEvaluatorFactory.createFormatEvaluator() : null;
|
? formatEvaluatorFactory.createFormatEvaluator() : null;
|
||||||
DataSource dataSource = dataSourceFactory.createDataSource();
|
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||||
return new DefaultSmoothStreamingChunkSource(manifestLoader, manifest, elementIndex,
|
return new DefaultSsChunkSource(manifestLoader, manifest, elementIndex,
|
||||||
trackGroup, tracks, dataSource, adaptiveEvaluator,
|
trackGroup, tracks, dataSource, adaptiveEvaluator,
|
||||||
trackEncryptionBoxes);
|
trackEncryptionBoxes);
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ public class DefaultSmoothStreamingChunkSource implements SmoothStreamingChunkSo
|
|||||||
private final Evaluation evaluation;
|
private final Evaluation evaluation;
|
||||||
private final FormatEvaluator adaptiveFormatEvaluator;
|
private final FormatEvaluator adaptiveFormatEvaluator;
|
||||||
|
|
||||||
private SmoothStreamingManifest manifest;
|
private SsManifest manifest;
|
||||||
private int currentManifestChunkOffset;
|
private int currentManifestChunkOffset;
|
||||||
|
|
||||||
private IOException fatalError;
|
private IOException fatalError;
|
||||||
@ -97,8 +98,8 @@ public class DefaultSmoothStreamingChunkSource implements SmoothStreamingChunkSo
|
|||||||
* @param adaptiveFormatEvaluator For adaptive tracks, selects from the available formats.
|
* @param adaptiveFormatEvaluator For adaptive tracks, selects from the available formats.
|
||||||
* @param trackEncryptionBoxes Track encryption boxes for the stream.
|
* @param trackEncryptionBoxes Track encryption boxes for the stream.
|
||||||
*/
|
*/
|
||||||
public DefaultSmoothStreamingChunkSource(Loader manifestLoader, SmoothStreamingManifest manifest,
|
public DefaultSsChunkSource(Loader manifestLoader, SsManifest manifest, int elementIndex,
|
||||||
int elementIndex, TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
||||||
FormatEvaluator adaptiveFormatEvaluator, TrackEncryptionBox[] trackEncryptionBoxes) {
|
FormatEvaluator adaptiveFormatEvaluator, TrackEncryptionBox[] trackEncryptionBoxes) {
|
||||||
this.manifestLoader = manifestLoader;
|
this.manifestLoader = manifestLoader;
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
@ -136,7 +137,7 @@ public class DefaultSmoothStreamingChunkSource implements SmoothStreamingChunkSo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateManifest(SmoothStreamingManifest newManifest) {
|
public void updateManifest(SsManifest newManifest) {
|
||||||
StreamElement currentElement = manifest.streamElements[elementIndex];
|
StreamElement currentElement = manifest.streamElements[elementIndex];
|
||||||
int currentElementChunkCount = currentElement.chunkCount;
|
int currentElementChunkCount = currentElement.chunkCount;
|
||||||
StreamElement newElement = newManifest.streamElements[elementIndex];
|
StreamElement newElement = newManifest.streamElements[elementIndex];
|
@ -18,21 +18,21 @@ package com.google.android.exoplayer2.source.smoothstreaming;
|
|||||||
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
|
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.chunk.ChunkSource;
|
import com.google.android.exoplayer2.source.chunk.ChunkSource;
|
||||||
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ChunkSource} for SmoothStreaming.
|
* A {@link ChunkSource} for SmoothStreaming.
|
||||||
*/
|
*/
|
||||||
public interface SmoothStreamingChunkSource extends ChunkSource {
|
public interface SsChunkSource extends ChunkSource {
|
||||||
|
|
||||||
interface Factory {
|
interface Factory {
|
||||||
|
|
||||||
SmoothStreamingChunkSource createChunkSource(Loader manifestLoader,
|
SsChunkSource createChunkSource(Loader manifestLoader, SsManifest manifest, int elementIndex,
|
||||||
SmoothStreamingManifest manifest, int elementIndex, TrackGroup trackGroup, int[] tracks,
|
TrackGroup trackGroup, int[] tracks, TrackEncryptionBox[] trackEncryptionBoxes);
|
||||||
TrackEncryptionBox[] trackEncryptionBoxes);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateManifest(SmoothStreamingManifest newManifest);
|
void updateManifest(SsManifest newManifest);
|
||||||
|
|
||||||
}
|
}
|
@ -29,8 +29,10 @@ import com.google.android.exoplayer2.source.SequenceableLoader;
|
|||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
|
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement;
|
||||||
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
|
||||||
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
@ -51,9 +53,9 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* A SmoothStreaming {@link MediaSource}.
|
* A SmoothStreaming {@link MediaSource}.
|
||||||
*/
|
*/
|
||||||
public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSource,
|
public final class SsMediaSource implements MediaPeriod, MediaSource,
|
||||||
SequenceableLoader.Callback<ChunkSampleStream<SmoothStreamingChunkSource>>,
|
SequenceableLoader.Callback<ChunkSampleStream<SsChunkSource>>,
|
||||||
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
|
Loader.Callback<ParsingLoadable<SsManifest>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default minimum number of times to retry loading data prior to failing.
|
* The default minimum number of times to retry loading data prior to failing.
|
||||||
@ -65,18 +67,18 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
|
|
||||||
private final Uri manifestUri;
|
private final Uri manifestUri;
|
||||||
private final DataSource.Factory dataSourceFactory;
|
private final DataSource.Factory dataSourceFactory;
|
||||||
private final SmoothStreamingChunkSource.Factory chunkSourceFactory;
|
private final SsChunkSource.Factory chunkSourceFactory;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final SmoothStreamingManifestParser manifestParser;
|
private final SsManifestParser manifestParser;
|
||||||
|
|
||||||
private DataSource manifestDataSource;
|
private DataSource manifestDataSource;
|
||||||
private Loader manifestLoader;
|
private Loader manifestLoader;
|
||||||
private ChunkSampleStream<SmoothStreamingChunkSource>[] sampleStreams;
|
private ChunkSampleStream<SsChunkSource>[] sampleStreams;
|
||||||
private CompositeSequenceableLoader sequenceableLoader;
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
|
|
||||||
private long manifestLoadStartTimestamp;
|
private long manifestLoadStartTimestamp;
|
||||||
private SmoothStreamingManifest manifest;
|
private SsManifest manifest;
|
||||||
|
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private Allocator allocator;
|
private Allocator allocator;
|
||||||
@ -87,15 +89,15 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private int[] trackGroupElementIndices;
|
private int[] trackGroupElementIndices;
|
||||||
|
|
||||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory,
|
public SsMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory,
|
||||||
SmoothStreamingChunkSource.Factory chunkSourceFactory, Handler eventHandler,
|
SsChunkSource.Factory chunkSourceFactory, Handler eventHandler,
|
||||||
AdaptiveMediaSourceEventListener eventListener) {
|
AdaptiveMediaSourceEventListener eventListener) {
|
||||||
this(manifestUri, manifestDataSourceFactory, chunkSourceFactory,
|
this(manifestUri, manifestDataSourceFactory, chunkSourceFactory,
|
||||||
DEFAULT_MIN_LOADABLE_RETRY_COUNT, eventHandler, eventListener);
|
DEFAULT_MIN_LOADABLE_RETRY_COUNT, eventHandler, eventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
public SsMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||||
SmoothStreamingChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount,
|
SsChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount,
|
||||||
Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) {
|
Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) {
|
||||||
this.manifestUri = Util.toLowerInvariant(manifestUri.getLastPathSegment()).equals("manifest")
|
this.manifestUri = Util.toLowerInvariant(manifestUri.getLastPathSegment()).equals("manifest")
|
||||||
? manifestUri : Uri.withAppendedPath(manifestUri, "Manifest");
|
? manifestUri : Uri.withAppendedPath(manifestUri, "Manifest");
|
||||||
@ -103,7 +105,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
this.chunkSourceFactory = chunkSourceFactory;
|
this.chunkSourceFactory = chunkSourceFactory;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
manifestParser = new SmoothStreamingManifestParser();
|
manifestParser = new SsManifestParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
// MediaSource implementation.
|
// MediaSource implementation.
|
||||||
@ -162,12 +164,12 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
int newEnabledSourceCount = sampleStreams.length + newSelections.size() - oldStreams.size();
|
int newEnabledSourceCount = sampleStreams.length + newSelections.size() - oldStreams.size();
|
||||||
ChunkSampleStream<SmoothStreamingChunkSource>[] newSampleStreams =
|
ChunkSampleStream<SsChunkSource>[] newSampleStreams =
|
||||||
newSampleStreamArray(newEnabledSourceCount);
|
newSampleStreamArray(newEnabledSourceCount);
|
||||||
int newEnabledSourceIndex = 0;
|
int newEnabledSourceIndex = 0;
|
||||||
|
|
||||||
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
||||||
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
|
||||||
if (oldStreams.contains(sampleStream)) {
|
if (oldStreams.contains(sampleStream)) {
|
||||||
sampleStream.release();
|
sampleStream.release();
|
||||||
} else {
|
} else {
|
||||||
@ -206,7 +208,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
@Override
|
@Override
|
||||||
public long getBufferedPositionUs() {
|
public long getBufferedPositionUs() {
|
||||||
long bufferedPositionUs = Long.MAX_VALUE;
|
long bufferedPositionUs = Long.MAX_VALUE;
|
||||||
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
|
||||||
long rendererBufferedPositionUs = sampleStream.getBufferedPositionUs();
|
long rendererBufferedPositionUs = sampleStream.getBufferedPositionUs();
|
||||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
||||||
@ -217,7 +219,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long seekToUs(long positionUs) {
|
public long seekToUs(long positionUs) {
|
||||||
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
|
||||||
sampleStream.seekToUs(positionUs);
|
sampleStream.seekToUs(positionUs);
|
||||||
}
|
}
|
||||||
return positionUs;
|
return positionUs;
|
||||||
@ -231,7 +233,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
manifestLoader = null;
|
manifestLoader = null;
|
||||||
}
|
}
|
||||||
if (sampleStreams != null) {
|
if (sampleStreams != null) {
|
||||||
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
|
||||||
sampleStream.release();
|
sampleStream.release();
|
||||||
}
|
}
|
||||||
sampleStreams = null;
|
sampleStreams = null;
|
||||||
@ -256,15 +258,15 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(
|
public void onContinueLoadingRequested(
|
||||||
ChunkSampleStream<SmoothStreamingChunkSource> sampleStream) {
|
ChunkSampleStream<SsChunkSource> sampleStream) {
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loader.Callback implementation
|
// Loader.Callback implementation
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadCompleted(ParsingLoadable<SmoothStreamingManifest> loadable,
|
public void onLoadCompleted(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
|
||||||
long elapsedRealtimeMs, long loadDurationMs) {
|
long loadDurationMs) {
|
||||||
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
||||||
loadDurationMs, loadable.bytesLoaded());
|
loadDurationMs, loadable.bytesLoaded());
|
||||||
manifest = loadable.getResult();
|
manifest = loadable.getResult();
|
||||||
@ -281,7 +283,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
prepared = true;
|
prepared = true;
|
||||||
callback.onPeriodPrepared(this);
|
callback.onPeriodPrepared(this);
|
||||||
} else {
|
} else {
|
||||||
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
|
||||||
sampleStream.getChunkSource().updateManifest(manifest);
|
sampleStream.getChunkSource().updateManifest(manifest);
|
||||||
}
|
}
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
@ -290,14 +292,14 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadCanceled(ParsingLoadable<SmoothStreamingManifest> loadable,
|
public void onLoadCanceled(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
|
||||||
long elapsedRealtimeMs, long loadDurationMs, boolean released) {
|
long loadDurationMs, boolean released) {
|
||||||
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
||||||
loadDurationMs, loadable.bytesLoaded());
|
loadDurationMs, loadable.bytesLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onLoadError(ParsingLoadable<SmoothStreamingManifest> loadable, long elapsedRealtimeMs,
|
public int onLoadError(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
|
||||||
long loadDurationMs, IOException error) {
|
long loadDurationMs, IOException error) {
|
||||||
boolean isFatal = error instanceof ParserException;
|
boolean isFatal = error instanceof ParserException;
|
||||||
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs,
|
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs,
|
||||||
@ -322,13 +324,13 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startLoadingManifest() {
|
private void startLoadingManifest() {
|
||||||
ParsingLoadable<SmoothStreamingManifest> loadable = new ParsingLoadable<>(manifestDataSource,
|
ParsingLoadable<SsManifest> loadable = new ParsingLoadable<>(manifestDataSource,
|
||||||
manifestUri, C.DATA_TYPE_MANIFEST, manifestParser);
|
manifestUri, C.DATA_TYPE_MANIFEST, manifestParser);
|
||||||
long elapsedRealtimeMs = manifestLoader.startLoading(loadable, this, minLoadableRetryCount);
|
long elapsedRealtimeMs = manifestLoader.startLoading(loadable, this, minLoadableRetryCount);
|
||||||
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
|
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildTrackGroups(SmoothStreamingManifest manifest) {
|
private void buildTrackGroups(SsManifest manifest) {
|
||||||
int trackGroupCount = 0;
|
int trackGroupCount = 0;
|
||||||
trackGroupElementIndices = new int[manifest.streamElements.length];
|
trackGroupElementIndices = new int[manifest.streamElements.length];
|
||||||
TrackGroup[] trackGroupArray = new TrackGroup[manifest.streamElements.length];
|
TrackGroup[] trackGroupArray = new TrackGroup[manifest.streamElements.length];
|
||||||
@ -350,11 +352,11 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkSampleStream<SmoothStreamingChunkSource> buildSampleStream(TrackSelection selection,
|
private ChunkSampleStream<SsChunkSource> buildSampleStream(TrackSelection selection,
|
||||||
long positionUs) {
|
long positionUs) {
|
||||||
int[] selectedTracks = selection.getTracks();
|
int[] selectedTracks = selection.getTracks();
|
||||||
int streamElementIndex = trackGroupElementIndices[selection.group];
|
int streamElementIndex = trackGroupElementIndices[selection.group];
|
||||||
SmoothStreamingChunkSource chunkSource = chunkSourceFactory.createChunkSource(manifestLoader,
|
SsChunkSource chunkSource = chunkSourceFactory.createChunkSource(manifestLoader,
|
||||||
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks,
|
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks,
|
||||||
trackEncryptionBoxes);
|
trackEncryptionBoxes);
|
||||||
return new ChunkSampleStream<>(manifest.streamElements[streamElementIndex].type, chunkSource,
|
return new ChunkSampleStream<>(manifest.streamElements[streamElementIndex].type, chunkSource,
|
||||||
@ -362,7 +364,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static ChunkSampleStream<SmoothStreamingChunkSource>[] newSampleStreamArray(int length) {
|
private static ChunkSampleStream<SsChunkSource>[] newSampleStreamArray(int length) {
|
||||||
return new ChunkSampleStream[length];
|
return new ChunkSampleStream[length];
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.smoothstreaming;
|
package com.google.android.exoplayer2.source.smoothstreaming.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
@ -32,7 +32,7 @@ import java.util.UUID;
|
|||||||
* @see <a href="http://msdn.microsoft.com/en-us/library/ee673436(v=vs.90).aspx">
|
* @see <a href="http://msdn.microsoft.com/en-us/library/ee673436(v=vs.90).aspx">
|
||||||
* IIS Smooth Streaming Client Manifest Format</a>
|
* IIS Smooth Streaming Client Manifest Format</a>
|
||||||
*/
|
*/
|
||||||
public class SmoothStreamingManifest {
|
public class SsManifest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The client manifest major version.
|
* The client manifest major version.
|
||||||
@ -92,7 +92,7 @@ public class SmoothStreamingManifest {
|
|||||||
* protected.
|
* protected.
|
||||||
* @param streamElements The contained stream elements.
|
* @param streamElements The contained stream elements.
|
||||||
*/
|
*/
|
||||||
public SmoothStreamingManifest(int majorVersion, int minorVersion, long timescale, long duration,
|
public SsManifest(int majorVersion, int minorVersion, long timescale, long duration,
|
||||||
long dvrWindowLength, int lookAheadCount, boolean isLive, ProtectionElement protectionElement,
|
long dvrWindowLength, int lookAheadCount, boolean isLive, ProtectionElement protectionElement,
|
||||||
StreamElement[] streamElements) {
|
StreamElement[] streamElements) {
|
||||||
this.majorVersion = majorVersion;
|
this.majorVersion = majorVersion;
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.smoothstreaming;
|
package com.google.android.exoplayer2.source.smoothstreaming.manifest;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
@ -21,8 +21,8 @@ import com.google.android.exoplayer2.ParserException;
|
|||||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
|
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil;
|
import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
|
||||||
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
|
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
|
||||||
@ -52,12 +52,11 @@ import java.util.UUID;
|
|||||||
* @see <a href="http://msdn.microsoft.com/en-us/library/ee673436(v=vs.90).aspx">
|
* @see <a href="http://msdn.microsoft.com/en-us/library/ee673436(v=vs.90).aspx">
|
||||||
* IIS Smooth Streaming Client Manifest Format</a>
|
* IIS Smooth Streaming Client Manifest Format</a>
|
||||||
*/
|
*/
|
||||||
public class SmoothStreamingManifestParser implements
|
public class SsManifestParser implements ParsingLoadable.Parser<SsManifest> {
|
||||||
ParsingLoadable.Parser<SmoothStreamingManifest> {
|
|
||||||
|
|
||||||
private final XmlPullParserFactory xmlParserFactory;
|
private final XmlPullParserFactory xmlParserFactory;
|
||||||
|
|
||||||
public SmoothStreamingManifestParser() {
|
public SsManifestParser() {
|
||||||
try {
|
try {
|
||||||
xmlParserFactory = XmlPullParserFactory.newInstance();
|
xmlParserFactory = XmlPullParserFactory.newInstance();
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
@ -66,13 +65,13 @@ public class SmoothStreamingManifestParser implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SmoothStreamingManifest parse(Uri uri, InputStream inputStream) throws IOException {
|
public SsManifest parse(Uri uri, InputStream inputStream) throws IOException {
|
||||||
try {
|
try {
|
||||||
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
||||||
xmlParser.setInput(inputStream, null);
|
xmlParser.setInput(inputStream, null);
|
||||||
SmoothStreamMediaParser smoothStreamMediaParser =
|
SmoothStreamingMediaParser smoothStreamingMediaParser =
|
||||||
new SmoothStreamMediaParser(null, uri.toString());
|
new SmoothStreamingMediaParser(null, uri.toString());
|
||||||
return (SmoothStreamingManifest) smoothStreamMediaParser.parse(xmlParser);
|
return (SsManifest) smoothStreamingMediaParser.parse(xmlParser);
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
throw new ParserException(e);
|
throw new ParserException(e);
|
||||||
}
|
}
|
||||||
@ -163,12 +162,12 @@ public class SmoothStreamingManifestParser implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ElementParser newChildParser(ElementParser parent, String name, String baseUri) {
|
private ElementParser newChildParser(ElementParser parent, String name, String baseUri) {
|
||||||
if (TrackElementParser.TAG.equals(name)) {
|
if (QualityLevelParser.TAG.equals(name)) {
|
||||||
return new TrackElementParser(parent, baseUri);
|
return new QualityLevelParser(parent, baseUri);
|
||||||
} else if (ProtectionElementParser.TAG.equals(name)) {
|
} else if (ProtectionParser.TAG.equals(name)) {
|
||||||
return new ProtectionElementParser(parent, baseUri);
|
return new ProtectionParser(parent, baseUri);
|
||||||
} else if (StreamElementParser.TAG.equals(name)) {
|
} else if (StreamIndexParser.TAG.equals(name)) {
|
||||||
return new StreamElementParser(parent, baseUri);
|
return new StreamIndexParser(parent, baseUri);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -322,7 +321,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SmoothStreamMediaParser extends ElementParser {
|
private static class SmoothStreamingMediaParser extends ElementParser {
|
||||||
|
|
||||||
public static final String TAG = "SmoothStreamingMedia";
|
public static final String TAG = "SmoothStreamingMedia";
|
||||||
|
|
||||||
@ -345,7 +344,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
private boolean isLive;
|
private boolean isLive;
|
||||||
private ProtectionElement protectionElement;
|
private ProtectionElement protectionElement;
|
||||||
|
|
||||||
public SmoothStreamMediaParser(ElementParser parent, String baseUri) {
|
public SmoothStreamingMediaParser(ElementParser parent, String baseUri) {
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
lookAheadCount = -1;
|
lookAheadCount = -1;
|
||||||
protectionElement = null;
|
protectionElement = null;
|
||||||
@ -387,13 +386,13 @@ public class SmoothStreamingManifestParser implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new SmoothStreamingManifest(majorVersion, minorVersion, timescale, duration,
|
return new SsManifest(majorVersion, minorVersion, timescale, duration, dvrWindowLength,
|
||||||
dvrWindowLength, lookAheadCount, isLive, protectionElement, streamElementArray);
|
lookAheadCount, isLive, protectionElement, streamElementArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ProtectionElementParser extends ElementParser {
|
private static class ProtectionParser extends ElementParser {
|
||||||
|
|
||||||
public static final String TAG = "Protection";
|
public static final String TAG = "Protection";
|
||||||
public static final String TAG_PROTECTION_HEADER = "ProtectionHeader";
|
public static final String TAG_PROTECTION_HEADER = "ProtectionHeader";
|
||||||
@ -404,7 +403,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private byte[] initData;
|
private byte[] initData;
|
||||||
|
|
||||||
public ProtectionElementParser(ElementParser parent, String baseUri) {
|
public ProtectionParser(ElementParser parent, String baseUri) {
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,7 +449,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StreamElementParser extends ElementParser {
|
private static class StreamIndexParser extends ElementParser {
|
||||||
|
|
||||||
public static final String TAG = "StreamIndex";
|
public static final String TAG = "StreamIndex";
|
||||||
private static final String TAG_STREAM_FRAGMENT = "c";
|
private static final String TAG_STREAM_FRAGMENT = "c";
|
||||||
@ -492,7 +491,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
|
|
||||||
private long lastChunkDuration;
|
private long lastChunkDuration;
|
||||||
|
|
||||||
public StreamElementParser(ElementParser parent, String baseUri) {
|
public StreamIndexParser(ElementParser parent, String baseUri) {
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
this.baseUri = baseUri;
|
this.baseUri = baseUri;
|
||||||
formats = new LinkedList<>();
|
formats = new LinkedList<>();
|
||||||
@ -599,7 +598,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TrackElementParser extends ElementParser {
|
private static class QualityLevelParser extends ElementParser {
|
||||||
|
|
||||||
public static final String TAG = "QualityLevel";
|
public static final String TAG = "QualityLevel";
|
||||||
|
|
||||||
@ -616,7 +615,7 @@ public class SmoothStreamingManifestParser implements
|
|||||||
|
|
||||||
private Format format;
|
private Format format;
|
||||||
|
|
||||||
public TrackElementParser(ElementParser parent, String baseUri) {
|
public QualityLevelParser(ElementParser parent, String baseUri) {
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
}
|
}
|
||||||
|
|
@ -180,8 +180,12 @@ public class TestUtil {
|
|||||||
|
|
||||||
public static byte[] getByteArray(Instrumentation instrumentation, String fileName)
|
public static byte[] getByteArray(Instrumentation instrumentation, String fileName)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
InputStream is = instrumentation.getContext().getResources().getAssets().open(fileName);
|
return Util.toByteArray(getInputStream(instrumentation, fileName));
|
||||||
return Util.toByteArray(is);
|
}
|
||||||
|
|
||||||
|
public static InputStream getInputStream(Instrumentation instrumentation, String fileName)
|
||||||
|
throws IOException {
|
||||||
|
return instrumentation.getContext().getResources().getAssets().open(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getString(Instrumentation instrumentation, String fileName)
|
public static String getString(Instrumentation instrumentation, String fileName)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user