Commit b8656777 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Implement media metrics for WebEngine

Added new PlaybackEventsRecorder interface that allows to record media
pipeline events. It's implemented only for Fuchsia and logs events that
we need to be logged from WebEngine.

Bug: 1067068
Change-Id: I7994d41af67f4ec29e5773147ed302bb86b3c3c4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2148037
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarKevin Marshall <kmarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#761184}
parent a4331b54
......@@ -181,7 +181,10 @@ test("media_unittests") {
}
if (is_fuchsia) {
deps += [ "//media/fuchsia/audio:unittests" ]
deps += [
"//media/fuchsia/audio:unittests",
"//media/fuchsia/metrics:unittests",
]
}
if (enable_media_remoting) {
......
......@@ -261,6 +261,9 @@ class WatchTimeReporterTest
const std::string& taskName,
mojo::PendingReceiver<media::learning::mojom::LearningTaskController>
receiver) override {}
void AcquirePlaybackEventsRecorder(
mojo::PendingReceiver<mojom::PlaybackEventsRecorder> receiver)
override {}
void Initialize(bool is_mse, mojom::MediaURLScheme url_scheme) override {}
void OnError(PipelineStatus status) override {}
void SetIsEME() override {}
......
......@@ -413,6 +413,9 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
base::BindRepeating(&WebMediaPlayerImpl::OnMainThreadMemoryDump,
weak_this_, media_log_->id()));
media_metrics_provider_->AcquirePlaybackEventsRecorder(
playback_events_recorder_.BindNewPipeAndPassReceiver());
#if defined(OS_ANDROID)
renderer_factory_selector_->SetRemotePlayStateChangeCB(
BindToCurrentLoop(base::BindRepeating(
......@@ -788,6 +791,9 @@ void WebMediaPlayerImpl::Play() {
// Try to create the smoothness helper, in case we were paused before.
UpdateSmoothnessHelper();
if (playback_events_recorder_)
playback_events_recorder_->OnPlaying();
watch_time_reporter_->SetAutoplayInitiated(client_->WasAutoplayInitiated());
// If we're seeking we'll trigger the watch time reporter upon seek completed;
......@@ -839,6 +845,9 @@ void WebMediaPlayerImpl::Pause() {
if (observer_)
observer_->OnPaused();
if (playback_events_recorder_)
playback_events_recorder_->OnPaused();
DCHECK(watch_time_reporter_);
watch_time_reporter_->OnPaused();
......@@ -894,6 +903,9 @@ void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
return;
}
if (playback_events_recorder_)
playback_events_recorder_->OnSeeking();
// Call this before setting |seeking_| so that the current media time can be
// recorded by the reporter.
if (watch_time_reporter_)
......@@ -1590,6 +1602,8 @@ void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
} else {
DCHECK(watch_time_reporter_);
watch_time_reporter_->OnPlaying();
if (playback_events_recorder_)
playback_events_recorder_->OnPlaying();
}
if (time_updated)
should_notify_time_changed_ = true;
......@@ -1824,6 +1838,8 @@ void WebMediaPlayerImpl::OnError(PipelineStatus status) {
simple_watch_timer_.Stop();
media_log_->NotifyError(status);
media_metrics_provider_->OnError(status);
if (playback_events_recorder_)
playback_events_recorder_->OnError(status);
if (watch_time_reporter_)
watch_time_reporter_->OnError(status);
......@@ -1854,6 +1870,9 @@ void WebMediaPlayerImpl::OnEnded() {
ended_ = true;
client_->TimeChanged();
if (playback_events_recorder_)
playback_events_recorder_->OnEnded();
// We don't actually want this to run until |client_| calls seek() or pause(),
// but that should have already happened in timeChanged() and so this is
// expected to be a no-op.
......@@ -2139,6 +2158,9 @@ void WebMediaPlayerImpl::OnBufferingStateChangeInternal(
watch_time_reporter_->OnUnderflowComplete(elapsed);
underflow_timer_.reset();
}
if (playback_events_recorder_)
playback_events_recorder_->OnBufferingComplete();
} else {
// Buffering has underflowed.
DCHECK_EQ(state, BUFFERING_HAVE_NOTHING);
......@@ -2150,6 +2172,9 @@ void WebMediaPlayerImpl::OnBufferingStateChangeInternal(
!seeking_) {
underflow_timer_ = std::make_unique<base::ElapsedTimer>();
watch_time_reporter_->OnUnderflow();
if (playback_events_recorder_)
playback_events_recorder_->OnBuffering();
}
// It shouldn't be possible to underflow if we've not advanced past
......@@ -3650,6 +3675,9 @@ void WebMediaPlayerImpl::RecordVideoNaturalSize(const gfx::Size& natural_size) {
UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.EME", height);
UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.All", height);
if (playback_events_recorder_)
playback_events_recorder_->OnNaturalSizeChanged(natural_size);
}
#undef UMA_HISTOGRAM_VIDEO_HEIGHT
......@@ -3747,6 +3775,9 @@ void WebMediaPlayerImpl::MaybeUpdateBufferSizesForPlayback() {
void WebMediaPlayerImpl::OnSimpleWatchTimerTick() {
RecordSimpleWatchTimeUMA(reported_renderer_type_);
if (playback_events_recorder_)
playback_events_recorder_->OnPipelineStatistics(GetPipelineStatistics());
}
GURL WebMediaPlayerImpl::GetSrcAfterRedirects() {
......
......@@ -45,6 +45,7 @@
#include "media/blink/webmediaplayer_params.h"
#include "media/filters/pipeline_controller.h"
#include "media/learning/common/media_learning_tasks.h"
#include "media/mojo/mojom/playback_events_recorder.mojom.h"
#include "media/renderers/paint_canvas_video_renderer.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/public/cpp/media_position.h"
......@@ -1004,6 +1005,7 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
base::CancelableClosure update_background_status_cb_;
mojo::Remote<mojom::MediaMetricsProvider> media_metrics_provider_;
mojo::Remote<mojom::PlaybackEventsRecorder> playback_events_recorder_;
base::Optional<ReadyState> stale_state_override_for_testing_;
......
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("metrics") {
sources = [
"fuchsia_playback_events_recorder.cc",
"fuchsia_playback_events_recorder.h",
]
deps = [
"//media/mojo/mojom",
"//mojo/public/cpp/bindings",
]
}
source_set("unittests") {
testonly = true
deps = [
":metrics",
"//base",
"//base/test:test_support",
"//media",
"//testing/gtest",
]
sources = [ "fuchsia_playback_events_recorder_test.cc" ]
}
include_rules = [
"+mojo/public",
]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/fuchsia/metrics/fuchsia_playback_events_recorder.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/stringprintf.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
namespace media {
namespace {
void RecordEventWithValueAt(const char* name,
int64_t value,
base::TimeTicks time) {
base::RecordComputedActionAt(
base::StringPrintf("WebEngine.Media.%s:%ld", name, value), time);
}
void RecordEventWithValue(const char* name, int64_t value) {
RecordEventWithValueAt(name, value, base::TimeTicks::Now());
}
constexpr base::TimeDelta kBitrateReportPeriod =
base::TimeDelta::FromSeconds(5);
} // namespace
FuchsiaPlaybackEventsRecorder::BitrateEstimator::BitrateEstimator() {}
FuchsiaPlaybackEventsRecorder::BitrateEstimator::~BitrateEstimator() {}
void FuchsiaPlaybackEventsRecorder::BitrateEstimator::Update(
const PipelineStatistics& stats) {
base::TimeTicks now = base::TimeTicks::Now();
// The code below trusts that |stats| are valid even though they came from an
// untrusted process. That's accepable because the stats are used only to
// record metrics.
if (last_stats_) {
time_elapsed_ += now - last_stats_time_;
audio_bytes_ +=
stats.audio_bytes_decoded - last_stats_->audio_bytes_decoded;
video_bytes_ +=
stats.video_bytes_decoded - last_stats_->video_bytes_decoded;
if (time_elapsed_ >= kBitrateReportPeriod) {
size_t audio_bitrate_kbps =
8 * audio_bytes_ / time_elapsed_.InMilliseconds();
RecordEventWithValueAt("AudioBitrate", audio_bitrate_kbps, now);
size_t video_bitrate_kbps =
8 * video_bytes_ / time_elapsed_.InMilliseconds();
RecordEventWithValueAt("VideoBitrate", video_bitrate_kbps, now);
time_elapsed_ = base::TimeDelta();
audio_bytes_ = 0;
video_bytes_ = 0;
}
}
last_stats_ = stats;
last_stats_time_ = now;
}
void FuchsiaPlaybackEventsRecorder::BitrateEstimator::OnPause() {
last_stats_ = {};
}
// static
void FuchsiaPlaybackEventsRecorder::Create(
mojo::PendingReceiver<mojom::PlaybackEventsRecorder> receiver) {
mojo::MakeSelfOwnedReceiver(std::make_unique<FuchsiaPlaybackEventsRecorder>(),
std::move(receiver));
}
FuchsiaPlaybackEventsRecorder::FuchsiaPlaybackEventsRecorder() = default;
FuchsiaPlaybackEventsRecorder::~FuchsiaPlaybackEventsRecorder() = default;
void FuchsiaPlaybackEventsRecorder::OnPlaying() {
base::RecordComputedAction("WebEngine.Media.Playing");
}
void FuchsiaPlaybackEventsRecorder::OnPaused() {
base::RecordComputedAction("WebEngine.Media.Pause");
bitrate_estimator_.OnPause();
}
void FuchsiaPlaybackEventsRecorder::OnSeeking() {
buffering_state_ = BufferingState::kInitialBuffering;
}
void FuchsiaPlaybackEventsRecorder::OnEnded() {
base::RecordComputedAction("WebEngine.Media.Ended");
}
void FuchsiaPlaybackEventsRecorder::OnBuffering() {
DCHECK(buffering_state_ == BufferingState::kBuffered);
buffering_start_time_ = base::TimeTicks::Now();
buffering_state_ = BufferingState::kBuffering;
bitrate_estimator_.OnPause();
}
void FuchsiaPlaybackEventsRecorder::OnBufferingComplete() {
auto now = base::TimeTicks::Now();
if (buffering_state_ == BufferingState::kBuffering) {
base::TimeDelta time_between_buffering =
buffering_start_time_ - last_buffering_end_time_;
RecordEventWithValueAt("PlayTimeBeforeAutoPause",
time_between_buffering.InMilliseconds(), now);
base::TimeDelta buffering_user_time = now - buffering_start_time_;
RecordEventWithValueAt("AutoPauseTime",
buffering_user_time.InMilliseconds(), now);
}
buffering_state_ = BufferingState::kBuffered;
last_buffering_end_time_ = now;
}
void FuchsiaPlaybackEventsRecorder::OnError(PipelineStatus status) {
RecordEventWithValue("Error", status);
}
void FuchsiaPlaybackEventsRecorder::OnNaturalSizeChanged(
const gfx::Size& size) {
base::RecordComputedAction(base::StringPrintf(
"WebEngine.Media.VideoResolution:%dx%d", size.width(), size.height()));
}
void FuchsiaPlaybackEventsRecorder::OnPipelineStatistics(
const PipelineStatistics& stats) {
bitrate_estimator_.Update(stats);
}
} // namespace media
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FUCHSIA_METRICS_FUCHSIA_PLAYBACK_EVENTS_RECORDER_H_
#define MEDIA_FUCHSIA_METRICS_FUCHSIA_PLAYBACK_EVENTS_RECORDER_H_
#include "media/mojo/mojom/playback_events_recorder.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace media {
class FuchsiaPlaybackEventsRecorder : public mojom::PlaybackEventsRecorder {
public:
static void Create(
mojo::PendingReceiver<mojom::PlaybackEventsRecorder> receiver);
FuchsiaPlaybackEventsRecorder();
~FuchsiaPlaybackEventsRecorder() final;
FuchsiaPlaybackEventsRecorder(const FuchsiaPlaybackEventsRecorder&) = delete;
FuchsiaPlaybackEventsRecorder& operator=(
const FuchsiaPlaybackEventsRecorder&) = delete;
// mojom::PlaybackEventsRecorder implementation.
void OnPlaying() final;
void OnPaused() final;
void OnSeeking() final;
void OnEnded() final;
void OnBuffering() final;
void OnBufferingComplete() final;
void OnError(PipelineStatus status) final;
void OnNaturalSizeChanged(const gfx::Size& size) final;
void OnPipelineStatistics(const PipelineStatistics& stats) final;
private:
class BitrateEstimator {
public:
BitrateEstimator();
~BitrateEstimator();
void Update(const PipelineStatistics& stats);
void OnPause();
private:
base::TimeDelta time_elapsed_;
size_t audio_bytes_ = 0;
size_t video_bytes_ = 0;
base::Optional<PipelineStatistics> last_stats_;
base::TimeTicks last_stats_time_;
};
enum class BufferingState {
kInitialBuffering,
kBuffering,
kBuffered,
};
BufferingState buffering_state_ = BufferingState::kInitialBuffering;
base::TimeTicks buffering_start_time_;
base::TimeTicks last_buffering_end_time_;
BitrateEstimator bitrate_estimator_;
};
} // namespace media
#endif // MEDIA_FUCHSIA_METRICS_FUCHSIA_PLAYBACK_EVENTS_RECORDER_H_
\ No newline at end of file
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/fuchsia/metrics/fuchsia_playback_events_recorder.h"
#include "base/metrics/user_metrics.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
constexpr base::TimeDelta kSecond = base::TimeDelta::FromSeconds(1);
class FuchsiaPlaybackEventsRecorderTest : public testing::Test {
public:
FuchsiaPlaybackEventsRecorderTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
time_base_ = base::TimeTicks::Now();
base::SetRecordActionTaskRunner(
task_environment_.GetMainThreadTaskRunner());
action_callback_ = base::BindRepeating(
&FuchsiaPlaybackEventsRecorderTest::OnAction, base::Unretained(this));
base::AddActionCallback(action_callback_);
}
~FuchsiaPlaybackEventsRecorderTest() override {
base::RemoveActionCallback(action_callback_);
}
protected:
struct Event {
base::TimeTicks time;
std::string name;
bool operator==(const Event& other) const {
return time == other.time && name == other.name;
}
};
void OnAction(const std::string& name, base::TimeTicks time) {
recorded_events_.push_back({time, name});
}
void ExpectEvents(const std::vector<Event>& expected) {
EXPECT_EQ(recorded_events_.size(), expected.size());
size_t end = std::min(recorded_events_.size(), expected.size());
for (size_t i = 0; i < end; ++i) {
SCOPED_TRACE(i);
EXPECT_EQ(recorded_events_[i].time, expected[i].time);
EXPECT_EQ(recorded_events_[i].name, expected[i].name);
}
}
base::test::TaskEnvironment task_environment_;
base::SimpleTestTickClock test_clock_;
base::TimeTicks time_base_;
base::ActionCallback action_callback_;
FuchsiaPlaybackEventsRecorder recorder_;
std::vector<Event> recorded_events_;
};
TEST_F(FuchsiaPlaybackEventsRecorderTest, PlayPause) {
recorder_.OnNaturalSizeChanged(gfx::Size(640, 480));
recorder_.OnPlaying();
task_environment_.AdvanceClock(2 * kSecond);
recorder_.OnPaused();
ExpectEvents({
{time_base_, "WebEngine.Media.VideoResolution:640x480"},
{time_base_, "WebEngine.Media.Playing"},
{time_base_ + 2 * kSecond, "WebEngine.Media.Pause"},
});
}
TEST_F(FuchsiaPlaybackEventsRecorderTest, Error) {
recorder_.OnPlaying();
task_environment_.AdvanceClock(2 * kSecond);
recorder_.OnError(PIPELINE_ERROR_DECODE);
ExpectEvents({
{time_base_, "WebEngine.Media.Playing"},
{time_base_ + 2 * kSecond, "WebEngine.Media.Error:3"},
});
}
TEST_F(FuchsiaPlaybackEventsRecorderTest, Buffering) {
recorder_.OnPlaying();
recorder_.OnBufferingComplete();
task_environment_.AdvanceClock(2 * kSecond);
recorder_.OnBuffering();
task_environment_.AdvanceClock(3 * kSecond);
recorder_.OnBufferingComplete();
ExpectEvents({
{time_base_, "WebEngine.Media.Playing"},
{time_base_ + 5 * kSecond,
"WebEngine.Media.PlayTimeBeforeAutoPause:2000"},
{time_base_ + 5 * kSecond, "WebEngine.Media.AutoPauseTime:3000"},
});
}
TEST_F(FuchsiaPlaybackEventsRecorderTest, Bitrate) {
recorder_.OnPlaying();
recorder_.OnBufferingComplete();
PipelineStatistics stats;
recorder_.OnPipelineStatistics(stats);
for (int i = 0; i < 5; ++i) {
stats.audio_bytes_decoded += 5000;
stats.video_bytes_decoded += 10000;
task_environment_.AdvanceClock(kSecond);
recorder_.OnPipelineStatistics(stats);
}
ExpectEvents({
{time_base_, "WebEngine.Media.Playing"},
{time_base_ + 5 * kSecond, "WebEngine.Media.AudioBitrate:40"},
{time_base_ + 5 * kSecond, "WebEngine.Media.VideoBitrate:80"},
});
}
TEST_F(FuchsiaPlaybackEventsRecorderTest, BitrateAfterPause) {
recorder_.OnPlaying();
recorder_.OnBufferingComplete();
PipelineStatistics stats;
recorder_.OnPipelineStatistics(stats);
for (int i = 0; i < 3; ++i) {
stats.audio_bytes_decoded += 5000;
stats.video_bytes_decoded += 10000;
task_environment_.AdvanceClock(kSecond);
recorder_.OnPipelineStatistics(stats);
}
recorder_.OnPaused();
task_environment_.AdvanceClock(10 * kSecond);
recorder_.OnPlaying();
for (int i = 0; i < 3; ++i) {
stats.audio_bytes_decoded += 5000;
stats.video_bytes_decoded += 10000;
task_environment_.AdvanceClock(kSecond);
recorder_.OnPipelineStatistics(stats);
}
ExpectEvents({
{time_base_, "WebEngine.Media.Playing"},
{time_base_ + 3 * kSecond, "WebEngine.Media.Pause"},
{time_base_ + 13 * kSecond, "WebEngine.Media.Playing"},
{time_base_ + 16 * kSecond, "WebEngine.Media.AudioBitrate:40"},
{time_base_ + 16 * kSecond, "WebEngine.Media.VideoBitrate:80"},
});
}
TEST_F(FuchsiaPlaybackEventsRecorderTest, BitrateAfterBuffering) {
recorder_.OnPlaying();
recorder_.OnBufferingComplete();
PipelineStatistics stats;
recorder_.OnPipelineStatistics(stats);
for (int i = 0; i < 3; ++i) {
stats.audio_bytes_decoded += 5000;
stats.video_bytes_decoded += 10000;
task_environment_.AdvanceClock(kSecond);
recorder_.OnPipelineStatistics(stats);
}
recorder_.OnBuffering();
task_environment_.AdvanceClock(10 * kSecond);
recorder_.OnBufferingComplete();
for (int i = 0; i < 3; ++i) {
stats.audio_bytes_decoded += 5000;
stats.video_bytes_decoded += 10000;
task_environment_.AdvanceClock(kSecond);
recorder_.OnPipelineStatistics(stats);
}
ExpectEvents({
{time_base_, "WebEngine.Media.Playing"},
{time_base_ + 13 * kSecond,
"WebEngine.Media.PlayTimeBeforeAutoPause:3000"},
{time_base_ + 13 * kSecond, "WebEngine.Media.AutoPauseTime:10000"},
{time_base_ + 16 * kSecond, "WebEngine.Media.AudioBitrate:40"},
{time_base_ + 16 * kSecond, "WebEngine.Media.VideoBitrate:80"},
});
}
} // namespace media
\ No newline at end of file
......@@ -32,6 +32,7 @@ mojom("mojom") {
"media_types.mojom",
"output_protection.mojom",
"platform_verification.mojom",
"playback_events_recorder.mojom",
"provision_fetcher.mojom",
"renderer.mojom",
"renderer_extensions.mojom",
......
......@@ -7,6 +7,7 @@ module media.mojom;
import "media/learning/mojo/public/mojom/learning_task_controller.mojom";
import "media/mojo/mojom/media_types.mojom";
import "media/mojo/mojom/video_decode_stats_recorder.mojom";
import "media/mojo/mojom/playback_events_recorder.mojom";
import "media/mojo/mojom/watch_time_recorder.mojom";
import "mojo/public/mojom/base/time.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
......@@ -64,8 +65,13 @@ interface MediaMetricsProvider {
// Returns a LearningTaskController for the given |taskName|.
AcquireLearningTaskController(
string taskName,
pending_receiver<media.learning.mojom.LearningTaskController> controller);
string taskName,
pending_receiver<media.learning.mojom.LearningTaskController> controller);
// Returns a PlaybackEventsRecorder instance. Implementation may drop the
// |receiver| if it's not interested in recording playback events.
AcquirePlaybackEventsRecorder(
pending_receiver<PlaybackEventsRecorder> receiver);
// Can be called multiple times to set properties about a playback.
SetHasAudio(AudioCodec codec);
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module media.mojom;
import "media/mojo/mojom/media_types.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
// PlaybackEventsRecorder allows to observe and record events occurring in the
// media pipeline. The interface is called by the renderer process (in
// blink::WebMediaPlayerImpl), while the implementation normally runs in the
// browser.
interface PlaybackEventsRecorder {
// Called when player has been started or resumed.
OnPlaying();
// Called when player has been paused.
OnPaused();
// Called when player position is being changed.
OnSeeking();
// Called when the player has reached the end of the current file.
OnEnded();
// Called when playback has failed due to the specified error.
OnError(PipelineStatus status);
// Called when playback has been suspended while buffering the media.
OnBuffering();
// Called after media buffering has completed. The player is in buffering
// state after the following events until this method is called:
// 1. Player initialized (i.e. after PlaybackEventsRecorder is created).
// 2. Seek operation, see OnSeeking().
// 3. Buffering started, see OnBuffering().
OnBufferingComplete();
// Called when video playback starts and every time video resolution changes.
OnNaturalSizeChanged(gfx.mojom.Size size);
// Called periodically (e.g. every second) while playback is active.
OnPipelineStatistics(PipelineStatistics stats);
};
......@@ -109,6 +109,10 @@ jumbo_component("services") {
]
}
if (is_fuchsia) {
deps += [ "//media/fuchsia/metrics" ]
}
if (enable_media_drm_storage) {
sources += [
"mojo_media_drm_storage.cc",
......
......@@ -20,7 +20,11 @@
#if !defined(OS_ANDROID)
#include "media/filters/decrypting_video_decoder.h"
#endif
#endif // !defined(OS_ANDROID)
#if defined(OS_FUCHSIA)
#include "media/fuchsia/metrics/fuchsia_playback_events_recorder.h"
#endif // defined(OS_FUCHSIA)
namespace media {
......@@ -290,6 +294,13 @@ void MediaMetricsProvider::AcquireVideoDecodeStatsRecorder(
std::move(receiver));
}
void MediaMetricsProvider::AcquirePlaybackEventsRecorder(
mojo::PendingReceiver<mojom::PlaybackEventsRecorder> receiver) {
#if defined(OS_FUCHSIA)
FuchsiaPlaybackEventsRecorder::Create(std::move(receiver));
#endif
}
void MediaMetricsProvider::AcquireLearningTaskController(
const std::string& taskName,
mojo::PendingReceiver<media::learning::mojom::LearningTaskController>
......
......@@ -121,6 +121,8 @@ class MEDIA_MOJO_EXPORT MediaMetricsProvider
mojo::PendingReceiver<mojom::WatchTimeRecorder> receiver) override;
void AcquireVideoDecodeStatsRecorder(
mojo::PendingReceiver<mojom::VideoDecodeStatsRecorder> receiver) override;
void AcquirePlaybackEventsRecorder(
mojo::PendingReceiver<mojom::PlaybackEventsRecorder> receiver) override;
void AcquireLearningTaskController(
const std::string& taskName,
mojo::PendingReceiver<media::learning::mojom::LearningTaskController>
......
......@@ -159,6 +159,11 @@ class FakeMediaMetricsProvider
}
FAIL();
}
void AcquirePlaybackEventsRecorder(
mojo::PendingReceiver<media::mojom::blink::PlaybackEventsRecorder>
receiver) override {
FAIL();
}
void Initialize(bool is_mse,
media::mojom::MediaURLScheme url_scheme) override {}
void OnError(media::mojom::PipelineStatus status) override {}
......
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