-1

我试图用 ExoPlayer2.x 制作一个流媒体应用程序。现在我陷入了一个问题。我正在尝试制作一个Bitrate Changer. 我不想使用TrackSelector. 我只想使用一种方法来更改Bitrate单个视频以在低速连接时使用。

用户可以bitrate从对话框中手动选择

我的竞争对手已经做到了这一点。所以请大家有什么想法和我分享。示例代码赞赏

我已经尝试过使用它,但问题是这在2.x 版本中不起作用

player.prepare(mediaSource, !haveResumePosition, false);
    trackSelector.setParameters(trackSelector.getParameters()
            .withMaxVideoBitrate(bitrate)
            .withMaxVideoSize(width, height));

提前致谢 !

4

2 回答 2

0

要将所需的比特率设置为 exoplayer,您需要实现自定义 TrackSelector检查此以获取更多详细信息

于 2018-04-06T12:07:59.533 回答
0

你可以覆盖BaseTrackSelection,有功能determineIdealSelectedIndex,这是你需要的。

这是我为我的项目制作的方法:

public enum HLSQuality {
    Auto, Quality1080, Quality720, Quality480, NoValue
}

public class ClassAdaptiveTrackSelection extends BaseTrackSelection {

    public static final class Factory implements TrackSelection.Factory {
        private final BandwidthMeter bandwidthMeter;
        private final int maxInitialBitrate = 2000000;
        private final int minDurationForQualityIncreaseMs = 10000;
        private final int maxDurationForQualityDecreaseMs = 25000;
        private final int minDurationToRetainAfterDiscardMs = 25000;
        private final float bandwidthFraction = 0.75f;
        private final float bufferedFractionToLiveEdgeForQualityIncrease = 0.75f;

        public Factory(BandwidthMeter bandwidthMeter) {
            this.bandwidthMeter = bandwidthMeter;
        }

        @Override
        public ClassAdaptiveTrackSelection createTrackSelection(TrackGroup group, int... tracks) {
            Log.d(ClassAdaptiveTrackSelection.class.getSimpleName(), " Video player quality reset to Auto");
            sHLSQuality = HLSQuality.Auto;

            return new ClassAdaptiveTrackSelection(
                    group,
                    tracks,
                    bandwidthMeter,
                    maxInitialBitrate,
                    minDurationForQualityIncreaseMs,
                    maxDurationForQualityDecreaseMs,
                    minDurationToRetainAfterDiscardMs,
                    bandwidthFraction,
                    bufferedFractionToLiveEdgeForQualityIncrease
            );
        }
    }

    private static HLSQuality sHLSQuality = HLSQuality.Auto;
    private final BandwidthMeter bandwidthMeter;
    private final int maxInitialBitrate;
    private final long minDurationForQualityIncreaseUs;
    private final long maxDurationForQualityDecreaseUs;
    private final long minDurationToRetainAfterDiscardUs;
    private final float bandwidthFraction;
    private final float bufferedFractionToLiveEdgeForQualityIncrease;

    private int selectedIndex;
    private int reason;

    private ClassAdaptiveTrackSelection(TrackGroup group,
                                        int[] tracks,
                                        BandwidthMeter bandwidthMeter,
                                        int maxInitialBitrate,
                                        long minDurationForQualityIncreaseMs,
                                        long maxDurationForQualityDecreaseMs,
                                        long minDurationToRetainAfterDiscardMs,
                                        float bandwidthFraction,
                                        float bufferedFractionToLiveEdgeForQualityIncrease) {
        super(group, tracks);
        this.bandwidthMeter = bandwidthMeter;
        this.maxInitialBitrate = maxInitialBitrate;
        this.minDurationForQualityIncreaseUs = minDurationForQualityIncreaseMs * 1000L;
        this.maxDurationForQualityDecreaseUs = maxDurationForQualityDecreaseMs * 1000L;
        this.minDurationToRetainAfterDiscardUs = minDurationToRetainAfterDiscardMs * 1000L;
        this.bandwidthFraction = bandwidthFraction;
        this.bufferedFractionToLiveEdgeForQualityIncrease = bufferedFractionToLiveEdgeForQualityIncrease;
        selectedIndex = determineIdealSelectedIndex(Long.MIN_VALUE);
        reason = C.SELECTION_REASON_INITIAL;
    }

    @Override
    public void updateSelectedTrack(long playbackPositionUs, long bufferedDurationUs, long availableDurationUs) {
        long nowMs = SystemClock.elapsedRealtime();
        // Stash the current selection, then make a new one.
        int currentSelectedIndex = selectedIndex;
        selectedIndex = determineIdealSelectedIndex(nowMs);
        if (selectedIndex == currentSelectedIndex) {
            return;
        }

        if (!isBlacklisted(currentSelectedIndex, nowMs)) {
            // Revert back to the current selection if conditions are not suitable for switching.
            Format currentFormat = getFormat(currentSelectedIndex);
            Format selectedFormat = getFormat(selectedIndex);
            if (selectedFormat.bitrate > currentFormat.bitrate
                    && bufferedDurationUs < minDurationForQualityIncreaseUs(availableDurationUs)) {
                // The selected track is a higher quality, but we have insufficient buffer to safely switch
                // up. Defer switching up for now.
                selectedIndex = currentSelectedIndex;
            } else if (selectedFormat.bitrate < currentFormat.bitrate
                    && bufferedDurationUs >= maxDurationForQualityDecreaseUs) {
                // The selected track is a lower quality, but we have sufficient buffer to defer switching
                // down for now.
                selectedIndex = currentSelectedIndex;
            }
        }
        // If we adapted, update the trigger.
        if (selectedIndex != currentSelectedIndex) {
            reason = C.SELECTION_REASON_ADAPTIVE;
        }
    }

    @Override
    public int getSelectedIndex() {
        return selectedIndex;
    }

    @Override
    public int getSelectionReason() {
        return reason;
    }

    @Override
    public Object getSelectionData() {
        return null;
    }

    @Override
    public int evaluateQueueSize(long playbackPositionUs, List<? extends MediaChunk> queue) {
        if (queue.isEmpty()) {
            return 0;
        }
        int queueSize = queue.size();
        long bufferedDurationUs = queue.get(queueSize - 1).endTimeUs - playbackPositionUs;
        if (bufferedDurationUs < minDurationToRetainAfterDiscardUs) {
            return queueSize;
        }
        int idealSelectedIndex = determineIdealSelectedIndex(SystemClock.elapsedRealtime());
        Format idealFormat = getFormat(idealSelectedIndex);
        // If the chunks contain video, discard from the first SD chunk beyond
        // minDurationToRetainAfterDiscardUs whose resolution and bitrate are both lower than the ideal
        // track.
        for (int i = 0; i < queueSize; i++) {
            MediaChunk chunk = queue.get(i);
            Format format = chunk.trackFormat;
            long durationBeforeThisChunkUs = chunk.startTimeUs - playbackPositionUs;
            if (durationBeforeThisChunkUs >= minDurationToRetainAfterDiscardUs
                    && format.bitrate < idealFormat.bitrate
                    && format.height != Format.NO_VALUE && format.height < 720
                    && format.width != Format.NO_VALUE && format.width < 1280
                    && format.height < idealFormat.height) {
                return i;
            }
        }
        return queueSize;
    }

    private int determineIdealSelectedIndex(long nowMs) {
        if (sHLSQuality != HLSQuality.Auto) {
            Log.d(ClassAdaptiveTrackSelection.class.getSimpleName(), " Video player quality seeking for " + String.valueOf(sHLSQuality));
            for (int i = 0; i < length; i++) {
                Format format = getFormat(i);
                if (HLSUtil.getQuality(format) == sHLSQuality) {
                    Log.d(ClassAdaptiveTrackSelection.class.getSimpleName(), " Video player quality set to " + String.valueOf(sHLSQuality));
                    return i;
                }
            }
        }

        Log.d(ClassAdaptiveTrackSelection.class.getSimpleName(), " Video player quality seeking for auto quality " + String.valueOf(sHLSQuality));
        long bitrateEstimate = bandwidthMeter.getBitrateEstimate();
        long effectiveBitrate = bitrateEstimate == BandwidthMeter.NO_ESTIMATE
                ? maxInitialBitrate : (long) (bitrateEstimate * bandwidthFraction);
        int lowestBitrateNonBlacklistedIndex = 0;
        for (int i = 0; i < length; i++) {
            if (nowMs == Long.MIN_VALUE || !isBlacklisted(i, nowMs)) {
                Format format = getFormat(i);
                if (format.bitrate <= effectiveBitrate && HLSUtil.isQualityPlayable(format)) {
                    Log.d(ClassAdaptiveTrackSelection.class.getSimpleName(), " Video player quality auto quality found " + String.valueOf(sHLSQuality));
                    return i;
                } else {
                    lowestBitrateNonBlacklistedIndex = i;
                }
            }
        }
        return lowestBitrateNonBlacklistedIndex;
    }

    private long minDurationForQualityIncreaseUs(long availableDurationUs) {
        boolean isAvailableDurationTooShort = availableDurationUs != C.TIME_UNSET
                && availableDurationUs <= minDurationForQualityIncreaseUs;
        return isAvailableDurationTooShort
                ? (long) (availableDurationUs * bufferedFractionToLiveEdgeForQualityIncrease)
                : minDurationForQualityIncreaseUs;
    }

    static void setHLSQuality(HLSQuality HLSQuality) {
        sHLSQuality = HLSQuality;
    }
}


//this part goes as initialization of your exo player    
mDefaultTrackSelector = new DefaultTrackSelector(new ClassAdaptiveTrackSelection.Factory(mDefaultBandwidthMeter));

//when you want to set max speed rate just use 
ClassAdaptiveTrackSelection.setHLSQuality(HLSQuality.Quality480);
于 2018-04-06T12:35:32.507 回答