2013-04-09 9 views
5

の内側に私の問題は、私はアイドル状態この道を行くだけアンドロイド4.2.2アンドロイドmediaplyer seekTo onPrepared

に起こるようです - >初期化された状態 - > prepareAsync() - >とでseekToが呼び出されるonPreparedが、上このアンドロイドバージョンメディアプレーヤが

返します

を、私はポイントがないので、最初から再生を開始し、「ファイルの過去の最後まで追求する試みを要求= {int型> 0}、durationMs = 0」これをキャッチすることも、リスナーも、このメッセージをログに書き込むだけで、私は本当にそれに反応することはできません。

何でも見知らぬ人であることは、私はonPreparedでmediaPlayer.getDurationを()()を呼び出した場合、それは適切な値を返し、0ではなく

は、それがメディアプレーヤのバグであるか、どこへより良い場所があるあなたと思いますかということですcall seekTo?またはseekToを知る方法がうまくいかなかったのでしょうか?私は定期的に現在の位置を確認することを避けたい場合は、希望の位置よりも小さく、このアプローチは、多くの異なる問題があるため、シークを呼び出してみてください。

それはここでスムーズなストリーミングビデオコンテンツ

答えて

5

私は現在、同じ問題の解決方法を探しています。これまでのベストは、以下の通りです。

私は次のコールバックを受信したことに気付きました4.2で

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

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

あなたが述べたように、あなたがseekToを呼び出す場合(2)メディアプレーヤーが警告「ファイルの過去の最後をシークしよう」を生成

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バージョンで動作する優れたソリューションを持っていれば、それを聞いてみたいです。

+0

Robinの答えに続いて、メディアプレーヤーのソースコードをトレースして、期間値が最終的に設定される場所を探しました。私は、mDurationUsメンバの値を保持していると思われるAwesomePlayer構造体を持つStageFrightPlayerクラスを調べました。これは、initAudioDecoderまたはinitVideoDecoderのいずれかを呼び出したときに設定されるようです。私は理想的なソリューションは、これらの2つの関数のいずれかをJava MediaPlayer.start()関数を呼び出す必要なく呼び出されるのだろうと思いますか? – Simon

+0

この情報をAndroidのコメントとして追加しました[問題54112](http://code.google.com/p/android/issues/detail?id=54112)。 – Simon

+0

これは私の仕事です、ありがとう! – Eric

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を(呼び出すことをお勧め)デュレーションフィールドを初期化する強制的にメディアプレーヤのインスタンスを聞かせて最初。 それ以外の場合は、seekTo()の前にstart()を呼び出したり、start()の後にseekTo()を呼び出してみてください。

+1

残念なことに、getTo()をseekTo()の前に呼び出すと、seekTo()の前にstart()が呼び出され、seekToを呼び出すと遅延が発生することがあります。 –

2

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