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 の 2 つのアクティビティがあります。

TextureViewActivity-A は、を使用してリモート ストリームから にビデオを再生しMediaPlayerます。ボタンも保持します。目的は次のとおりです。

  1. mediaPlayer.pause() を呼び出します。

  2. アクティビティ B を開きます。

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

アクティビティ 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 でそれらを再生しようとするたびにまったく同じフレームで開始されます。1 つの動画は一番最初、他のものは毎回別のポイントから始まります。

メソッドの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

を使用してアクティビティ A からアクティビティ B に MediaPlayer の位置を渡してみてくださいIntent.putExtra()。したがって、基本的に、アクティビティ 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);
}

アクティビティ B で、次のように、start を呼び出す前に mediaplayer が一時停止された位置をシークします。

@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 に答える