chromium_67.0.3364.0

chromium在60版本之后,在media部分做了些许改变,此文档就当笔记,以免以后忘记。


使用优酷,腾讯,爱奇艺等国内网站全屏播放视频时,此时当有第三方APP打断,如接听电话,微信,短信等,当浏览器切回到后端再返回的时候,android上使用67版本会必现crash。


以下是APP相关log:

/sprdroid9.0_trunk/vendor/sprd/platform/packages/apps/SprdBrowser/src/com/android/browser/BrowserActivity.java
  protected void onStop()
 
/sprdroid9.0_trunk/vendor/sprd/platform/packages/apps/SprdBrowser/src/com/android/browser/Controller.java
  pauseWebViewTimer
     onBrowserActivityPause

 WebViewTimersControl: onBrowserActivityResume


以下是暂停的流程:

bool RendererWebMediaPlayerDelegate::OnMessageReceived   MediaPlayerDelegateMsg_Pause
 void RendererWebMediaPlayerDelegate::OnMediaDelegatePause(int player_id)
  void WebMediaPlayerImpl::OnPause() 
   void WebMediaPlayerImpl::Pause() 
bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg)
 

 

bool RenderWidget::OnMessageReceived(const IPC::Message& message)    IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
    
  void RenderWidget::OnWasHidden() 

    void RenderFrameImpl::WasHidden()

        void RendererWebMediaPlayerDelegate::WasHidden()    

            void WebMediaPlayerImpl::OnFrameHidden()    
    
                void WebMediaPlayerImpl::UpdatePlayState()    
    
                     void WebMediaPlayerImpl::SetSuspendState(bool is_suspended)    
    
                          void PipelineController::Suspend()
                            
                               void PipelineController::Dispatch()
                                    181
                                    void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb)
                                    
                                         void PipelineImpl::RendererWrapper::Suspend() 
                                         
                                              void PipelineImpl::RendererWrapper::CompleteSuspend(PipelineStatus status)
                                              
                                                   void PipelineImpl::OnSuspendDone()  is_suspended_ = true;
                                                                                              
bool RenderViewImpl::OnMessageReceived(const IPC::Message& message)
   IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))

 

 

bool RendererWebMediaPlayerDelegate::OnMessageReceived  MediaPlayerDelegateMsg_Play

    void RendererWebMediaPlayerDelegate::OnMediaDelegatePlay
    
        void WebMediaPlayerImpl::OnPlay()
        
            void WebMediaPlayerImpl::Play()
            
                void WebMediaPlayerImpl::UpdatePlayState()
                
                    void WebMediaPlayerImpl::SetSuspendState(bool is_suspended)
                    
                        void PipelineController::Resume()
                        
                            void PipelineController::Dispatch()
                            
                                void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer,
                                         
                                    void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer,   renderer  null
                                         
                                           void PipelineImpl::RendererWrapper::InitializeRenderer  shared_state_.renderer=0x0
                                               
bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg)

 

由于问题是必现问题,所以经过2周的分析,发现chromium在60版本之后,当全屏暂停之后重新开始播放的时候的createrender的流程与一开始启动浏览器播放视频的createrender不同,在59版本上面,无论是否暂停使用的都是default_renderer_factory.cc

但是在chromium_67.0.3364.0版本上面,启动和暂停的factory是不相同的,启动播放的是:

src\media\renderers\default_renderer_factory.cc

暂停后再次创建使用的是:

src\media\mojo\clients\mojo_renderer_factory.cc    CourierRendererFactory

而在CourierRendererFactory中暂停后在android中使用的话就会一直返回nullptr.

std::unique_ptr<Renderer> CourierRendererFactory::CreateRenderer(
    const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
    const scoped_refptr<base::TaskRunner>& worker_task_runner,
    AudioRendererSink* audio_renderer_sink,
    VideoRendererSink* video_renderer_sink,
    const RequestOverlayInfoCB& request_overlay_info_cb,
    const gfx::ColorSpace& target_color_space) {
  DCHECK(IsRemotingActive());
#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC)
  return std::make_unique<CourierRenderer>(
      media_task_runner, controller_->GetWeakPtr(), video_renderer_sink);
#else
  return nullptr;
#endif
}

 

void PipelineImpl::RendererWrapper::InitializeRenderer(
    const PipelineStatusCB& done_cb) {
  DCHECK(media_task_runner_->BelongsToCurrentThread());

  switch (demuxer_->GetType()) {
    case MediaResource::Type::STREAM:
      if (demuxer_->GetAllStreams().empty()) {
        DVLOG(1) << "Error: demuxer does not have an audio or a video stream.";
        done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
        return;
      }
      break;

    case MediaResource::Type::URL:
      // NOTE: Empty GURL are not valid.
      if (!demuxer_->GetMediaUrlParams().media_url.is_valid()) {
        DVLOG(1) << "Error: demuxer does not have a valid URL.";
        done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
        return;
      }
      break;
  }

  if (cdm_context_) {
    shared_state_.renderer->SetCdm(cdm_context_,
                                   base::BindRepeating(&IgnoreCdmAttached));
  }

  shared_state_.renderer->Initialize(demuxer_, this, done_cb);
}

 

void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer,
                                           base::TimeDelta timestamp) {
  DCHECK(media_task_runner_->BelongsToCurrentThread());

  // Tracking down http://crbug.com/827990
  CHECK(renderer);

  // Suppress resuming if we're not suspended.
  if (state_ != kSuspended) {
    DCHECK(state_ == kStopping || state_ == kStopped)
        << "Receive resume in unexpected state: " << state_;
    OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
    return;
  }
  DCHECK(!pending_callbacks_.get());

  SetState(kResuming);

  {
    base::AutoLock auto_lock(shared_state_lock_);
    DCHECK(!shared_state_.renderer);
    shared_state_.renderer = std::move(renderer);
  }

  renderer_ended_ = false;
  text_renderer_ended_ = false;
  base::TimeDelta start_timestamp =
      std::max(timestamp, demuxer_->GetStartTime());

  // Queue the asynchronous actions required to start playback.
  SerialRunner::Queue fns;

  fns.Push(base::BindRepeating(&Demuxer::Seek, base::Unretained(demuxer_),
                               start_timestamp));

  fns.Push(base::BindRepeating(&RendererWrapper::InitializeRenderer,
                               weak_factory_.GetWeakPtr()));

  pending_callbacks_ = SerialRunner::Run(
      fns, base::BindRepeating(&RendererWrapper::CompleteSeek,
                               weak_factory_.GetWeakPtr(), start_timestamp));
}

在播放过程中,暂停之后会调用DestroyRenderer,之后resume到的shared_state_.renderer值为空。在resume添加了调用栈,最终发现是类型为RendererFactoryCB的 renderer_factory_cb_为空,进而分析到PipelineController对象被析构掉了,最后得到当浏览器切回到前端时,之前的render被DestroyRenderer掉之后,resume的时候shared_state_.renderer的值在CreateRenderer的时候一直返回空,所以修改了media/media_options.gni的配置enable_media_remoting_rpc = enable_media_remoting && is_android;解决此问题。

 

但是我还是有一个疑问,如果60版本之后android上enable_media_remoting_rpc这个宏是关闭的情况下,68版本又是好用的,所以我觉得还是跟gn args的配置有关系。

本文中使用的gn args如下;

target_os = "android"

target_cpu = "arm" # (default)

is_debug = false # (default)

symbol_level = 2

is_official_build=true

is_chrome_branded=false

use_official_google_api_keys=false

exclude_unwind_tables=false

enable_resource_whitelist_generation=true

ffmpeg_branding="Chrome"

proprietary_codecs=true

enable_remoting=true

ignore_elf32_limitations=true

 

如有转发,请注明出处,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值