ExoPlayer播放高分辨率视频遇问题:解码失败、画面旋转异常求助
ExoPlayer 高分辨率播放解码失败与画面旋转异常解决方案
问题1:高分辨率视频解码失败
不设置自定义RenderersFactory时,默认工厂可能无法适配高分辨率视频的硬件解码需求,导致解码失败。解决方式是使用DefaultRenderersFactory并开启解码器 fallback、优先硬件加速:
// 替换原ExoPlayer初始化代码 DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(holder.mVideoView.getContext()) .setEnableDecoderFallback(true) // 解码失败时自动切换备选解码器 .setPreferredVideoDecoderType(C.DECODER_TYPE_HARDWARE); // 优先硬件解码 exoPlayer = new ExoPlayer.Builder(holder.mVideoView.getContext()) .setLoadControl(loadControl) .setRenderersFactory(renderersFactory) .build();
问题2:画面旋转不稳定
默认RenderersFactory对视频旋转元数据的处理可能受RecyclerView复用、视频元数据不一致影响。可以通过监听视频尺寸变化事件,手动控制画面旋转:
- 添加Player监听,处理旋转逻辑:
exoPlayer.addListener(new Player.Listener() { @Override public void onVideoSizeChanged(VideoSize videoSize) { // 获取视频自带的旋转角度 int rotation = videoSize.videoRotationDegrees; // 强制设置VideoView的旋转角度 holder.mVideoView.setRotation(rotation); } @Override public void onPlaybackStateChanged(int playbackState) { // 播放状态闲置时重置旋转(防止RecyclerView复用残留状态) if (playbackState == Player.STATE_IDLE) { holder.mVideoView.setRotation(0); } } });
- 配合RecyclerView复用逻辑,在
onViewDetachedFromWindow中额外重置旋转状态:
@Override public void onViewDetachedFromWindow(@NonNull ViewHolder holder) { super.onViewDetachedFromWindow(holder); // 释放播放器前重置旋转 holder.mVideoView.setRotation(0); holder.player.stop(); holder.player.release(); holder.player = null; }
修改后的完整初始化代码
// 初始化RenderFactory DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(holder.mVideoView.getContext()) .setEnableDecoderFallback(true) .setPreferredVideoDecoderType(C.DECODER_TYPE_HARDWARE); // 创建ExoPlayer实例 exoPlayer = new ExoPlayer.Builder(holder.mVideoView.getContext()) .setLoadControl(loadControl) .setRenderersFactory(renderersFactory) .build(); holder.mVideoView.setPlayer(exoPlayer); holder.mVideoView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM); holder.mVideoView.setShutterBackgroundColor(Color.TRANSPARENT); holder.mVideoView.setKeepContentOnPlayerReset(true); // 添加旋转监听 exoPlayer.addListener(new Player.Listener() { @Override public void onVideoSizeChanged(VideoSize videoSize) { holder.mVideoView.setRotation(videoSize.videoRotationDegrees); } @Override public void onPlaybackStateChanged(int playbackState) { if (playbackState == Player.STATE_IDLE) { holder.mVideoView.setRotation(0); } } }); exoPlayer.setRepeatMode(Player.REPEAT_MODE_ONE); // 构建MediaSource mediaSource = new ProgressiveMediaSource.Factory( new CacheDataSource.Factory() .setCache(SimpleMediaPlayer.getInstance(mContext)) .setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory() .setUserAgent(mContext.getString(R.string.app_name))) .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR) ).createMediaSource(MediaItem.fromUri(videoItem.videoURL)); exoPlayer.addMediaSource(mediaSource); exoPlayer.prepare(); exoPlayer.setPlayWhenReady(true);
内容的提问来源于stack exchange,提问作者Manali joshi
相关产品推荐
相关产品推荐

