6

编辑

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

我将尝试简化问题:我有一个处于暂停状态的 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。

TextureViewActivity-A使用 a将视频从远程流播放到 a MediaPlayer,它还包含一个按钮,其目的是:

  1. 调用 mediaPlayer.pause();

  2. 打开活动-B。

Activity-B 还包含一个TextureView应该使用相同MediaPlayer对象在其当前位置播放相同视频的 a。

Activity-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.

任何帮助将不胜感激。谢谢!

4

2 回答 2

8

看来您的问题出在此特定视频上,更多关键帧将有助于播放器更准确地恢复播放。

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

-g=25 -keyint_min=25
于 2013-10-17T13:03:19.200 回答
0

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

 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);
}

现在在 Activity 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();
    }
于 2013-10-17T01:50:46.660 回答