处于暂停状态时Android的MediaPlayer setSurface

时间:2013-10-10 15:01:50

标签: android android-mediaplayer android-video-player

修改

显然这与多项活动无关,这与视频文件的编码有关。

我将尝试简化问题:我有一个处于暂停状态的MediaPlayer对象,当我调用mediaPlayer.getCurrentPosition()时,我得到的结果是准确的。当我在此对象上调用mediaPlayer.setSurface()(使用不同的曲面)后跟mediaPlayer.play()时,视频的播放位置与getCurrentPosition()返回的位置不同。我正在测试API> = ICE_CREAM_SANDWICH。

  • 使用项目中的本地资源和网络流进行测试,结果:没有区别。

链接到视频文件:http://wpc.4ba9.edgecastcdn.net/804BA9/testenvmedia/m_8705_LuS3w7ctSZjB.mov.bs.mp4


我有两项活动,活动A和活动B.

活动-A使用TextureView将视频从远程流播放到MediaPlayer, 它还有一个按钮,其目的是:

  1. 调用mediaPlayer.pause();

  2. 打开活动-B。

  3. 活动-B还有一个TextureView,它应该使用相同的MediaPlayer对象在其当前位置播放相同的视频。

    活动-A onCreate方法:

        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {        
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int w, int h) {
                try {
                    final MediaPlayer mediaPlayer = MyApplication.getMediaPlayer();
                    mediaPlayer.setDataSource(context, videoURI);
                    mediaPlayer.setSurface(new Surface(surfaceTexture));
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    mediaPlayer.setLooping(shouldLoop);
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mp.start();
                        }
                    });
    
                    mediaPlayer.prepareAsync();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
    
            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; }
    
            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
        });
    
        btnFullScreen.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {     
            Log.e("WHATEVER", ">>> pause video at " + MyApplication.getMediaPlayer().getCurrentPosition());
            MyApplication.getMediaPlayer().pause();
            Intent intent = new Intent(getActivity(), ActivityB.class);
            startActivity(intent);
        }});
    

    Activity-B onCreate方法:

            textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int w, int h) {
                MediaPlayer mediaPlayer = MyApplication.getMediaPlayer();
                mediaPlayer.setSurface(new Surface(surface));
    
                Log.e("WHATEVER", ">>> resume video at " + mediaPlayer.getCurrentPosition());
                mediaPlayer.start();
            }
    
            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            }
    
            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                return false;
            }
    
            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {
            }
        });
    

    LogCat输出:

    10-10 17:33:15.966  13886-13886/com.whatever.android.debug E/WHATEVER﹕ >>> pause video at 1958
    10-10 17:33:16.817  13886-13886/com.whatever.android.debug E/WHATEVER﹕ >>> resume video at 1958
    

    所以即使看起来MediaPlayer会从那个确切的位置恢复,我对不同的视频会有不同的行为,每次我尝试在Activity-B中播放时,大多数都会从完全相同的帧开始视频从一开始就开始,另一个视频每次都从其他点开始。

    来自Android的MediaPlayer.SetSurface()方法文档:

    This method can be called in any state and calling it does not change the object state.

    非常感谢任何帮助。 谢谢!

2 个答案:

答案 0 :(得分:7)

似乎您的问题在于此特定视频,更多关键帧将有助于玩家更准确地恢复播放。

尝试再次重新编码,使用ffmpeg和libx264尝试添加以下参数:

-g=25 -keyint_min=25

答案 1 :(得分:0)

尝试使用Intent.putExtra()将MediaPlayer的位置从活动A传递到活动B.所以基本上在活动A中你打算开始活动B的意图,你会这样做:

 public void onClick(View v) {     
    Log.e("WHATEVER", ">>> pause video at " + MyApplication.getMediaPlayer().getCurrentPosition());
    MyApplication.getMediaPlayer().pause();
    int position = MyApplication.getMediaPlayer().getCurrentPosition(); //new line added
    Intent intent = new Intent(getActivity(), ActivityB.class);
    intent.putExtra("position", position); //another new line of code
    startActivity(intent);
}

现在在活动B中,在调用start之前寻找媒体播放器暂停的位置,如下所示:

@Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int w, int h) {
        MediaPlayer mediaPlayer = MyApplication.getMediaPlayer();
        mediaPlayer.setSurface(new Surface(surface));

        Log.e("WHATEVER", ">>> resume video at " + mediaPlayer.getCurrentPosition());
        mediaPlayer.seekTo(getIntent().getExtras().getInt("position"));// new line of code
        mediaPlayer.start();
    }