2013-04-09 69 views
5

我的問題似乎我去只發生在Android 4.2.2安卓mediaplyer seekTo內onPrepared

這樣空閒狀態 - >初始化狀態 - > prepareAsync() - >和onPrepared的seekTo被調用,但這個Android版本的媒體播放器返回

「試圖謀求過去文件的末尾:請求= {int>的0},DURATION毫秒= 0」

,並開始從開始玩,因爲沒有點在哪裏可以捕捉到這一點,也沒有任何聽衆,它只是寫這條消息到日誌,我不能對此做出反應。

更奇怪的是,如果我叫mediaPlayer.getDuration()在onPrepared()返回正確的值,而不是0

,你認爲這是一個媒體播放器的bug或者有更好的地方在哪裏請致電seekTo?或者如何知道seekTo失敗的方法?我想避免定期檢查當前位置,如果它小於所需位置,並嘗試呼叫尋求,因爲這種方法有很多不同的問題。

它是一個流暢的流媒體視頻內容

回答

5

我目前正試圖找到解決同一問題的方法。到目前爲止我所得到的最好結果如下。

在4.2我注意到以下回調被接收:

1)onVideoSizeChanged() - ,其中高度和寬度= 0
2)onPrepared()
3)onVideoSizeChanged() - 適當的高度和寬度

由於玩家尚未準備好,您無法在(1)中調用seekTo。

正如你提到的,如果你在調用seekTo(2)媒體播放器生成警告「試圖尋求過去的文件結束」

您只收到(3)如果MediaPlayer.start()已叫,但在這一點上,你可以成功調用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中的媒體播放器的樣品,它類似的東西)。

通過一系列設備/操作系統版本進行測試,這提供了一個通用的解決方案。但是,有一個4.2的錯誤。調用mMediaPlayer.start()似乎會導致在seekTo()發生之前開始播放視頻的前幾幀,這對於我的情況幾乎不可見,但對您而言可能更明顯。我目前正在尋找隱藏我的表面視圖,直到我收到onSeekComplete()事件,但這並不理想。

如果任何人有更好的解決方案,適用於所有操作系統版本,我很樂意聽到它。

+0

繼Robin的回答之後,我試圖追蹤媒體播放器源代碼,最終設置持續時間值。我最終看到了StageFrightPlayer類,它有一個AwesomePlayer結構,它似乎在其mDurationUs成員中保存了值。當調用initAudioDecoder或initVideoDecoder時,這似乎會被設置。我想理想的解決方案會導致這兩個函數之一被調用,而不需要調用java MediaPlayer.start()函數? – Simon 2013-04-11 15:35:54

+0

我也剛剛在Android上添加了這條信息作爲評論[Issue 54112](http://code.google.com/p/android/issues/detail?id=54112)。 – Simon 2013-04-11 16:35:52

+0

這是爲我工作,謝謝! – Eric 2014-06-18 17:02:36

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

謝謝你的回覆,遺憾的是在seekTo沒有幫助之前調用getDuration(),seekTo()之前的start()也沒有幫助,並且延遲調用seekTo不是一個可靠的解決方案。 – 2013-04-10 07:00:33

2

這是NuPlayer實現中的問題。與使用AwesomePlayer進行本地播放不同,NuPlayer沒有正確的準備狀態實現。只有在調用start()之後才建立網絡連接,之後的持續時間是已知的。如果持續時間爲0,則可以通過繞過持續時間檢查來解決問題,我之前已經嘗試過。