/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link DemoPlayer} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding * type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be * null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.audioRenderer = renderers[TYPE_AUDIO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link VideoPlayer} TYPE_* constants. An * individual element may be null if there do not exist tracks of the * corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be * null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {link RendererBuilder}. * * @param renderers Renderers indexed by {link DemoPlayer} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link ExoPlayerHelper} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link DemoPlayer} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
private int getVariantIndexForBandwidth(long bitrateEstimate) { if (bitrateEstimate == BandwidthMeter.NO_ESTIMATE) { // Select the lowest quality. bitrateEstimate = 0; } int effectiveBitrate = (int) (bitrateEstimate * BANDWIDTH_FRACTION); int lowestQualityEnabledVariantIndex = -1; for (int i = 0; i < variants.length; i++) { if (variantBlacklistTimes[i] == 0) { if (variants[i].format.bitrate <= effectiveBitrate) { return i; } lowestQualityEnabledVariantIndex = i; } } // At least one variant should always be enabled. Assertions.checkState(lowestQualityEnabledVariantIndex != -1); return lowestQualityEnabledVariantIndex; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link Player} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link DemoPlayer} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding * type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
public void onRenderers(TrackRenderer[] renderers, @Nullable BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[RENDER_VIDEO]; this.audioRenderer = renderers[RENDER_AUDIO]; pushSurface(false); player.prepare(renderers); rendererBuildingState = RenderBuildingState.BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link ExoPlayerWrapper} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ protected void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.audioRenderer = renderers[TYPE_AUDIO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link FlyingPlayer} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link DemoPlayer} TYPE_* constants. An individual * element may be null if there do not exist tracks of the corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ /* package */ void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.audioRenderer = renderers[TYPE_AUDIO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; this.bandwidthMeter = bandwidthMeter; pushSurface(false); player.prepare(renderers); rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
public void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { //如果没有注入视频音频渲染器,则放入虚拟的渲染器(无作用) renderers[i] = new DummyTrackRenderer(); } } // 播放器准备完成 this.videoRenderer = renderers[TYPE_VIDEO]; this.audioRenderer = renderers[TYPE_AUDIO]; pushSurface(false); //注入渲染器 player.prepare(renderers); //改变渲染器状态 rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; }
/** * Invoked with the results from a {@link RendererBuilder}. * * @param renderers Renderers indexed by {@link ExoplayerWrapper} TYPE_* constants. An * individual element may be null if there do not exist tracks of the * corresponding type. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. May be null. */ public void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { // Normalize the results. if (trackNames == null) { trackNames = new String[RENDERER_COUNT][]; } for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; this.codecCounters = videoRenderer instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) videoRenderer).codecCounters : renderers[TYPE_AUDIO] instanceof MediaCodecTrackRenderer ? ((MediaCodecTrackRenderer) renderers[TYPE_AUDIO]).codecCounters : null; rendererBuildingState = RENDERER_BUILDING_STATE_BUILT; this.bandwidthMeter = bandwidthMeter; maybeReportPlayerState(); pushSurfaceAndVideoTrack(false); player.prepare(renderers); }
public void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < renderers.length; i++) { if (renderers[i] == null) { renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; pushSurface(false); player.prepare(renderers); player.setPlayWhenReady(true); }
public void onRenderers(TrackRenderer[] renderers, BandwidthMeter bandwidthMeter) { for (int i = 0; i < RENDERER_COUNT; i++) { if (renderers[i] == null) { Log.e(TAG, "onRenderers dummy " + i); // Convert a null renderer to a dummy renderer. renderers[i] = new DummyTrackRenderer(); } } // Complete preparation. this.videoRenderer = renderers[TYPE_VIDEO]; pushSurface(false); player.prepare(renderers); }
public HlsChunkSource(DataSource dataSource, String playlistUrl, HlsPlaylist playlist, BandwidthMeter bandwidthMeter, int[] variantIndices, int adaptiveMode, AudioCapabilities audioCapabilities) { this(dataSource, playlistUrl, playlist, bandwidthMeter, variantIndices, adaptiveMode, DEFAULT_MIN_BUFFER_TO_SWITCH_UP_MS, DEFAULT_MAX_BUFFER_TO_SWITCH_DOWN_MS, audioCapabilities); }
private int getNextVariantIndex(TsChunk previousTsChunk, long playbackPositionUs) { clearStaleBlacklistedVariants(); long bitrateEstimate = bandwidthMeter.getBitrateEstimate(); if (variantBlacklistTimes[selectedVariantIndex] != 0) { // The current variant has been blacklisted, so we have no choice but to re-evaluate. return getVariantIndexForBandwidth(bitrateEstimate); } if (previousTsChunk == null) { // Don't consider switching if we don't have a previous chunk. return selectedVariantIndex; } if (bitrateEstimate == BandwidthMeter.NO_ESTIMATE) { // Don't consider switching if we don't have a bandwidth estimate. return selectedVariantIndex; } int idealIndex = getVariantIndexForBandwidth(bitrateEstimate); if (idealIndex == selectedVariantIndex) { // We're already using the ideal variant. return selectedVariantIndex; } // We're not using the ideal variant for the available bandwidth, but only switch if the // conditions are appropriate. long bufferedPositionUs = adaptiveMode == ADAPTIVE_MODE_SPLICE ? previousTsChunk.startTimeUs : previousTsChunk.endTimeUs; long bufferedUs = bufferedPositionUs - playbackPositionUs; if (variantBlacklistTimes[selectedVariantIndex] != 0 || (idealIndex > selectedVariantIndex && bufferedUs < maxBufferDurationToSwitchDownUs) || (idealIndex < selectedVariantIndex && bufferedUs > minBufferDurationToSwitchUpUs)) { // Switch variant. return idealIndex; } // Stick with the current variant for now. return selectedVariantIndex; }
/** * @param bandwidthMeter Provides an estimate of the currently available bandwidth. */ public AdaptiveEvaluator(BandwidthMeter bandwidthMeter) { this (bandwidthMeter, DEFAULT_MAX_INITIAL_BITRATE, DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, DEFAULT_BANDWIDTH_FRACTION); }
/** * Compute the ideal format ignoring buffer health. */ private Format determineIdealFormat(Format[] formats, long bitrateEstimate) { long effectiveBitrate = bitrateEstimate == BandwidthMeter.NO_ESTIMATE ? maxInitialBitrate : (long) (bitrateEstimate * bandwidthFraction); for (int i = 0; i < formats.length; i++) { Format format = formats[i]; if (format.bitrate <= effectiveBitrate) { return format; } } // We didn't manage to calculate a suitable format. Return the lowest quality format. return formats[formats.length - 1]; }
private String getBandwidthString() { BandwidthMeter bandwidthMeter = debuggable.getBandwidthMeter(); if (bandwidthMeter == null || bandwidthMeter.getBitrateEstimate() == BandwidthMeter.NO_ESTIMATE) { return "bw:?"; } else { return "bw:" + (bandwidthMeter.getBitrateEstimate() / 1000); } }
/** * @param isMaster True if this is the master source for the playback. False otherwise. Each * playback must have exactly one master source, which should be the source providing video * chunks (or audio chunks for audio only playbacks). * @param dataSource A {@link DataSource} suitable for loading the media data. * @param playlist The HLS playlist. * @param trackSelector Selects tracks to be exposed by this source. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. * @param timestampAdjusterProvider A provider of {@link PtsTimestampAdjuster} instances. If * multiple {@link HlsChunkSource}s are used for a single playback, they should all share the * same provider. * @param adaptiveMode The mode for switching from one variant to another. One of * {@link #ADAPTIVE_MODE_NONE}, {@link #ADAPTIVE_MODE_ABRUPT} and * {@link #ADAPTIVE_MODE_SPLICE}. * @param minBufferDurationToSwitchUpMs The minimum duration of media that needs to be buffered * for a switch to a higher quality variant to be considered. * @param maxBufferDurationToSwitchDownMs The maximum duration of media that needs to be buffered * for a switch to a lower quality variant to be considered. * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. */ public HlsChunkSource(boolean isMaster, DataSource dataSource, HlsPlaylist playlist, HlsTrackSelector trackSelector, BandwidthMeter bandwidthMeter, PtsTimestampAdjusterProvider timestampAdjusterProvider, int adaptiveMode, long minBufferDurationToSwitchUpMs, long maxBufferDurationToSwitchDownMs, Handler eventHandler, EventListener eventListener) { this.isMaster = isMaster; this.dataSource = dataSource; this.trackSelector = trackSelector; this.bandwidthMeter = bandwidthMeter; this.timestampAdjusterProvider = timestampAdjusterProvider; this.adaptiveMode = adaptiveMode; this.eventListener = eventListener; this.eventHandler = eventHandler; minBufferDurationToSwitchUpUs = minBufferDurationToSwitchUpMs * 1000; maxBufferDurationToSwitchDownUs = maxBufferDurationToSwitchDownMs * 1000; baseUri = playlist.baseUri; playlistParser = new HlsPlaylistParser(); tracks = new ArrayList<>(); if (playlist.type == HlsPlaylist.TYPE_MASTER) { masterPlaylist = (HlsMasterPlaylist) playlist; } else { Format format = new Format("0", MimeTypes.APPLICATION_M3U8, -1, -1, -1, -1, -1, -1, null, null); List<Variant> variants = new ArrayList<>(); variants.add(new Variant(baseUri, format)); masterPlaylist = new HlsMasterPlaylist(baseUri, variants, Collections.<Variant>emptyList(), Collections.<Variant>emptyList(), null, null); } }
protected int computeDefaultVariantIndex(HlsMasterPlaylist playlist, Variant[] variants, BandwidthMeter bandwidthMeter) { int defaultVariantIndex = 0; int minOriginalVariantIndex = Integer.MAX_VALUE; for (int i = 0; i < variants.length; i++) { int originalVariantIndex = playlist.variants.indexOf(variants[i]); if (originalVariantIndex < minOriginalVariantIndex) { minOriginalVariantIndex = originalVariantIndex; defaultVariantIndex = i; } } return defaultVariantIndex; }