AwesomePlayer 原始碼分析

來源:互聯網
上載者:User

 

  1,AwesomeEvent 這個是同步相應的事件而做的一個類,跟framework層的looper和handler作用相似,player有一些非同步作業比如解析檔案,這些操作比較耗時,做非同步作業然後做回調會有更好的使用者體驗

struct AwesomeEvent : public TimedEventQueue::Event

    繼承自TimedEventQueue::Event  ,關於c++的內部類可以參考以前的blog,TimedEventQueue會起一個thread,來做event的post操作

 

  2, AwesomeRemoteRenderer

   AwesomeLocalRenderer

 這兩個類是往surface上post資料,而remote據說是因為omx node的使用,還沒有細研究,而localrenderer會根據有無硬體加速調用不同的方法

 

3 建構函式會初始化event,這些後面再說

mediaplayer的一般方法流程是

setdatasource

prepareAsync

start

現在只針對filesource做流程分析

 

 setdatasource 一般會設定file的uri

mUri = uri;現在只是設定一下uri,下面有段注釋

    // The actual work will be done during preparation in the call to
    // ::finishSetDataSource_l to avoid blocking the calling thread in
    // setDataSource for any significant time.

現在不會做其他的操作,因為會消耗太多的時間有可能導致上層的ANR,這個操作是同步操作

重頭戲就在prepareAsync裡面了,看這個函數

    if (!mQueueStarted) {
        mQueue.start();
        mQueueStarted = true;
    }//會把eventqueue開啟,為以後的event post做準備,這個時候會建立一個線程

    mAsyncPrepareEvent = new AwesomeEvent(
            this, &AwesomePlayer::onPrepareAsyncEvent);

    mQueue.postEvent(mAsyncPrepareEvent);
//為了能非同步,postevent

 

到   onPrepareAsyncEvent()

 if (mUri.size() > 0) {
        status_t err = finishSetDataSource_l();

        if (err != OK) {
            abortPrepare(err);
            return;
        }
    }

 

finishSetDataSource_l();//這個就是上面注釋的那個函數 這個函數會根據source類型建立不同的extractor

針對filesource,實際就是這個dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);//uriheaders為null,不用管它

接著跳轉 到source = new FileSource(uri+7);建立filesource,它會註冊不同的extractor,sniffer出不同的mimetype,操作filesource

接著回到  finishSetDataSource_l(),

sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource,mime);

這個時候datasource會sniffer出不同的extractor,從而根據mime type建立不同的extractor

最後就是setdatasource這個本來應該第一步做的操作

這個時候會解析出audio track和viedo track,為下面的codec做準備

    if (mVideoTrack != NULL && mVideoSource == NULL) {
        // Use NPT timestamps if playing
        // RTSP streaming with video only content
        // (no audio to drive the clock for media time)
        uint32_t flags = 0;
        if (mRTSPController != NULL && mAudioTrack == NULL) {
            flags |= OMXCodec::kUseNptTimestamp;
        }
        status_t err = initVideoDecoder(flags);

        if (err != OK) {
            abortPrepare(err);
            return;
        }
    }

    if (mAudioTrack != NULL && mAudioSource == NULL) {
        status_t err = initAudioDecoder();

        if (err != OK) {
            abortPrepare(err);
            return;
        }
    }

這個就是涉及最關鍵的部分了 codec部分

從上面下來 audiotrack 和videotrack都已經有了 這個時候就要初始化codec了

initVideoDecoder(flags);

initAudioDecoder();

{
    mVideoSource = OMXCodec::Create(
            mClient.interface(), mVideoTrack->getFormat(),
            false, // createEncoder
            mVideoTrack,
            NULL, flags);

OMXCodec是個很關鍵的類,這個就到了前幾天寫的stagefright的code裡面了,我會繼續寫那個,不在這裡說了,總之會返回一個Videosource,這個是根據videotrack解碼過的資料

    if (mVideoSource != NULL) {

        int64_t durationUs;
        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
            Mutex::Autolock autoLock(mMiscStateLock);
            if (mDurationUs < 0 || durationUs > mDurationUs) {
                mDurationUs = durationUs;
            }
        }

        CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
        CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));

        status_t err = mVideoSource->start(); //這個時候videosource和viedotrack都會準備好,申請buffer

        if (err != OK) {
            mVideoSource.clear();
            return err;
        }
    }

    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
}

弄好以後就會更改狀態,做上層的prepareAsync的回調

資料已經準備了,

play_l()

if ((mVideoSource != NULL) && (!mVideoBuffer))

{
    // Changes to fix Audio starts playing before video.
    // First video frame is returned late as it is referenced to decode subsequent P and B frames.
    // For higher resolutions (e.g. 1080p) this returning time is significant.
    // We need to trigger Video decoder earlier than audio so that Video catch up with audio in time.
        MediaSource::ReadOptions options;
        if (mSeeking) {
            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);

            options.setSeekTo(
                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
        }
        for (;;) {
            status_t err = mVideoSource->read(&mVideoBuffer, &options);
            options.clearSeekTo();

            if (err != OK) {
                CHECK_EQ(mVideoBuffer, NULL);

                if (err == INFO_FORMAT_CHANGED) {
                    LOGV("VideoSource signalled format change.");

                    if (mVideoRenderer != NULL) {
                        mVideoRendererIsPreview = false;
                        initRenderer_l();
                    }
                    continue;
                }
                break;
            }

 

            break;
        }
    }

    if (mVideoSource != NULL) {
        // Kick off video playback
        postVideoEvent_l();
    }

就會把得到的mVideoBuffer render到surface上面

而audio會調用audioplayer

 mAudioPlayer = new AudioPlayer(mAudioSink, this);
                mAudioPlayer->setSource(mAudioSource);

                // We've already started the MediaSource in order to enable
                // the prefetcher to read its data.
                status_t err = mAudioPlayer->start(
                        true /* sourceAlreadyStarted */);

還有音視頻同步,seek的問題,下次再寫

ps-----這篇是針對2.3的代碼,4.0以後又發生了一些變化,後面的問題就沒有寫完,會寫一些4.0相關的東西

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.