• 在 Libgdx 中播放视频(一)


    我记得之前写过这篇帖子,找不到了现在,知道从别处粘贴过来

    我现在做的一款游戏使用 Libgdx ,其中需要播放小段视频过度游戏场景,想到传统的办法是跳转 Activity ,显然这样做不是我会选择的! 
    我想直接在当前游戏 Activity 中插播视频。 
    播放视频其实只需要:MediaPlayer 和 SurfaceView  

    刚开始在网上找到了一段这样的实例代码,拿来用没问题:

    View Code
     1 package com.thirdparty;
     2 
     3 public class AAA {
     4     public class VideoPlayerActivity extends Activity implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, SurfaceHolder.Callback, OnClickListener {
     5 
     6         private SurfaceView surfaceView;
     7         private MediaPlayer mPlayer; // MediaPlayer对象
     8         private SurfaceHolder mSurfaceHolder; // SurfaceHolder对象
     9 
    10         private Button mSkipVideoBtn;
    11 
    12         @Override
    13         protected void onCreate(Bundle savedInstanceState) {
    14             super.onCreate(savedInstanceState);
    15             requestWindowFeature(Window.FEATURE_NO_TITLE);
    16             getWindow().setFlags(0x400, 0x400);
    17 
    18             setContentView(R.layout.video_player);
    19 
    20             surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
    21 
    22             /* 初始化mSurfaceHolder */
    23             mSurfaceHolder = surfaceView.getHolder();
    24             mSurfaceHolder.addCallback(this); // 设置回调接口
    25             mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 设置为Buffer类型(播放视频&Camera预览)
    26 
    27             /* 初始化MediaPlayer */
    28             mPlayer = MediaPlayer.create(this, getIntent().getIntExtra("resId", R.raw.video2));
    29             mPlayer.setOnPreparedListener(this);
    30             mPlayer.setOnCompletionListener(this);
    31 
    32             mSkipVideoBtn = (Button) findViewById(R.id.button1);
    33             mSkipVideoBtn.setOnClickListener(this);
    34         }
    35 
    36         @Override
    37         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    38         }
    39 
    40         @Override
    41         public void surfaceCreated(SurfaceHolder holder) {
    42             mPlayer.setDisplay(holder); // 指定SurfaceHolder
    43             // mPlayer.prepareAsync(); // 异步准备(将回调OnPreparedListener接口)
    44         }
    45 
    46         @Override
    47         public void surfaceDestroyed(SurfaceHolder holder) {
    48             // TODO Auto-generated method stub
    49 
    50         }
    51 
    52         @Override
    53         public void onPrepared(MediaPlayer player) {
    54             /* 获得窗口宽长 */
    55             Display display = getWindowManager().getDefaultDisplay();
    56             int wWidth = display.getWidth();
    57             int wHeight = display.getHeight();
    58 
    59             /* 获得视频宽长 */
    60             int vWidth = mPlayer.getVideoWidth();
    61             int vHeight = mPlayer.getVideoHeight();
    62 
    63             /* 最适屏幕 */
    64             float wRatio = (float) vWidth / (float) wWidth; // 宽度比
    65             float hRatio = (float) vHeight / (float) wHeight; // 高度比
    66             float ratio = Math.max(wRatio, hRatio); // 较大的比
    67             vWidth = (int) Math.ceil((float) vWidth / ratio); // 新视频宽度
    68             vHeight = (int) Math.ceil((float) vHeight / ratio); // 新视频高度
    69 
    70             // 改变SurfaceHolder大小
    71             mSurfaceHolder.setFixedSize(vWidth, vHeight);
    72             // 设置新布局参数(这在samsung i9088上出现stretch的错误==)
    73             // surfaceView.setLayoutParams(new LinearLayout.LayoutParams(vWidth,
    74             // vHeight));
    75             // 启动播放
    76             mPlayer.start();
    77         }
    78     }
    79 }

    这里最主要的就是: MediaPlayer.setDisplay(),新建一个SurfaceView,将 SurfaceView 的 SurfaceHolder 设置给 MediaPlayer 然后设置播放视频,prepare() 、 start() 就可以正常播放视频了,不过据说只支持 .mp4 .3gp,我没亲测。

    起初这段源代码给我带来帮助,在感谢原作者之余他也在代码里设下了一个陷阱,作者当时估计没测试到就是!

    如果你使用这段代码,在有些手机上是可以正常播放视频的,而有些手机就是不行(你只能听见声音、看不到画面),系统没给任何提示,只有2个警告信息,如下图:

    于是百度“mediaPlayer错误信息”得知 35 在 native 层是这样定义的:const PVMFStatus PVMFInfoTrackDisable = 35;

    于是 Google “PVMFInfoTrackDisable ” 果然有人跟我遇到同样的问题,在 stackoverflow 论坛有一篇这样的帖子:

    http://stackoverflow.com/questions/7509818/android-mediaplayer-sometimes-no-video-is-played-even-though-audio-plays

    这里不得不说下,stackoverflow 论坛能够找到你遇到的各种疑难杂症,嘿嘿!

    这里面说法很多,但没找到根本原因,倒是在另外一篇帖子找到了答案:

    这哥们才发现了问题的根本,大概意思就是:在 surfaceCreated 没被系统调用之前,SurfaceView 的 SurfaceHolder 是无效的,而我们一般习惯在 MediaPlayer 构造完后就给他设置数据,而我在 surfaceCreated 才调用了 mPlayer.setDisplay(holder); 这样 MediaPlayer 就没有设置显示器就开始播放了,这样自然看不到画面,而后来系统调用 surfaceCreated 的时候是于事无补的!

    这也难怪看到有些人回复说第二次在播放视频的时候就可以,因为前面第一次设置了 holder 嘛!

    知道了问题的根本就好办了, 在 surfaceCreated 里设置 holder,然后设置视频数据,然后调用 prepare,这样总是没问题了吧!

  • 相关阅读:
    C++面试考点
    C++面试考点
    C++11 引用叠加规则和模板参数类型推导规则
    C++11 引用叠加规则和模板参数类型推导规则
    C++11 auto和decltype推导规则
    C++11 auto和decltype推导规则
    RVO和NRVO
    RVO和NRVO
    Strange Bank(找零问题)
    eli和字符串 (牛客假期训练)
  • 原文地址:https://www.cnblogs.com/yichouangle/p/3046073.html
Copyright © 2020-2023  润新知