5

私の問題はAndroid 4.2.2でのみ発生するようです

私はこのようにアイドル状態に行きます->初期化された状態-> prepareAsync()->そしてonPreparedでseekToが呼び出されますが、このAndroidバージョンではmediaplayerが返されます

「ファイルの終わりを超えてシークしようとしています: request = {int>0}、durationMs = 0」

最初から再生を開始します。これをキャッチできるポイントもリスナーもいないため、このメッセージをログに書き込むだけで、実際に反応することはできません。

さらに奇妙なのは、onPrepared() で mediaPlayer.getDuration() を呼び出すと、0 ではなく適切な値が返されることです。

それはメディアプレーヤーのバグだと思いますか、それとも seekTo を呼び出すのに適した場所はありますか? または、 seekTo が失敗したことを知る方法はありますか? 現在の位置が目的の位置よりも小さい場合は定期的にチェックすることを避け、このアプローチにはさまざまな問題があるため、シークを呼び出そうとします。

スムーズなストリーミング動画コンテンツです

4

3 に答える 3

5

私は現在、同じ問題の解決策を見つけようとしています。これまでのところ、私が思いついた最高のものは次のとおりです。

4.2 では、次のコールバックが受信されることに気付きました。

1) onVideoSizeChanged() - 高さと幅 = 0
2) onPrepared()
3) onVideoSizeChanged() - 適切な高さと幅

プレーヤーがまだ準備されていないため、(1) で seekTo を呼び出すことはできません。

ご指摘のとおり、(2) で seekTo を呼び出すと、メディア プレーヤーは「Attempt to seek to past end of file」という警告を生成します。

MediaPlayer.start() が呼び出された場合にのみ (3) を受け取りますが、この時点で seekTo() を正常に呼び出すことができます。

MediaPlayer mMediaPlayer = new MediaPlayer(); // + some initialisation code
boolean mVideoSizeIsSet = false;
boolean mMediaPlayerIsPrepared = false;

public void onPrepared(MediaPlayer mediaplayer) {
    Log.d(TAG, "onPrepared called");
    mMediaPlayerIsPrepared = true;

    if (mVideoSizeIsSet) {
        mMediaPlayer.seekTo();
    }

    mMediaPlayer.start()
}


public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
    Log.d(TAG, "onVideoSizeChanged called");

    if (width == 0 || height == 0) {
        Log.d(TAG, "invalid video width(" + width + ") or height(" + height + ")");
    } else {

        mVideoSizeIsSet = true;

        if (mMediaPlayerIsPrepared) {
            mMediaPlayer.seekTo();
        }
    }
}

(私は個人的にブール ガードの使用が好きではありませんが、SDK で提供されているメディア プレーヤーのサンプルを見ると、同様のことが行われています)。

さまざまなデバイス/OS バージョンにわたってテストすることで、一般的なソリューションが提供されます。ただし、4.2 にはバグがあります。mMediaPlayer.start() の呼び出しにより、seekTo() が発生する前にビデオの最初の数フレームの再生が開始されるようです。これは私の状況ではほとんど見えませんが、あなたにとってはもっと見えるかもしれません。現在、onSeekComplete() イベントを受け取るまで何らかの方法でサーフェス ビューを非表示にすることを検討していますが、これは理想的ではありません。

誰かがすべての OS バージョンで機能するより良い解決策を持っているなら、ぜひ聞いてみたいです。

于 2013-04-11T11:09:53.533 に答える
2

これは NuPlayer の実装の問題です。NuPlayer には、AwesomePlayer によるローカル再生とは異なり、適切な準備状態の実装がありません。ネットワーク接続は、start() が呼び出されたときにのみ確立され、その後の期間は既知です。期間が0の場合、期間チェックをバイパスすることで問題を解決できます。以前に試しました。

于 2013-06-07T05:53:49.010 に答える
0

ソースコードは次のとおりです。

418 status_t MediaPlayer::seekTo_l(int msec)
419 {
420     ALOGV("seekTo %d", msec);
421     if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
422         if ( msec < 0 ) {
423             ALOGW("Attempt to seek to invalid position: %d", msec);
424             msec = 0;
425         } else if ((mDuration > 0) && (msec > mDuration)) {
426             ALOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
427             msec = mDuration;
428         }
429         // cache duration
430         mCurrentPosition = msec;
431         if (mSeekPosition < 0) {
432             getDuration_l(NULL);
433             mSeekPosition = msec;
434             return mPlayer->seekTo(msec);
435         }
436         else {
437             ALOGV("Seek in progress - queue up seekTo[%d]", msec);
438             return NO_ERROR;
439         }
440     }
441     ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
442     return INVALID_OPERATION;
443 }

最初に getDuration() を呼び出して、mediaplayer インスタンスが期間フィールドを強制的に初期化できるようにすることをお勧めします。それ以外の場合は、seekTo() の前に start() を呼び出すか、start() の少し後に seekTo() を呼び出すようにしてください。

于 2013-04-09T09:50:58.430 に答える