【问题标题】:ExoPlayer doesn work on some devicesExoPlayer 不适用于某些设备
【发布时间】:2016-04-19 08:32:08
【问题描述】:

我想在我的 Android 应用中实现视频播放器 (ExoPlayer)。播放器必须从某个网址播放视频(不大,约 2-3 分钟)。在 nexus 5 上它运行良好,但在手机“Samsung GT-I8552 Galaxy Win”上很遗憾它不起作用。编译启动app后有异常日志:

内部运行时错误。
java.lang.IllegalStateException

在 android.media.MediaCodec.dequeueOutputBuffer(Native Method)

这是我的代码:

      private SurfaceView surfaceView;
      private ExoPlayer player;
      private MediaCodecVideoTrackRenderer videoRenderer;
      private MediaCodecAudioTrackRenderer audioRenderer;
      private CustomMediaController mediaController;
      private String userAgent;
      private final int RENDERER_COUNT = 8;
      private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
      private static final int BUFFER_SEGMENT_COUNT =  256;  
      private static final int minBufferMs = 10000;
      private static final int minRebufferMs = 5000;
      private final String videoUrl_2 = "someurl...";

...

    surfaceView = (SurfaceView) findViewById(R.id.surface_view);
    player = ExoPlayer.Factory.newInstance(RENDERER_COUNT, minBufferMs, minRebufferMs);
    userAgent = Util.getUserAgent(this, "MyPlayer");
    Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
    DataSource dataSource = new DefaultUriDataSource(context, null, userAgent);

    ExtractorSampleSource sampleSource = new ExtractorSampleSource(Uri.parse(videoUrl_2), dataSource, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
    videoRenderer = new MediaCodecVideoTrackRenderer(context,
            sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
    audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, MediaCodecSelector.DEFAULT);
    player.prepare(videoRenderer, audioRenderer);
    player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surfaceView.getHolder().getSurface());

    player.setPlayWhenReady(true);

    CustomMediaPlayerControl customMediaPlayerControl = new CustomMediaPlayerControl(player);
    mediaController = new CustomMediaController(context);
    mediaController.setMediaPlayer(customMediaPlayerControl);
    mediaController.setAnchorView(surfaceView);
    mediaController.setEnabled(true);

我的班级CustomMediaPlayerControl:

public class CustomMediaPlayerControl implements MediaController.MediaPlayerControl {
private ExoPlayer player;

public CustomMediaPlayerControl(ExoPlayer player) {
    this.player = player;
}

@Override
public void start() {
    player.setPlayWhenReady(true);
}

@Override
public void pause() {
    player.setPlayWhenReady(false);
}

@Override
public int getDuration() {
    return (int) player.getDuration();
}

@Override
public int getCurrentPosition() {
    return (int) player.getCurrentPosition();
}

@Override
public void seekTo(int pos) {
    player.seekTo(pos);
}

@Override
public boolean isPlaying() {
    return player.getPlayWhenReady();
}

@Override
public int getBufferPercentage() {
    return (int) player.getBufferedPercentage();
}

@Override
public boolean canPause() {
    return true;
}

@Override
public boolean canSeekBackward() {
    return true;
}

@Override
public boolean canSeekForward() {
    return true;
}

@Override
public int getAudioSessionId() {
    return 0;
}
}

还有我的班级 CustomMediaController:

public class CustomMediaController extends MediaController {

private MediaController.MediaPlayerControl playerControl;

public CustomMediaController(Context context) {
    super(context);
}

@Override
public void setMediaPlayer(MediaController.MediaPlayerControl playerControl) {
    super.setMediaPlayer(playerControl);
    this.playerControl = playerControl;
}

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    int keyCode = event.getKeyCode();
    if (playerControl.canSeekForward() && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            playerControl.seekTo(playerControl.getCurrentPosition() + 15000); // milliseconds
            show();
        }
        return true;
    } else if (playerControl.canSeekBackward() && keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            playerControl.seekTo(playerControl.getCurrentPosition() - 5000); // milliseconds
            show();
        }
        return true;
    }
    return super.dispatchKeyEvent(event);
}
}

【问题讨论】:

    标签: android exoplayer


    【解决方案1】:

    ExoPlayer 的 sdk 最低要求为 16 级。

    ExoPlayer 的标准音频和视频组件依赖于 Android 的 MediaCodec API,该 API 在 Android 4.1(API 级别 16)中发布。因此,它们不适用于早期版本的 Android。
    来自:https://google.github.io/ExoPlayer/guide.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-19
      • 1970-01-01
      • 1970-01-01
      • 2012-10-26
      • 1970-01-01
      • 2016-10-11
      • 2013-12-08
      • 2016-02-06
      相关资源
      最近更新 更多