mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 16:25:38 +00:00
Bug 1628792 - p2: update GeckoHls* for API changes in exoplayer. r=agi,geckoview-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D78390
This commit is contained in:
parent
68b7382249
commit
b6a091d9dd
@ -23,6 +23,7 @@ import org.mozilla.thirdparty.com.google.android.exoplayer2.mediacodec.MediaCode
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.util.MimeTypes;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
public class GeckoHlsAudioRenderer extends GeckoHlsRendererBase {
|
||||
public GeckoHlsAudioRenderer(final GeckoHlsPlayer.ComponentEventDispatcher eventDispatcher) {
|
||||
@ -55,18 +56,19 @@ public class GeckoHlsAudioRenderer extends GeckoHlsRendererBase {
|
||||
*/
|
||||
String mimeType = format.sampleMimeType;
|
||||
if (!MimeTypes.isAudio(mimeType)) {
|
||||
return RendererCapabilities.FORMAT_UNSUPPORTED_TYPE;
|
||||
return RendererCapabilities.create(FORMAT_UNSUPPORTED_TYPE);
|
||||
}
|
||||
MediaCodecInfo decoderInfo = null;
|
||||
List<MediaCodecInfo> decoderInfos = null;
|
||||
try {
|
||||
MediaCodecSelector mediaCodecSelector = MediaCodecSelector.DEFAULT;
|
||||
decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false);
|
||||
decoderInfos = mediaCodecSelector.getDecoderInfos(mimeType, false, false);
|
||||
} catch (MediaCodecUtil.DecoderQueryException e) {
|
||||
Log.e(LOGTAG, e.getMessage());
|
||||
}
|
||||
if (decoderInfo == null) {
|
||||
return RendererCapabilities.FORMAT_UNSUPPORTED_SUBTYPE;
|
||||
if (decoderInfos == null || decoderInfos.isEmpty()) {
|
||||
return RendererCapabilities.create(FORMAT_UNSUPPORTED_SUBTYPE);
|
||||
}
|
||||
MediaCodecInfo info = decoderInfos.get(0);
|
||||
/*
|
||||
* Note : If the code can make it to this place, ExoPlayer assumes
|
||||
* support for unknown sampleRate and channelCount when
|
||||
@ -75,13 +77,13 @@ public class GeckoHlsAudioRenderer extends GeckoHlsRendererBase {
|
||||
*/
|
||||
boolean decoderCapable = (Build.VERSION.SDK_INT < 21) ||
|
||||
((format.sampleRate == Format.NO_VALUE ||
|
||||
decoderInfo.isAudioSampleRateSupportedV21(format.sampleRate)) &&
|
||||
info.isAudioSampleRateSupportedV21(format.sampleRate)) &&
|
||||
(format.channelCount == Format.NO_VALUE ||
|
||||
decoderInfo.isAudioChannelCountSupportedV21(format.channelCount)));
|
||||
int formatSupport = decoderCapable ?
|
||||
RendererCapabilities.FORMAT_HANDLED :
|
||||
RendererCapabilities.FORMAT_EXCEEDS_CAPABILITIES;
|
||||
return RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | formatSupport;
|
||||
info.isAudioChannelCountSupportedV21(format.channelCount)));
|
||||
return RendererCapabilities.create(
|
||||
decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES,
|
||||
ADAPTIVE_NOT_SEAMLESS,
|
||||
TUNNELING_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,13 +14,12 @@ import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.DefaultLoadControl;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.ExoPlayer;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.Format;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.PlaybackParameters;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.RendererCapabilities;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.Timeline;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.source.MediaSource;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.source.MediaSourceEventListener;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.source.TrackGroup;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
||||
@ -29,8 +28,6 @@ import org.mozilla.thirdparty.com.google.android.exoplayer2.trackselection.Defau
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DataSource;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DefaultAllocator;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
@ -44,14 +41,13 @@ import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.annotation.ReflectionTarget;
|
||||
import org.mozilla.geckoview.BuildConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ReflectionTarget
|
||||
public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
private static final String LOGTAG = "GeckoHlsPlayer";
|
||||
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
|
||||
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter.Builder(null).build();
|
||||
private static final int MAX_TIMELINE_ITEM_LINES = 3;
|
||||
private static final boolean DEBUG = !BuildConfig.MOZILLA_OFFICIAL;
|
||||
|
||||
@ -78,7 +74,6 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
// Default value is PLAY_STATE_PREPARING and it will be set to PLAY_STATE_PLAYING
|
||||
// once HTMLMediaElement calls PlayInternal().
|
||||
private MediaDecoderPlayState mMediaDecoderPlayState = MediaDecoderPlayState.PLAY_STATE_PREPARING;
|
||||
private DataSource.Factory mMediaDataSourceFactory;
|
||||
|
||||
private Handler mMainHandler;
|
||||
private HandlerThread mThread;
|
||||
@ -202,77 +197,28 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
private final class SourceEventListener implements AdaptiveMediaSourceEventListener {
|
||||
public void onLoadStarted(final DataSpec dataSpec,
|
||||
final int dataType,
|
||||
final int trackType,
|
||||
final Format trackFormat,
|
||||
final int trackSelectionReason,
|
||||
final Object trackSelectionData,
|
||||
final long mediaStartTimeMs,
|
||||
final long mediaEndTimeMs,
|
||||
final long elapsedRealtimeMs) {
|
||||
private final class SourceEventListener implements MediaSourceEventListener {
|
||||
public void onLoadStarted(
|
||||
final int windowIndex,
|
||||
final MediaSource.MediaPeriodId mediaPeriodId,
|
||||
final LoadEventInfo loadEventInfo,
|
||||
final MediaLoadData mediaLoadData) {
|
||||
if (mediaLoadData.dataType != C.DATA_TYPE_MEDIA) {
|
||||
// Don't report non-media URLs.
|
||||
return;
|
||||
}
|
||||
if (mMainHandler != null && mResourceCallbacks != null) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "[SourceEvent] load-started: url=" + dataSpec.uri + " track=" + trackType + " format=" + trackFormat);
|
||||
Log.d(LOGTAG, "on-load: url=" + loadEventInfo.uri);
|
||||
}
|
||||
mResourceCallbacks.onLoad(dataSpec.uri.toString());
|
||||
mResourceCallbacks.onLoad(loadEventInfo.uri.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// Not interested in the following events.
|
||||
public void onLoadCompleted(final DataSpec dataSpec,
|
||||
final int dataType,
|
||||
final int trackType,
|
||||
final Format trackFormat,
|
||||
final int trackSelectionReason,
|
||||
final Object trackSelectionData,
|
||||
final long mediaStartTimeMs,
|
||||
final long mediaEndTimeMs,
|
||||
final long elapsedRealtimeMs,
|
||||
final long loadDurationMs,
|
||||
final long bytesLoaded) {
|
||||
}
|
||||
public void onLoadCanceled(final DataSpec dataSpec,
|
||||
final int dataType,
|
||||
final int trackType,
|
||||
final Format trackFormat,
|
||||
final int trackSelectionReason,
|
||||
final Object trackSelectionData,
|
||||
final long mediaStartTimeMs,
|
||||
final long mediaEndTimeMs,
|
||||
final long elapsedRealtimeMs,
|
||||
final long loadDurationMs,
|
||||
final long bytesLoaded) {
|
||||
}
|
||||
public void onLoadError(final DataSpec dataSpec,
|
||||
final int dataType,
|
||||
final int trackType,
|
||||
final Format trackFormat,
|
||||
final int trackSelectionReason,
|
||||
final Object trackSelectionData,
|
||||
final long mediaStartTimeMs,
|
||||
final long mediaEndTimeMs,
|
||||
final long elapsedRealtimeMs,
|
||||
final long loadDurationMs,
|
||||
final long bytesLoaded,
|
||||
final IOException error,
|
||||
final boolean wasCanceled) {
|
||||
}
|
||||
public void onUpstreamDiscarded(final int trackType,
|
||||
final long mediaStartTimeMs,
|
||||
final long mediaEndTimeMs) {
|
||||
}
|
||||
public void onDownstreamFormatChanged(final int trackType,
|
||||
final Format trackFormat,
|
||||
final int trackSelectionReason,
|
||||
final Object trackSelectionData,
|
||||
final long mediaTimeMs) {
|
||||
}
|
||||
}
|
||||
|
||||
public final class ComponentEventDispatcher {
|
||||
@ -372,10 +318,10 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
private DataSource.Factory buildDataSourceFactory(final Context ctx,
|
||||
private HlsMediaSource.Factory buildDataSourceFactory(final Context ctx,
|
||||
final DefaultBandwidthMeter bandwidthMeter) {
|
||||
return new DefaultDataSourceFactory(ctx, bandwidthMeter,
|
||||
buildHttpDataSourceFactory(bandwidthMeter));
|
||||
return new HlsMediaSource.Factory(new DefaultDataSourceFactory(ctx, bandwidthMeter,
|
||||
buildHttpDataSourceFactory(bandwidthMeter)));
|
||||
}
|
||||
|
||||
private HttpDataSource.Factory buildHttpDataSourceFactory(
|
||||
@ -459,9 +405,9 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
|
||||
// Called on GeckoHlsPlayerThread from ExoPlayer
|
||||
@Override
|
||||
public void onPositionDiscontinuity() {
|
||||
public void onPositionDiscontinuity(final int reason) {
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "positionDiscontinuity");
|
||||
Log.d(LOGTAG, "positionDiscontinuity: reason=" + reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -572,7 +518,7 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
|
||||
// Called on GeckoHlsPlayerThread from ExoPlayer
|
||||
@Override
|
||||
public synchronized void onTimelineChanged(final Timeline timeline, final Object manifest) {
|
||||
public synchronized void onTimelineChanged(final Timeline timeline, final int reason) {
|
||||
// For now, we use the interface ExoPlayer.getDuration() for gecko,
|
||||
// so here we create local variable 'window' & 'peroid' to obtain
|
||||
// the dynamic duration.
|
||||
@ -685,21 +631,24 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||
mRenderers[0] = mVRenderer;
|
||||
mRenderers[1] = mARenderer;
|
||||
|
||||
DefaultLoadControl dlc =
|
||||
new DefaultLoadControl(
|
||||
new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
|
||||
DEFAULT_MIN_BUFFER_MS,
|
||||
DEFAULT_MAX_BUFFER_MS,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
|
||||
DefaultLoadControl dlc = new DefaultLoadControl.Builder()
|
||||
.setAllocator(new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE))
|
||||
.setBufferDurationsMs(DEFAULT_MIN_BUFFER_MS,
|
||||
DEFAULT_MAX_BUFFER_MS,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
||||
.createDefaultLoadControl();
|
||||
// Create ExoPlayer instance with specific components.
|
||||
mPlayer = ExoPlayerFactory.newInstance(mRenderers, mTrackSelector, dlc);
|
||||
mPlayer = new ExoPlayer.Builder(ctx, mRenderers)
|
||||
.setTrackSelector(mTrackSelector)
|
||||
.setLoadControl(dlc)
|
||||
.build();
|
||||
mPlayer.addListener(this);
|
||||
|
||||
Uri uri = Uri.parse(url);
|
||||
mMediaDataSourceFactory = buildDataSourceFactory(ctx, BANDWIDTH_METER);
|
||||
mMediaSource = buildDataSourceFactory(ctx, BANDWIDTH_METER).createMediaSource(uri);
|
||||
mSourceEventListener = new SourceEventListener();
|
||||
mMediaSource = new HlsMediaSource(uri, mMediaDataSourceFactory, mMainHandler, mSourceEventListener);
|
||||
mMediaSource.addEventListener(mMainHandler, mSourceEventListener);
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "Uri is " + uri +
|
||||
", ContentType is " + Util.inferContentType(uri.getLastPathSegment()));
|
||||
|
@ -14,6 +14,7 @@ import org.mozilla.thirdparty.com.google.android.exoplayer2.decoder.DecoderInput
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.Format;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.FormatHolder;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.RendererCapabilities;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
@ -191,7 +192,10 @@ public abstract class GeckoHlsRendererBase extends BaseRenderer {
|
||||
createInputBuffer();
|
||||
mInitialized = true;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw ExoPlaybackException.createForRenderer(new RuntimeException(e), getIndex());
|
||||
throw ExoPlaybackException.createForRenderer(new RuntimeException(e),
|
||||
getIndex(),
|
||||
mFormats.isEmpty() ? null : getFormat(mFormats.size() - 1),
|
||||
RendererCapabilities.FORMAT_HANDLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ import org.mozilla.thirdparty.com.google.android.exoplayer2.RendererCapabilities
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.util.MimeTypes;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class GeckoHlsVideoRenderer extends GeckoHlsRendererBase {
|
||||
@ -89,21 +90,28 @@ public class GeckoHlsVideoRenderer extends GeckoHlsRendererBase {
|
||||
*/
|
||||
final String mimeType = format.sampleMimeType;
|
||||
if (!MimeTypes.isVideo(mimeType)) {
|
||||
return RendererCapabilities.FORMAT_UNSUPPORTED_TYPE;
|
||||
return RendererCapabilities.create(FORMAT_UNSUPPORTED_TYPE);
|
||||
}
|
||||
|
||||
MediaCodecInfo decoderInfo = null;
|
||||
List<MediaCodecInfo> decoderInfos = null;
|
||||
try {
|
||||
MediaCodecSelector mediaCodecSelector = MediaCodecSelector.DEFAULT;
|
||||
decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false);
|
||||
decoderInfos = mediaCodecSelector.getDecoderInfos(mimeType, false, false);
|
||||
} catch (MediaCodecUtil.DecoderQueryException e) {
|
||||
Log.e(LOGTAG, e.getMessage());
|
||||
}
|
||||
if (decoderInfo == null) {
|
||||
return RendererCapabilities.FORMAT_UNSUPPORTED_SUBTYPE;
|
||||
if (decoderInfos == null || decoderInfos.isEmpty()) {
|
||||
return RendererCapabilities.create(FORMAT_UNSUPPORTED_SUBTYPE);
|
||||
}
|
||||
|
||||
boolean decoderCapable = decoderInfo.isCodecSupported(format.codecs);
|
||||
boolean decoderCapable = false;
|
||||
MediaCodecInfo info = null;
|
||||
for (MediaCodecInfo i : decoderInfos) {
|
||||
if (i.isCodecSupported(format)) {
|
||||
decoderCapable = true;
|
||||
info = i;
|
||||
}
|
||||
}
|
||||
if (decoderCapable && format.width > 0 && format.height > 0) {
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
try {
|
||||
@ -118,20 +126,16 @@ public class GeckoHlsVideoRenderer extends GeckoHlsRendererBase {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
decoderCapable =
|
||||
decoderInfo.isVideoSizeAndRateSupportedV21(format.width,
|
||||
format.height,
|
||||
format.frameRate);
|
||||
decoderCapable = info.isVideoSizeAndRateSupportedV21(format.width,
|
||||
format.height,
|
||||
format.frameRate);
|
||||
}
|
||||
}
|
||||
|
||||
int adaptiveSupport = decoderInfo.adaptive ?
|
||||
RendererCapabilities.ADAPTIVE_SEAMLESS :
|
||||
RendererCapabilities.ADAPTIVE_NOT_SEAMLESS;
|
||||
int formatSupport = decoderCapable ?
|
||||
RendererCapabilities.FORMAT_HANDLED :
|
||||
RendererCapabilities.FORMAT_EXCEEDS_CAPABILITIES;
|
||||
return adaptiveSupport | formatSupport;
|
||||
return RendererCapabilities.create(
|
||||
decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES,
|
||||
info != null && info.adaptive ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS,
|
||||
TUNNELING_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,7 +153,10 @@ public class GeckoHlsVideoRenderer extends GeckoHlsRendererBase {
|
||||
mInputBuffer = ByteBuffer.wrap(new byte[mCodecMaxValues.inputSize]);
|
||||
} catch (OutOfMemoryError e) {
|
||||
Log.e(LOGTAG, "cannot allocate input buffer of size " + mCodecMaxValues.inputSize, e);
|
||||
throw ExoPlaybackException.createForRenderer(new Exception(e), getIndex());
|
||||
throw ExoPlaybackException.createForRenderer(new Exception(e),
|
||||
getIndex(),
|
||||
mFormats.isEmpty() ? null : getFormat(mFormats.size() - 1),
|
||||
RendererCapabilities.FORMAT_HANDLED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,7 +436,7 @@ public class GeckoHlsVideoRenderer extends GeckoHlsRendererBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStreamChanged(final Format[] formats) {
|
||||
protected void onStreamChanged(final Format[] formats, final long offsetUs) {
|
||||
mStreamFormats = formats;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user