Commit 95af6365 authored by Matt Wolenetz's avatar Matt Wolenetz Committed by Commit Bot

MSE: Destroy WMPI's ChunkDemuxer object using a background task

This change helps avoid renderer hang crashes on Windows by doing the
potentially costly destruction of a ChunkDemuxer object on a background
task.  The duration of that destruction, not including any initial
scheduling delay, is recorded in a new histogram:
"Media.MSE.DemuxerDestructionTime".

BUG=774268,774288,796704

Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I77dcb3ac1f7d5c5777f5302a7fc87199bf693d74
Reviewed-on: https://chromium-review.googlesource.com/838701
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Cr-Commit-Position: refs/heads/master@{#527125}
parent 70f3d32a
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/task_runner_util.h" #include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -336,10 +337,44 @@ WebMediaPlayerImpl::~WebMediaPlayerImpl() { ...@@ -336,10 +337,44 @@ WebMediaPlayerImpl::~WebMediaPlayerImpl() {
vfc_task_runner_->DeleteSoon(FROM_HERE, std::move(compositor_)); vfc_task_runner_->DeleteSoon(FROM_HERE, std::move(compositor_));
if (chunk_demuxer_) {
// Continue destruction of |chunk_demuxer_| on the |media_task_runner_| to
// avoid racing other pending tasks on |chunk_demuxer_| on that runner while
// not further blocking |main_task_runner_| to perform the destruction.
media_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&WebMediaPlayerImpl::DemuxerDestructionHelper,
media_task_runner_, std::move(demuxer_)));
}
media_log_->AddEvent( media_log_->AddEvent(
media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
} }
// static
void WebMediaPlayerImpl::DemuxerDestructionHelper(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<Demuxer> demuxer) {
DCHECK(task_runner->BelongsToCurrentThread());
// ChunkDemuxer's streams may contain much buffered, compressed media that may
// need to be paged back in during destruction. Paging delay may exceed the
// renderer hang monitor's threshold on at least Windows while also blocking
// other work on the renderer main thread, so we do the actual destruction in
// the background without blocking WMPI destruction or |task_runner|. On
// advice of task_scheduler OWNERS, MayBlock() is not used because virtual
// memory overhead is not considered blocking I/O; and CONTINUE_ON_SHUTDOWN is
// used to allow process termination to not block on completing the task.
base::PostTaskWithTraits(
FROM_HERE,
{base::TaskPriority::BACKGROUND,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(
[](std::unique_ptr<Demuxer> demuxer_to_destroy) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.MSE.DemuxerDestructionTime");
demuxer_to_destroy.reset();
},
std::move(demuxer)));
}
void WebMediaPlayerImpl::Load(LoadType load_type, void WebMediaPlayerImpl::Load(LoadType load_type,
const blink::WebMediaPlayerSource& source, const blink::WebMediaPlayerSource& source,
CORSMode cors_mode) { CORSMode cors_mode) {
...@@ -1131,6 +1166,7 @@ bool WebMediaPlayerImpl::CopyVideoTextureToPlatformTexture( ...@@ -1131,6 +1166,7 @@ bool WebMediaPlayerImpl::CopyVideoTextureToPlatformTexture(
format, type, level, premultiply_alpha, flip_y); format, type, level, premultiply_alpha, flip_y);
} }
// static
void WebMediaPlayerImpl::ComputeFrameUploadMetadata( void WebMediaPlayerImpl::ComputeFrameUploadMetadata(
VideoFrame* frame, VideoFrame* frame,
int already_uploaded_id, int already_uploaded_id,
...@@ -1386,8 +1422,10 @@ void WebMediaPlayerImpl::OnMemoryPressure( ...@@ -1386,8 +1422,10 @@ void WebMediaPlayerImpl::OnMemoryPressure(
memory_pressure_level == memory_pressure_level ==
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
// base::Unretained is safe, since chunk_demuxer_ is actually owned by // base::Unretained is safe, since |chunk_demuxer_| is actually owned by
// |this| via this->demuxer_. // |this| via this->demuxer_. Note the destruction of |chunk_demuxer_| is done
// from ~WMPI by first hopping to |media_task_runner_| to prevent race with
// this task.
media_task_runner_->PostTask( media_task_runner_->PostTask(
FROM_HERE, base::Bind(&ChunkDemuxer::OnMemoryPressure, FROM_HERE, base::Bind(&ChunkDemuxer::OnMemoryPressure,
base::Unretained(chunk_demuxer_), base::Unretained(chunk_demuxer_),
......
...@@ -108,6 +108,15 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl ...@@ -108,6 +108,15 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
std::unique_ptr<WebMediaPlayerParams> params); std::unique_ptr<WebMediaPlayerParams> params);
~WebMediaPlayerImpl() override; ~WebMediaPlayerImpl() override;
// Destroys |demuxer| and records a UMA for the time taken to destroy it.
// |task_runner| is the expected runner on which this method is called, and is
// used as a parameter to ensure a scheduled task bound to this method is run
// (to prevent uncontrolled |demuxer| destruction if |task_runner| has no
// other references before such task is executed.)
static void DemuxerDestructionHelper(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<Demuxer> demuxer);
// WebSurfaceLayerBridgeObserver implementation. // WebSurfaceLayerBridgeObserver implementation.
void OnWebLayerUpdated() override; void OnWebLayerUpdated() override;
void RegisterContentsLayer(blink::WebLayer* web_layer) override; void RegisterContentsLayer(blink::WebLayer* web_layer) override;
......
...@@ -6,20 +6,22 @@ ...@@ -6,20 +6,22 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <algorithm> #include <algorithm>
#include <queue>
#include <utility> #include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "media/base/audio_decoder_config.h" #include "media/base/audio_decoder_config.h"
#include "media/base/decoder_buffer.h" #include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h" #include "media/base/decrypt_config.h"
...@@ -1335,9 +1337,10 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> { ...@@ -1335,9 +1337,10 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
return true; return true;
} }
base::test::ScopedTaskEnvironment scoped_task_environment_;
StrictMock<MockMediaLog> media_log_; StrictMock<MockMediaLog> media_log_;
base::MessageLoop message_loop_;
MockDemuxerHost host_; MockDemuxerHost host_;
std::unique_ptr<ChunkDemuxer> demuxer_; std::unique_ptr<ChunkDemuxer> demuxer_;
......
...@@ -34503,6 +34503,14 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. ...@@ -34503,6 +34503,14 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary> </summary>
</histogram> </histogram>
<histogram name="Media.MSE.DemuxerDestructionTime" units="ms">
<owner>wolenetz@chromium.org</owner>
<summary>
Amount of time taken to destroy one ChunkDemuxer object, not including
initial background task scheduling delay.
</summary>
</histogram>
<histogram name="Media.MSE.DetectedTrackCount.Audio"> <histogram name="Media.MSE.DetectedTrackCount.Audio">
<owner>wolenetz@chromium.org</owner> <owner>wolenetz@chromium.org</owner>
<summary> <summary>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment