parent
f7ffeb75cf
commit
8db1331021
@ -22,7 +22,6 @@ import com.google.android.exoplayer.MediaFormat;
|
|||||||
import com.google.android.exoplayer.MediaFormatHolder;
|
import com.google.android.exoplayer.MediaFormatHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.audio.AudioTrack;
|
import com.google.android.exoplayer.audio.AudioTrack;
|
||||||
import com.google.android.exoplayer.ext.opus.OpusDecoderWrapper.InputBuffer;
|
import com.google.android.exoplayer.ext.opus.OpusDecoderWrapper.InputBuffer;
|
||||||
@ -125,9 +124,10 @@ public final class LibopusAudioTrackRenderer extends SampleSourceTrackRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return MimeTypes.AUDIO_OPUS.equalsIgnoreCase(trackInfo.mimeType)
|
// TODO: Stop claiming to handle the WebM mime type (b/22996976).
|
||||||
|| MimeTypes.AUDIO_WEBM.equalsIgnoreCase(trackInfo.mimeType);
|
return MimeTypes.AUDIO_OPUS.equalsIgnoreCase(mediaFormat.mimeType)
|
||||||
|
|| MimeTypes.AUDIO_WEBM.equalsIgnoreCase(mediaFormat.mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,7 +21,6 @@ import com.google.android.exoplayer.MediaFormat;
|
|||||||
import com.google.android.exoplayer.MediaFormatHolder;
|
import com.google.android.exoplayer.MediaFormatHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.InputBuffer;
|
import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.InputBuffer;
|
||||||
import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.OutputBuffer;
|
import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.OutputBuffer;
|
||||||
@ -149,9 +148,10 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return MimeTypes.VIDEO_VP9.equalsIgnoreCase(trackInfo.mimeType)
|
// TODO: Stop claiming to handle the WebM mime type (b/22996976).
|
||||||
|| MimeTypes.VIDEO_WEBM.equalsIgnoreCase(trackInfo.mimeType);
|
return MimeTypes.VIDEO_VP9.equalsIgnoreCase(mediaFormat.mimeType)
|
||||||
|
|| MimeTypes.VIDEO_WEBM.equalsIgnoreCase(mediaFormat.mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,8 +69,8 @@ public final class MediaFormatTest extends TestCase {
|
|||||||
assertOptionalV16(out, android.media.MediaFormat.KEY_HEIGHT, in.height);
|
assertOptionalV16(out, android.media.MediaFormat.KEY_HEIGHT, in.height);
|
||||||
assertOptionalV16(out, android.media.MediaFormat.KEY_CHANNEL_COUNT, in.channelCount);
|
assertOptionalV16(out, android.media.MediaFormat.KEY_CHANNEL_COUNT, in.channelCount);
|
||||||
assertOptionalV16(out, android.media.MediaFormat.KEY_SAMPLE_RATE, in.sampleRate);
|
assertOptionalV16(out, android.media.MediaFormat.KEY_SAMPLE_RATE, in.sampleRate);
|
||||||
assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_WIDTH, in.getMaxVideoWidth());
|
assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_WIDTH, in.maxWidth);
|
||||||
assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_HEIGHT, in.getMaxVideoHeight());
|
assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_HEIGHT, in.maxHeight);
|
||||||
for (int i = 0; i < in.initializationData.size(); i++) {
|
for (int i = 0; i < in.initializationData.size(); i++) {
|
||||||
byte[] originalData = in.initializationData.get(i);
|
byte[] originalData = in.initializationData.get(i);
|
||||||
ByteBuffer frameworkBuffer = out.getByteBuffer("csd-" + i);
|
ByteBuffer frameworkBuffer = out.getByteBuffer("csd-" + i);
|
||||||
|
@ -91,11 +91,11 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
public void testMaxVideoDimensions() {
|
public void testMaxVideoDimensions() {
|
||||||
DashChunkSource chunkSource = new DashChunkSource(generateVodMpd(), AdaptationSet.TYPE_VIDEO,
|
DashChunkSource chunkSource = new DashChunkSource(generateVodMpd(), AdaptationSet.TYPE_VIDEO,
|
||||||
null, null, null);
|
null, null, null);
|
||||||
MediaFormat out = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null);
|
MediaFormat format = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null);
|
||||||
chunkSource.getMaxVideoDimensions(out);
|
format = chunkSource.getWithMaxVideoDimensions(format);
|
||||||
|
|
||||||
assertEquals(WIDE_WIDTH, out.getMaxVideoWidth());
|
assertEquals(WIDE_WIDTH, format.maxWidth);
|
||||||
assertEquals(TALL_HEIGHT, out.getMaxVideoHeight());
|
assertEquals(TALL_HEIGHT, format.maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetSeekRangeOnVod() {
|
public void testGetSeekRangeOnVod() {
|
||||||
@ -121,11 +121,11 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
|||||||
Representation.newInstance(0, 0, null, 0, WIDE_VIDEO, segmentBase2);
|
Representation.newInstance(0, 0, null, 0, WIDE_VIDEO, segmentBase2);
|
||||||
|
|
||||||
DashChunkSource chunkSource = new DashChunkSource(null, null, representation1, representation2);
|
DashChunkSource chunkSource = new DashChunkSource(null, null, representation1, representation2);
|
||||||
MediaFormat out = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null);
|
MediaFormat format = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null);
|
||||||
chunkSource.getMaxVideoDimensions(out);
|
format = chunkSource.getWithMaxVideoDimensions(format);
|
||||||
|
|
||||||
assertEquals(WIDE_WIDTH, out.getMaxVideoWidth());
|
assertEquals(WIDE_WIDTH, format.maxWidth);
|
||||||
assertEquals(TALL_HEIGHT, out.getMaxVideoHeight());
|
assertEquals(TALL_HEIGHT, format.maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLiveEdgeNoLatency() {
|
public void testLiveEdgeNoLatency() {
|
||||||
|
@ -35,7 +35,7 @@ public final class DummyTrackRenderer extends TrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TrackInfo getTrackInfo(int track) {
|
protected MediaFormat getFormat(int track) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
private final Handler eventHandler;
|
private final Handler eventHandler;
|
||||||
private final ExoPlayerImplInternal internalPlayer;
|
private final ExoPlayerImplInternal internalPlayer;
|
||||||
private final CopyOnWriteArraySet<Listener> listeners;
|
private final CopyOnWriteArraySet<Listener> listeners;
|
||||||
private final TrackInfo[][] trackInfos;
|
private final MediaFormat[][] trackFormats;
|
||||||
private final int[] selectedTrackIndices;
|
private final int[] selectedTrackIndices;
|
||||||
|
|
||||||
private boolean playWhenReady;
|
private boolean playWhenReady;
|
||||||
@ -58,7 +58,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
this.playWhenReady = false;
|
this.playWhenReady = false;
|
||||||
this.playbackState = STATE_IDLE;
|
this.playbackState = STATE_IDLE;
|
||||||
this.listeners = new CopyOnWriteArraySet<>();
|
this.listeners = new CopyOnWriteArraySet<>();
|
||||||
this.trackInfos = new TrackInfo[rendererCount][];
|
this.trackFormats = new MediaFormat[rendererCount][];
|
||||||
this.selectedTrackIndices = new int[rendererCount];
|
this.selectedTrackIndices = new int[rendererCount];
|
||||||
eventHandler = new Handler() {
|
eventHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
@ -92,7 +92,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(TrackRenderer... renderers) {
|
public void prepare(TrackRenderer... renderers) {
|
||||||
Arrays.fill(trackInfos, null);
|
Arrays.fill(trackFormats, null);
|
||||||
internalPlayer.prepare(renderers);
|
internalPlayer.prepare(renderers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,12 +116,12 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
|
|
||||||
// TODO: Expose in ExoPlayer.
|
// TODO: Expose in ExoPlayer.
|
||||||
public int getRendererTrackCount(int rendererIndex) {
|
public int getRendererTrackCount(int rendererIndex) {
|
||||||
return trackInfos[rendererIndex] != null ? trackInfos[rendererIndex].length : 0;
|
return trackFormats[rendererIndex] != null ? trackFormats[rendererIndex].length : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Expose in ExoPlayer.
|
// TODO: Expose in ExoPlayer.
|
||||||
public TrackInfo getRendererTrackInfo(int rendererIndex, int trackIndex) {
|
public MediaFormat getRendererTrackInfo(int rendererIndex, int trackIndex) {
|
||||||
return trackInfos[rendererIndex][trackIndex];
|
return trackFormats[rendererIndex][trackIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Expose in ExoPlayer.
|
// TODO: Expose in ExoPlayer.
|
||||||
@ -212,8 +212,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
/* package */ void handleEvent(Message msg) {
|
/* package */ void handleEvent(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case ExoPlayerImplInternal.MSG_PREPARED: {
|
case ExoPlayerImplInternal.MSG_PREPARED: {
|
||||||
TrackInfo[][] trackInfos = (TrackInfo[][]) msg.obj;
|
System.arraycopy(msg.obj, 0, trackFormats, 0, trackFormats.length);
|
||||||
System.arraycopy(trackInfos, 0, this.trackInfos, 0, trackInfos.length);
|
|
||||||
playbackState = msg.arg1;
|
playbackState = msg.arg1;
|
||||||
for (Listener listener : listeners) {
|
for (Listener listener : listeners) {
|
||||||
listener.onPlayerStateChanged(playWhenReady, playbackState);
|
listener.onPlayerStateChanged(playWhenReady, playbackState);
|
||||||
|
@ -67,7 +67,7 @@ import java.util.List;
|
|||||||
private final Handler eventHandler;
|
private final Handler eventHandler;
|
||||||
private final StandaloneMediaClock standaloneMediaClock;
|
private final StandaloneMediaClock standaloneMediaClock;
|
||||||
private final List<TrackRenderer> enabledRenderers;
|
private final List<TrackRenderer> enabledRenderers;
|
||||||
private final TrackInfo[][] trackInfos;
|
private final MediaFormat[][] trackFormats;
|
||||||
private final int[] selectedTrackIndices;
|
private final int[] selectedTrackIndices;
|
||||||
private final long minBufferUs;
|
private final long minBufferUs;
|
||||||
private final long minRebufferUs;
|
private final long minRebufferUs;
|
||||||
@ -101,7 +101,7 @@ import java.util.List;
|
|||||||
|
|
||||||
standaloneMediaClock = new StandaloneMediaClock();
|
standaloneMediaClock = new StandaloneMediaClock();
|
||||||
enabledRenderers = new ArrayList<>(selectedTrackIndices.length);
|
enabledRenderers = new ArrayList<>(selectedTrackIndices.length);
|
||||||
trackInfos = new TrackInfo[selectedTrackIndices.length][];
|
trackFormats = new MediaFormat[selectedTrackIndices.length][];
|
||||||
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
||||||
// not normally change to this priority" is incorrect.
|
// not normally change to this priority" is incorrect.
|
||||||
internalPlaybackThread = new PriorityHandlerThread(getClass().getSimpleName() + ":Handler",
|
internalPlaybackThread = new PriorityHandlerThread(getClass().getSimpleName() + ":Handler",
|
||||||
@ -253,7 +253,7 @@ import java.util.List;
|
|||||||
private void prepareInternal(TrackRenderer[] renderers) throws ExoPlaybackException {
|
private void prepareInternal(TrackRenderer[] renderers) throws ExoPlaybackException {
|
||||||
resetInternal();
|
resetInternal();
|
||||||
this.renderers = renderers;
|
this.renderers = renderers;
|
||||||
Arrays.fill(trackInfos, null);
|
Arrays.fill(trackFormats, null);
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
MediaClock mediaClock = renderers[i].getMediaClock();
|
MediaClock mediaClock = renderers[i].getMediaClock();
|
||||||
if (mediaClock != null) {
|
if (mediaClock != null) {
|
||||||
@ -292,11 +292,11 @@ import java.util.List;
|
|||||||
for (int rendererIndex = 0; rendererIndex < renderers.length; rendererIndex++) {
|
for (int rendererIndex = 0; rendererIndex < renderers.length; rendererIndex++) {
|
||||||
TrackRenderer renderer = renderers[rendererIndex];
|
TrackRenderer renderer = renderers[rendererIndex];
|
||||||
int rendererTrackCount = renderer.getTrackCount();
|
int rendererTrackCount = renderer.getTrackCount();
|
||||||
TrackInfo[] rendererTrackInfos = new TrackInfo[rendererTrackCount];
|
MediaFormat[] rendererTrackFormats = new MediaFormat[rendererTrackCount];
|
||||||
for (int trackIndex = 0; trackIndex < rendererTrackCount; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < rendererTrackCount; trackIndex++) {
|
||||||
rendererTrackInfos[trackIndex] = renderer.getTrackInfo(trackIndex);
|
rendererTrackFormats[trackIndex] = renderer.getFormat(trackIndex);
|
||||||
}
|
}
|
||||||
trackInfos[rendererIndex] = rendererTrackInfos;
|
trackFormats[rendererIndex] = rendererTrackFormats;
|
||||||
if (rendererTrackCount > 0) {
|
if (rendererTrackCount > 0) {
|
||||||
if (durationUs == TrackRenderer.UNKNOWN_TIME_US) {
|
if (durationUs == TrackRenderer.UNKNOWN_TIME_US) {
|
||||||
// We've already encountered a track for which the duration is unknown, so the media
|
// We've already encountered a track for which the duration is unknown, so the media
|
||||||
@ -312,7 +312,7 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int trackIndex = selectedTrackIndices[rendererIndex];
|
int trackIndex = selectedTrackIndices[rendererIndex];
|
||||||
if (0 <= trackIndex && trackIndex < rendererTrackInfos.length) {
|
if (0 <= trackIndex && trackIndex < rendererTrackFormats.length) {
|
||||||
renderer.enable(trackIndex, positionUs, false);
|
renderer.enable(trackIndex, positionUs, false);
|
||||||
enabledRenderers.add(renderer);
|
enabledRenderers.add(renderer);
|
||||||
allRenderersEnded = allRenderersEnded && renderer.isEnded();
|
allRenderersEnded = allRenderersEnded && renderer.isEnded();
|
||||||
@ -332,7 +332,7 @@ import java.util.List;
|
|||||||
|
|
||||||
// Fire an event indicating that the player has been prepared, passing the initial state and
|
// Fire an event indicating that the player has been prepared, passing the initial state and
|
||||||
// renderer track information.
|
// renderer track information.
|
||||||
eventHandler.obtainMessage(MSG_PREPARED, state, 0, trackInfos).sendToTarget();
|
eventHandler.obtainMessage(MSG_PREPARED, state, 0, trackFormats).sendToTarget();
|
||||||
|
|
||||||
// Start the renderers if required, and schedule the first piece of work.
|
// Start the renderers if required, and schedule the first piece of work.
|
||||||
if (playWhenReady && state == ExoPlayer.STATE_READY) {
|
if (playWhenReady && state == ExoPlayer.STATE_READY) {
|
||||||
@ -610,7 +610,7 @@ import java.util.List;
|
|||||||
|
|
||||||
boolean isEnabled = rendererState == TrackRenderer.STATE_ENABLED
|
boolean isEnabled = rendererState == TrackRenderer.STATE_ENABLED
|
||||||
|| rendererState == TrackRenderer.STATE_STARTED;
|
|| rendererState == TrackRenderer.STATE_STARTED;
|
||||||
boolean shouldEnable = 0 <= trackIndex && trackIndex < trackInfos[rendererIndex].length;
|
boolean shouldEnable = 0 <= trackIndex && trackIndex < trackFormats[rendererIndex].length;
|
||||||
|
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
// The renderer is currently enabled. We need to disable it, so that we can either re-enable
|
// The renderer is currently enabled. We need to disable it, so that we can either re-enable
|
||||||
|
@ -73,7 +73,7 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
|
|||||||
|
|
||||||
private IOException preparationError;
|
private IOException preparationError;
|
||||||
private MediaExtractor extractor;
|
private MediaExtractor extractor;
|
||||||
private TrackInfo[] trackInfos;
|
private MediaFormat[] trackFormats;
|
||||||
private boolean prepared;
|
private boolean prepared;
|
||||||
private int remainingReleaseCount;
|
private int remainingReleaseCount;
|
||||||
private int[] trackStates;
|
private int[] trackStates;
|
||||||
@ -144,13 +144,9 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
|
|||||||
|
|
||||||
trackStates = new int[extractor.getTrackCount()];
|
trackStates = new int[extractor.getTrackCount()];
|
||||||
pendingDiscontinuities = new boolean[trackStates.length];
|
pendingDiscontinuities = new boolean[trackStates.length];
|
||||||
trackInfos = new TrackInfo[trackStates.length];
|
trackFormats = new MediaFormat[trackStates.length];
|
||||||
for (int i = 0; i < trackStates.length; i++) {
|
for (int i = 0; i < trackStates.length; i++) {
|
||||||
android.media.MediaFormat format = extractor.getTrackFormat(i);
|
trackFormats[i] = createMediaFormat(extractor.getTrackFormat(i));
|
||||||
long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
|
||||||
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
|
||||||
String mime = format.getString(android.media.MediaFormat.KEY_MIME);
|
|
||||||
trackInfos[i] = new TrackInfo(mime, durationUs);
|
|
||||||
}
|
}
|
||||||
prepared = true;
|
prepared = true;
|
||||||
}
|
}
|
||||||
@ -164,9 +160,9 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo(int track) {
|
public MediaFormat getFormat(int track) {
|
||||||
Assertions.checkState(prepared);
|
Assertions.checkState(prepared);
|
||||||
return trackInfos[track];
|
return trackFormats[track];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -200,7 +196,7 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
|
|||||||
return NOTHING_READ;
|
return NOTHING_READ;
|
||||||
}
|
}
|
||||||
if (trackStates[track] != TRACK_STATE_FORMAT_SENT) {
|
if (trackStates[track] != TRACK_STATE_FORMAT_SENT) {
|
||||||
formatHolder.format = createMediaFormat(extractor.getTrackFormat(track));
|
formatHolder.format = trackFormats[track];
|
||||||
formatHolder.drmInitData = Util.SDK_INT >= 18 ? getDrmInitDataV18() : null;
|
formatHolder.drmInitData = Util.SDK_INT >= 18 ? getDrmInitDataV18() : null;
|
||||||
trackStates[track] = TRACK_STATE_FORMAT_SENT;
|
trackStates[track] = TRACK_STATE_FORMAT_SENT;
|
||||||
return FORMAT_READ;
|
return FORMAT_READ;
|
||||||
@ -319,7 +315,8 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
|
|||||||
long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
||||||
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
||||||
return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, MediaFormat.NO_VALUE,
|
return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, MediaFormat.NO_VALUE,
|
||||||
channelCount, sampleRate, language, initializationData);
|
channelCount, sampleRate, language, initializationData, MediaFormat.NO_VALUE,
|
||||||
|
MediaFormat.NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(16)
|
@TargetApi(16)
|
||||||
|
@ -193,8 +193,9 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return MimeTypes.isAudio(trackInfo.mimeType);
|
// TODO: Check the mime type against the available decoders (b/22996976).
|
||||||
|
return MimeTypes.isAudio(mediaFormat.mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -256,8 +256,9 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return MimeTypes.isVideo(trackInfo.mimeType);
|
// TODO: Check the mime type against the available decoders (b/22996976).
|
||||||
|
return MimeTypes.isVideo(mediaFormat.mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,6 +35,11 @@ public final class MediaFormat {
|
|||||||
public final String mimeType;
|
public final String mimeType;
|
||||||
public final int maxInputSize;
|
public final int maxInputSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration in microseconds, or {@link C#UNKNOWN_TIME_US} if the duration is unknown, or
|
||||||
|
* {@link C#MATCH_LONGEST_US} if the duration should match the duration of the longest track whose
|
||||||
|
* duration is known.
|
||||||
|
*/
|
||||||
public final long durationUs;
|
public final long durationUs;
|
||||||
|
|
||||||
public final int width;
|
public final int width;
|
||||||
@ -48,8 +53,8 @@ public final class MediaFormat {
|
|||||||
|
|
||||||
public final List<byte[]> initializationData;
|
public final List<byte[]> initializationData;
|
||||||
|
|
||||||
private int maxWidth;
|
public final int maxWidth;
|
||||||
private int maxHeight;
|
public final int maxHeight;
|
||||||
|
|
||||||
// Lazy-initialized hashcode.
|
// Lazy-initialized hashcode.
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
@ -71,7 +76,7 @@ public final class MediaFormat {
|
|||||||
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, long durationUs,
|
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, long durationUs,
|
||||||
int width, int height, float pixelWidthHeightRatio, List<byte[]> initializationData) {
|
int width, int height, float pixelWidthHeightRatio, List<byte[]> initializationData) {
|
||||||
return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, pixelWidthHeightRatio,
|
return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, pixelWidthHeightRatio,
|
||||||
NO_VALUE, NO_VALUE, null, initializationData);
|
NO_VALUE, NO_VALUE, null, initializationData, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount,
|
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount,
|
||||||
@ -83,7 +88,7 @@ public final class MediaFormat {
|
|||||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, long durationUs,
|
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, long durationUs,
|
||||||
int channelCount, int sampleRate, List<byte[]> initializationData) {
|
int channelCount, int sampleRate, List<byte[]> initializationData) {
|
||||||
return new MediaFormat(mimeType, maxInputSize, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new MediaFormat(mimeType, maxInputSize, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
channelCount, sampleRate, null, initializationData);
|
channelCount, sampleRate, null, initializationData, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createTextFormat(String mimeType, String language) {
|
public static MediaFormat createTextFormat(String mimeType, String language) {
|
||||||
@ -92,7 +97,7 @@ public final class MediaFormat {
|
|||||||
|
|
||||||
public static MediaFormat createTextFormat(String mimeType, String language, long durationUs) {
|
public static MediaFormat createTextFormat(String mimeType, String language, long durationUs) {
|
||||||
return new MediaFormat(mimeType, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new MediaFormat(mimeType, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, language, null);
|
NO_VALUE, NO_VALUE, language, null, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createFormatForMimeType(String mimeType) {
|
public static MediaFormat createFormatForMimeType(String mimeType) {
|
||||||
@ -101,12 +106,12 @@ public final class MediaFormat {
|
|||||||
|
|
||||||
public static MediaFormat createFormatForMimeType(String mimeType, long durationUs) {
|
public static MediaFormat createFormatForMimeType(String mimeType, long durationUs) {
|
||||||
return new MediaFormat(mimeType, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new MediaFormat(mimeType, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, null, null);
|
NO_VALUE, NO_VALUE, null, null, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ MediaFormat(String mimeType, int maxInputSize, long durationUs, int width,
|
/* package */ MediaFormat(String mimeType, int maxInputSize, long durationUs, int width,
|
||||||
int height, float pixelWidthHeightRatio, int channelCount, int sampleRate, String language,
|
int height, float pixelWidthHeightRatio, int channelCount, int sampleRate, String language,
|
||||||
List<byte[]> initializationData) {
|
List<byte[]> initializationData, int maxWidth, int maxHeight) {
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.maxInputSize = maxInputSize;
|
this.maxInputSize = maxInputSize;
|
||||||
this.durationUs = durationUs;
|
this.durationUs = durationUs;
|
||||||
@ -118,26 +123,13 @@ public final class MediaFormat {
|
|||||||
this.language = language;
|
this.language = language;
|
||||||
this.initializationData = initializationData == null ? Collections.<byte[]>emptyList()
|
this.initializationData = initializationData == null ? Collections.<byte[]>emptyList()
|
||||||
: initializationData;
|
: initializationData;
|
||||||
maxWidth = NO_VALUE;
|
|
||||||
maxHeight = NO_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
|
||||||
public void setMaxVideoDimensions(int maxWidth, int maxHeight) {
|
|
||||||
this.maxWidth = maxWidth;
|
this.maxWidth = maxWidth;
|
||||||
this.maxHeight = maxHeight;
|
this.maxHeight = maxHeight;
|
||||||
if (frameworkMediaFormat != null) {
|
|
||||||
maybeSetIntegerV16(frameworkMediaFormat, android.media.MediaFormat.KEY_MAX_WIDTH, maxWidth);
|
|
||||||
maybeSetIntegerV16(frameworkMediaFormat, android.media.MediaFormat.KEY_MAX_HEIGHT, maxHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxVideoWidth() {
|
public MediaFormat copyWithMaxVideoDimension(int maxWidth, int maxHeight) {
|
||||||
return maxWidth;
|
return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, pixelWidthHeightRatio,
|
||||||
}
|
channelCount, sampleRate, language, initializationData, maxWidth, maxHeight);
|
||||||
|
|
||||||
public int getMaxVideoHeight() {
|
|
||||||
return maxHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,9 +20,9 @@ import java.io.IOException;
|
|||||||
/**
|
/**
|
||||||
* A source of media samples.
|
* A source of media samples.
|
||||||
* <p>
|
* <p>
|
||||||
* A {@link SampleSource} may expose one or multiple tracks. The number of tracks and information
|
* A {@link SampleSource} may expose one or multiple tracks. The number of tracks and each track's
|
||||||
* about each can be queried using {@link SampleSourceReader#getTrackCount()} and
|
* media format can be queried using {@link SampleSourceReader#getTrackCount()} and
|
||||||
* {@link SampleSourceReader#getTrackInfo(int)} respectively.
|
* {@link SampleSourceReader#getFormat(int)} respectively.
|
||||||
*/
|
*/
|
||||||
public interface SampleSource {
|
public interface SampleSource {
|
||||||
|
|
||||||
@ -87,13 +87,14 @@ public interface SampleSource {
|
|||||||
public int getTrackCount();
|
public int getTrackCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about the specified track.
|
* Returns the format of the specified track.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should not be called until after the source has been successfully prepared.
|
* This method should not be called until after the source has been successfully prepared.
|
||||||
*
|
*
|
||||||
* @return Information about the specified track.
|
* @param track The track index.
|
||||||
|
* @return The format of the specified track.
|
||||||
*/
|
*/
|
||||||
public TrackInfo getTrackInfo(int track);
|
public MediaFormat getFormat(int track);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the specified track. This allows the track's format and samples to be read from
|
* Enable the specified track. This allows the track's format and samples to be read from
|
||||||
|
@ -30,7 +30,6 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
|
|
||||||
private int enabledSourceTrackIndex;
|
private int enabledSourceTrackIndex;
|
||||||
private int[] handledSourceTrackIndices;
|
private int[] handledSourceTrackIndices;
|
||||||
private TrackInfo[] trackInfos;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param source The upstream source from which the renderer obtains samples.
|
* @param source The upstream source from which the renderer obtains samples.
|
||||||
@ -48,27 +47,24 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
int handledTrackCount = 0;
|
int handledTrackCount = 0;
|
||||||
int sourceTrackCount = source.getTrackCount();
|
int sourceTrackCount = source.getTrackCount();
|
||||||
int[] trackIndices = new int[sourceTrackCount];
|
int[] trackIndices = new int[sourceTrackCount];
|
||||||
TrackInfo[] trackInfos = new TrackInfo[sourceTrackCount];
|
|
||||||
for (int trackIndex = 0; trackIndex < sourceTrackCount; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < sourceTrackCount; trackIndex++) {
|
||||||
TrackInfo trackInfo = source.getTrackInfo(trackIndex);
|
MediaFormat format = source.getFormat(trackIndex);
|
||||||
if (handlesTrack(trackInfo)) {
|
if (handlesTrack(format)) {
|
||||||
trackIndices[handledTrackCount] = trackIndex;
|
trackIndices[handledTrackCount] = trackIndex;
|
||||||
trackInfos[handledTrackCount] = trackInfo;
|
|
||||||
handledTrackCount++;
|
handledTrackCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.handledSourceTrackIndices = Arrays.copyOf(trackIndices, handledTrackCount);
|
this.handledSourceTrackIndices = Arrays.copyOf(trackIndices, handledTrackCount);
|
||||||
this.trackInfos = Arrays.copyOf(trackInfos, handledTrackCount);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this renderer is capable of handling the provided track.
|
* Returns whether this renderer is capable of handling the provided track.
|
||||||
*
|
*
|
||||||
* @param trackInfo The track.
|
* @param mediaFormat The track.
|
||||||
* @return True if the renderer can handle the track, false otherwise.
|
* @return True if the renderer can handle the track, false otherwise.
|
||||||
*/
|
*/
|
||||||
protected abstract boolean handlesTrack(TrackInfo trackInfo);
|
protected abstract boolean handlesTrack(MediaFormat mediaFormat);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onEnabled(int track, long positionUs, boolean joining)
|
protected void onEnabled(int track, long positionUs, boolean joining)
|
||||||
@ -89,7 +85,7 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getDurationUs() {
|
protected long getDurationUs() {
|
||||||
return source.getTrackInfo(enabledSourceTrackIndex).durationUs;
|
return source.getFormat(enabledSourceTrackIndex).durationUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -123,12 +119,12 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final int getTrackCount() {
|
protected final int getTrackCount() {
|
||||||
return trackInfos.length;
|
return handledSourceTrackIndices.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final TrackInfo getTrackInfo(int track) {
|
protected final MediaFormat getFormat(int track) {
|
||||||
return trackInfos[track];
|
return source.getFormat(handledSourceTrackIndices[track]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import com.google.android.exoplayer.upstream.DataSource;
|
|||||||
import com.google.android.exoplayer.upstream.DataSpec;
|
import com.google.android.exoplayer.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer.upstream.Loader;
|
import com.google.android.exoplayer.upstream.Loader;
|
||||||
import com.google.android.exoplayer.upstream.Loader.Loadable;
|
import com.google.android.exoplayer.upstream.Loader.Loadable;
|
||||||
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@ -43,15 +44,18 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
*/
|
*/
|
||||||
private static final int INITIAL_SAMPLE_SIZE = 1;
|
private static final int INITIAL_SAMPLE_SIZE = 1;
|
||||||
|
|
||||||
|
private static final int STATE_SEND_FORMAT = 0;
|
||||||
|
private static final int STATE_SEND_SAMPLE = 1;
|
||||||
|
private static final int STATE_END_OF_STREAM = 2;
|
||||||
|
|
||||||
private final Uri uri;
|
private final Uri uri;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final MediaFormat format;
|
private final MediaFormat format;
|
||||||
private final TrackInfo trackInfo;
|
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
|
|
||||||
|
private int state;
|
||||||
private byte[] sampleData;
|
private byte[] sampleData;
|
||||||
private int sampleSize;
|
private int sampleSize;
|
||||||
private boolean pendingSample;
|
|
||||||
|
|
||||||
private boolean loadingFinished;
|
private boolean loadingFinished;
|
||||||
private Loader loader;
|
private Loader loader;
|
||||||
@ -69,7 +73,6 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
trackInfo = new TrackInfo(format.mimeType, format.durationUs);
|
|
||||||
sampleData = new byte[INITIAL_SAMPLE_SIZE];
|
sampleData = new byte[INITIAL_SAMPLE_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,13 +95,13 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo(int track) {
|
public MediaFormat getFormat(int track) {
|
||||||
return trackInfo;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enable(int track, long positionUs) {
|
public void enable(int track, long positionUs) {
|
||||||
pendingSample = true;
|
state = STATE_SEND_FORMAT;
|
||||||
clearCurrentLoadableException();
|
clearCurrentLoadableException();
|
||||||
maybeStartLoading();
|
maybeStartLoading();
|
||||||
}
|
}
|
||||||
@ -121,9 +124,16 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
SampleHolder sampleHolder, boolean onlyReadDiscontinuity) {
|
SampleHolder sampleHolder, boolean onlyReadDiscontinuity) {
|
||||||
if (onlyReadDiscontinuity) {
|
if (onlyReadDiscontinuity) {
|
||||||
return NOTHING_READ;
|
return NOTHING_READ;
|
||||||
} else if (!pendingSample) {
|
} else if (state == STATE_END_OF_STREAM) {
|
||||||
return END_OF_STREAM;
|
return END_OF_STREAM;
|
||||||
} else if (!loadingFinished) {
|
} else if (state == STATE_SEND_FORMAT) {
|
||||||
|
formatHolder.format = format;
|
||||||
|
state = STATE_SEND_SAMPLE;
|
||||||
|
return FORMAT_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assertions.checkState(state == STATE_SEND_SAMPLE);
|
||||||
|
if (!loadingFinished) {
|
||||||
return NOTHING_READ;
|
return NOTHING_READ;
|
||||||
} else {
|
} else {
|
||||||
sampleHolder.timeUs = 0;
|
sampleHolder.timeUs = 0;
|
||||||
@ -133,13 +143,16 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
sampleHolder.replaceBuffer(sampleHolder.size);
|
sampleHolder.replaceBuffer(sampleHolder.size);
|
||||||
}
|
}
|
||||||
sampleHolder.data.put(sampleData, 0, sampleSize);
|
sampleHolder.data.put(sampleData, 0, sampleSize);
|
||||||
|
state = STATE_END_OF_STREAM;
|
||||||
return SAMPLE_READ;
|
return SAMPLE_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seekToUs(long positionUs) {
|
public void seekToUs(long positionUs) {
|
||||||
pendingSample = true;
|
if (state == STATE_END_OF_STREAM) {
|
||||||
|
state = STATE_SEND_SAMPLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -149,7 +162,7 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable(int track) {
|
public void disable(int track) {
|
||||||
pendingSample = false;
|
state = STATE_END_OF_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -163,7 +176,7 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade
|
|||||||
// Private methods.
|
// Private methods.
|
||||||
|
|
||||||
private void maybeStartLoading() {
|
private void maybeStartLoading() {
|
||||||
if (loadingFinished || !pendingSample || loader.isLoading()) {
|
if (loadingFinished || state != STATE_END_OF_STREAM || loader.isLoading()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (currentLoadableException != null) {
|
if (currentLoadableException != null) {
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds high level information about a media track.
|
|
||||||
*/
|
|
||||||
public final class TrackInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The mime type.
|
|
||||||
*/
|
|
||||||
public final String mimeType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The duration in microseconds, or {@link C#UNKNOWN_TIME_US} if the duration is unknown, or
|
|
||||||
* {@link C#MATCH_LONGEST_US} if the duration should match the duration of the longest track whose
|
|
||||||
* duration is known.
|
|
||||||
*/
|
|
||||||
public final long durationUs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mimeType The mime type.
|
|
||||||
* @param durationUs The duration in microseconds, or {@link C#UNKNOWN_TIME_US} if the duration
|
|
||||||
* is unknown, or {@link C#MATCH_LONGEST_US} if the duration should match the duration of the
|
|
||||||
* longest track whose duration is known.
|
|
||||||
*/
|
|
||||||
public TrackInfo(String mimeType, long durationUs) {
|
|
||||||
this.mimeType = mimeType;
|
|
||||||
this.durationUs = durationUs;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -138,17 +138,17 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about the specified track.
|
* Returns the format of the specified track.
|
||||||
* <p>
|
* <p>
|
||||||
* This method may be called when the renderer is in the following states:
|
* This method may be called when the renderer is in the following states:
|
||||||
* {@link #STATE_PREPARED}, {@link #STATE_ENABLED}, {@link #STATE_STARTED}
|
* {@link #STATE_PREPARED}, {@link #STATE_ENABLED}, {@link #STATE_STARTED}
|
||||||
*
|
*
|
||||||
* @param track The track index.
|
* @param track The track index.
|
||||||
* @return Information about the specified track.
|
* @return The format of the specified track.
|
||||||
*/
|
*/
|
||||||
// TODO: This method should be abstract. This implementation is provided as an interim step only.
|
// TODO: This method should be abstract. This implementation is provided as an interim step only.
|
||||||
protected TrackInfo getTrackInfo(int track) {
|
protected MediaFormat getFormat(int track) {
|
||||||
return new TrackInfo("application/octet-stream", getDurationUs());
|
return MediaFormat.createFormatForMimeType("application/octet-stream", getDurationUs());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,6 @@ import com.google.android.exoplayer.MediaFormatHolder;
|
|||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
|
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.extractor.DefaultTrackOutput;
|
import com.google.android.exoplayer.extractor.DefaultTrackOutput;
|
||||||
import com.google.android.exoplayer.upstream.Loader;
|
import com.google.android.exoplayer.upstream.Loader;
|
||||||
@ -132,7 +131,7 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load
|
|||||||
if (state == STATE_PREPARED) {
|
if (state == STATE_PREPARED) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
loader = new Loader("Loader:" + chunkSource.getTrackInfo().mimeType);
|
loader = new Loader("Loader:" + chunkSource.getFormat().mimeType);
|
||||||
state = STATE_PREPARED;
|
state = STATE_PREPARED;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -144,10 +143,10 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo(int track) {
|
public MediaFormat getFormat(int track) {
|
||||||
Assertions.checkState(state == STATE_PREPARED || state == STATE_ENABLED);
|
Assertions.checkState(state == STATE_PREPARED || state == STATE_ENABLED);
|
||||||
Assertions.checkState(track == 0);
|
Assertions.checkState(track == 0);
|
||||||
return chunkSource.getTrackInfo();
|
return chunkSource.getFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -232,7 +231,7 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load
|
|||||||
if (haveSamples || currentChunk.isMediaFormatFinal) {
|
if (haveSamples || currentChunk.isMediaFormatFinal) {
|
||||||
MediaFormat mediaFormat = currentChunk.getMediaFormat();
|
MediaFormat mediaFormat = currentChunk.getMediaFormat();
|
||||||
if (!mediaFormat.equals(downstreamMediaFormat, true)) {
|
if (!mediaFormat.equals(downstreamMediaFormat, true)) {
|
||||||
chunkSource.getMaxVideoDimensions(mediaFormat);
|
mediaFormat = chunkSource.getWithMaxVideoDimensions(mediaFormat);
|
||||||
formatHolder.format = mediaFormat;
|
formatHolder.format = mediaFormat;
|
||||||
formatHolder.drmInitData = currentChunk.getDrmInitData();
|
formatHolder.drmInitData = currentChunk.getDrmInitData();
|
||||||
downstreamMediaFormat = mediaFormat;
|
downstreamMediaFormat = mediaFormat;
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package com.google.android.exoplayer.chunk;
|
package com.google.android.exoplayer.chunk;
|
||||||
|
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -32,23 +31,24 @@ import java.util.List;
|
|||||||
public interface ChunkSource {
|
public interface ChunkSource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets information about the track for which this instance provides {@link Chunk}s.
|
* Gets the format.
|
||||||
* <p>
|
* <p>
|
||||||
* May be called when the source is disabled or enabled.
|
* May be called when the source is disabled or enabled.
|
||||||
*
|
*
|
||||||
* @return Information about the track.
|
* @return The format.
|
||||||
*/
|
*/
|
||||||
TrackInfo getTrackInfo();
|
MediaFormat getFormat();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adaptive video {@link ChunkSource} implementations must set the maximum video dimensions on
|
* Adaptive video {@link ChunkSource} implementations must return a copy of the provided
|
||||||
* the supplied {@link MediaFormat}. Other implementations do nothing.
|
* {@link MediaFormat} with the maximum video dimensions set. Other implementations can return
|
||||||
* <p>
|
* the provided {@link MediaFormat} directly.
|
||||||
* Only called when the source is enabled.
|
|
||||||
*
|
*
|
||||||
* @param out The {@link MediaFormat} on which the maximum video dimensions should be set.
|
* @param format The format to be copied or returned.
|
||||||
|
* @return A copy of the provided {@link MediaFormat} with the maximum video dimensions set, or
|
||||||
|
* the provided format.
|
||||||
*/
|
*/
|
||||||
void getMaxVideoDimensions(MediaFormat out);
|
MediaFormat getWithMaxVideoDimensions(MediaFormat format);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the source is enabled.
|
* Called when the source is enabled.
|
||||||
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer.chunk;
|
|||||||
import com.google.android.exoplayer.ExoPlaybackException;
|
import com.google.android.exoplayer.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer.ExoPlayer.ExoPlayerComponent;
|
import com.google.android.exoplayer.ExoPlayer.ExoPlayerComponent;
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -61,8 +60,8 @@ public final class MultiTrackChunkSource implements ChunkSource, ExoPlayerCompon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo() {
|
public MediaFormat getFormat() {
|
||||||
return selectedSource.getTrackInfo();
|
return selectedSource.getFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,8 +93,8 @@ public final class MultiTrackChunkSource implements ChunkSource, ExoPlayerCompon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getMaxVideoDimensions(MediaFormat out) {
|
public MediaFormat getWithMaxVideoDimensions(MediaFormat format) {
|
||||||
selectedSource.getMaxVideoDimensions(out);
|
return selectedSource.getWithMaxVideoDimensions(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer.chunk;
|
|||||||
|
|
||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.upstream.DataSource;
|
import com.google.android.exoplayer.upstream.DataSource;
|
||||||
import com.google.android.exoplayer.upstream.DataSpec;
|
import com.google.android.exoplayer.upstream.DataSpec;
|
||||||
|
|
||||||
@ -36,7 +35,6 @@ public final class SingleSampleChunkSource implements ChunkSource {
|
|||||||
private final Format format;
|
private final Format format;
|
||||||
private final long durationUs;
|
private final long durationUs;
|
||||||
private final MediaFormat mediaFormat;
|
private final MediaFormat mediaFormat;
|
||||||
private final TrackInfo trackInfo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param dataSource A {@link DataSource} suitable for loading the sample data.
|
* @param dataSource A {@link DataSource} suitable for loading the sample data.
|
||||||
@ -54,17 +52,16 @@ public final class SingleSampleChunkSource implements ChunkSource {
|
|||||||
this.format = format;
|
this.format = format;
|
||||||
this.durationUs = durationUs;
|
this.durationUs = durationUs;
|
||||||
this.mediaFormat = mediaFormat;
|
this.mediaFormat = mediaFormat;
|
||||||
trackInfo = new TrackInfo(format.mimeType, durationUs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo() {
|
public MediaFormat getFormat() {
|
||||||
return trackInfo;
|
return mediaFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getMaxVideoDimensions(MediaFormat out) {
|
public MediaFormat getWithMaxVideoDimensions(MediaFormat format) {
|
||||||
// Do nothing.
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer.dash;
|
|||||||
import com.google.android.exoplayer.BehindLiveWindowException;
|
import com.google.android.exoplayer.BehindLiveWindowException;
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.TimeRange;
|
import com.google.android.exoplayer.TimeRange;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.chunk.Chunk;
|
import com.google.android.exoplayer.chunk.Chunk;
|
||||||
import com.google.android.exoplayer.chunk.ChunkExtractorWrapper;
|
import com.google.android.exoplayer.chunk.ChunkExtractorWrapper;
|
||||||
@ -98,7 +97,7 @@ public class DashChunkSource implements ChunkSource {
|
|||||||
private final Handler eventHandler;
|
private final Handler eventHandler;
|
||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
|
|
||||||
private final TrackInfo trackInfo;
|
private final MediaFormat mediaFormat;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final FormatEvaluator formatEvaluator;
|
private final FormatEvaluator formatEvaluator;
|
||||||
private final Evaluation evaluation;
|
private final Evaluation evaluation;
|
||||||
@ -263,7 +262,9 @@ public class DashChunkSource implements ChunkSource {
|
|||||||
adaptationSetIndex, representationIndices);
|
adaptationSetIndex, representationIndices);
|
||||||
long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US)
|
long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US)
|
||||||
? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000;
|
? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000;
|
||||||
this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs);
|
// TODO: Remove this and pass proper formats instead (b/22996976).
|
||||||
|
this.mediaFormat = MediaFormat.createFormatForMimeType(representations[0].format.mimeType,
|
||||||
|
periodDurationUs);
|
||||||
|
|
||||||
this.formats = new Format[representations.length];
|
this.formats = new Format[representations.length];
|
||||||
this.representationHolders = new HashMap<>();
|
this.representationHolders = new HashMap<>();
|
||||||
@ -284,15 +285,14 @@ public class DashChunkSource implements ChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void getMaxVideoDimensions(MediaFormat out) {
|
public final MediaFormat getWithMaxVideoDimensions(MediaFormat format) {
|
||||||
if (trackInfo.mimeType.startsWith("video")) {
|
return MimeTypes.isVideo(mediaFormat.mimeType)
|
||||||
out.setMaxVideoDimensions(maxWidth, maxHeight);
|
? format.copyWithMaxVideoDimension(maxWidth, maxHeight) : format;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final TrackInfo getTrackInfo() {
|
public final MediaFormat getFormat() {
|
||||||
return trackInfo;
|
return mediaFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisibleForTesting
|
// VisibleForTesting
|
||||||
|
@ -22,7 +22,6 @@ import com.google.android.exoplayer.ParserException;
|
|||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
|
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData;
|
import com.google.android.exoplayer.drm.DrmInitData;
|
||||||
import com.google.android.exoplayer.upstream.Allocator;
|
import com.google.android.exoplayer.upstream.Allocator;
|
||||||
@ -163,7 +162,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe
|
|||||||
|
|
||||||
private boolean prepared;
|
private boolean prepared;
|
||||||
private int enabledTrackCount;
|
private int enabledTrackCount;
|
||||||
private TrackInfo[] trackInfos;
|
private MediaFormat[] mediaFormats;
|
||||||
private long maxTrackDurationUs;
|
private long maxTrackDurationUs;
|
||||||
private boolean[] pendingMediaFormat;
|
private boolean[] pendingMediaFormat;
|
||||||
private boolean[] pendingDiscontinuities;
|
private boolean[] pendingDiscontinuities;
|
||||||
@ -292,11 +291,11 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe
|
|||||||
trackEnabledStates = new boolean[trackCount];
|
trackEnabledStates = new boolean[trackCount];
|
||||||
pendingDiscontinuities = new boolean[trackCount];
|
pendingDiscontinuities = new boolean[trackCount];
|
||||||
pendingMediaFormat = new boolean[trackCount];
|
pendingMediaFormat = new boolean[trackCount];
|
||||||
trackInfos = new TrackInfo[trackCount];
|
mediaFormats = new MediaFormat[trackCount];
|
||||||
maxTrackDurationUs = C.UNKNOWN_TIME_US;
|
maxTrackDurationUs = C.UNKNOWN_TIME_US;
|
||||||
for (int i = 0; i < trackCount; i++) {
|
for (int i = 0; i < trackCount; i++) {
|
||||||
MediaFormat format = sampleQueues.valueAt(i).getFormat();
|
MediaFormat format = sampleQueues.valueAt(i).getFormat();
|
||||||
trackInfos[i] = new TrackInfo(format.mimeType, format.durationUs);
|
mediaFormats[i] = format;
|
||||||
if (format.durationUs != C.UNKNOWN_TIME_US && format.durationUs > maxTrackDurationUs) {
|
if (format.durationUs != C.UNKNOWN_TIME_US && format.durationUs > maxTrackDurationUs) {
|
||||||
maxTrackDurationUs = format.durationUs;
|
maxTrackDurationUs = format.durationUs;
|
||||||
}
|
}
|
||||||
@ -314,9 +313,9 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo(int track) {
|
public MediaFormat getFormat(int track) {
|
||||||
Assertions.checkState(prepared);
|
Assertions.checkState(prepared);
|
||||||
return trackInfos[track];
|
return mediaFormats[track];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -224,19 +224,17 @@ public class HlsChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adaptive implementations must set the maximum video dimensions on the supplied
|
* Adaptive implementations must return a copy of the provided {@link MediaFormat} with the
|
||||||
* {@link MediaFormat}. Other implementations do nothing.
|
* maximum video dimensions set. Other implementations can return the provided {@link MediaFormat}
|
||||||
* <p>
|
* directly.
|
||||||
* Only called when the source is enabled.
|
|
||||||
*
|
*
|
||||||
* @param out The {@link MediaFormat} on which the maximum video dimensions should be set.
|
* @param format The format to be copied or returned.
|
||||||
|
* @return A copy of the provided {@link MediaFormat} with the maximum video dimensions set, or
|
||||||
|
* the provided format.
|
||||||
*/
|
*/
|
||||||
public void getMaxVideoDimensions(MediaFormat out) {
|
public MediaFormat getMaxVideoDimensions(MediaFormat format) {
|
||||||
if (maxWidth == -1 || maxHeight == -1) {
|
return (maxWidth == -1 || maxHeight == -1) ? format
|
||||||
// Not adaptive.
|
: format.copyWithMaxVideoDimension(maxWidth, maxHeight);
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.setMaxVideoDimensions(maxWidth, maxHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,6 @@ import com.google.android.exoplayer.MediaFormatHolder;
|
|||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
|
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.chunk.BaseChunkSampleSourceEventListener;
|
import com.google.android.exoplayer.chunk.BaseChunkSampleSourceEventListener;
|
||||||
import com.google.android.exoplayer.chunk.Chunk;
|
import com.google.android.exoplayer.chunk.Chunk;
|
||||||
@ -71,7 +70,7 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader,
|
|||||||
private int enabledTrackCount;
|
private int enabledTrackCount;
|
||||||
private boolean[] trackEnabledStates;
|
private boolean[] trackEnabledStates;
|
||||||
private boolean[] pendingDiscontinuities;
|
private boolean[] pendingDiscontinuities;
|
||||||
private TrackInfo[] trackInfos;
|
private MediaFormat[] mediaFormats;
|
||||||
private MediaFormat[] downstreamMediaFormats;
|
private MediaFormat[] downstreamMediaFormats;
|
||||||
private Format downstreamFormat;
|
private Format downstreamFormat;
|
||||||
|
|
||||||
@ -135,10 +134,9 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader,
|
|||||||
trackEnabledStates = new boolean[trackCount];
|
trackEnabledStates = new boolean[trackCount];
|
||||||
pendingDiscontinuities = new boolean[trackCount];
|
pendingDiscontinuities = new boolean[trackCount];
|
||||||
downstreamMediaFormats = new MediaFormat[trackCount];
|
downstreamMediaFormats = new MediaFormat[trackCount];
|
||||||
trackInfos = new TrackInfo[trackCount];
|
mediaFormats = new MediaFormat[trackCount];
|
||||||
for (int i = 0; i < trackCount; i++) {
|
for (int i = 0; i < trackCount; i++) {
|
||||||
MediaFormat format = extractor.getMediaFormat(i);
|
mediaFormats[i] = extractor.getMediaFormat(i);
|
||||||
trackInfos[i] = new TrackInfo(format.mimeType, chunkSource.getDurationUs());
|
|
||||||
}
|
}
|
||||||
prepared = true;
|
prepared = true;
|
||||||
return true;
|
return true;
|
||||||
@ -170,9 +168,9 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackInfo getTrackInfo(int track) {
|
public MediaFormat getFormat(int track) {
|
||||||
Assertions.checkState(prepared);
|
Assertions.checkState(prepared);
|
||||||
return trackInfos[track];
|
return mediaFormats[track];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
package com.google.android.exoplayer.metadata;
|
package com.google.android.exoplayer.metadata;
|
||||||
|
|
||||||
import com.google.android.exoplayer.ExoPlaybackException;
|
import com.google.android.exoplayer.ExoPlaybackException;
|
||||||
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.MediaFormatHolder;
|
import com.google.android.exoplayer.MediaFormatHolder;
|
||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ public final class MetadataTrackRenderer<T> extends SampleSourceTrackRenderer im
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return metadataParser.canParse(trackInfo.mimeType);
|
return metadataParser.canParse(mediaFormat.mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer.smoothstreaming;
|
|||||||
|
|
||||||
import com.google.android.exoplayer.BehindLiveWindowException;
|
import com.google.android.exoplayer.BehindLiveWindowException;
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.chunk.Chunk;
|
import com.google.android.exoplayer.chunk.Chunk;
|
||||||
import com.google.android.exoplayer.chunk.ChunkExtractorWrapper;
|
import com.google.android.exoplayer.chunk.ChunkExtractorWrapper;
|
||||||
import com.google.android.exoplayer.chunk.ChunkOperationHolder;
|
import com.google.android.exoplayer.chunk.ChunkOperationHolder;
|
||||||
@ -59,7 +58,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000;
|
private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000;
|
||||||
private static final int INITIALIZATION_VECTOR_SIZE = 8;
|
private static final int INITIALIZATION_VECTOR_SIZE = 8;
|
||||||
|
|
||||||
private final TrackInfo trackInfo;
|
private final MediaFormat mediaFormat;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final FormatEvaluator formatEvaluator;
|
private final FormatEvaluator formatEvaluator;
|
||||||
private final Evaluation evaluation;
|
private final Evaluation evaluation;
|
||||||
@ -135,7 +134,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000;
|
this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000;
|
||||||
|
|
||||||
StreamElement streamElement = getElement(initialManifest);
|
StreamElement streamElement = getElement(initialManifest);
|
||||||
trackInfo = new TrackInfo(streamElement.tracks[0].format.mimeType, initialManifest.durationUs);
|
// TODO: Remove this and pass proper formats instead (b/22996976).
|
||||||
|
mediaFormat = MediaFormat.createFormatForMimeType(streamElement.tracks[0].format.mimeType,
|
||||||
|
initialManifest.durationUs);
|
||||||
evaluation = new Evaluation();
|
evaluation = new Evaluation();
|
||||||
|
|
||||||
TrackEncryptionBox[] trackEncryptionBoxes = null;
|
TrackEncryptionBox[] trackEncryptionBoxes = null;
|
||||||
@ -180,15 +181,14 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void getMaxVideoDimensions(MediaFormat out) {
|
public final MediaFormat getWithMaxVideoDimensions(MediaFormat format) {
|
||||||
if (trackInfo.mimeType.startsWith("video")) {
|
return MimeTypes.isVideo(mediaFormat.mimeType)
|
||||||
out.setMaxVideoDimensions(maxWidth, maxHeight);
|
? format.copyWithMaxVideoDimension(maxWidth, maxHeight) : format;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final TrackInfo getTrackInfo() {
|
public final MediaFormat getFormat() {
|
||||||
return trackInfo;
|
return mediaFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -384,7 +384,6 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||||||
if (streamElement.type == StreamElement.TYPE_VIDEO) {
|
if (streamElement.type == StreamElement.TYPE_VIDEO) {
|
||||||
MediaFormat format = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE,
|
MediaFormat format = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE,
|
||||||
trackFormat.width, trackFormat.height, Arrays.asList(trackElement.csd));
|
trackFormat.width, trackFormat.height, Arrays.asList(trackElement.csd));
|
||||||
format.setMaxVideoDimensions(streamElement.maxWidth, streamElement.maxHeight);
|
|
||||||
return format;
|
return format;
|
||||||
} else if (streamElement.type == StreamElement.TYPE_AUDIO) {
|
} else if (streamElement.type == StreamElement.TYPE_AUDIO) {
|
||||||
List<byte[]> csd;
|
List<byte[]> csd;
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
package com.google.android.exoplayer.text;
|
package com.google.android.exoplayer.text;
|
||||||
|
|
||||||
import com.google.android.exoplayer.ExoPlaybackException;
|
import com.google.android.exoplayer.ExoPlaybackException;
|
||||||
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.MediaFormatHolder;
|
import com.google.android.exoplayer.MediaFormatHolder;
|
||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
|
|
||||||
@ -150,15 +150,15 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return getParserIndex(trackInfo) != -1;
|
return getParserIndex(mediaFormat) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onEnabled(int track, long positionUs, boolean joining)
|
protected void onEnabled(int track, long positionUs, boolean joining)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
super.onEnabled(track, positionUs, joining);
|
super.onEnabled(track, positionUs, joining);
|
||||||
parserIndex = getParserIndex(getTrackInfo(track));
|
parserIndex = getParserIndex(getFormat(track));
|
||||||
parserThread = new HandlerThread("textParser");
|
parserThread = new HandlerThread("textParser");
|
||||||
parserThread.start();
|
parserThread.start();
|
||||||
parserHelper = new SubtitleParserHelper(parserThread.getLooper(), subtitleParsers[parserIndex]);
|
parserHelper = new SubtitleParserHelper(parserThread.getLooper(), subtitleParsers[parserIndex]);
|
||||||
@ -296,9 +296,9 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement
|
|||||||
textRenderer.onCues(cues);
|
textRenderer.onCues(cues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getParserIndex(TrackInfo trackInfo) {
|
private int getParserIndex(MediaFormat mediaFormat) {
|
||||||
for (int i = 0; i < subtitleParsers.length; i++) {
|
for (int i = 0; i < subtitleParsers.length; i++) {
|
||||||
if (subtitleParsers[i].canParse(trackInfo.mimeType)) {
|
if (subtitleParsers[i].canParse(mediaFormat.mimeType)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ package com.google.android.exoplayer.text.eia608;
|
|||||||
|
|
||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.ExoPlaybackException;
|
import com.google.android.exoplayer.ExoPlaybackException;
|
||||||
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.MediaFormatHolder;
|
import com.google.android.exoplayer.MediaFormatHolder;
|
||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
import com.google.android.exoplayer.SampleSourceTrackRenderer;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
import com.google.android.exoplayer.text.Cue;
|
import com.google.android.exoplayer.text.Cue;
|
||||||
import com.google.android.exoplayer.text.TextRenderer;
|
import com.google.android.exoplayer.text.TextRenderer;
|
||||||
@ -89,8 +89,8 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handlesTrack(TrackInfo trackInfo) {
|
protected boolean handlesTrack(MediaFormat mediaFormat) {
|
||||||
return eia608Parser.canParse(trackInfo.mimeType);
|
return eia608Parser.canParse(mediaFormat.mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user