android - Exoplayer 2 质量再现,如 320p、480p、720p 和 1080p

标签 android android-studio playback exoplayer2.x

我希望实现质量再现选项,例如(320p、480p、720p 和 1080p)YouTube 支持使用 Exoplayer 2 的方式。真的很努力寻找答案,但找不到任何东西。由于我是 Exoplayer 的新手,因此如果我能得到一些帮助,那就太好了。

这是我的 MainActivity.java 的代码

package com.geoffledak.exoplayerfullscreen;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private final String STATE_RESUME_WINDOW = "resumeWindow";
private final String STATE_RESUME_POSITION = "resumePosition";
private final String STATE_PLAYER_FULLSCREEN = "playerFullscreen";

private SimpleExoPlayerView mExoPlayerView;
private MediaSource mVideoSource;
private boolean mExoPlayerFullscreen = false;
private FrameLayout mFullScreenButton;
private ImageView mFullScreenIcon;
private ImageButton btn_settings;
private ExoPlayer player;

private Dialog mFullScreenDialog;

private int mResumeWindow;
private long mResumePosition;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn_settings = (ImageButton) findViewById(R.id.btn_settings);

    btn_settings.setOnClickListener(this);


    if (savedInstanceState != null) {
        mResumeWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW);
        mResumePosition = savedInstanceState.getLong(STATE_RESUME_POSITION);
        mExoPlayerFullscreen = savedInstanceState.getBoolean(STATE_PLAYER_FULLSCREEN);
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {

    outState.putInt(STATE_RESUME_WINDOW, mResumeWindow);
    outState.putLong(STATE_RESUME_POSITION, mResumePosition);
    outState.putBoolean(STATE_PLAYER_FULLSCREEN, mExoPlayerFullscreen);

    super.onSaveInstanceState(outState);
}

private void initFullscreenDialog() {

    mFullScreenDialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
        public void onBackPressed() {
            if (mExoPlayerFullscreen)
                closeFullscreenDialog();
            super.onBackPressed();
        }
    };
}

 private void openFullscreenDialog() {

    ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
    mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fullscreen_shrink));
    mExoPlayerFullscreen = true;
    mFullScreenDialog.show();
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}


private void closeFullscreenDialog() {

    ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
    ((FrameLayout) findViewById(R.id.main_media_frame)).addView(mExoPlayerView);
    mExoPlayerFullscreen = false;
    mFullScreenDialog.dismiss();
    mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fullscreen_expand));
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

private void initFullscreenButton() {
    PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
    mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
    mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
    mFullScreenButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!mExoPlayerFullscreen)
                openFullscreenDialog();
            else
                closeFullscreenDialog();
        }
    });
}

private void initExoPlayer() {

    BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
    TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
    TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
    LoadControl loadControl = new DefaultLoadControl();
    SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), trackSelector, loadControl);
    mExoPlayerView.setPlayer(player);

    boolean haveResumePosition = mResumeWindow != C.INDEX_UNSET;

    if (haveResumePosition) {
        mExoPlayerView.getPlayer().seekTo(mResumeWindow, mResumePosition);
    }
    mExoPlayerView.getPlayer().prepare(mVideoSource);
    mExoPlayerView.getPlayer().setPlayWhenReady(true);
}


@Override
protected void onResume() {
    super.onResume();
    if (mExoPlayerView == null) {
        mExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.exoplayer);
        initFullscreenDialog();
        initFullscreenButton();
        String streamUrl = "http://playertest.longtailvideo.com/adaptive/bbbfull/bbbfull.m3u8";
        String userAgent = Util.getUserAgent(MainActivity.this, getApplicationContext().getApplicationInfo().packageName);
        DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent, null, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true);
        DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(MainActivity.this, null, httpDataSourceFactory);
        Uri daUri = Uri.parse(streamUrl);

        mVideoSource = new HlsMediaSource(daUri, dataSourceFactory, 1, null, null);
    }

    initExoPlayer();

    if (mExoPlayerFullscreen) {
        ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
        mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fullscreen_shrink));
        mFullScreenDialog.show();
    }
}


@Override
protected void onPause() {

    super.onPause();

    if (mExoPlayerView != null && mExoPlayerView.getPlayer() != null) {
        mResumeWindow = mExoPlayerView.getPlayer().getCurrentWindowIndex();
        mResumePosition = Math.max(0, mExoPlayerView.getPlayer().getContentPosition());

        mExoPlayerView.getPlayer().release();
    }

    if (mFullScreenDialog != null)
        mFullScreenDialog.dismiss();
}

@Override
public void onClick(View view) {
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "Landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "Portrait", Toast.LENGTH_SHORT).show();
    }
}

}

最佳答案

您要研究的核心点是围绕轨道选择(通过 TrackSelector)以及 TrackSelectionHelper。我将在下面包含重要的代码示例,希望它们足以让您继续前进。但最终,只需在演示应用程序中遵循类似的内容,您就可以到达您需要的地方。

您将握住用于初始化播放器的轨道选择器,并将其用于几乎所有内容。

下面只是一段代码,可以理想地涵盖您正在尝试做的事情的要点,因为该演示确实似乎使事情变得过于复杂。另外我还没有运行代码,但它已经足够接近了。

这里有一点描述。

我检查了解决方案here ,我相信它会帮助你。

    // 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、SelectionOverride 和 Track/TrackGroups 以使其工作。

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

谢谢你,我希望它有所帮助。

关于android - Exoplayer 2 质量再现,如 320p、480p、720p 和 1080p,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48859968/

相关文章:

android - 如何更改 ListView 中复选框的文本?

android - 如果您有 adb 访问权限,是否可以流式传输 Android 手机的屏幕?

java - 由于以下原因导致Android Studio崩溃:java.lang.ArrayIndexOutOfBoundsException:length = 1;指数= 6

java - 从 Android 存储访问框架中选取时文件是只读的

Android Studio 许多错误 : Could not find class 'android.XXX'

ios - 在 Swift 中从服务器播放视频文件

javascript - 通过 jQuery 一次播放和暂停一个 HTML5 音频元素

android - 无法在 API 25 (Android 7.1.1) 中找到移动系统镜像

flash - 简单的声音暂停/播放切换按钮

gradle - Android Studio 编译构建 ViewPagerIndicator 但运行时说包不存在