ExoPlayer 2的质量选择器

时间:2017-08-23 09:18:12

标签: android exoplayer exoplayer2.x

我目前正在开发一个实时和电影播放器​​应用程序。我选择 ExoPlayer第2版来播放电影,我对此并不了解。我想让用户在播放器屏幕上选择电影质量,例如720p或1080p等。 但我不知道如何获得现有质量列表并将其显示给用户。 以下代码是我对SimpleExoPlayer的实现:

private void initPlayer(String path){
    Handler handler = new Handler();
    // 1. Create a default TrackSelector
    BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
    TrackSelection.Factory videoTrackSelectionFactory =
            new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
    TrackSelector trackSelector =
            new DefaultTrackSelector(videoTrackSelectionFactory);

    // 2. Create a default LoadControl
    LoadControl loadControl = new DefaultLoadControl();
    // 3. Create the player
    player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);

    SimpleExoPlayerView playerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
    playerView.setPlayer(player);
    playerView.setKeepScreenOn(true);
    // Produces DataSource instances through which media data is loaded.
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));

    // This is the MediaSource representing the media to be played.
    MediaSource videoSource = new HlsMediaSource(Uri.parse(path),
            dataSourceFactory,handler, null);
    // Prepare the player with the source.
    player.addListener(this);
    player.prepare(videoSource);
    playerView.requestFocus();
    player.setPlayWhenReady(true); // to play video when ready. Use false to pause a video
}

// ExoPlayer Listener Methods :
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {

}

@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

}

@Override
public void onLoadingChanged(boolean isLoading) {

}

@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
    switch (playbackState) {
        case ExoPlayer.STATE_BUFFERING:
            //You can use progress dialog to show user that video is preparing or buffering so please wait
            progressBar.setVisibility(View.VISIBLE);
            break;
        case ExoPlayer.STATE_IDLE:
            //idle state
            break;
        case ExoPlayer.STATE_READY:
            // dismiss your dialog here because our video is ready to play now
            progressBar.setVisibility(GONE);
            //Toast.makeText(getApplicationContext(),String.valueOf(player.getCurrentTrackSelections().get(0).getSelectedFormat().bitrate),Toast.LENGTH_SHORT).show();
            break;
        case ExoPlayer.STATE_ENDED:
            // do your processing after ending of video
            break;
    }
}

@Override
public void onPlayerError(ExoPlaybackException error) {
    // show user that something went wrong. it can be a dialog
}

@Override
public void onPositionDiscontinuity() {

}

请帮助解决这个问题。 非常感谢。

2 个答案:

答案 0 :(得分:6)

您想要实现的所有内容都可以在ExoPlayer2 demo app中查看。更具体地说是PlayerActivity类。

您还可以查看有关该主题的good article

您要查看的核心要点是跟踪选择(通过TrackSelectionHelper)以及// These two could be fields OR passed around int videoRendererIndex; TrackGroupArray trackGroups; // This is the body of the logic for see if there are even video tracks // It also does some field setting MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); for (int i = 0; i < mappedTrackInfo.length; i++) { TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i); if (trackGroups.length != 0) { switch (player.getRendererType(i)) { case C.TRACK_TYPE_VIDEO: videoRendererIndex = i; return true; } } } // This next part is actually about getting the list. It doesn't include // some additional logic they put in for adaptive tracks (DASH/HLS/SS), // but you can look at the sample for that (TrackSelectionHelper#buildView()) // Below you'd be building up items in a list. This just does // views directly, but you could just have a list of track names (with indexes) for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { TrackGroup group = trackGroups.get(groupIndex); for (int trackIndex = 0; trackIndex < group.length; trackIndex++) { if (trackIndex == 0) { // Beginning of a new set, the demo app adds a divider } CheckedTextView trackView = ...; // The TextView to show in the list // The below points to a util which extracts the quality from the TrackGroup trackView.setText(DemoUtil.buildTrackName(group.getFormat(trackIndex))); } // Assuming you tagged the view with the groupIndex and trackIndex, you // can build your override with that info. Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag(); int groupIndex = tag.first; int trackIndex = tag.second; // This is the override you'd use for something that isn't adaptive. override = new SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex); // Otherwise they call their helper for adaptives, which roughly does: int[] tracks = getTracksAdding(override, trackIndex); TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY : adaptiveTrackSelectionFactory; override = new SelectionOverride(factory, groupIndex, tracks); // Then we actually set our override on the selector to switch the quality/track selector.setSelectionOverride(rendererIndex, trackGroups, override); 。我将在下面列出重要的代码示例,希望这些示例足以让您前进。但最终只需在演示应用程序中执行类似操作即可获得所需的位置。

您将保持启动播放器的轨道选择器,并将其用于几乎所有内容。

以下只是一段代码,理想地涵盖了您尝试做的事情的要点,因为演示看起来似乎使头发过于复杂。此外,我还没有运行代码,但它足够接近。

TrackSelector

正如我上面提到的,这个过程略微过于简单化,但核心部分是你正在弄乱SelectionOverrideTrackTrackGroups / {{1}}让它发挥作用。

您可以想象地逐字复制演示代码并且它应该可以工作,但我强烈建议您花时间了解每个部分正在做什么,并根据您的用例定制解决方案。

如果我有更多时间,我可以将其编译并运行。但是,如果你可以获得我的样本,那么随时编辑我的帖子。

希望有所帮助:)

答案 1 :(得分:0)

我避开上面发布的方式。我的方法是使用DefaultTrackSelector,如下所示:

trackSelector.setParameters(trackSelector.getParameters()
                          .withMaxVideoBitrate(bitrate)
                          .withMaxVideoSize(width, height));

我已经使用HLS视频进行过测试,但它似乎以正确的方式运行。我从HlsManifest得到了比特率,宽度和高度。