Android MediaPlayer - 有时候只播放音频而没有视频

20
我正在开发一款Android应用程序,并使用Android SDK的MediaPlayer在我的应用程序中播放一些视频。当我在应用程序中播放视频时,大约五分之一的时间,音频会没有视频。这不是简单的编码错误,因为大多数情况下视频都可以正常播放。
我考虑到我的代码中可能存在竞争条件导致了这个bug。然而,我添加了许多调试语句,当视频未播放时,一切似乎都设置正确。
我已经在网上和SO上搜索解决方案,但没有一个是充分的(请参见下面)。
有人遇到过这种问题吗?如果是这样,你做了什么?
类似的问题: MediaPlayer Video not played android media player shows audio but no video android video, hear sound but no video 一些更多的细节:
  • 我在两部手机上遇到了这个bug。在三星Charge上,视频播放80%的时间,20%的时间有声音但没有视频。在T-Mobile Comet上,情况要严重得多;只有大约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函数将带有参数what==MEDIA_ERROR_UNKNOWN(0x1)extra==35。我查看了Android代码库,试图确定未知错误35的含义。我找到了文件pv_player_interface.h,该文件指出错误代码35对应于一个称为PVMFInfoTrackDisable的内容。我谷歌了这个术语,找到了一个名为pvmf_return_codes.pdf的文件。该文件给出了以下难以理解的解释:

4.34. PVMFInfoTrackDisable

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

我感觉我走了很远,但离找到答案还很远……仍在调查中。


1
你是每次播放相同的媒体内容还是不同的内容? - bluefalcon
你测试过多个设备以确保不是设备错误了吗? - Cameron
我已经在评论中回复了你的意见。 - speedplane
这似乎是视频编解码器的问题,你能把logcat中的日志粘贴过来吗?如果最终证实是编解码器的问题,那么除了更改内容之外,你无法做任何事情。 - bluefalcon
让我补充一下,由于Android源代码和kernel.org被黑客攻击而关闭,追踪这些问题变得更加困难...愚蠢的黑客。 - speedplane
5个回答

19

我用了一个完全hackish(笨拙的)的方法解决了这个问题。实际上有两个问题:

  1. 邪恶信息35消息: 我发现有时候MediaPlayer.OnInfoListener会被调用,extra==35。当这种情况发生时,你将无法正常播放视频。我不知道是什么原因导致的。唯一的解决方法是尝试重新启动视频并重新进行整个prepareAsync过程。第二次通常可以正常播放视频。

  2. 视频大小未设置: 即使MediaPlayer.OnPreparedListener已经被发出(或者prepare()已返回),视频大小可能还没有被设置。视频大小通常在prepare返回后几毫秒内设置,但在短暂的时间内处于模糊状态。如果你在视频大小未设置的情况下调用MediaPlayer.start(),则有时(但不总是)会播放失败。有两种潜在的解决办法:(1)轮询MediaPlayer.getVideoHeight() 或 getVideoWidth()直到它们不为零,或者(2)等待OnVideoSizeChangedListener被调用。只有在这两个事件之后,才应该调用start()。

通过这两个修复,视频播放更加稳定了。很可能这些问题是我的手机(三星Charge和T-Mobile Comet)的错误,所以如果其他手机上出现不同但类似的问题,我也不会感到惊讶。


我在这个问题上苦苦挣扎了好几天。OnPrepareListener并不意味着完全准备就绪。我采用了解决方案(1),它起作用了。非常感谢! - wayne_bai
对我来说不起作用 :-(。我没有收到35错误,高度和宽度始终正常。 - Nativ
谢谢,第二点对我很有帮助。我在重复创建新的“MediaPlayers”时遇到了间歇性问题,播放器偶尔会出现空白(我的设备上没有扬声器,但我认为声音正在按照OP的要求播放),它还没有足够远以触发“OnInfo”。 - tallpaul
嗨 @speedplane,我在三星设备上遇到了 MEDIAINFO VIDEO_NOT_PLAYING = 805 的问题,额外的代码是 -12。不知道该如何解决这个问题,请帮忙。 - Dharmishtha

4

按照speedplane的建议,我写出了以下代码。如果MediaPlayer.getVideoHeight()在onPrepared中返回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();
            }
         });
   }

3
我已经研究了这个问题两周,大致理解了真正的问题。当然,我在谈论“邪恶信息35号”。如果你遇到了这个奇怪的错误,现在你可以高兴地射击一些像三星这样的供应商 :D ...
问题是由于用户无法看到表面视图(在选项卡中的活动或暂停唤醒功能中,有时不在焦点中,有时也不在前面(也许))而导致的。
这就是为什么当某些视频重置时,它可以正常运行,因为它获得了焦点,或者可能是另一个活动/对象没有重叠它。
当发生这些情况之一时,媒体播放器认为您无法看到视频或无法播放,并禁用视频轨道,使您在工作中听音乐曲目时头痛欲裂。
下一个bug再见,祝好运。:D

-4

我在我的Desire HD上也遇到了这个问题,大约有一两次。我尝试了很多方法,但错误始终存在。最终我选择在设备上安装自定义ROM。之后,它完美地工作,我再也没有遇到这个问题。

我知道这不是你想听到的答案,但我没有找到其他解决方案。

在这里,您可以找到适用于您设备的自定义ROM:XDA Developers

我希望我能帮到你。

最好的祝福和愉快的观影体验

safari =)


谢谢,但我正在编写一个应用程序,而不仅仅是在手机上尝试播放视频。我不能要求我的用户安装新的ROM。 - speedplane

-5

根本问题是:在调用surfaceCreated之前开始视频播放,当holder还没有准备好MediaPlayer时,你只能听到声音但看不到画面!

正确的方法是:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接