mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Refactored ExoPlayer to use String-based format ids.
This commit is contained in:
parent
563b434de2
commit
4fd4c89518
@ -91,7 +91,7 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadStarted(int sourceId, int formatId, int trigger, boolean isInitialization,
|
public void onLoadStarted(int sourceId, String formatId, int trigger, boolean isInitialization,
|
||||||
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes) {
|
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes) {
|
||||||
loadStartTimeMs[sourceId] = SystemClock.elapsedRealtime();
|
loadStartTimeMs[sourceId] = SystemClock.elapsedRealtime();
|
||||||
if (VerboseLogUtil.isTagEnabled(TAG)) {
|
if (VerboseLogUtil.isTagEnabled(TAG)) {
|
||||||
@ -110,13 +110,13 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoFormatEnabled(int formatId, int trigger, int mediaTimeMs) {
|
public void onVideoFormatEnabled(String formatId, int trigger, int mediaTimeMs) {
|
||||||
Log.d(TAG, "videoFormat [" + getSessionTimeString() + ", " + formatId + ", " +
|
Log.d(TAG, "videoFormat [" + getSessionTimeString() + ", " + formatId + ", " +
|
||||||
Integer.toString(trigger) + "]");
|
Integer.toString(trigger) + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAudioFormatEnabled(int formatId, int trigger, int mediaTimeMs) {
|
public void onAudioFormatEnabled(String formatId, int trigger, int mediaTimeMs) {
|
||||||
Log.d(TAG, "audioFormat [" + getSessionTimeString() + ", " + formatId + ", " +
|
Log.d(TAG, "audioFormat [" + getSessionTimeString() + ", " + formatId + ", " +
|
||||||
Integer.toString(trigger) + "]");
|
Integer.toString(trigger) + "]");
|
||||||
}
|
}
|
||||||
|
@ -118,11 +118,11 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
|||||||
* A listener for debugging information.
|
* A listener for debugging information.
|
||||||
*/
|
*/
|
||||||
public interface InfoListener {
|
public interface InfoListener {
|
||||||
void onVideoFormatEnabled(int formatId, int trigger, int mediaTimeMs);
|
void onVideoFormatEnabled(String formatId, int trigger, int mediaTimeMs);
|
||||||
void onAudioFormatEnabled(int formatId, int trigger, int mediaTimeMs);
|
void onAudioFormatEnabled(String formatId, int trigger, int mediaTimeMs);
|
||||||
void onDroppedFrames(int count, long elapsed);
|
void onDroppedFrames(int count, long elapsed);
|
||||||
void onBandwidthSample(int elapsedMs, long bytes, long bandwidthEstimate);
|
void onBandwidthSample(int elapsedMs, long bytes, long bandwidthEstimate);
|
||||||
void onLoadStarted(int sourceId, int formatId, int trigger, boolean isInitialization,
|
void onLoadStarted(int sourceId, String formatId, int trigger, boolean isInitialization,
|
||||||
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes);
|
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes);
|
||||||
void onLoadCompleted(int sourceId);
|
void onLoadCompleted(int sourceId);
|
||||||
}
|
}
|
||||||
@ -398,7 +398,8 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownstreamFormatChanged(int sourceId, int formatId, int trigger, int mediaTimeMs) {
|
public void onDownstreamFormatChanged(int sourceId, String formatId, int trigger,
|
||||||
|
int mediaTimeMs) {
|
||||||
if (infoListener == null) {
|
if (infoListener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -469,7 +470,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadStarted(int sourceId, int formatId, int trigger, boolean isInitialization,
|
public void onLoadStarted(int sourceId, String formatId, int trigger, boolean isInitialization,
|
||||||
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes) {
|
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes) {
|
||||||
if (infoListener != null) {
|
if (infoListener != null) {
|
||||||
infoListener.onLoadStarted(sourceId, formatId, trigger, isInitialization, mediaStartTimeMs,
|
infoListener.onLoadStarted(sourceId, formatId, trigger, isInitialization, mediaStartTimeMs,
|
||||||
|
@ -59,7 +59,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
|
|||||||
* load is for initialization data.
|
* load is for initialization data.
|
||||||
* @param totalBytes The length of the data being loaded in bytes.
|
* @param totalBytes The length of the data being loaded in bytes.
|
||||||
*/
|
*/
|
||||||
void onLoadStarted(int sourceId, int formatId, int trigger, boolean isInitialization,
|
void onLoadStarted(int sourceId, String formatId, int trigger, boolean isInitialization,
|
||||||
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes);
|
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,7 +126,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
|
|||||||
* {@link ChunkSource}.
|
* {@link ChunkSource}.
|
||||||
* @param mediaTimeMs The media time at which the change occurred.
|
* @param mediaTimeMs The media time at which the change occurred.
|
||||||
*/
|
*/
|
||||||
void onDownstreamFormatChanged(int sourceId, int formatId, int trigger, int mediaTimeMs);
|
void onDownstreamFormatChanged(int sourceId, String formatId, int trigger, int mediaTimeMs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
|
|||||||
}
|
}
|
||||||
return NOTHING_READ;
|
return NOTHING_READ;
|
||||||
}
|
}
|
||||||
} else if (downstreamFormat == null || downstreamFormat.id != mediaChunk.format.id) {
|
} else if (downstreamFormat == null || !downstreamFormat.id.equals(mediaChunk.format.id)) {
|
||||||
notifyDownstreamFormatChanged(mediaChunk.format.id, mediaChunk.trigger,
|
notifyDownstreamFormatChanged(mediaChunk.format.id, mediaChunk.trigger,
|
||||||
mediaChunk.startTimeUs);
|
mediaChunk.startTimeUs);
|
||||||
MediaFormat format = mediaChunk.getMediaFormat();
|
MediaFormat format = mediaChunk.getMediaFormat();
|
||||||
@ -653,7 +653,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
|
|||||||
return (int) (timeUs / 1000);
|
return (int) (timeUs / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyLoadStarted(final int formatId, final int trigger,
|
private void notifyLoadStarted(final String formatId, final int trigger,
|
||||||
final boolean isInitialization, final long mediaStartTimeUs, final long mediaEndTimeUs,
|
final boolean isInitialization, final long mediaStartTimeUs, final long mediaEndTimeUs,
|
||||||
final long totalBytes) {
|
final long totalBytes) {
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
@ -724,7 +724,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyDownstreamFormatChanged(final int formatId, final int trigger,
|
private void notifyDownstreamFormatChanged(final String formatId, final int trigger,
|
||||||
final long mediaTimeUs) {
|
final long mediaTimeUs) {
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
|
@ -20,7 +20,7 @@ import java.util.Comparator;
|
|||||||
/**
|
/**
|
||||||
* A format definition for streams.
|
* A format definition for streams.
|
||||||
*/
|
*/
|
||||||
public final class Format {
|
public class Format {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts {@link Format} objects in order of decreasing bandwidth.
|
* Sorts {@link Format} objects in order of decreasing bandwidth.
|
||||||
@ -37,7 +37,7 @@ public final class Format {
|
|||||||
/**
|
/**
|
||||||
* An identifier for the format.
|
* An identifier for the format.
|
||||||
*/
|
*/
|
||||||
public final int id;
|
public final String id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mime type of the format.
|
* The mime type of the format.
|
||||||
@ -70,6 +70,8 @@ public final class Format {
|
|||||||
public final int bandwidth;
|
public final int bandwidth;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated Format identifiers are now strings.
|
||||||
|
*
|
||||||
* @param id The format identifier.
|
* @param id The format identifier.
|
||||||
* @param mimeType The format mime type.
|
* @param mimeType The format mime type.
|
||||||
* @param width The width of the video in pixels, or -1 for non-video formats.
|
* @param width The width of the video in pixels, or -1 for non-video formats.
|
||||||
@ -78,8 +80,23 @@ public final class Format {
|
|||||||
* @param audioSamplingRate The audio sampling rate in Hz, or -1 for non-audio formats.
|
* @param audioSamplingRate The audio sampling rate in Hz, or -1 for non-audio formats.
|
||||||
* @param bandwidth The average bandwidth of the format in bytes per second.
|
* @param bandwidth The average bandwidth of the format in bytes per second.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Format(int id, String mimeType, int width, int height, int numChannels,
|
public Format(int id, String mimeType, int width, int height, int numChannels,
|
||||||
int audioSamplingRate, int bandwidth) {
|
int audioSamplingRate, int bandwidth) {
|
||||||
|
this(String.valueOf(id), mimeType, width, height, numChannels, audioSamplingRate, bandwidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id The format identifier.
|
||||||
|
* @param mimeType The format mime type.
|
||||||
|
* @param width The width of the video in pixels, or -1 for non-video formats.
|
||||||
|
* @param height The height of the video in pixels, or -1 for non-video formats.
|
||||||
|
* @param numChannels The number of audio channels, or -1 for non-audio formats.
|
||||||
|
* @param audioSamplingRate The audio sampling rate in Hz, or -1 for non-audio formats.
|
||||||
|
* @param bandwidth The average bandwidth of the format in bytes per second.
|
||||||
|
*/
|
||||||
|
public Format(String id, String mimeType, int width, int height, int numChannels,
|
||||||
|
int audioSamplingRate, int bandwidth) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
|
@ -146,7 +146,7 @@ public interface FormatEvaluator {
|
|||||||
public void evaluate(List<? extends MediaChunk> queue, long playbackPositionUs,
|
public void evaluate(List<? extends MediaChunk> queue, long playbackPositionUs,
|
||||||
Format[] formats, Evaluation evaluation) {
|
Format[] formats, Evaluation evaluation) {
|
||||||
Format newFormat = formats[random.nextInt(formats.length)];
|
Format newFormat = formats[random.nextInt(formats.length)];
|
||||||
if (evaluation.format != null && evaluation.format.id != newFormat.id) {
|
if (evaluation.format != null && !evaluation.format.id.equals(newFormat.id)) {
|
||||||
evaluation.trigger = TRIGGER_ADAPTIVE;
|
evaluation.trigger = TRIGGER_ADAPTIVE;
|
||||||
}
|
}
|
||||||
evaluation.format = newFormat;
|
evaluation.format = newFormat;
|
||||||
|
@ -35,10 +35,10 @@ import com.google.android.exoplayer.upstream.DataSpec;
|
|||||||
import com.google.android.exoplayer.upstream.NonBlockingInputStream;
|
import com.google.android.exoplayer.upstream.NonBlockingInputStream;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,8 +64,8 @@ public class DashMp4ChunkSource implements ChunkSource {
|
|||||||
private final int numSegmentsPerChunk;
|
private final int numSegmentsPerChunk;
|
||||||
|
|
||||||
private final Format[] formats;
|
private final Format[] formats;
|
||||||
private final SparseArray<Representation> representations;
|
private final HashMap<String, Representation> representations;
|
||||||
private final SparseArray<FragmentedMp4Extractor> extractors;
|
private final HashMap<String, FragmentedMp4Extractor> extractors;
|
||||||
|
|
||||||
private boolean lastChunkWasInitialization;
|
private boolean lastChunkWasInitialization;
|
||||||
|
|
||||||
@ -92,8 +92,8 @@ public class DashMp4ChunkSource implements ChunkSource {
|
|||||||
this.evaluator = evaluator;
|
this.evaluator = evaluator;
|
||||||
this.numSegmentsPerChunk = numSegmentsPerChunk;
|
this.numSegmentsPerChunk = numSegmentsPerChunk;
|
||||||
this.formats = new Format[representations.length];
|
this.formats = new Format[representations.length];
|
||||||
this.extractors = new SparseArray<FragmentedMp4Extractor>();
|
this.extractors = new HashMap<String, FragmentedMp4Extractor>();
|
||||||
this.representations = new SparseArray<Representation>();
|
this.representations = new HashMap<String, Representation>();
|
||||||
this.trackInfo = new TrackInfo(representations[0].format.mimeType,
|
this.trackInfo = new TrackInfo(representations[0].format.mimeType,
|
||||||
representations[0].periodDuration * 1000);
|
representations[0].periodDuration * 1000);
|
||||||
this.evaluation = new Evaluation();
|
this.evaluation = new Evaluation();
|
||||||
@ -103,7 +103,7 @@ public class DashMp4ChunkSource implements ChunkSource {
|
|||||||
formats[i] = representations[i].format;
|
formats[i] = representations[i].format;
|
||||||
maxWidth = Math.max(formats[i].width, maxWidth);
|
maxWidth = Math.max(formats[i].width, maxWidth);
|
||||||
maxHeight = Math.max(formats[i].height, maxHeight);
|
maxHeight = Math.max(formats[i].height, maxHeight);
|
||||||
extractors.append(formats[i].id, new FragmentedMp4Extractor());
|
extractors.put(formats[i].id, new FragmentedMp4Extractor());
|
||||||
this.representations.put(formats[i].id, representations[i]);
|
this.representations.put(formats[i].id, representations[i]);
|
||||||
}
|
}
|
||||||
this.maxWidth = maxWidth;
|
this.maxWidth = maxWidth;
|
||||||
@ -152,7 +152,7 @@ public class DashMp4ChunkSource implements ChunkSource {
|
|||||||
out.chunk = null;
|
out.chunk = null;
|
||||||
return;
|
return;
|
||||||
} else if (out.queueSize == queue.size() && out.chunk != null
|
} else if (out.queueSize == queue.size() && out.chunk != null
|
||||||
&& out.chunk.format.id == selectedFormat.id) {
|
&& out.chunk.format.id.equals(selectedFormat.id)) {
|
||||||
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
||||||
// of the queue. Leave unchanged.
|
// of the queue. Leave unchanged.
|
||||||
return;
|
return;
|
||||||
|
@ -35,10 +35,10 @@ import com.google.android.exoplayer.upstream.DataSpec;
|
|||||||
import com.google.android.exoplayer.upstream.NonBlockingInputStream;
|
import com.google.android.exoplayer.upstream.NonBlockingInputStream;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,8 +57,8 @@ public class DashWebmChunkSource implements ChunkSource {
|
|||||||
private final int numSegmentsPerChunk;
|
private final int numSegmentsPerChunk;
|
||||||
|
|
||||||
private final Format[] formats;
|
private final Format[] formats;
|
||||||
private final SparseArray<Representation> representations;
|
private final HashMap<String, Representation> representations;
|
||||||
private final SparseArray<WebmExtractor> extractors;
|
private final HashMap<String, WebmExtractor> extractors;
|
||||||
|
|
||||||
private boolean lastChunkWasInitialization;
|
private boolean lastChunkWasInitialization;
|
||||||
|
|
||||||
@ -73,8 +73,8 @@ public class DashWebmChunkSource implements ChunkSource {
|
|||||||
this.evaluator = evaluator;
|
this.evaluator = evaluator;
|
||||||
this.numSegmentsPerChunk = numSegmentsPerChunk;
|
this.numSegmentsPerChunk = numSegmentsPerChunk;
|
||||||
this.formats = new Format[representations.length];
|
this.formats = new Format[representations.length];
|
||||||
this.extractors = new SparseArray<WebmExtractor>();
|
this.extractors = new HashMap<String, WebmExtractor>();
|
||||||
this.representations = new SparseArray<Representation>();
|
this.representations = new HashMap<String, Representation>();
|
||||||
this.trackInfo = new TrackInfo(
|
this.trackInfo = new TrackInfo(
|
||||||
representations[0].format.mimeType, representations[0].periodDuration * 1000);
|
representations[0].format.mimeType, representations[0].periodDuration * 1000);
|
||||||
this.evaluation = new Evaluation();
|
this.evaluation = new Evaluation();
|
||||||
@ -84,7 +84,7 @@ public class DashWebmChunkSource implements ChunkSource {
|
|||||||
formats[i] = representations[i].format;
|
formats[i] = representations[i].format;
|
||||||
maxWidth = Math.max(formats[i].width, maxWidth);
|
maxWidth = Math.max(formats[i].width, maxWidth);
|
||||||
maxHeight = Math.max(formats[i].height, maxHeight);
|
maxHeight = Math.max(formats[i].height, maxHeight);
|
||||||
extractors.append(formats[i].id, new WebmExtractor());
|
extractors.put(formats[i].id, new WebmExtractor());
|
||||||
this.representations.put(formats[i].id, representations[i]);
|
this.representations.put(formats[i].id, representations[i]);
|
||||||
}
|
}
|
||||||
this.maxWidth = maxWidth;
|
this.maxWidth = maxWidth;
|
||||||
@ -133,7 +133,7 @@ public class DashWebmChunkSource implements ChunkSource {
|
|||||||
out.chunk = null;
|
out.chunk = null;
|
||||||
return;
|
return;
|
||||||
} else if (out.queueSize == queue.size() && out.chunk != null
|
} else if (out.queueSize == queue.size() && out.chunk != null
|
||||||
&& out.chunk.format.id == selectedFormat.id) {
|
&& out.chunk.format.id.equals(selectedFormat.id)) {
|
||||||
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
||||||
// of the queue. Leave unchanged.
|
// of the queue. Leave unchanged.
|
||||||
return;
|
return;
|
||||||
|
@ -21,7 +21,6 @@ import com.google.android.exoplayer.upstream.DataSpec;
|
|||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.xml.sax.helpers.DefaultHandler;
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
@ -45,8 +44,6 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public class MediaPresentationDescriptionParser extends DefaultHandler {
|
public class MediaPresentationDescriptionParser extends DefaultHandler {
|
||||||
|
|
||||||
private static final String TAG = "MediaPresentationDescriptionParser";
|
|
||||||
|
|
||||||
// Note: Does not support the date part of ISO 8601
|
// Note: Does not support the date part of ISO 8601
|
||||||
private static final Pattern DURATION =
|
private static final Pattern DURATION =
|
||||||
Pattern.compile("^PT(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?$");
|
Pattern.compile("^PT(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?$");
|
||||||
@ -214,14 +211,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler {
|
|||||||
private Representation parseRepresentation(XmlPullParser xpp, String contentId, long periodStart,
|
private Representation parseRepresentation(XmlPullParser xpp, String contentId, long periodStart,
|
||||||
long periodDuration, String parentMimeType, List<Segment.Timeline> segmentTimelineList)
|
long periodDuration, String parentMimeType, List<Segment.Timeline> segmentTimelineList)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
int id;
|
String id = xpp.getAttributeValue(null, "id");
|
||||||
try {
|
|
||||||
id = parseInt(xpp, "id");
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
Log.d(TAG, "Unable to parse id; " + nfe.getMessage());
|
|
||||||
// TODO: need a way to generate a unique and stable id; use hashCode for now
|
|
||||||
id = xpp.getAttributeValue(null, "id").hashCode();
|
|
||||||
}
|
|
||||||
int bandwidth = parseInt(xpp, "bandwidth") / 8;
|
int bandwidth = parseInt(xpp, "bandwidth") / 8;
|
||||||
int audioSamplingRate = parseInt(xpp, "audioSamplingRate");
|
int audioSamplingRate = parseInt(xpp, "audioSamplingRate");
|
||||||
int width = parseInt(xpp, "width");
|
int width = parseInt(xpp, "width");
|
||||||
|
@ -81,7 +81,7 @@ public class Representation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a cache key for the {@link Representation}, in the format
|
* Generates a cache key for the {@link Representation}, in the format
|
||||||
* {@link #contentId}.{@link #format.id}.{@link #revisionId}.
|
* {@code contentId + "." + format.id + "." + revisionId}.
|
||||||
*
|
*
|
||||||
* @return A cache key.
|
* @return A cache key.
|
||||||
*/
|
*/
|
||||||
|
@ -63,7 +63,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
|
|
||||||
private final SparseArray<FragmentedMp4Extractor> extractors;
|
private final SparseArray<FragmentedMp4Extractor> extractors;
|
||||||
private final Format[] formats;
|
private final SmoothStreamingFormat[] formats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param baseUrl The base URL for the streams.
|
* @param baseUrl The base URL for the streams.
|
||||||
@ -94,16 +94,16 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length;
|
int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length;
|
||||||
formats = new Format[trackCount];
|
formats = new SmoothStreamingFormat[trackCount];
|
||||||
extractors = new SparseArray<FragmentedMp4Extractor>();
|
extractors = new SparseArray<FragmentedMp4Extractor>();
|
||||||
int maxWidth = 0;
|
int maxWidth = 0;
|
||||||
int maxHeight = 0;
|
int maxHeight = 0;
|
||||||
for (int i = 0; i < trackCount; i++) {
|
for (int i = 0; i < trackCount; i++) {
|
||||||
int trackIndex = trackIndices != null ? trackIndices[i] : i;
|
int trackIndex = trackIndices != null ? trackIndices[i] : i;
|
||||||
TrackElement trackElement = streamElement.tracks[trackIndex];
|
TrackElement trackElement = streamElement.tracks[trackIndex];
|
||||||
formats[i] = new Format(trackIndex, trackElement.mimeType, trackElement.maxWidth,
|
formats[i] = new SmoothStreamingFormat(String.valueOf(trackIndex), trackElement.mimeType,
|
||||||
trackElement.maxHeight, trackElement.numChannels, trackElement.sampleRate,
|
trackElement.maxWidth, trackElement.maxHeight, trackElement.numChannels,
|
||||||
trackElement.bitrate / 8);
|
trackElement.sampleRate, trackElement.bitrate / 8, trackIndex);
|
||||||
maxWidth = Math.max(maxWidth, trackElement.maxWidth);
|
maxWidth = Math.max(maxWidth, trackElement.maxWidth);
|
||||||
maxHeight = Math.max(maxHeight, trackElement.maxHeight);
|
maxHeight = Math.max(maxHeight, trackElement.maxHeight);
|
||||||
|
|
||||||
@ -155,14 +155,14 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
long playbackPositionUs, ChunkOperationHolder out) {
|
long playbackPositionUs, ChunkOperationHolder out) {
|
||||||
evaluation.queueSize = queue.size();
|
evaluation.queueSize = queue.size();
|
||||||
formatEvaluator.evaluate(queue, playbackPositionUs, formats, evaluation);
|
formatEvaluator.evaluate(queue, playbackPositionUs, formats, evaluation);
|
||||||
Format selectedFormat = evaluation.format;
|
SmoothStreamingFormat selectedFormat = (SmoothStreamingFormat) evaluation.format;
|
||||||
out.queueSize = evaluation.queueSize;
|
out.queueSize = evaluation.queueSize;
|
||||||
|
|
||||||
if (selectedFormat == null) {
|
if (selectedFormat == null) {
|
||||||
out.chunk = null;
|
out.chunk = null;
|
||||||
return;
|
return;
|
||||||
} else if (out.queueSize == queue.size() && out.chunk != null
|
} else if (out.queueSize == queue.size() && out.chunk != null
|
||||||
&& out.chunk.format.id == evaluation.format.id) {
|
&& out.chunk.format.id.equals(evaluation.format.id)) {
|
||||||
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
||||||
// of the queue. Do nothing.
|
// of the queue. Do nothing.
|
||||||
return;
|
return;
|
||||||
@ -181,11 +181,12 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isLastChunk = nextChunkIndex == streamElement.chunkCount - 1;
|
boolean isLastChunk = nextChunkIndex == streamElement.chunkCount - 1;
|
||||||
String requestUrl = streamElement.buildRequestUrl(selectedFormat.id, nextChunkIndex);
|
String requestUrl = streamElement.buildRequestUrl(selectedFormat.trackIndex,
|
||||||
|
nextChunkIndex);
|
||||||
Uri uri = Uri.parse(baseUrl + '/' + requestUrl);
|
Uri uri = Uri.parse(baseUrl + '/' + requestUrl);
|
||||||
Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null,
|
Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null,
|
||||||
extractors.get(selectedFormat.id), dataSource, nextChunkIndex, isLastChunk,
|
extractors.get(Integer.parseInt(selectedFormat.id)), dataSource, nextChunkIndex,
|
||||||
streamElement.getStartTimeUs(nextChunkIndex),
|
isLastChunk, streamElement.getStartTimeUs(nextChunkIndex),
|
||||||
isLastChunk ? -1 : streamElement.getStartTimeUs(nextChunkIndex + 1), 0);
|
isLastChunk ? -1 : streamElement.getStartTimeUs(nextChunkIndex + 1), 0);
|
||||||
out.chunk = mediaChunk;
|
out.chunk = mediaChunk;
|
||||||
}
|
}
|
||||||
@ -254,4 +255,16 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
data[secondPosition] = temp;
|
data[secondPosition] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class SmoothStreamingFormat extends Format {
|
||||||
|
|
||||||
|
public final int trackIndex;
|
||||||
|
|
||||||
|
public SmoothStreamingFormat(String id, String mimeType, int width, int height,
|
||||||
|
int numChannels, int audioSamplingRate, int bandwidth, int trackIndex) {
|
||||||
|
super(id, mimeType, width, height, numChannels, audioSamplingRate, bandwidth);
|
||||||
|
this.trackIndex = trackIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user