为了快速的将视频绘制到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.cc,OnInitialize(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的基本流程走完。
网友评论