Commit 62d17cab by Oliver Woodman

Add support for SegmentTemplate and SegmentList mpds.

Misc Notes:
- Removed content type filters because some of third parties
  don't set content type.
parent 87461821
......@@ -52,7 +52,7 @@ public class SampleChooserActivity extends Activity {
sampleAdapter.addAll((Object[]) Samples.SIMPLE);
sampleAdapter.add(new Header("YouTube DASH"));
sampleAdapter.addAll((Object[]) Samples.YOUTUBE_DASH_MP4);
sampleAdapter.add(new Header("Widevine DASH GTS"));
sampleAdapter.add(new Header("Widevine GTS DASH"));
sampleAdapter.addAll((Object[]) Samples.WIDEVINE_GTS);
sampleAdapter.add(new Header("SmoothStreaming"));
sampleAdapter.addAll((Object[]) Samples.SMOOTHSTREAMING);
......
......@@ -129,10 +129,6 @@ package com.google.android.exoplayer.demo;
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
+ "&expire=19000000000&signature=88DC53943385CED8CF9F37ADD9E9843E3BF621E6."
+ "22727BB612D24AA4FACE4EF62726F9461A9BF57A&key=ik0", DemoUtil.TYPE_DASH_VOD, true, true),
new Sample("WV: 30s license duration", "f9a34cab7b05881a",
"http://dash.edgesuite.net/digitalprimates/fraunhofer/480p_video/heaac_2_0_with_video/ElephantsDream/elephants_dream_480p_heaac2_0.mpd", DemoUtil.TYPE_DASH_VOD, false, true),
};
public static final Sample[] MISC = new Sample[] {
......
......@@ -160,8 +160,7 @@ public class DashVodRendererBuilder implements RendererBuilder,
}
// Build the video renderer.
DataSource videoDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource videoDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
ChunkSource videoChunkSource;
String mimeType = videoRepresentations[0].format.mimeType;
if (mimeType.equals(MimeTypes.VIDEO_MP4)) {
......@@ -192,8 +191,7 @@ public class DashVodRendererBuilder implements RendererBuilder,
audioChunkSource = null;
audioRenderer = null;
} else {
DataSource audioDataSource = new HttpDataSource(userAgent,
HttpDataSource.REJECT_PAYWALL_TYPES, bandwidthMeter);
DataSource audioDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
audioTrackNames = new String[audioRepresentationsList.size()];
ChunkSource[] audioChunkSources = new ChunkSource[audioRepresentationsList.size()];
FormatEvaluator audioEvaluator = new FormatEvaluator.FixedEvaluator();
......
......@@ -150,8 +150,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
}
// Build the video renderer.
DataSource videoDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource videoDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
ChunkSource videoChunkSource = new SmoothStreamingChunkSource(url, manifest,
videoStreamElementIndex, videoTrackIndices, videoDataSource,
new AdaptiveEvaluator(bandwidthMeter));
......@@ -173,8 +172,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
} else {
audioTrackNames = new String[audioStreamElementCount];
ChunkSource[] audioChunkSources = new ChunkSource[audioStreamElementCount];
DataSource audioDataSource = new HttpDataSource(userAgent,
HttpDataSource.REJECT_PAYWALL_TYPES, bandwidthMeter);
DataSource audioDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
FormatEvaluator audioFormatEvaluator = new FormatEvaluator.FixedEvaluator();
audioStreamElementCount = 0;
for (int i = 0; i < manifest.streamElements.length; i++) {
......@@ -204,8 +202,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
} else {
textTrackNames = new String[textStreamElementCount];
ChunkSource[] textChunkSources = new ChunkSource[textStreamElementCount];
DataSource ttmlDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource ttmlDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
FormatEvaluator ttmlFormatEvaluator = new FormatEvaluator.FixedEvaluator();
textStreamElementCount = 0;
for (int i = 0; i < manifest.streamElements.length; i++) {
......
......@@ -115,8 +115,7 @@ import java.util.ArrayList;
videoRepresentationsList.toArray(videoRepresentations);
// Build the video renderer.
DataSource videoDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource videoDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
ChunkSource videoChunkSource = new DashMp4ChunkSource(videoDataSource,
new AdaptiveEvaluator(bandwidthMeter), videoRepresentations);
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl,
......@@ -125,8 +124,7 @@ import java.util.ArrayList;
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50);
// Build the audio renderer.
DataSource audioDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource audioDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
ChunkSource audioChunkSource = new DashMp4ChunkSource(audioDataSource,
new FormatEvaluator.FixedEvaluator(), audioRepresentation);
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
......
......@@ -115,8 +115,7 @@ import java.util.ArrayList;
}
// Build the video renderer.
DataSource videoDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource videoDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
ChunkSource videoChunkSource = new SmoothStreamingChunkSource(url, manifest,
videoStreamElementIndex, videoTrackIndices, videoDataSource,
new AdaptiveEvaluator(bandwidthMeter));
......@@ -126,8 +125,7 @@ import java.util.ArrayList;
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50);
// Build the audio renderer.
DataSource audioDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES,
bandwidthMeter);
DataSource audioDataSource = new HttpDataSource(userAgent, null, bandwidthMeter);
ChunkSource audioChunkSource = new SmoothStreamingChunkSource(url, manifest,
audioStreamElementIndex, new int[] {0}, audioDataSource,
new FormatEvaluator.FixedEvaluator());
......
......@@ -309,7 +309,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
}
MediaFormat mediaFormat = mediaChunk.getMediaFormat();
if (downstreamMediaFormat == null || !downstreamMediaFormat.equals(mediaFormat)) {
if (mediaFormat != null && !mediaFormat.equals(downstreamMediaFormat)) {
chunkSource.getMaxVideoDimensions(mediaFormat);
formatHolder.format = mediaFormat;
formatHolder.drmInitData = mediaChunk.getPsshInfo();
......
......@@ -74,7 +74,7 @@ public class DashMp4ChunkSource implements ChunkSource {
this.segmentIndexes = new HashMap<String, DashSegmentIndex>();
this.representations = new HashMap<String, Representation>();
this.trackInfo = new TrackInfo(representations[0].format.mimeType,
representations[0].periodDuration * 1000);
representations[0].periodDurationMs * 1000);
this.evaluation = new Evaluation();
int maxWidth = 0;
int maxHeight = 0;
......@@ -198,7 +198,7 @@ public class DashMp4ChunkSource implements ChunkSource {
RangedUri requestUri;
if (initializationUri != null) {
// It's common for initialization and index data to be stored adjacently. Attempt to merge
// the two requests together to request at once.
// the two requests together to request both at once.
expectedExtractorResult |= FragmentedMp4Extractor.RESULT_READ_MOOV;
requestUri = initializationUri.attemptMerge(indexUri);
if (requestUri != null) {
......
......@@ -70,7 +70,7 @@ public class DashWebmChunkSource implements ChunkSource {
this.segmentIndexes = new HashMap<String, DashSegmentIndex>();
this.representations = new HashMap<String, Representation>();
this.trackInfo = new TrackInfo(
representations[0].format.mimeType, representations[0].periodDuration * 1000);
representations[0].format.mimeType, representations[0].periodDurationMs * 1000);
this.evaluation = new Evaluation();
int maxWidth = 0;
int maxHeight = 0;
......
......@@ -23,46 +23,37 @@ import java.util.List;
*/
public final class Period {
/**
* The period identifier, if one exists.
*/
public final String id;
public final long start;
/**
* The start time of the period in milliseconds.
*/
public final long startMs;
public final long duration;
/**
* The duration of the period in milliseconds, or -1 if the duration is unknown.
*/
public final long durationMs;
/**
* The adaptation sets belonging to the period.
*/
public final List<AdaptationSet> adaptationSets;
public final List<Segment.Timeline> segmentList;
public final int segmentStartNumber;
public final int segmentTimescale;
public final long presentationTimeOffset;
/**
* @param id The period identifier. May be null.
* @param start The start time of the period in milliseconds.
* @param duration The duration of the period in milliseconds, or -1 if the duration is unknown.
* @param adaptationSets The adaptation sets belonging to the period.
*/
public Period(String id, long start, long duration, List<AdaptationSet> adaptationSets) {
this(id, start, duration, adaptationSets, null, 0, 0, 0);
}
public Period(String id, long start, long duration, List<AdaptationSet> adaptationSets,
List<Segment.Timeline> segmentList, int segmentStartNumber, int segmentTimescale) {
this(id, start, duration, adaptationSets, segmentList, segmentStartNumber, segmentTimescale, 0);
}
public Period(String id, long start, long duration, List<AdaptationSet> adaptationSets,
List<Segment.Timeline> segmentList, int segmentStartNumber, int segmentTimescale,
long presentationTimeOffset) {
this.id = id;
this.start = start;
this.duration = duration;
this.startMs = start;
this.durationMs = duration;
this.adaptationSets = Collections.unmodifiableList(adaptationSets);
if (segmentList != null) {
this.segmentList = Collections.unmodifiableList(segmentList);
} else {
this.segmentList = null;
}
this.segmentStartNumber = segmentStartNumber;
this.segmentTimescale = segmentTimescale;
this.presentationTimeOffset = presentationTimeOffset;
}
}
/*
* Copyright (C) 2014 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.exoplayer.dash.mpd;
/**
* Represents a particular segment in a Representation.
*
*/
public abstract class Segment {
public final String relativeUri;
public final long sequenceNumber;
public final long duration;
public Segment(String relativeUri, long sequenceNumber, long duration) {
this.relativeUri = relativeUri;
this.sequenceNumber = sequenceNumber;
this.duration = duration;
}
/**
* Represents a timeline segment from the MPD's SegmentTimeline list.
*/
public static class Timeline extends Segment {
public Timeline(long sequenceNumber, long duration) {
super(null, sequenceNumber, duration);
}
}
/**
* Represents an initialization segment.
*/
public static class Initialization extends Segment {
public final long initializationStart;
public final long initializationEnd;
public Initialization(String relativeUri, long initializationStart,
long initializationEnd) {
super(relativeUri, -1, -1);
this.initializationStart = initializationStart;
this.initializationEnd = initializationEnd;
}
}
/**
* Represents a media segment.
*/
public static class Media extends Segment {
public final long mediaStart;
public Media(String relativeUri, long sequenceNumber, long duration) {
this(relativeUri, 0, sequenceNumber, duration);
}
public Media(String uri, long mediaStart, long sequenceNumber, long duration) {
super(uri, sequenceNumber, duration);
this.mediaStart = mediaStart;
}
}
}
/*
* Copyright (C) 2014 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.exoplayer.dash.mpd;
import com.google.android.exoplayer.chunk.Format;
import com.google.android.exoplayer.upstream.DataSpec;
import android.net.Uri;
import java.util.List;
/**
* Represents a DASH Representation which uses the SegmentList structure (i.e. it has a list of
* Segment URLs instead of a single URL).
*/
public class SegmentedRepresentation extends Representation {
private List<Segment> segmentList;
public SegmentedRepresentation(String contentId, Format format, Uri uri, long initializationStart,
long initializationEnd, long indexStart, long indexEnd, long periodStart, long periodDuration,
List<Segment> segmentList) {
super(contentId, -1, format, uri, DataSpec.LENGTH_UNBOUNDED, initializationStart,
initializationEnd, indexStart, indexEnd, periodStart, periodDuration);
this.segmentList = segmentList;
}
public int getNumSegments() {
return segmentList.size();
}
public Segment getSegment(int i) {
return segmentList.get(i);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment