zoukankan      html  css  js  c++  java
  • stagefright框架(一)Video Playback的流程

    在Android上,預設的多媒體框架(multimedia framework)是OpenCORE。 OpenCORE的優點是兼顧了跨平台的移植性,而且已經過多方驗證,所以相對來說較為穩定;但是其缺點是過於龐大複雜,需要耗費相當多的時間去維護。從 Android 2.0開始,Google引進了架構稍為簡潔的Stagefright,並且有逐漸取代OpenCORE的趨勢 (註1)。
    stagefright框架(一)Video <wbr>Playback的流程

    [圖1] Stagefright在Android多媒體架構中的位置。

    stagefright框架(一)Video <wbr>Playback的流程

    [圖2] Stagefright所涵蓋的模組 (註2)
    以下我們就先來看看Stagefright是如何播放一個影片檔。

    Stagefright
    在Android中是以shared library的形式存在(libstagefright.so),其中的module -- AwesomePlayer可用來播放video/audio (註3)。AwesomePlayer提供許多API,可以讓上層的應用程式(Java/JNI)來呼叫,我們以一個簡單的程式來說明video playback的流程。

    在Java中,若要播放一個影片檔,我們會這樣寫:

    MediaPlayer mp = new MediaPlayer();
    mp.setDataSource(PATH_TO_FILE); ...... (1)
    mp.prepare(); ........................ (2)、(3)
    mp.start(); .......................... (4)

    在Stagefright中,則會看到相對應的處理;

    (1) 將檔案的絕對路徑指定給mUri

    status_t AwesomePlayer::setDataSource(const char* uri...)
    {
      return setDataSource_l(uri...);
    }

    status_t AwesomePlayer::setDataSource_l(const char* uri...)
    {
      mUri = uri;
    }


    (2) 啟動mQueue,作為event handler

    status_t AwesomePlayer::prepare()
    {
      return prepare_l();
    }

    status_t AwesomePlayer::prepare_l()
    {
      prepareAsync_l();

      while (mFlags & PREPARING)
      {
        mPreparedCondition.wait(mLock);
      }
    }

    status_t AwesomePlayer::prepareAsync_l()
    {
      mQueue.start();

      mFlags |= PREPARING;
      mAsyncPrepareEvent new AwesomeEvent(
                                 this
                                 &AwesomePlayer::onPrepareAsyncEvent);
      mQueue.postEvent(mAsyncPrepareEvent);
    }


    (3) onPrepareAsyncEvent被觸發

    void AwesomePlayer::onPrepareAsyncEvent()
    {
      finishSetDataSource_l();

      initVideoDecoder().....(3.3)
      initAudioDecoder();
    }

    status_t AwesomePlayer::finishSetDataSource_l()
    {
      dataSource = DataSource::CreateFromURI(mUri.string()...);
      sp<MediaExtractor> extractor =
                         MediaExtractor::Create(dataSource)....(3.1)

      return setDataSource_l(extractor)........................(3.2)
    }


    (3.1) 解析mUri所指定的檔案,並且根據其header來選擇對應的extractor

    sp<MediaExtractorMediaExtractor::Create(const sp<DataSource&source...)
    {
      source->sniff(&tmp...);
      mime = tmp.string();

      if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
      {
        return new MPEG4Extractor(source);
      }
      else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG))
      {
        return new MP3Extractor(source);
      }
      else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
      {
        return new AMRExtractor(source);
      }
    }


    (3.2) 使用extractor對檔案做A/V的分離 (mVideoTrack/mAudioTrack)

    status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor&extractor)
    {
      for (size_t i = 0; i < extractor->countTracks()++i)
      {
        sp<MetaData> meta = extractor->getTrackMetaData(i);

        CHECK(meta->findCString(kKeyMIMEType&mime));

        if (!haveVideo &!strncasecmp(mime"video/", 6))
        {
          setVideoSource(extractor->getTrack(i));
          haveVideo true;
        }
        else if (!haveAudio &!strncasecmp(mime"audio/", 6))
        {
          setAudioSource(extractor->getTrack(i));
          haveAudio true;
        }
      }
    }

    void AwesomePlayer::setVideoSource(sp<MediaSource> source)
    {
      mVideoTrack = source;
    }


    (3.3) 根據mVideoTrack中的編碼類型來選擇video decoder (mVideoSource)

    status_t AwesomePlayer::initVideoDecoder()
    {
      mVideoSource = OMXCodec::Create(mClient.interface(),
                                      mVideoTrack->getFormat(),
                                      false,
                                      mVideoTrack);
    }


    (4) 將mVideoEvent放入mQueue中,開始解碼播放,並交由mVideoRenderer來畫出

    status_t AwesomePlayer::play()
    {
      return play_l();
    }

    status_t AwesomePlayer::play_l()
    {
      postVideoEvent_l();
    }

    void AwesomePlayer::postVideoEvent_l(int64_t delayUs)
    {
      mQueue.postEventWithDelay(mVideoEvent, delayUs);
    }

    void AwesomePlayer::onVideoEvent()
    {
      mVideoSource->read(&mVideoBuffer&options);
      [Check Timestamp]
      mVideoRenderer->render(mVideoBuffer);

      postVideoEvent_l();
    }



    stagefright框架(一)Video <wbr>Playback的流程
  • 相关阅读:
    java—— 字节流
    20-转>ES6转ES5的实现原理
    18-检验闭包是否真正理解?
    17-数组中去除基本数据类型和NaN的重复项(并保证原有数组顺序)
    16-实现一个Promise.all 和 Promise.race
    14-数组求和之递归方式
    13-斐波那契数列
    12-找到数组中的两项的和等于传入的指定数
    11-合并两个有序数组
    10-判断两个对象是否相等(有点类型every的实现)
  • 原文地址:https://www.cnblogs.com/shakin/p/4097089.html
Copyright © 2011-2022 走看看