Android MediaPlayer - 有时即使播放音频也不会播放视频

2022-09-02 10:47:31

我正在开发一个Android应用程序,我正在使用Android SDK在我的应用程序中播放一些视频。当我在应用中播放视频时,大约五分之一的音频在没有视频的情况下播放。这不是一个简单的编码错误,因为大多数时候视频可以完美地播放。MediaPlayer

我认为我的代码中的争用条件导致了这个错误。但是,我添加了许多调试语句,当视频无法播放时,所有内容似乎都已正确设置。

我已经扫描了网络和SO试图找到解决方案,但没有一个是足够的(见下文)。

以前有人遇到过这种类型的问题吗?如果是这样,你做了什么?

类似问题:

媒体播放器 视频未播放

安卓媒体播放器显示音频但没有视频

安卓视频,听到声音但没有视频

更多细节:

  • 我在两部手机上遇到了这个错误。在Samsung Charge视频上,80%的时间播放,20%的时间有音频但没有视频。在T-Mobile彗星上,情况要糟糕得多。视频只播放大约10%的时间。
  • 这不是文件的问题,我已经尝试了各种视频文件和编解码器,并得到了同样的问题。
  • 这不是存储介质的问题。我尝试过播放视频时,当它存储在内部存储和SD卡上时,两者都没有区别。我甚至在播放之前尝试读取一些文件,希望系统会缓存它,但这似乎也没有帮助。

更新:

我一直在调试这个并查看logcat。我发现当视频工作时,logcat中会出现如下内容:

09-28 00:09:03.651: VERBOSE/PVPlayer(10875): setVideoSurface(0x65638)

但是,当视频无法播放时,看起来有一个空条目:

09-28 00:03:35.284: VERBOSE/PVPlayer(10875): setVideoSurface(0x0)

更新 2:

当视频无法播放时,函数 MediaPlayer.OnInfoListener 带有参数和 。我查看了Android代码库,试图确定未知错误35的含义。我遇到了pv_player_interface.h的文件,它指示错误代码35对应于称为.我用谷歌搜索了那个术语,它把我带到了一个名为.该文件给了我以下难以理解的解释:what==MEDIA_ERROR_UNKNOWN(0x1)extra==35PVMFInfoTrackDisablepvmf_return_codes.pdf

4.34. PVMFInfoTrackDisable

禁用轨道的通知。这个是基于每轨的。对于未压缩的音频/视频格式,在选择内容中可用的轨道的过程中,如果解码器不支持该轨道,则会发送 PVMFInfoTrackDisable 事件。如有必要,该事件将按轨道发送一次。

我觉得我已经走了很长的路,但我并没有更接近找到答案......仍在调查中。


答案 1

我解决了这个问题,尽管是以一种完全黑客的方式。实际上有两个问题:

  1. 邪恶信息35消息:我发现偶尔会使用MediaPlayer.OnInfoListener调用extra==35。发生这种情况时,您将被搞砸,视频将无法正常播放。我不知道是什么原因造成的。我发现的唯一修复方法是尝试重新启动视频并再次执行整个prepAsync过程。视频播放通常第二次工作。

  2. 未设置视频大小:即使在 MediaPlayer.OnPreparedListener 发出(或等效地准备() 返回)之后,也可能无法设置视频大小。视频大小通常会在准备返回后设置几毫秒,但片刻处于模糊状态。如果在设置视频大小之前调用 MediaPlayer.start(),则播放有时会(但并非总是)失败。有两种潜在的解决方案:(1)poll MediaPlayer.getVideoHeight()或getVideoWidth()直到它们不为零或(2)等到OnVideoSizeChangedListener被调用。只有在这两个事件之一之后,才应该调用 start()。

通过这两个修复程序,视频播放更加一致。这些问题很可能是我的手机(三星充电和T-Mobile彗星)的错误,所以如果其他手机上存在不同但类似的问题,我不会感到惊讶。


答案 2

根据Speedplane的建议,我想出了以下代码。如果 MediaPlayer.getVideoHeight() 在 Preprepped 上返回 0,那么我延迟 1 秒,然后重试。现在,如果它第一次没有播放,它通常会在1秒后播放。我已经看到它需要几次尝试。

   private void videoPlayer(String path){
      if (mMediaController == null)
      {
         mMediaController = new MediaController(this);
         mVideoView.setMediaController(mMediaController);
      }
      if (!mMediaController.isShowing())
         mMediaController.show();

      getWindow().setFormat(PixelFormat.TRANSLUCENT);
      mVideoView.setVideoPath(path);
      mVideoView.requestFocus();
      mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
               public void onPrepared(final MediaPlayer mp) {
               mVideoView.seekTo(mImageSeek);
               if (mp.getVideoHeight() == 0) {
                  final Handler handler = new Handler();
                  handler.postDelayed(new Runnable() {
                        @Override
                           public void run() {
                           mVideoView.stopPlayback();
                           mMediaController = null;
                           videoPlayer(mImageFilepath);
                        }
                     }, 1000);
               } else 
                  mVideoView.start();
            }
         });
   }

推荐