Android's MediaPlayer setSurface while on paused state

匿名 (未验证) 提交于 2019-12-03 03:08:02

问题:

EDIT:

So apparently this has nothing to do with multiple activities, and this has something to do with the encoding of the video file.

I will try to simplify the question: I have a MediaPlayer object in a paused state, when I call mediaPlayer.getCurrentPosition() I get a result which is accurate. When I call mediaPlayer.setSurface() (using a different surface) followed by mediaPlayer.play() on this object the video is played in a different position than the one returned by getCurrentPosition(). I am testing on API >= ICE_CREAM_SANDWICH.

  • Tested both using a local resource in the project and via network stream, result: no difference.

Link to video file: http://wpc.4ba9.edgecastcdn.net/804BA9/testenvmedia/m_8705_LuS3w7ctSZjB.mov.bs.mp4


I have two activities, Activity-A and Activity-B.

Activity-A plays video from a remote stream to a TextureView using a MediaPlayer, it also holds a button, who's purpose is to:

  1. Call mediaPlayer.pause();

  2. Open Activity-B.

Activity-B holds also a TextureView which is supposed to play the same video at it's current location using the same MediaPlayer object.

Activity-A onCreate method:

    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 method:

        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 output:

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 

So even though it seems like the MediaPlayer is going to resume from that exact position, I get different behaviour for different videos, most of them start at the exact same frame every time I try to play those in Activity-B, one video starts at the very beginning, other one starts at some other point every time.

From Android's documentation of MediaPlayer.SetSurface() method:

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

Any help would be greatly appreciated. Thanks!

回答1:

it seems your problem is with this specific video, more keyframes will help the player to resume the playing more accurately.

try to re-encode again, with ffmpeg and libx264 try adding these parameters:

-g=25 -keyint_min=25 


回答2:

Try passing the position of your MediaPlayer from activity A to Activity B using Intent.putExtra(). So Basically in Activity A where you call intent to start activity B, you would do this:

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

Now in Activity B seek to the position where mediaplayer was paused before calling start, like this:

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


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!