美文网首页chromium从入门到放弃
chromium media 视频链接获取流程

chromium media 视频链接获取流程

作者: imesong | 来源:发表于2017-10-23 10:02 被阅读318次

为了快速的将视频绘制到WebView,内核获取到视频的URL之后,通过回调给到应用层,再设置给应用层播放器模块。

media_player_bridge.cc

void MediaPlayerBridge::Initialize() {
if (cvc) {
      Java_MediaPlayerBridge_createVideoView(
          env, j_media_player_bridge_.obj(), j_url_string.obj(), video_size_width_, video_size_height_, cvc->GetJavaObject().obj());
    }
}

browser_media_player_manager.cc

MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
    const MediaPlayerHostMsg_Initialize_Params& media_player_params,
    bool hide_url_log,
    MediaPlayerManager* manager,
    BrowserDemuxerAndroid* demuxer) {
     if (!content_view_core_impl) {
        // May reach here due to prerendering. Don't extract the metadata
        // since it is expensive.
        // TODO(qinmin): extract the metadata once the user decided to load
        // the page.
        browser_media_player_manager->OnMediaMetadataChanged(
            media_player_params.player_id, base::TimeDelta(), 0, 0, false);
      } else if (!content_view_core_impl->ShouldBlockMediaRequest(
            media_player_params.url)) {
        media_player_bridge->Initialize();
      }
      return media_player_bridge;
    }

browser_meida_player_manager.ccOnInitialize(xxxx)方法调用上面的方法

void BrowserMediaPlayerManager::OnInitialize(
    const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
    //llllllll.....
 MediaPlayerAndroid* player =
      CreateMediaPlayer(media_player_params,host->GetBrowserContext()->IsOffTheRecord(),this,host->browser_demuxer_android().get());   
}    

OnInitialize(xxx)方法通过IPC方式调用

media_web_contents_observer.cc

IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize,
                        GetMediaPlayerManager(render_frame_host),
                        BrowserMediaPlayerManager::OnInitialize)

发送IPC的地方

render_media_player_manager.cc

void RendererMediaPlayerManager::Initialize(
    MediaPlayerHostMsg_Initialize_Type type,
    int player_id,
    const GURL& url,
    const GURL& first_party_for_cookies,
    int demuxer_client_id,
    const GURL& frame_url,
    bool allow_credentials,
    const std::string& title,
    bool is_video,
    float video_size_width,
    float video_size_height) {
  MediaPlayerHostMsg_Initialize_Params media_player_params;
  media_player_params.type = type;
  media_player_params.player_id = player_id;
  media_player_params.demuxer_client_id = demuxer_client_id;
  media_player_params.url = url;
  media_player_params.first_party_for_cookies = first_party_for_cookies;
  media_player_params.frame_url = frame_url;
  media_player_params.allow_credentials = allow_credentials;
  media_player_params.title = title;
  media_player_params.is_video = is_video;
  media_player_params.video_size_width = video_size_width;
  media_player_params.video_size_height = video_size_height;
  Send(new MediaPlayerHostMsg_Initialize(routing_id(), media_player_params));
}    

webmediaplayer_android.cc

初始化 MediaPlayer 时调用上面的方法

void WebMediaPlayerAndroid::InitializePlayer(
    const GURL& url,
    const GURL& first_party_for_cookies,
    bool allow_stored_credentials,
    int demuxer_client_id) {
  if (player_type_ == MEDIA_PLAYER_TYPE_URL) {
    UMA_HISTOGRAM_BOOLEAN("Media.Android.IsHttpLiveStreamingMedia",
                          IsHLSStream());
  }
  allow_stored_credentials_ = allow_stored_credentials;

  //CS modify send title and video flag to Browser Process
  std::string title_std = frame_->document().title().utf8();
  player_manager_->Initialize(
      player_type_, player_id_, url, first_party_for_cookies, demuxer_client_id,
      frame_->document().url(), allow_stored_credentials, title_std, is_video_, video_size_width_, video_size_height_);
  //CS end

  if (is_fullscreen_)
    player_manager_->EnterFullscreen(player_id_);
}

在执行 load(xxx)和load2345(xxxx)时,会调用上面的方法。我们以load2345(xxx)为例接着跟踪

void WebMediaPlayerAndroid::load2345(LoadType load_type,
                                 const blink::WebURL& url,
                                 CORSMode cors_mode,
                                 bool is_video,
                                 float width,
                                 float height) {
                                 
     if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE) {
      media::SetDecryptorReadyCB set_decryptor_ready_cb =
          media::BindToCurrentLoop(
              base::Bind(&WebMediaPlayerAndroid::SetDecryptorReadyCB,
                         weak_factory_.GetWeakPtr()));

      media_source_delegate_->InitializeMediaSource(
          base::Bind(&WebMediaPlayerAndroid::OnMediaSourceOpened,
                     weak_factory_.GetWeakPtr()),
          base::Bind(&WebMediaPlayerAndroid::OnEncryptedMediaInitData,
                     weak_factory_.GetWeakPtr()),
          set_decryptor_ready_cb,
          base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,
                     weak_factory_.GetWeakPtr()),
          base::Bind(&WebMediaPlayerAndroid::OnDurationChanged,
                     weak_factory_.GetWeakPtr()));
      InitializePlayer(url_, frame_->document().firstPartyForCookies(),
                       true, demuxer_client_id);
    }
}                                 

再跟踪WebMediaPlayerAndroid 中 load2345(xxx)被调用的地方。这个比较复杂,牵扯到 MediaPlayer,MediaPlayClient,MediaPlayerClientImpl

WebMediaPlayerClientImpl.cpp

void WebMediaPlayerClientImpl::load2345(WebMediaPlayer::LoadType loadType, const WTF::String& url, WebMediaPlayer::CORSMode corsMode, bool is_video, float width, float height)
{
    m_webMediaPlayer->load2345(loadType, kurl, corsMode, is_video, width, height);
}

上面的方法中,第二个参数就是视频链接的URL

HTMLMediaElement.cpp

void HTMLMediaElement::startPlayerLoad()
{
    // Filter out user:pass as those two URL components aren't
    // considered for media resource fetches (including for the CORS
    // use-credentials mode.) That behavior aligns with Gecko, with IE
    // being more restrictive and not allowing fetches to such URLs.
    // Spec reference: http://whatwg.org/c/#concept-media-load-resource
    // FIXME: when the HTML spec switches to specifying resource
    // fetches in terms of Fetch (http://fetch.spec.whatwg.org), and
    // along with that potentially also specifying a setting for its
    // 'authentication flag' to control how user:pass embedded in a
    // media resource URL should be treated, then update the handling
    // here to match.
    KURL requestURL = m_currentSrc;
    if (!requestURL.user().isEmpty())
        requestURL.setUser(String());
    if (!requestURL.pass().isEmpty())
        requestURL.setPass(String());

    if(isHTMLVideoElement())
        m_player->load2345(loadType(), requestURL, corsMode(), true, m_size_width2345, m_size_height2345);
    else
        m_player->load(loadType(), requestURL, corsMode());
}

startPlayerLoad()方法中的注释挺重要的,URL 在这里赋值


void HTMLMediaElement::executeDeferredLoad()
{
// resource fetch algorithm step 3 - continued from deferLoad().
    // 5. Wait for an implementation-defined event (e.g. the user requesting that the media element begin playback).
    // This is assumed to be whatever 'event' ended up calling this method.
    cancelDeferredLoad();
    // 6. Set the element's delaying-the-load-event flag back to true (this
    // delays the load event again, in case it hasn't been fired yet).
    setShouldDelayLoadEvent(true);
    // 7. Set the networkState to NETWORK_LOADING.
    m_networkState = NETWORK_LOADING;
    startProgressEventTimer();
    startPlayerLoad();
}
void HTMLMediaElement::startDeferredLoad()
{
    if (m_deferredLoadState == WaitingForTrigger) {
        executeDeferredLoad();
        return;
    }
    ASSERT(m_deferredLoadState == WaitingForStopDelayingLoadEventTask);
    m_deferredLoadState = ExecuteOnStopDelayingLoadEventTask;
}

两个方法 setPlayerPreload() 和 prepareToPlay() 调用上面的方法

void HTMLMediaElement::setPlayerPreload()
{
    m_player->setPreload(m_preload);

    if (loadIsDeferred() && m_preload != MediaPlayer::None)
        startDeferredLoad();
}

void HTMLMediaElement::prepareToPlay()
{
    WTF_LOG(Media, "HTMLMediaElement::prepareToPlay(%p)", this);
    if (m_havePreparedToPlay)
        return;
    m_havePreparedToPlay = true;

    if (loadIsDeferred())
        startDeferredLoad();
}

调用 setPlayerPreload()方法的地方

void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
//里面的逻辑代码被我们修改,主要解决视频自动播放遇到的问题
  // The attribute must be ignored if the autoplay attribute is present
        if (!autoplay() && m_player)
            setPlayerPreload();
}

void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType, const String& keySystem)
{
    if (!autoplay())
        setPlayerPreload();
}

调用 prepareToPlay()的方法

void HTMLMediaElement::load()
{
    //lllllue去若干
    prepareForLoad();
    loadInternal();
    prepareToPlay();
}

void HTMLMediaElement::updatePlayState()
{
    // some other codes
    if (couldPlayIfEnoughData())
         prepareToPlay();
    //some other codes     
}

到此,获取URL的基本流程走完。

相关文章

网友评论

    本文标题:chromium media 视频链接获取流程

    本文链接:https://www.haomeiwen.com/subject/ptibyxtx.html