對於http streaming,更新buffer進度的處理在AwesomePlayer::onBufferingUpdate()函數中,首先判斷mCachedSource != NULL,即是http://流媒體的情況下,通過getBitrate(&bitrate)函數取得bitrate,然後計算出buffer的進度,通過notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage)發訊息,在MediaPlayer.cpp類對應MediaPlayer::notify函數接收到MEDIA_BUFFERING_UPDATE訊息,然後在應用程式層通過註冊MediaPlayer的setOnBufferingUpdateListener監聽,接收到MEDIA_BUFFERING_UPDATE訊息,即可以獲得buffer更新的進度值percent。
1.AwesomePlayer::onBufferingUpdate()函數
計算buffer更新的percent
if (getBitrate(&bitrate)) { LOGV("onBufferingUpdate: bitrate: %lld", bitrate); size_t lowWaterThreshold = (size_t) ((bitrate * kLowWaterMarkUs * (1.0f + kThresholdPaddingFactor)) / 8000000ll); size_t highWaterThreshold = (size_t) ((bitrate * kHighWaterMarkUs * (1.0f + kThresholdPaddingFactor)) / 8000000ll); mCachedSource->setThresholds(lowWaterThreshold, highWaterThreshold); size_t cachedSize = mCachedSource->cachedSize(); int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; if (percentage > 100) { percentage = 100; } notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); } else {
其中8000000ll為1byte以us為單位的bit數,單位long long類型,即1byte = 1byte * 8bits/byte * 1000000us = 8000000ll
2.AwesomePlayer::getBitrate函數
bool AwesomePlayer::getBitrate(int64_t *bitrate) { off64_t size; if (mDurationUs >= 0 && mCachedSource != NULL && mCachedSource->getSize(&size) == OK) { *bitrate = size * 8000000ll / mDurationUs; // in bits/sec return true; } if (mBitrate >= 0) { *bitrate = mBitrate; return true; } *bitrate = 0; return false;}
3. NuCachedSource2::getSize
調用其成員變數mSource的getSize函數取得當前更新的size大小,mSouce即為NuCachedSource2建構函式傳遞的參數,此參數為AwesomePlayer::finishSetDataSource_l()函數中建立mCachedSource對象時傳遞的類型為NuHTTPDataSource的參數mConnectingDataSource。
所以,mSource->getSize調用的是NuHTTPDataSource的getSize函數。
status_t NuCachedSource2::getSize(off64_t *size) { return mSource->getSize(size);}
4.NuHTTPDataSource::getSize函數
此函數取得size值為mContentLength的值,取得mContentLength的值的處理在NuHTTPDataSource::connect函數,從http header中讀取的,即從"Content-Length"或者"Content-Range"頭域指定的值中計算出的。
NuCachedSource2和NuHTTPDataSource類以及getSize函數的關係圖如下:
5.mediaplayer.cpp的MediaPlayer::notify函數
void MediaPlayer::notify(int msg, int ext1, int ext2){... case MEDIA_BUFFERING_UPDATE: LOGV("buffering %d", ext1); break;... sp<MediaPlayerListener> listener = mListener; if (locked) mLock.unlock(); // this prevents re-entrant calls into client code if ((listener != 0) && send) { Mutex::Autolock _l(mNotifyLock); LOGV("callback application"); listener->notify(msg, ext1, ext2); // 發送訊息給MediaPlayer.java,然後應用程式層就接收到 LOGV("back from callback"); }
6.MediaPlayer.java的setOnBufferingUpdateListener函數
在onBufferingUpdate函數中的參數percent即為buffer更新進度值0-100.
/** * Interface definition of a callback to be invoked indicating buffering * status of a media resource being streamed over the network. */ public interface OnBufferingUpdateListener { /** * Called to update status in buffering a media stream. * * @param mp the MediaPlayer the update pertains to * @param percent the percentage (0-100) of the buffer * that has been filled thus far */ void onBufferingUpdate(MediaPlayer mp, int percent); } /** * Register a callback to be invoked when the status of a network * stream's buffer has changed. * * @param listener the callback that will be run. */ public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) { mOnBufferingUpdateListener = listener; }