summaryrefslogtreecommitdiff
path: root/chromium/media/mojo
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/mojo')
-rw-r--r--chromium/media/mojo/clients/mojo_audio_decoder.cc4
-rw-r--r--chromium/media/mojo/clients/mojo_audio_decoder.h1
-rw-r--r--chromium/media/mojo/clients/mojo_audio_decoder_unittest.cc10
-rw-r--r--chromium/media/mojo/clients/mojo_cdm.cc29
-rw-r--r--chromium/media/mojo/clients/mojo_cdm.h28
-rw-r--r--chromium/media/mojo/clients/mojo_cdm_factory.cc10
-rw-r--r--chromium/media/mojo/clients/mojo_cdm_unittest.cc62
-rw-r--r--chromium/media/mojo/clients/mojo_decryptor_unittest.cc6
-rw-r--r--chromium/media/mojo/clients/mojo_renderer_unittest.cc31
-rw-r--r--chromium/media/mojo/clients/mojo_video_decoder.cc4
-rw-r--r--chromium/media/mojo/clients/mojo_video_decoder.h1
-rw-r--r--chromium/media/mojo/clients/mojo_video_encode_accelerator.cc71
-rw-r--r--chromium/media/mojo/clients/win/media_foundation_renderer_client.cc11
-rw-r--r--chromium/media/mojo/clients/win/media_foundation_renderer_client.h7
-rw-r--r--chromium/media/mojo/common/BUILD.gn2
-rw-r--r--chromium/media/mojo/common/audio_data_s16_converter.cc120
-rw-r--r--chromium/media/mojo/common/audio_data_s16_converter.h67
-rw-r--r--chromium/media/mojo/common/mojo_shared_buffer_video_frame.cc23
-rw-r--r--chromium/media/mojo/common/mojo_shared_buffer_video_frame.h2
-rw-r--r--chromium/media/mojo/mojom/BUILD.gn10
-rw-r--r--chromium/media/mojo/mojom/audio_stream_factory.mojom100
-rw-r--r--chromium/media/mojo/mojom/cdm_infobar_service.mojom11
-rw-r--r--chromium/media/mojo/mojom/content_decryption_module.mojom24
-rw-r--r--chromium/media/mojo/mojom/interface_factory.mojom11
-rw-r--r--chromium/media/mojo/mojom/key_system_support.mojom1
-rw-r--r--chromium/media/mojo/mojom/media_foundation_service.mojom35
-rw-r--r--chromium/media/mojo/mojom/media_player.mojom28
-rw-r--r--chromium/media/mojo/mojom/media_types.mojom7
-rw-r--r--chromium/media/mojo/mojom/speech_recognition_service.mojom72
-rw-r--r--chromium/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc2
-rw-r--r--chromium/media/mojo/mojom/video_encoder_info.mojom6
-rw-r--r--chromium/media/mojo/mojom/video_encoder_info_mojom_traits.cc13
-rw-r--r--chromium/media/mojo/mojom/video_encoder_info_mojom_traits.h19
-rw-r--r--chromium/media/mojo/mojom/video_frame_mojom_traits.cc56
-rw-r--r--chromium/media/mojo/mojom/video_frame_mojom_traits_unittest.cc40
-rw-r--r--chromium/media/mojo/services/BUILD.gn3
-rw-r--r--chromium/media/mojo/services/cdm_service.cc49
-rw-r--r--chromium/media/mojo/services/cdm_service_unittest.cc84
-rw-r--r--chromium/media/mojo/services/gpu_mojo_media_client.cc13
-rw-r--r--chromium/media/mojo/services/interface_factory_impl.cc125
-rw-r--r--chromium/media/mojo/services/interface_factory_impl.h40
-rw-r--r--chromium/media/mojo/services/media_foundation_mojo_media_client.cc34
-rw-r--r--chromium/media/mojo/services/media_foundation_mojo_media_client.h16
-rw-r--r--chromium/media/mojo/services/media_foundation_service.cc48
-rw-r--r--chromium/media/mojo/services/media_foundation_service.h48
-rw-r--r--chromium/media/mojo/services/media_metrics_provider_unittest.cc2
-rw-r--r--chromium/media/mojo/services/media_service_factory.cc6
-rw-r--r--chromium/media/mojo/services/media_service_factory.h1
-rw-r--r--chromium/media/mojo/services/media_service_unittest.cc10
-rw-r--r--chromium/media/mojo/services/mojo_audio_decoder_service.cc10
-rw-r--r--chromium/media/mojo/services/mojo_cdm_service.cc122
-rw-r--r--chromium/media/mojo/services/mojo_cdm_service.h40
-rw-r--r--chromium/media/mojo/services/mojo_decryptor_service.cc17
-rw-r--r--chromium/media/mojo/services/mojo_demuxer_stream_adapter.cc6
-rw-r--r--chromium/media/mojo/services/mojo_media_client.cc9
-rw-r--r--chromium/media/mojo/services/mojo_media_client.h14
-rw-r--r--chromium/media/mojo/services/mojo_renderer_service.cc5
-rw-r--r--chromium/media/mojo/services/mojo_video_decoder_service.cc38
-rw-r--r--chromium/media/mojo/services/mojo_video_decoder_service.h3
-rw-r--r--chromium/media/mojo/services/test_mojo_media_client.cc3
-rw-r--r--chromium/media/mojo/services/video_decode_perf_history_unittest.cc3
-rw-r--r--chromium/media/mojo/services/video_decode_stats_recorder_unittest.cc5
-rw-r--r--chromium/media/mojo/services/watch_time_recorder_unittest.cc4
63 files changed, 1064 insertions, 618 deletions
diff --git a/chromium/media/mojo/clients/mojo_audio_decoder.cc b/chromium/media/mojo/clients/mojo_audio_decoder.cc
index 2bf1b1a59b9..76259add30c 100644
--- a/chromium/media/mojo/clients/mojo_audio_decoder.cc
+++ b/chromium/media/mojo/clients/mojo_audio_decoder.cc
@@ -51,10 +51,6 @@ AudioDecoderType MojoAudioDecoder::GetDecoderType() const {
return decoder_type_;
}
-std::string MojoAudioDecoder::GetDisplayName() const {
- return "MojoAudioDecoder";
-}
-
void MojoAudioDecoder::FailInit(InitCB init_cb, Status err) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), std::move(err)));
diff --git a/chromium/media/mojo/clients/mojo_audio_decoder.h b/chromium/media/mojo/clients/mojo_audio_decoder.h
index fbb85ab5f72..04a40615daa 100644
--- a/chromium/media/mojo/clients/mojo_audio_decoder.h
+++ b/chromium/media/mojo/clients/mojo_audio_decoder.h
@@ -36,7 +36,6 @@ class MojoAudioDecoder final : public AudioDecoder,
// Decoder implementation
bool IsPlatformDecoder() const final;
bool SupportsDecryption() const final;
- std::string GetDisplayName() const override;
AudioDecoderType GetDecoderType() const override;
// AudioDecoder implementation.
diff --git a/chromium/media/mojo/clients/mojo_audio_decoder_unittest.cc b/chromium/media/mojo/clients/mojo_audio_decoder_unittest.cc
index daba06f1470..8f4ad6ca715 100644
--- a/chromium/media/mojo/clients/mojo_audio_decoder_unittest.cc
+++ b/chromium/media/mojo/clients/mojo_audio_decoder_unittest.cc
@@ -65,9 +65,9 @@ class MojoAudioDecoderTest : public ::testing::Test {
base::BindOnce(&MojoAudioDecoderTest::ConnectToService,
base::Unretained(this),
remote_audio_decoder.InitWithNewPipeAndPassReceiver()));
- mojo_audio_decoder_.reset(
- new MojoAudioDecoder(task_environment_.GetMainThreadTaskRunner(),
- std::move(remote_audio_decoder)));
+ mojo_audio_decoder_ = std::make_unique<MojoAudioDecoder>(
+ task_environment_.GetMainThreadTaskRunner(),
+ std::move(remote_audio_decoder));
}
~MojoAudioDecoderTest() override {
@@ -91,13 +91,13 @@ class MojoAudioDecoderTest : public ::testing::Test {
void RunLoop() {
DVLOG(1) << __func__;
- run_loop_.reset(new base::RunLoop());
+ run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
void RunLoopUntilIdle() {
DVLOG(1) << __func__;
- run_loop_.reset(new base::RunLoop());
+ run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->RunUntilIdle();
}
diff --git a/chromium/media/mojo/clients/mojo_cdm.cc b/chromium/media/mojo/clients/mojo_cdm.cc
index 403c19f040f..f0098346345 100644
--- a/chromium/media/mojo/clients/mojo_cdm.cc
+++ b/chromium/media/mojo/clients/mojo_cdm.cc
@@ -36,21 +36,24 @@ void RecordConnectionError(bool connection_error_happened) {
} // namespace
MojoCdm::MojoCdm(mojo::Remote<mojom::ContentDecryptionModule> remote_cdm,
- const base::Optional<base::UnguessableToken>& cdm_id,
- mojo::PendingRemote<mojom::Decryptor> decryptor_remote,
+ media::mojom::CdmContextPtr cdm_context,
const SessionMessageCB& session_message_cb,
const SessionClosedCB& session_closed_cb,
const SessionKeysChangeCB& session_keys_change_cb,
const SessionExpirationUpdateCB& session_expiration_update_cb)
: remote_cdm_(std::move(remote_cdm)),
- cdm_id_(cdm_id),
- decryptor_remote_(std::move(decryptor_remote)),
+ cdm_id_(cdm_context->cdm_id),
+ decryptor_remote_(std::move(cdm_context->decryptor)),
+#if defined(OS_WIN)
+ requires_media_foundation_renderer_(
+ cdm_context->requires_media_foundation_renderer),
+#endif // defined(OS_WIN)
session_message_cb_(session_message_cb),
session_closed_cb_(session_closed_cb),
session_keys_change_cb_(session_keys_change_cb),
session_expiration_update_cb_(session_expiration_update_cb) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(cdm_id);
+ DCHECK(cdm_id_);
DVLOG(2) << __func__ << " cdm_id: "
<< CdmContext::CdmIdToString(base::OptionalOrNullptr(cdm_id_));
DCHECK(session_message_cb_);
@@ -58,12 +61,6 @@ MojoCdm::MojoCdm(mojo::Remote<mojom::ContentDecryptionModule> remote_cdm,
DCHECK(session_keys_change_cb_);
DCHECK(session_expiration_update_cb_);
-#if defined(OS_WIN)
- // TODO(xhwang): Need a way to implement RequiresMediaFoundationRenderer().
- // The plan is to pass back this info when we create the CDM, e.g. in the
- // `cdm_created_cb` of `MojoCdmFactory::Create()`.
-#endif // defined(OS_WIN)
-
remote_cdm_->SetClient(client_receiver_.BindNewEndpointAndPassRemote());
// Report a false event here as a baseline.
@@ -273,17 +270,17 @@ Decryptor* MojoCdm::GetDecryptor() {
base::Optional<base::UnguessableToken> MojoCdm::GetCdmId() const {
// Can be called on a different thread.
base::AutoLock auto_lock(lock_);
- DVLOG(2) << __func__ << ": cdm_id = "
+ DVLOG(2) << __func__ << ": cdm_id="
<< CdmContext::CdmIdToString(base::OptionalOrNullptr(cdm_id_));
return cdm_id_;
}
#if defined(OS_WIN)
bool MojoCdm::RequiresMediaFoundationRenderer() {
- DVLOG(2) << __func__ << " this:" << this
- << " is_mf_renderer_content_:" << is_mf_renderer_content_;
-
- return is_mf_renderer_content_;
+ base::AutoLock auto_lock(lock_);
+ DVLOG(2) << __func__ << ": requires_media_foundation_renderer_="
+ << requires_media_foundation_renderer_;
+ return requires_media_foundation_renderer_;
}
#endif // defined(OS_WIN)
diff --git a/chromium/media/mojo/clients/mojo_cdm.h b/chromium/media/mojo/clients/mojo_cdm.h
index b0f88e5c01c..ca886cc99cf 100644
--- a/chromium/media/mojo/clients/mojo_cdm.h
+++ b/chromium/media/mojo/clients/mojo_cdm.h
@@ -44,9 +44,9 @@ class MojoCdm final : public ContentDecryptionModule,
public:
using MessageType = CdmMessageType;
+ // All parameters must be non-null.
MojoCdm(mojo::Remote<mojom::ContentDecryptionModule> remote_cdm,
- const base::Optional<base::UnguessableToken>& cdm_id,
- mojo::PendingRemote<mojom::Decryptor> decryptor_remote,
+ media::mojom::CdmContextPtr cdm_context,
const SessionMessageCB& session_message_cb,
const SessionClosedCB& session_closed_cb,
const SessionKeysChangeCB& session_keys_change_cb,
@@ -117,26 +117,31 @@ class MojoCdm final : public ContentDecryptionModule,
mojo::AssociatedReceiver<ContentDecryptionModuleClient> client_receiver_{
this};
- // Protects |cdm_id_|, |decryptor_remote_|, |decryptor_| and
- // |decryptor_task_runner_| which could be accessed from other threads.
- // See CdmContext implementation above.
+ // Protects |cdm_id_|, |decryptor_remote_|, |decryptor_|,
+ // |decryptor_task_runner_| and |requires_media_foundation_renderer_|, which
+ // could be accessed from other threads. See CdmContext implementation above.
mutable base::Lock lock_;
// CDM ID of the remote CDM. Set after initialization is completed. Must not
// be invalid if initialization succeeded.
- base::Optional<base::UnguessableToken> cdm_id_;
+ base::Optional<base::UnguessableToken> cdm_id_ GUARDED_BY(lock_);
// The mojo::PendingRemote<mojom::Decryptor> exposed by the remote CDM. Set
// after initialization is completed and cleared after |decryptor_| is
// created. May be invalid after initialization if the CDM doesn't support a
// Decryptor.
- mojo::PendingRemote<mojom::Decryptor> decryptor_remote_;
+ mojo::PendingRemote<mojom::Decryptor> decryptor_remote_ GUARDED_BY(lock_);
// Decryptor based on |decryptor_remote_|, lazily created in
// GetDecryptor(). Since GetDecryptor() can be called on a different thread,
// use |decryptor_task_runner_| to bind |decryptor_| to that thread.
- std::unique_ptr<MojoDecryptor> decryptor_;
- scoped_refptr<base::SingleThreadTaskRunner> decryptor_task_runner_;
+ std::unique_ptr<MojoDecryptor> decryptor_ GUARDED_BY(lock_);
+ scoped_refptr<base::SingleThreadTaskRunner> decryptor_task_runner_
+ GUARDED_BY(lock_);
+
+#if defined(OS_WIN)
+ bool requires_media_foundation_renderer_ GUARDED_BY(lock_) = false;
+#endif // defined(OS_WIN)
// Callbacks for firing session events.
SessionMessageCB session_message_cb_;
@@ -152,11 +157,6 @@ class MojoCdm final : public ContentDecryptionModule,
CallbackRegistry<EventCB::RunType> event_callbacks_;
-#if defined(OS_WIN)
- // The current content is for MediaFoundationRenderer or not.
- bool is_mf_renderer_content_ = false;
-#endif // defined(OS_WIN)
-
// This must be the last member.
base::WeakPtrFactory<MojoCdm> weak_factory_{this};
diff --git a/chromium/media/mojo/clients/mojo_cdm_factory.cc b/chromium/media/mojo/clients/mojo_cdm_factory.cc
index 7d95271465a..8e4732a3e9c 100644
--- a/chromium/media/mojo/clients/mojo_cdm_factory.cc
+++ b/chromium/media/mojo/clients/mojo_cdm_factory.cc
@@ -15,6 +15,7 @@
#include "media/base/key_systems.h"
#include "media/cdm/aes_decryptor.h"
#include "media/mojo/clients/mojo_cdm.h"
+#include "media/mojo/mojom/content_decryption_module.mojom.h"
#include "media/mojo/mojom/interface_factory.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -30,21 +31,20 @@ void OnCdmCreated(
const SessionExpirationUpdateCB& session_expiration_update_cb,
CdmCreatedCB cdm_created_cb,
mojo::PendingRemote<mojom::ContentDecryptionModule> cdm_remote,
- const base::Optional<base::UnguessableToken>& cdm_id,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
+ media::mojom::CdmContextPtr cdm_context,
const std::string& error_message) {
// Convert from a PendingRemote to Remote so we can verify that it is
// connected, this will also check if |cdm_remote| is null.
mojo::Remote<mojom::ContentDecryptionModule> remote(std::move(cdm_remote));
- if (!remote || !remote.is_connected()) {
+ if (!remote || !remote.is_connected() || !cdm_context) {
std::move(cdm_created_cb).Run(nullptr, error_message);
return;
}
std::move(cdm_created_cb)
.Run(base::MakeRefCounted<MojoCdm>(
- std::move(remote), cdm_id, std::move(decryptor),
- session_message_cb, session_closed_cb, session_keys_change_cb,
+ std::move(remote), std::move(cdm_context), session_message_cb,
+ session_closed_cb, session_keys_change_cb,
session_expiration_update_cb),
"");
}
diff --git a/chromium/media/mojo/clients/mojo_cdm_unittest.cc b/chromium/media/mojo/clients/mojo_cdm_unittest.cc
index 08e24fb4722..3eb54feb6ed 100644
--- a/chromium/media/mojo/clients/mojo_cdm_unittest.cc
+++ b/chromium/media/mojo/clients/mojo_cdm_unittest.cc
@@ -28,7 +28,9 @@
using ::testing::_;
using ::testing::DoAll;
using ::testing::Invoke;
+using ::testing::Return;
using ::testing::ReturnNull;
+using ::testing::ReturnPointee;
using ::testing::StrictMock;
using ::testing::WithArg;
using ::testing::WithArgs;
@@ -68,10 +70,17 @@ class MojoCdmTest : public ::testing::Test {
};
MojoCdmTest() = default;
-
~MojoCdmTest() override = default;
void Initialize(ExpectedResult expected_result) {
+ EXPECT_CALL(*remote_cdm_, GetCdmContext())
+ .WillRepeatedly(Return(&cdm_context_));
+ EXPECT_CALL(cdm_context_, GetDecryptor()).WillRepeatedly(ReturnNull());
+#if defined(OS_WIN)
+ EXPECT_CALL(cdm_context_, RequiresMediaFoundationRenderer())
+ .WillRepeatedly(ReturnPointee(&requires_media_foundation_renderer_));
+#endif
+
if (expected_result == CONNECTION_ERROR_DURING) {
// Create() will be successful, so provide a callback that will break
// the connection before returning the CDM.
@@ -79,18 +88,17 @@ class MojoCdmTest : public ::testing::Test {
&MojoCdmTest::ForceConnectionError, base::Unretained(this)));
}
- MojoCdmService::Create(
- &cdm_factory_, &mojo_cdm_service_context_, kClearKeyKeySystem,
- CdmConfig(),
- base::BindOnce(&MojoCdmTest::OnCdmServiceCreated,
+ mojo_cdm_service_ =
+ std::make_unique<MojoCdmService>(&mojo_cdm_service_context_);
+ mojo_cdm_service_->Initialize(
+ &cdm_factory_, kClearKeyKeySystem, CdmConfig(),
+ base::BindOnce(&MojoCdmTest::OnCdmServiceInitialized,
base::Unretained(this), expected_result));
}
- void OnCdmServiceCreated(ExpectedResult expected_result,
- std::unique_ptr<MojoCdmService> cdm_service,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
- const std::string& error_message) {
- mojo_cdm_service_ = std::move(cdm_service);
+ void OnCdmServiceInitialized(ExpectedResult expected_result,
+ mojom::CdmContextPtr cdm_context,
+ const std::string& error_message) {
cdm_receiver_ =
std::make_unique<mojo::Receiver<mojom::ContentDecryptionModule>>(
mojo_cdm_service_.get());
@@ -103,8 +111,7 @@ class MojoCdmTest : public ::testing::Test {
mojo::Remote<mojom::ContentDecryptionModule> cdm_remote(
cdm_receiver_->BindNewPipeAndPassRemote());
mojo_cdm_ = base::MakeRefCounted<MojoCdm>(
- std::move(cdm_remote), mojo_cdm_service_->cdm_id(),
- std::move(decryptor),
+ std::move(cdm_remote), std::move(cdm_context),
base::BindRepeating(&MockCdmClient::OnSessionMessage,
base::Unretained(&cdm_client_)),
base::BindRepeating(&MockCdmClient::OnSessionClosed,
@@ -113,7 +120,6 @@ class MojoCdmTest : public ::testing::Test {
base::Unretained(&cdm_client_)),
base::BindRepeating(&MockCdmClient::OnSessionExpirationUpdate,
base::Unretained(&cdm_client_)));
- remote_cdm_ = cdm_factory_.GetCreatedCdm();
EXPECT_EQ(kClearKeyKeySystem, remote_cdm_->GetKeySystem());
base::RunLoop().RunUntilIdle();
}
@@ -349,8 +355,9 @@ class MojoCdmTest : public ::testing::Test {
base::TestMessageLoop message_loop_;
// |remote_cdm_| represents the CDM at the end of the mojo message pipe.
- MockCdm* remote_cdm_;
- MockCdmFactory cdm_factory_;
+ scoped_refptr<MockCdm> remote_cdm_{new MockCdm()};
+ MockCdmFactory cdm_factory_{remote_cdm_};
+ MockCdmContext cdm_context_;
MojoCdmServiceContext mojo_cdm_service_context_;
StrictMock<MockCdmClient> cdm_client_;
@@ -363,6 +370,10 @@ class MojoCdmTest : public ::testing::Test {
std::unique_ptr<mojo::Receiver<mojom::ContentDecryptionModule>> cdm_receiver_;
scoped_refptr<ContentDecryptionModule> mojo_cdm_;
+#if defined(OS_WIN)
+ bool requires_media_foundation_renderer_ = false;
+#endif
+
private:
DISALLOW_COPY_AND_ASSIGN(MojoCdmTest);
};
@@ -596,9 +607,6 @@ TEST_F(MojoCdmTest, SessionKeysChangeCB_Success) {
base::RunLoop().RunUntilIdle();
}
-// TODO(xhwang): Refactor MockCdmFactory to mock CdmFactory::Create() so that we
-// can set expectations and default actions on the created MockCdm, e.g. return
-// a non-null Decryptor to test the HasDecryptor case.
TEST_F(MojoCdmTest, NoDecryptor) {
Initialize(SUCCESS);
auto* cdm_context = mojo_cdm_->GetCdmContext();
@@ -607,4 +615,22 @@ TEST_F(MojoCdmTest, NoDecryptor) {
EXPECT_FALSE(decryptor);
}
+#if defined(OS_WIN)
+TEST_F(MojoCdmTest, RequiresMediaFoundationRenderer) {
+ requires_media_foundation_renderer_ = true;
+ Initialize(SUCCESS);
+ auto* cdm_context = mojo_cdm_->GetCdmContext();
+ EXPECT_TRUE(cdm_context) << "All CDMs should support CdmContext";
+ EXPECT_TRUE(cdm_context->RequiresMediaFoundationRenderer());
+}
+
+TEST_F(MojoCdmTest, NotRequireMediaFoundationRenderer) {
+ requires_media_foundation_renderer_ = false;
+ Initialize(SUCCESS);
+ auto* cdm_context = mojo_cdm_->GetCdmContext();
+ EXPECT_TRUE(cdm_context) << "All CDMs should support CdmContext";
+ EXPECT_FALSE(cdm_context->RequiresMediaFoundationRenderer());
+}
+#endif
+
} // namespace media
diff --git a/chromium/media/mojo/clients/mojo_decryptor_unittest.cc b/chromium/media/mojo/clients/mojo_decryptor_unittest.cc
index fa9638f6245..bd1d63a3408 100644
--- a/chromium/media/mojo/clients/mojo_decryptor_unittest.cc
+++ b/chromium/media/mojo/clients/mojo_decryptor_unittest.cc
@@ -42,10 +42,10 @@ class MojoDecryptorTest : public ::testing::Test {
void SetWriterCapacity(uint32_t capacity) { writer_capacity_ = capacity; }
void Initialize() {
- decryptor_.reset(new StrictMock<MockDecryptor>());
+ decryptor_ = std::make_unique<StrictMock<MockDecryptor>>();
- mojo_decryptor_service_.reset(
- new MojoDecryptorService(decryptor_.get(), nullptr));
+ mojo_decryptor_service_ =
+ std::make_unique<MojoDecryptorService>(decryptor_.get(), nullptr);
receiver_ = std::make_unique<mojo::Receiver<mojom::Decryptor>>(
mojo_decryptor_service_.get());
diff --git a/chromium/media/mojo/clients/mojo_renderer_unittest.cc b/chromium/media/mojo/clients/mojo_renderer_unittest.cc
index 0211d5ccee2..831017c1355 100644
--- a/chromium/media/mojo/clients/mojo_renderer_unittest.cc
+++ b/chromium/media/mojo/clients/mojo_renderer_unittest.cc
@@ -4,6 +4,8 @@
#include <stdint.h>
+#include <memory>
+
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -72,10 +74,10 @@ class MojoRendererTest : public ::testing::Test {
&mojo_cdm_service_context_, std::move(mock_renderer),
remote_renderer_remote.InitWithNewPipeAndPassReceiver());
- mojo_renderer_.reset(
- new MojoRenderer(message_loop_.task_runner(),
- std::unique_ptr<VideoOverlayFactory>(nullptr), nullptr,
- std::move(remote_renderer_remote)));
+ mojo_renderer_ = std::make_unique<MojoRenderer>(
+ message_loop_.task_runner(),
+ std::unique_ptr<VideoOverlayFactory>(nullptr), nullptr,
+ std::move(remote_renderer_remote));
// CreateAudioStream() and CreateVideoStream() overrides expectations for
// expected non-NULL streams.
@@ -168,19 +170,17 @@ class MojoRendererTest : public ::testing::Test {
base::RunLoop().RunUntilIdle();
}
- void OnCdmServiceCreated(std::unique_ptr<MojoCdmService> cdm_service,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
- const std::string& error_message) {
- EXPECT_TRUE(!!cdm_service);
- cdm_context_.set_cdm_id(base::OptionalOrNullptr(cdm_service->cdm_id()));
- mojo_cdm_service_ = std::move(cdm_service);
+ void OnCdmServiceInitialized(mojom::CdmContextPtr cdm_context,
+ const std::string& error_message) {
+ cdm_context_.set_cdm_id(cdm_context->cdm_id);
}
void CreateCdm() {
- MojoCdmService::Create(
- &cdm_factory_, &mojo_cdm_service_context_, kClearKeyKeySystem,
- CdmConfig(),
- base::BindOnce(&MojoRendererTest::OnCdmServiceCreated,
+ mojo_cdm_service_ =
+ std::make_unique<MojoCdmService>(&mojo_cdm_service_context_);
+ mojo_cdm_service_->Initialize(
+ &cdm_factory_, kClearKeyKeySystem, CdmConfig(),
+ base::BindOnce(&MojoRendererTest::OnCdmServiceInitialized,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
}
@@ -304,8 +304,7 @@ TEST_F(MojoRendererTest, SetCdm_InvalidCdmId) {
TEST_F(MojoRendererTest, SetCdm_NonExistCdmId) {
Initialize();
- auto cdm_id = base::UnguessableToken::Create();
- cdm_context_.set_cdm_id(&cdm_id);
+ cdm_context_.set_cdm_id(base::UnguessableToken::Create());
SetCdmAndExpect(false);
}
diff --git a/chromium/media/mojo/clients/mojo_video_decoder.cc b/chromium/media/mojo/clients/mojo_video_decoder.cc
index a093a377cd6..23c3bc5d7c1 100644
--- a/chromium/media/mojo/clients/mojo_video_decoder.cc
+++ b/chromium/media/mojo/clients/mojo_video_decoder.cc
@@ -147,10 +147,6 @@ VideoDecoderType MojoVideoDecoder::GetDecoderType() const {
return decoder_type_;
}
-std::string MojoVideoDecoder::GetDisplayName() const {
- return "MojoVideoDecoder";
-}
-
void MojoVideoDecoder::FailInit(InitCB init_cb, Status err) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), std::move(err)));
diff --git a/chromium/media/mojo/clients/mojo_video_decoder.h b/chromium/media/mojo/clients/mojo_video_decoder.h
index b5fdef8375d..1d85f48837d 100644
--- a/chromium/media/mojo/clients/mojo_video_decoder.h
+++ b/chromium/media/mojo/clients/mojo_video_decoder.h
@@ -60,7 +60,6 @@ class MojoVideoDecoder final : public VideoDecoder,
// Decoder implementation
bool IsPlatformDecoder() const final;
bool SupportsDecryption() const final;
- std::string GetDisplayName() const override;
VideoDecoderType GetDecoderType() const final;
// VideoDecoder implementation.
diff --git a/chromium/media/mojo/clients/mojo_video_encode_accelerator.cc b/chromium/media/mojo/clients/mojo_video_encode_accelerator.cc
index 2fdfdef3ba4..192c2c31ca0 100644
--- a/chromium/media/mojo/clients/mojo_video_encode_accelerator.cc
+++ b/chromium/media/mojo/clients/mojo_video_encode_accelerator.cc
@@ -134,18 +134,7 @@ void MojoVideoEncodeAccelerator::Encode(scoped_refptr<VideoFrame> frame,
DCHECK_EQ(num_planes, frame->layout().num_planes());
DCHECK(vea_.is_bound());
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
- // TODO(crbug.com/1003197): Remove this once we stop supporting STORAGE_DMABUF
- // in VideoEncodeAccelerator.
- if (frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
- DCHECK(frame->HasDmaBufs());
- vea_->Encode(
- frame, force_keyframe,
- base::BindOnce(base::DoNothing::Once<scoped_refptr<VideoFrame>>(),
- frame));
- return;
- }
-#endif
+ // GPU memory path: Pass-through.
if (frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
vea_->Encode(
frame, force_keyframe,
@@ -154,62 +143,26 @@ void MojoVideoEncodeAccelerator::Encode(scoped_refptr<VideoFrame> frame,
return;
}
- if ((frame->format() != PIXEL_FORMAT_I420 &&
- frame->format() != PIXEL_FORMAT_NV12) ||
- VideoFrame::STORAGE_SHMEM != frame->storage_type() ||
- !frame->shm_region()->IsValid()) {
- DLOG(ERROR) << "Unexpected video frame buffer";
- return;
- }
-
- // Oftentimes |frame|'s underlying planes will be aligned and not tightly
- // packed, so don't use VideoFrame::AllocationSize().
- const size_t allocation_size = frame->shm_region()->GetSize();
-
- // A MojoSharedBufferVideoFrame is created with an owned writable handle. As
- // the handle in |frame| is not owned, a new region must be created and
- // |frame| copied into it.
- mojo::ScopedSharedBufferHandle dst_handle =
- mojo::SharedBufferHandle::Create(allocation_size);
- if (!dst_handle->is_valid()) {
- DLOG(ERROR) << "Can't create new frame backing memory";
- return;
- }
- mojo::ScopedSharedBufferMapping dst_mapping =
- dst_handle->Map(allocation_size);
- if (!dst_mapping) {
- DLOG(ERROR) << "Can't map new frame backing memory";
+ // Mappable memory path: Copy buffer to shared memory.
+ if (frame->format() != PIXEL_FORMAT_I420 &&
+ frame->format() != PIXEL_FORMAT_NV12) {
+ DLOG(ERROR) << "Unexpected pixel format: "
+ << VideoPixelFormatToString(frame->format());
return;
}
- DCHECK(frame->shm_region());
- base::WritableSharedMemoryMapping src_mapping = frame->shm_region()->Map();
- if (!src_mapping.IsValid()) {
- DLOG(ERROR) << "Can't map src frame backing memory";
+ if (frame->storage_type() != VideoFrame::STORAGE_SHMEM &&
+ frame->storage_type() != VideoFrame::STORAGE_UNOWNED_MEMORY) {
+ DLOG(ERROR) << "Unexpected storage type: "
+ << VideoFrame::StorageTypeToString(frame->storage_type());
return;
}
- memcpy(dst_mapping.get(), src_mapping.memory(), allocation_size);
- std::vector<uint32_t> offsets(num_planes);
- std::vector<int32_t> strides(num_planes);
- for (size_t i = 0; i < num_planes; ++i) {
- offsets[i] = frame->data(i) - frame->data(0);
- strides[i] = frame->stride(i);
- }
-
- // Temporary Mojo VideoFrame to allow for marshalling.
scoped_refptr<MojoSharedBufferVideoFrame> mojo_frame =
- MojoSharedBufferVideoFrame::Create(
- frame->format(), frame->coded_size(), frame->visible_rect(),
- frame->natural_size(), std::move(dst_handle), allocation_size,
- std::move(offsets), std::move(strides), frame->timestamp());
+ MojoSharedBufferVideoFrame::CreateFromYUVFrame(*frame);
if (!mojo_frame) {
- DLOG(ERROR) << "Failed creating MojoSharedBufferVideoFrame";
+ DLOG(ERROR) << "Failed creating MojoSharedBufferVideoFrame from YUV";
return;
}
-
- // Encode() is synchronous: clients will assume full ownership of |frame| when
- // this gets destroyed and probably recycle its shared_memory_handle(): keep
- // the former alive until the remote end is actually finished.
vea_->Encode(
std::move(mojo_frame), force_keyframe,
base::BindOnce(base::DoNothing::Once<scoped_refptr<VideoFrame>>(),
diff --git a/chromium/media/mojo/clients/win/media_foundation_renderer_client.cc b/chromium/media/mojo/clients/win/media_foundation_renderer_client.cc
index 3bb5f2d15a7..66ef3880041 100644
--- a/chromium/media/mojo/clients/win/media_foundation_renderer_client.cc
+++ b/chromium/media/mojo/clients/win/media_foundation_renderer_client.cc
@@ -84,19 +84,20 @@ void MediaFoundationRendererClient::OnConnectionError() {
void MediaFoundationRendererClient::OnRemoteRendererInitialized(
PipelineStatus status) {
DVLOG_FUNC(1) << "status=" << status;
-
DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(!init_cb_.is_null());
+
if (status != media::PipelineStatus::PIPELINE_OK) {
- DCHECK(!init_cb_.is_null());
std::move(init_cb_).Run(status);
return;
}
if (has_video_) {
// TODO(frankli): Add code to init DCOMPTextureWrapper.
- } else {
- std::move(init_cb_).Run(status);
+ NOTIMPLEMENTED() << "Video compositing not implemented yet";
}
+
+ std::move(init_cb_).Run(status);
}
void MediaFoundationRendererClient::OnDCOMPSurfaceHandleCreated(bool success) {
@@ -385,7 +386,7 @@ void MediaFoundationRendererClient::OnVideoFrameRateChange(
scoped_refptr<media::VideoFrame> MediaFoundationRendererClient::Render(
base::TimeTicks deadline_min,
base::TimeTicks deadline_max,
- bool background_rendering) {
+ RenderingMode mode) {
// Returns no video frame as it is rendered independently by Windows Direct
// Composition.
return nullptr;
diff --git a/chromium/media/mojo/clients/win/media_foundation_renderer_client.h b/chromium/media/mojo/clients/win/media_foundation_renderer_client.h
index 7ba6d844dea..f9afedaa4f7 100644
--- a/chromium/media/mojo/clients/win/media_foundation_renderer_client.h
+++ b/chromium/media/mojo/clients/win/media_foundation_renderer_client.h
@@ -80,9 +80,10 @@ class MediaFoundationRendererClient
void OnVideoFrameRateChange(base::Optional<int>) override;
// media::VideoRendererSink::RenderCallback implementation.
- scoped_refptr<media::VideoFrame> Render(base::TimeTicks deadline_min,
- base::TimeTicks deadline_max,
- bool background_rendering) override;
+ scoped_refptr<media::VideoFrame> Render(
+ base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max,
+ RenderingMode rendering_mode) override;
void OnFrameDropped() override;
base::TimeDelta GetPreferredRenderInterval() override;
diff --git a/chromium/media/mojo/common/BUILD.gn b/chromium/media/mojo/common/BUILD.gn
index 384e9946cd4..8d33e8dc97c 100644
--- a/chromium/media/mojo/common/BUILD.gn
+++ b/chromium/media/mojo/common/BUILD.gn
@@ -4,6 +4,8 @@
source_set("common") {
sources = [
+ "audio_data_s16_converter.cc",
+ "audio_data_s16_converter.h",
"media_type_converters.cc",
"media_type_converters.h",
"mojo_data_pipe_read_write.cc",
diff --git a/chromium/media/mojo/common/audio_data_s16_converter.cc b/chromium/media/mojo/common/audio_data_s16_converter.cc
new file mode 100644
index 00000000000..add32e1e055
--- /dev/null
+++ b/chromium/media/mojo/common/audio_data_s16_converter.cc
@@ -0,0 +1,120 @@
+// Copyright 2021 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/mojo/common/audio_data_s16_converter.h"
+
+#include <memory>
+
+#include "media/base/audio_buffer.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/base/channel_mixer.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+
+namespace media {
+
+AudioDataS16Converter::AudioDataS16Converter() = default;
+AudioDataS16Converter::~AudioDataS16Converter() = default;
+
+mojom::AudioDataS16Ptr AudioDataS16Converter::ConvertToAudioDataS16(
+ scoped_refptr<AudioBuffer> buffer,
+ bool is_multichannel_supported) {
+ DCHECK_GT(buffer->frame_count(), 0);
+ DCHECK_GT(buffer->channel_count(), 0);
+ DCHECK_GT(buffer->sample_rate(), 0);
+
+ // If the audio is already in the interleaved signed int 16 format, directly
+ // assign it to the buffer, unless it is multichannel when multichannel is
+ // not supported.
+ if (buffer->sample_format() == SampleFormat::kSampleFormatS16 &&
+ (buffer->channel_count() == 1 || is_multichannel_supported)) {
+ auto signed_buffer = mojom::AudioDataS16::New();
+ signed_buffer->channel_count = buffer->channel_count();
+ signed_buffer->frame_count = buffer->frame_count();
+ signed_buffer->sample_rate = buffer->sample_rate();
+ int16_t* audio_data = reinterpret_cast<int16_t*>(buffer->channel_data()[0]);
+ signed_buffer->data.assign(
+ audio_data,
+ audio_data + buffer->frame_count() * buffer->channel_count());
+ return signed_buffer;
+ }
+
+ CopyBufferToTempAudioBus(*buffer);
+ return ConvertAudioBusToAudioDataS16Internal(
+ *temp_audio_bus_, buffer->sample_rate(), buffer->channel_layout(),
+ is_multichannel_supported);
+}
+
+mojom::AudioDataS16Ptr AudioDataS16Converter::ConvertToAudioDataS16(
+ std::unique_ptr<AudioBus> audio_bus,
+ int sample_rate,
+ ChannelLayout channel_layout,
+ bool is_multichannel_supported) {
+ DCHECK_GT(audio_bus->frames(), 0);
+ DCHECK_GT(audio_bus->channels(), 0);
+ return ConvertAudioBusToAudioDataS16Internal(
+ *audio_bus, sample_rate, channel_layout, is_multichannel_supported);
+}
+
+mojom::AudioDataS16Ptr
+AudioDataS16Converter::ConvertAudioBusToAudioDataS16Internal(
+ const AudioBus& audio_bus,
+ int sample_rate,
+ ChannelLayout channel_layout,
+ bool is_multichannel_supported) {
+ auto signed_buffer = mojom::AudioDataS16::New();
+ signed_buffer->channel_count = audio_bus.channels();
+ signed_buffer->frame_count = audio_bus.frames();
+ signed_buffer->sample_rate = sample_rate;
+
+ // If multichannel audio is not supported, mix the channels into a monaural
+ // channel before converting it.
+ if (audio_bus.channels() > 1 && !is_multichannel_supported) {
+ signed_buffer->channel_count = 1;
+ ResetChannelMixerIfNeeded(audio_bus.frames(), channel_layout);
+ signed_buffer->data.resize(audio_bus.frames());
+
+ channel_mixer_->Transform(&audio_bus, monaural_audio_bus_.get());
+ monaural_audio_bus_->ToInterleaved<SignedInt16SampleTypeTraits>(
+ monaural_audio_bus_->frames(), &signed_buffer->data[0]);
+
+ return signed_buffer;
+ }
+
+ signed_buffer->data.resize(audio_bus.frames() * audio_bus.channels());
+ audio_bus.ToInterleaved<SignedInt16SampleTypeTraits>(audio_bus.frames(),
+ &signed_buffer->data[0]);
+
+ return signed_buffer;
+}
+
+void AudioDataS16Converter::CopyBufferToTempAudioBus(
+ const AudioBuffer& buffer) {
+ if (!temp_audio_bus_ ||
+ buffer.channel_count() != temp_audio_bus_->channels() ||
+ buffer.frame_count() != temp_audio_bus_->frames()) {
+ temp_audio_bus_ =
+ AudioBus::Create(buffer.channel_count(), buffer.frame_count());
+ }
+
+ buffer.ReadFrames(buffer.frame_count(),
+ /* source_frame_offset */ 0, /* dest_frame_offset */ 0,
+ temp_audio_bus_.get());
+}
+
+void AudioDataS16Converter::ResetChannelMixerIfNeeded(
+ int frame_count,
+ ChannelLayout channel_layout) {
+ if (!monaural_audio_bus_ || frame_count != monaural_audio_bus_->frames()) {
+ monaural_audio_bus_ = AudioBus::Create(1 /* channels */, frame_count);
+ }
+
+ if (channel_layout != channel_layout_) {
+ channel_layout_ = channel_layout;
+ channel_mixer_ =
+ std::make_unique<ChannelMixer>(channel_layout, CHANNEL_LAYOUT_MONO);
+ }
+}
+
+} // namespace media \ No newline at end of file
diff --git a/chromium/media/mojo/common/audio_data_s16_converter.h b/chromium/media/mojo/common/audio_data_s16_converter.h
new file mode 100644
index 00000000000..ba18c40605b
--- /dev/null
+++ b/chromium/media/mojo/common/audio_data_s16_converter.h
@@ -0,0 +1,67 @@
+// Copyright 2021 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_MOJO_COMMON_AUDIO_DATA_S16_CONVERTER_H_
+#define MEDIA_MOJO_COMMON_AUDIO_DATA_S16_CONVERTER_H_
+
+#include <memory>
+
+#include "media/base/audio_buffer.h"
+#include "media/base/audio_bus.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+
+namespace media {
+
+class ChannelMixer;
+
+// Converts AudioBuffer or AudioBus into mojom::AudioDataS16.
+class AudioDataS16Converter {
+ public:
+ AudioDataS16Converter();
+ virtual ~AudioDataS16Converter();
+ AudioDataS16Converter(const AudioDataS16Converter&) = delete;
+ AudioDataS16Converter& operator=(const AudioDataS16Converter&) = delete;
+
+ mojom::AudioDataS16Ptr ConvertToAudioDataS16(
+ scoped_refptr<AudioBuffer> buffer,
+ bool is_multichannel_supported);
+
+ mojom::AudioDataS16Ptr ConvertToAudioDataS16(
+ std::unique_ptr<AudioBus> audio_bus,
+ int sample_rate,
+ ChannelLayout channel_layout,
+ bool is_multichannel_supported);
+
+ private:
+ mojom::AudioDataS16Ptr ConvertAudioBusToAudioDataS16Internal(
+ const AudioBus& audio_bus,
+ int sample_rate,
+ ChannelLayout channel_layout,
+ bool is_multichannel_supported);
+
+ // Recreates the temporary audio bus if the frame count or channel count
+ // changed and reads the frames from the buffer into the temporary audio bus.
+ void CopyBufferToTempAudioBus(const AudioBuffer& buffer);
+
+ // Resets the temporary monaural audio bus and the channel mixer used to
+ // combine multiple audio channels.
+ void ResetChannelMixerIfNeeded(int frame_count, ChannelLayout channel_layout);
+
+ // The temporary audio bus used to convert the raw audio to the appropriate
+ // format.
+ std::unique_ptr<AudioBus> temp_audio_bus_;
+
+ // The temporary audio bus used to mix multichannel audio into a single
+ // channel.
+ std::unique_ptr<AudioBus> monaural_audio_bus_;
+
+ std::unique_ptr<ChannelMixer> channel_mixer_;
+
+ // The layout used to instantiate the channel mixer.
+ ChannelLayout channel_layout_ = ChannelLayout::CHANNEL_LAYOUT_NONE;
+};
+
+} // namespace media
+
+#endif // MEDIA_MOJO_COMMON_AUDIO_DATA_S16_CONVERTER_H_
diff --git a/chromium/media/mojo/common/mojo_shared_buffer_video_frame.cc b/chromium/media/mojo/common/mojo_shared_buffer_video_frame.cc
index 649be420285..fab1dc1b489 100644
--- a/chromium/media/mojo/common/mojo_shared_buffer_video_frame.cc
+++ b/chromium/media/mojo/common/mojo_shared_buffer_video_frame.cc
@@ -79,7 +79,7 @@ MojoSharedBufferVideoFrame::CreateDefaultForTesting(
}
scoped_refptr<MojoSharedBufferVideoFrame>
-MojoSharedBufferVideoFrame::CreateFromYUVFrame(const VideoFrame& frame) {
+MojoSharedBufferVideoFrame::CreateFromYUVFrame(VideoFrame& frame) {
size_t num_planes = VideoFrame::NumPlanes(frame.format());
DCHECK_LE(num_planes, 3u);
DCHECK_GE(num_planes, 2u);
@@ -99,6 +99,11 @@ MojoSharedBufferVideoFrame::CreateFromYUVFrame(const VideoFrame& frame) {
mojo::ScopedSharedBufferHandle handle =
mojo::SharedBufferHandle::Create(aggregate_size);
+ if (!handle->is_valid()) {
+ DLOG(ERROR) << "Can't create new frame backing memory";
+ return nullptr;
+ }
+ mojo::ScopedSharedBufferMapping dst_mapping = handle->Map(aggregate_size);
// The data from |frame| may not be consecutive between planes. Copy data into
// a shared memory buffer which is tightly packed. Padding inside each planes
@@ -111,7 +116,21 @@ MojoSharedBufferVideoFrame::CreateFromYUVFrame(const VideoFrame& frame) {
frame.timestamp());
CHECK(!!mojo_frame);
- // Copy plane data.
+ // If the source memory region is a shared memory region we must map it too.
+ base::WritableSharedMemoryMapping src_mapping;
+ if (frame.storage_type() == VideoFrame::STORAGE_SHMEM) {
+ if (!frame.shm_region()->IsValid()) {
+ DLOG(ERROR) << "Invalid source shared memory region";
+ return nullptr;
+ }
+ src_mapping = frame.shm_region()->Map();
+ if (!src_mapping.IsValid()) {
+ DLOG(ERROR) << "Can't map source shared memory region";
+ return nullptr;
+ }
+ }
+
+ // Copy plane data while mappings are in scope.
for (size_t i = 0; i < num_planes; ++i) {
memcpy(mojo_frame->shared_buffer_data() + offsets[i],
static_cast<const void*>(frame.data(i)), sizes[i]);
diff --git a/chromium/media/mojo/common/mojo_shared_buffer_video_frame.h b/chromium/media/mojo/common/mojo_shared_buffer_video_frame.h
index 5bb63c9255d..5a852080ce6 100644
--- a/chromium/media/mojo/common/mojo_shared_buffer_video_frame.h
+++ b/chromium/media/mojo/common/mojo_shared_buffer_video_frame.h
@@ -47,7 +47,7 @@ class MojoSharedBufferVideoFrame : public VideoFrame {
// Internally the data from in-memory YUV frame will be copied to a
// consecutive block in shared memory. Will return null on failure.
static scoped_refptr<MojoSharedBufferVideoFrame> CreateFromYUVFrame(
- const VideoFrame& frame);
+ VideoFrame& frame);
// Creates a MojoSharedBufferVideoFrame that uses the memory in |handle|.
// This will take ownership of |handle|, so the caller can no longer use it.
diff --git a/chromium/media/mojo/mojom/BUILD.gn b/chromium/media/mojo/mojom/BUILD.gn
index 44e9f738a81..341e26de457 100644
--- a/chromium/media/mojo/mojom/BUILD.gn
+++ b/chromium/media/mojo/mojom/BUILD.gn
@@ -17,7 +17,7 @@ mojom("mojom") {
"audio_logging.mojom",
"audio_output_stream.mojom",
"audio_parameters.mojom",
- "cdm_infobar_service.mojom",
+ "audio_stream_factory.mojom",
"cdm_service.mojom",
"cdm_storage.mojom",
"content_decryption_module.mojom",
@@ -60,6 +60,10 @@ mojom("mojom") {
sources += [ "cast_application_media_info_manager.mojom" ]
}
+ if (is_win) {
+ sources += [ "media_foundation_service.mojom" ]
+ }
+
public_deps = [
"//gpu/ipc/common:interfaces",
"//media/learning/mojo/public/mojom",
@@ -415,10 +419,6 @@ mojom("mojom") {
{
types = [
{
- mojom = "media.mojom.ScalingSettings"
- cpp = "::media::ScalingSettings"
- },
- {
mojom = "media.mojom.ResolutionBitrateLimit"
cpp = "::media::ResolutionBitrateLimit"
},
diff --git a/chromium/media/mojo/mojom/audio_stream_factory.mojom b/chromium/media/mojo/mojom/audio_stream_factory.mojom
new file mode 100644
index 00000000000..0b1e61f23f1
--- /dev/null
+++ b/chromium/media/mojo/mojom/audio_stream_factory.mojom
@@ -0,0 +1,100 @@
+// Copyright 2018 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/audio_data_pipe.mojom";
+import "media/mojo/mojom/audio_input_stream.mojom";
+import "media/mojo/mojom/audio_logging.mojom";
+import "media/mojo/mojom/audio_output_stream.mojom";
+import "media/mojo/mojom/audio_parameters.mojom";
+import "mojo/public/mojom/base/shared_memory.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
+
+// Mutes a group of AudioOutputStreams while at least one binding to an instance
+// exists. Once the last binding is dropped, all streams in the group are
+// un-muted.
+interface LocalMuter {};
+
+// This interface is exposed by the audio service to allow trusted clients
+// (like the browser process) to create streams. Note that while the factory
+// interface itself is only for trusted clients, the created streams and data
+// pipes may be forwarded to untrusted clients.
+//
+// The client must keep the connection to the factory while streams are
+// running.
+interface AudioStreamFactory {
+ // Creates an AudioInputStream and returns the AudioDataPipe it writes data to
+ // and a bool indicating whether the stream is initially muted. |data_pipe| is
+ // null, |initially_muted| is false and |stream_id| is empty in case stream
+ // creation failed.
+ // |device_id| is either the |unique_id| field from an AudioDeviceDescription
+ // obtained from the audio.mojom.SystemInfo interface, or "default".
+ // |shared_memory_count| indicates how many buffer segments can the input
+ // stream client read at once, to avoid data overwriting. |enable_agc| is used
+ // for enabling automatic gain control. |key_press_count_buffer| is an
+ // optional readonly shared memory handle for reading the current key press
+ // count, updated by browser process in media::UserInputMonitor
+ // implementation.
+ CreateInputStream(
+ pending_receiver<media.mojom.AudioInputStream> stream,
+ pending_remote<media.mojom.AudioInputStreamClient> client,
+ pending_remote<media.mojom.AudioInputStreamObserver>? observer,
+ pending_remote<media.mojom.AudioLog>? log,
+ string device_id, media.mojom.AudioParameters params,
+ uint32 shared_memory_count, bool enable_agc,
+ mojo_base.mojom.ReadOnlySharedMemoryRegion? key_press_count_buffer)
+ => (media.mojom.ReadOnlyAudioDataPipe? data_pipe, bool initially_muted,
+ mojo_base.mojom.UnguessableToken? stream_id);
+
+ // Associates an output device with an input stream, so that the input knows
+ // which output device to cancel echo from. |input_stream_id| is the id
+ // returned when the stream was created. |output_device_id| is a raw device
+ // id. In case either of the parameters are invalid, the operation will
+ // silently fail.
+ AssociateInputAndOutputForAec(
+ mojo_base.mojom.UnguessableToken input_stream_id,
+ string output_device_id);
+
+ // Creates an AudioOutputStream and returns the AudioDataPipe it reads data
+ // from. |data_pipe| is null in case stream creation failed. |device_id| is
+ // either the |unique_id| field from an AudioDeviceDescription obtained from
+ // the audio.mojom.SystemInfo interface, or "default". The stream |group_id|
+ // is used for muting streams or capturing them for loopback.
+ CreateOutputStream(
+ pending_receiver<media.mojom.AudioOutputStream> stream,
+ pending_associated_remote<media.mojom.AudioOutputStreamObserver>? observer,
+ pending_remote<media.mojom.AudioLog>? log,
+ string device_id, media.mojom.AudioParameters params,
+ mojo_base.mojom.UnguessableToken group_id)
+ => (media.mojom.ReadWriteAudioDataPipe? data_pipe);
+
+ // Binds the request to the LocalMuter associated with the given |group_id|.
+ // While one or more bindings to a group's LocalMuter exists, all local audio
+ // playout for the streams in that group is muted.
+ //
+ // It is the responsibility of the client to bind to a muter before creating
+ // any output streams that should be started muted. Likewise, if existing
+ // output streams must remain muted until they are shut down, the binding to
+ // the muter must not be closed until after all other streams' binding. (This
+ // is the reason for the associated request argument.)
+ BindMuter(pending_associated_receiver<LocalMuter> receiver,
+ mojo_base.mojom.UnguessableToken group_id);
+
+ // Creates an AudioInputStream that provides the result of looping-back and
+ // mixing-together all current and future AudioOutputStreams tagged with the
+ // given |group_id|. The loopback re-mixes audio, if necessary, so that the
+ // resulting data stream format matches the specified |params|. All other args
+ // and the result are as described in CreateInputStream() above, except for
+ // |stream_id|. Loopback streams have no ID, since they cannot be used in
+ // echo cancellation.
+ CreateLoopbackStream(
+ pending_receiver<media.mojom.AudioInputStream> receiver,
+ pending_remote<media.mojom.AudioInputStreamClient> client,
+ pending_remote<media.mojom.AudioInputStreamObserver> observer,
+ media.mojom.AudioParameters params,
+ uint32 shared_memory_count,
+ mojo_base.mojom.UnguessableToken group_id)
+ => (media.mojom.ReadOnlyAudioDataPipe? data_pipe);
+};
diff --git a/chromium/media/mojo/mojom/cdm_infobar_service.mojom b/chromium/media/mojo/mojom/cdm_infobar_service.mojom
deleted file mode 100644
index 4da7c551c7c..00000000000
--- a/chromium/media/mojo/mojom/cdm_infobar_service.mojom
+++ /dev/null
@@ -1,11 +0,0 @@
-// 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;
-
-// Service to trigger info bar for CDM related events.
-interface CdmInfobarService {
- // Notifies that the platform is not supported.
- NotifyUnsupportedPlatform();
-}; \ No newline at end of file
diff --git a/chromium/media/mojo/mojom/content_decryption_module.mojom b/chromium/media/mojo/mojom/content_decryption_module.mojom
index 8181ceeeed2..c0e8e2510d3 100644
--- a/chromium/media/mojo/mojom/content_decryption_module.mojom
+++ b/chromium/media/mojo/mojom/content_decryption_module.mojom
@@ -132,6 +132,19 @@ interface ContentDecryptionModuleClient {
OnSessionExpirationUpdate(string session_id, double new_expiry_time_sec);
};
+// Context associated with the remote CDM, mostly to populate media::CdmContext.
+struct CdmContext {
+ // An ID that can be used to locate the CDM at the remote side.
+ mojo_base.mojom.UnguessableToken cdm_id;
+
+ // The remote Decryptor if the CDM implementation provides one.
+ pending_remote<Decryptor>? decryptor;
+
+ // Whether MediaFoundationRenderer is required by the CDM.
+ [EnableIf=is_win]
+ bool requires_media_foundation_renderer;
+};
+
// Factory interface used for creating ContentDecryptionModule instances.
interface CdmFactory {
// Creates a CDM based on the |key_system| and |cdm_config| provided. A
@@ -141,14 +154,11 @@ interface CdmFactory {
// untrusted process (e.g. renderer), so the implementation must fully
// validate |key_system| before creating the CDM. |cdm_config| specifies other
// properties of the CDM which may influence creation. Upon failure, the
- // returned |cdm| and |decryptor| will be null, |cdm_id| will be zero and
- // |error_message| will specify the error reason. Upon success, |cdm| will be
- // valid, |cdm_id| will be non-zero and will later be used to locate the CDM
- // at the remote side and |error_message| will be empty. |decryptor| will be
- // the remote Decryptor if the CDM implementation provides one.
+ // returned |cdm| and |cdm_context| will be null, and |error_message| will
+ // specify the error reason. Upon success, |cdm| and |cdm_context| will be
+ // valid, and |error_message| will be empty.
CreateCdm(string key_system, CdmConfig cdm_config) =>
(pending_remote<ContentDecryptionModule>? cdm,
- mojo_base.mojom.UnguessableToken? cdm_id,
- pending_remote<Decryptor>? decryptor,
+ CdmContext? cdm_context,
string error_message);
};
diff --git a/chromium/media/mojo/mojom/interface_factory.mojom b/chromium/media/mojo/mojom/interface_factory.mojom
index 09e7328dd7c..cf43b8cd012 100644
--- a/chromium/media/mojo/mojom/interface_factory.mojom
+++ b/chromium/media/mojo/mojom/interface_factory.mojom
@@ -70,14 +70,11 @@ interface InterfaceFactory {
// untrusted process (e.g. renderer), so the implementation must fully
// validate |key_system| before creating the CDM. |cdm_config| specifies other
// properties of the CDM which may influence creation. Upon failure, the
- // returned |cdm| and |decryptor| will be null, |cdm_id| will be zero and
- // |error_message| will specify the error reason. Upon success, |cdm| will be
- // valid, |cdm_id| will be non-zero and will later be used to locate the CDM
- // at the remote side and |error_message| will be empty. |decryptor| will be
- // the remote Decryptor if the CDM implementation provides one.
+ // returned |cdm| and |cdm_context| will be null, and |error_message| will
+ // specify the error reason. Upon success, |cdm| and |cdm_context| will be
+ // valid, and |error_message| will be empty.
CreateCdm(string key_system, CdmConfig cdm_config) =>
(pending_remote<ContentDecryptionModule>? cdm,
- mojo_base.mojom.UnguessableToken? cdm_id,
- pending_remote<Decryptor>? decryptor,
+ CdmContext? cdm_context,
string error_message);
};
diff --git a/chromium/media/mojo/mojom/key_system_support.mojom b/chromium/media/mojo/mojom/key_system_support.mojom
index 69d608ca7d5..ce6267224bd 100644
--- a/chromium/media/mojo/mojom/key_system_support.mojom
+++ b/chromium/media/mojo/mojom/key_system_support.mojom
@@ -13,7 +13,6 @@ import "media/mojo/mojom/media_types.mojom";
struct KeySystemCapability {
// Software secure codecs and encryption schemes supported by the CDM.
array<VideoCodec> video_codecs;
- bool supports_vp9_profile2;
array<EncryptionScheme> encryption_schemes;
// Hardware secure codecs and encryption schemes supported by the CDM.
diff --git a/chromium/media/mojo/mojom/media_foundation_service.mojom b/chromium/media/mojo/mojom/media_foundation_service.mojom
new file mode 100644
index 00000000000..e87f7b7944d
--- /dev/null
+++ b/chromium/media/mojo/mojom/media_foundation_service.mojom
@@ -0,0 +1,35 @@
+// Copyright 2021 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/frame_interface_factory.mojom";
+import "media/mojo/mojom/interface_factory.mojom";
+import "media/mojo/mojom/key_system_support.mojom";
+import "mojo/public/mojom/base/file_path.mojom";
+
+// A service to provide Windows MediaFoundation-based InterfaceFactory and
+// KeySystemCapability. The service runs in the MediaFoundationService process,
+// which is a specialized utility process with SandboxType::kMediaFoundationCdm.
+// The process is not sandboxed after launch. `Initialize()` must be called to
+// preload the CDM if needed, after which the sandbox will be sealed. The
+// service is always connected from the browser process. The remote
+// `InterfaceFactory` lives in the renderer process.
+interface MediaFoundationService {
+ // Must be called immediately after the `MediaFoundationService` is connected,
+ // before any other method can be called. Must seal the sandbox before return.
+ // If `cdm_path` is not empty, preloads the CDM into the process.
+ Initialize(mojo_base.mojom.FilePath cdm_path);
+
+ // Queries the capabilities of the MediaFoundation-based CDM.
+ IsKeySystemSupported(string key_system)
+ => (bool is_supported, KeySystemCapability? key_system_capability);
+
+ // Requests an InterfaceFactory. `frame_interfaces` can optionally be used to
+ // provide interfaces hosted by the caller to the remote InterfaceFactory
+ // implementation.
+ CreateInterfaceFactory(
+ pending_receiver<InterfaceFactory> factory,
+ pending_remote<FrameInterfaceFactory> frame_interfaces);
+};
diff --git a/chromium/media/mojo/mojom/media_player.mojom b/chromium/media/mojo/mojom/media_player.mojom
index 727d298ed49..1a7fe6cb761 100644
--- a/chromium/media/mojo/mojom/media_player.mojom
+++ b/chromium/media/mojo/mojom/media_player.mojom
@@ -11,12 +11,6 @@ import "ui/gfx/geometry/mojom/geometry.mojom";
// Implemented by HTMLMediaElement in the renderer process.
interface MediaPlayer {
- // Sends |observer| to the renderer process so that it can be established a
- // communication channel with the implementor of MediaPlayerObserver, and
- // allows multiple observers for more observers like PictureInPictureService.
- AddMediaPlayerObserver(
- pending_associated_remote<MediaPlayerObserver> observer);
-
// Requests the media player to start or resume media playback.
RequestPlay();
@@ -29,14 +23,33 @@ interface MediaPlayer {
// Requests the media player to move backward the media playback position.
RequestSeekBackward(mojo_base.mojom.TimeDelta seek_time);
+ // Requests the media player to move to a specific time.
+ RequestSeekTo(mojo_base.mojom.TimeDelta seek_time);
+
// Requests the media player to enter the Picture-in-Picture mode.
RequestEnterPictureInPicture();
// Requests the media player to exit the Picture-in-Picture mode.
RequestExitPictureInPicture();
+ // Set the volume multiplier to control audio ducking.
+ // Output volume should be set to |player_volume| * |multiplier|. The range
+ // of |multiplier| is [0, 1], where 1 indicates normal (non-ducked) playback.
+ SetVolumeMultiplier(double multiplier);
+
+ // Set the player as the persistent video. Persistent video should hide its
+ // controls and go fullscreen.
+ SetPersistentState(bool persistent);
+
+ // Notify the player that it is now eligible to start recording power
+ // measurements if |state| is true, else it is no longer eligible.
+ SetPowerExperimentState(bool enabled);
+
// Set the media player sink id to |sink_id|.
SetAudioSinkId(string sink_id);
+
+ // Suspends the media player when the host frame is closed.
+ SuspendForFrameClosed();
};
// Implemented by MediaWebContentsObserver::MediaPlayerObserverHostImpl in the
@@ -94,6 +107,9 @@ interface MediaPlayerHost {
// document owning the HTMLMediaElement that a new MediaPlayer is available,
// passing a pending remote (i.e. |player_remote|) that will be used in the
// browser process to establish a channel with the HTMLMediaElement.
+ // |observer| starts observing the MediaPlayer as soon as the player is
+ // created.
OnMediaPlayerAdded(pending_associated_remote<MediaPlayer> player_remote,
+ pending_associated_receiver<MediaPlayerObserver> observer,
int32 player_id);
};
diff --git a/chromium/media/mojo/mojom/media_types.mojom b/chromium/media/mojo/mojom/media_types.mojom
index 1ae7c91c0a8..1db4788ed02 100644
--- a/chromium/media/mojo/mojom/media_types.mojom
+++ b/chromium/media/mojo/mojom/media_types.mojom
@@ -372,7 +372,6 @@ struct VideoFrame {
union VideoFrameData {
EosVideoFrameData eos_data;
SharedBufferVideoFrameData shared_buffer_data;
- DmabufVideoFrameData dmabuf_data;
GpuMemoryBufferVideoFrameData gpu_memory_buffer_data;
MailboxVideoFrameData mailbox_data;
};
@@ -393,12 +392,6 @@ struct SharedBufferVideoFrameData {
array<uint32> offsets;
};
-// This defines video frame data stored in dmabuf.
-struct DmabufVideoFrameData {
- // Size depends on media::VideoFrame::NumPlanes with frame format.
- array<handle<platform>> dmabuf_fds;
-};
-
struct GpuMemoryBufferVideoFrameData {
gfx.mojom.GpuMemoryBufferHandle gpu_memory_buffer_handle;
array<gpu.mojom.MailboxHolder, 4> mailbox_holder;
diff --git a/chromium/media/mojo/mojom/speech_recognition_service.mojom b/chromium/media/mojo/mojom/speech_recognition_service.mojom
index 0c8b14579ca..ab4d55221b5 100644
--- a/chromium/media/mojo/mojom/speech_recognition_service.mojom
+++ b/chromium/media/mojo/mojom/speech_recognition_service.mojom
@@ -4,21 +4,42 @@
module media.mojom;
+import "media/mojo/mojom/audio_parameters.mojom";
+import "media/mojo/mojom/audio_stream_factory.mojom";
import "media/mojo/mojom/media_types.mojom";
import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/url_loader_factory.mojom";
+// Corresponds to the LangIdEvent.ConfidenceInterval defined in
+// http://google3/speech/soda/public/soda_event.proto.
+enum ConfidenceLevel {
+ kUnknown,
+ kNotConfident,
+ kConfident,
+ kHighlyConfident,
+};
+
// The main interface a client uses to interact with a speech recognition
-// service process. Every renderer can own one or more
+// service process. In Live Caption, every renderer can own one or more
// Remote<SpeechRecognitionContext>, with the receiver bound through the
-// BrowserInterfaceBroker. Returns a flag indicating whether multichannel
-// audio is supported by the speech recognition service.
+// BrowserInterfaceBroker. In Chrome OS features like Dictation and Projector,
+// every OnDeviceSpeechRecognizer can own a Remote<SpeechRecognitionContext>.
interface SpeechRecognitionContext {
- // Bind the recognizers to the speech recognition service.
+ // Bind the recognizers to the speech recognition service. Returns a flag
+ // indicating whether multichannel audio is supported by the speech
+ // recognition service.
BindRecognizer(pending_receiver<SpeechRecognitionRecognizer> receiver,
pending_remote<SpeechRecognitionRecognizerClient> client)
=> (bool is_multichannel_supported);
+
+ // Prepares microphone audio to be captured from within the
+ // SpeechRecognitionService process, with results passed back to the
+ // SpeechRecognitionRecognizerClient.
+ BindAudioSourceFetcher(
+ pending_receiver<AudioSourceFetcher> fetcher_receiver,
+ pending_remote<SpeechRecognitionRecognizerClient> client)
+ => (bool is_multichannel_supported);
};
// The main interface to a speech secognition service process.
@@ -43,6 +64,19 @@ interface SpeechRecognitionService {
pending_remote<SpeechRecognitionServiceClient> client);
};
+// The interface used to start and stop fetching audio from the microphone
+// for speech recognition.
+interface AudioSourceFetcher {
+ // Begin fetching audio. Results will be returned using the
+ // Remote<SpeechRecognitionRecognizerClient> which was passed in
+ // BindAudioSourceFetcher.
+ Start(pending_remote<AudioStreamFactory> factory, string device_id,
+ media.mojom.AudioParameters audio_parameters);
+
+ // Stops audio fetching.
+ Stop();
+};
+
// The interface used to send messages from the speech recognition service
// back to the consumer of the service.
interface SpeechRecognitionServiceClient {
@@ -68,6 +102,10 @@ interface SpeechRecognitionRecognizer {
// Notify the speech recognition recognizer that audio was received by the
// renderer after the caption bubble was closed.
AudioReceivedAfterBubbleClosed(mojo_base.mojom.TimeDelta duration);
+
+ // Notify the speech recognition recognizer that the language changed. Takes
+ // in the locale string (e.g. "en-US").
+ OnLanguageChanged(string language);
};
// The interface used to return speech recognition events from the speech
@@ -76,6 +114,12 @@ interface SpeechRecognitionRecognizer {
interface SpeechRecognitionRecognizerClient {
// Triggered by speech recognition process on a speech recognition event.
OnSpeechRecognitionRecognitionEvent(SpeechRecognitionResult result);
+
+ // Triggered by an error within the speech recognition service.
+ OnSpeechRecognitionError();
+
+ // Triggered by speech recognition process on a language identification event.
+ OnLanguageIdentificationEvent(LanguageIdentificationEvent event);
};
// A speech recognition result created by the speech service and passed to the
@@ -89,13 +133,27 @@ struct SpeechRecognitionResult {
bool is_final;
};
+// A language identification event created by the speech recognition service
+// and passed to the browser and renderer.
+struct LanguageIdentificationEvent {
+ // The locale of the language with the highest confidence.
+ string language;
+
+ // The confidence interval.
+ ConfidenceLevel confidence_level;
+};
+
// The interface used to notify the speech recognition client of events
// triggered by the browser. The remote lives in the browser process and the
// receiver lives in the renderer process.
-interface SpeechRecognitionAvailabilityObserver {
+interface SpeechRecognitionBrowserObserver {
// Notify the speech recognition client when speech recognition availability
// changes.
SpeechRecognitionAvailabilityChanged(bool is_speech_recognition_available);
+
+ // Notify the speech recognition client when the speech recognition language
+ // changes.
+ SpeechRecognitionLanguageChanged(string language);
};
// This interface between the speech recognition client and the browser.
@@ -103,6 +161,6 @@ interface SpeechRecognitionAvailabilityObserver {
// browser process.
interface SpeechRecognitionClientBrowserInterface {
// Bind the speech recognition availability observer.
- BindSpeechRecognitionAvailabilityObserver(
- pending_remote<SpeechRecognitionAvailabilityObserver> observer);
+ BindSpeechRecognitionBrowserObserver(
+ pending_remote<SpeechRecognitionBrowserObserver> observer);
};
diff --git a/chromium/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc b/chromium/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc
index 475dfee84d3..15d59d1d76a 100644
--- a/chromium/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc
+++ b/chromium/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc
@@ -15,8 +15,6 @@ namespace media {
TEST(VideoEncoderInfoStructTraitTest, RoundTrip) {
::media::VideoEncoderInfo input;
input.implementation_name = "FakeVideoEncodeAccelerator";
- // Scaling settings.
- input.scaling_settings = ::media::ScalingSettings(12, 123);
// FPS allocation.
for (size_t i = 0; i < ::media::VideoEncoderInfo::kMaxSpatialLayers; ++i)
input.fps_allocation[i] = {5, 5, 10};
diff --git a/chromium/media/mojo/mojom/video_encoder_info.mojom b/chromium/media/mojo/mojom/video_encoder_info.mojom
index a299ca7f84e..d0d15e386de 100644
--- a/chromium/media/mojo/mojom/video_encoder_info.mojom
+++ b/chromium/media/mojo/mojom/video_encoder_info.mojom
@@ -6,11 +6,6 @@ module media.mojom;
import "ui/gfx/geometry/mojom/geometry.mojom";
-struct ScalingSettings {
- uint8 min_qp;
- uint8 max_qp;
-};
-
struct ResolutionBitrateLimit {
gfx.mojom.Size frame_size;
int32 min_start_bitrate_bps;
@@ -26,7 +21,6 @@ struct VideoEncoderInfo {
bool is_hardware_accelerated;
bool supports_simulcast;
- ScalingSettings? scaling_settings;
// This array size is equal to media::VideoEncoderInfo::kMaxSpatialLayers.
array<array<uint8>, 5> fps_allocation;
array<ResolutionBitrateLimit> resolution_bitrate_limits;
diff --git a/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.cc b/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.cc
index 32262cc67fd..f30ce429b0e 100644
--- a/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.cc
+++ b/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.cc
@@ -7,16 +7,6 @@
namespace mojo {
// static
-bool StructTraits<
- media::mojom::ScalingSettingsDataView,
- media::ScalingSettings>::Read(media::mojom::ScalingSettingsDataView data,
- media::ScalingSettings* out) {
- out->min_qp = data.min_qp();
- out->max_qp = data.max_qp();
- return true;
-}
-
-// static
bool StructTraits<media::mojom::ResolutionBitrateLimitDataView,
media::ResolutionBitrateLimit>::
Read(media::mojom::ResolutionBitrateLimitDataView data,
@@ -42,9 +32,6 @@ bool StructTraits<
if (!data.ReadImplementationName(&out->implementation_name))
return false;
- if (!data.ReadScalingSettings(&out->scaling_settings))
- return false;
-
base::span<std::vector<uint8_t>> fps_allocation(out->fps_allocation);
if (!data.ReadFpsAllocation(&fps_allocation))
return false;
diff --git a/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.h b/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.h
index 30698bf4b56..39e911f8ca2 100644
--- a/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.h
+++ b/chromium/media/mojo/mojom/video_encoder_info_mojom_traits.h
@@ -13,21 +13,6 @@
namespace mojo {
template <>
-class StructTraits<media::mojom::ScalingSettingsDataView,
- media::ScalingSettings> {
- public:
- static int32_t min_qp(const media::ScalingSettings& scaling_settings) {
- return scaling_settings.min_qp;
- }
- static int32_t max_qp(const media::ScalingSettings& scaling_settings) {
- return scaling_settings.max_qp;
- }
-
- static bool Read(media::mojom::ScalingSettingsDataView data,
- media::ScalingSettings* out);
-};
-
-template <>
class StructTraits<media::mojom::ResolutionBitrateLimitDataView,
media::ResolutionBitrateLimit> {
public:
@@ -75,10 +60,6 @@ class StructTraits<media::mojom::VideoEncoderInfoDataView,
const media::VideoEncoderInfo& video_encoder_info) {
return video_encoder_info.supports_simulcast;
}
- static const base::Optional<media::ScalingSettings>& scaling_settings(
- const media::VideoEncoderInfo& video_encoder_info) {
- return video_encoder_info.scaling_settings;
- }
static base::span<const std::vector<uint8_t>,
media::VideoEncoderInfo::kMaxSpatialLayers>
fps_allocation(const media::VideoEncoderInfo& video_encoder_info) {
diff --git a/chromium/media/mojo/mojom/video_frame_mojom_traits.cc b/chromium/media/mojo/mojom/video_frame_mojom_traits.cc
index eac5560cc57..08ad8fc66ef 100644
--- a/chromium/media/mojo/mojom/video_frame_mojom_traits.cc
+++ b/chromium/media/mojo/mojom/video_frame_mojom_traits.cc
@@ -63,23 +63,6 @@ media::mojom::VideoFrameDataPtr MakeVideoFrameData(
std::move(offsets)));
}
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
- if (input->storage_type() == media::VideoFrame::STORAGE_DMABUFS) {
- std::vector<mojo::PlatformHandle> dmabuf_fds;
-
- const size_t num_planes = media::VideoFrame::NumPlanes(input->format());
- dmabuf_fds.reserve(num_planes);
- for (size_t i = 0; i < num_planes; i++) {
- const int dmabuf_fd = HANDLE_EINTR(dup(input->DmabufFds()[i].get()));
- dmabuf_fds.emplace_back(base::ScopedFD(dmabuf_fd));
- DCHECK(dmabuf_fds.back().is_valid());
- }
-
- return media::mojom::VideoFrameData::NewDmabufData(
- media::mojom::DmabufVideoFrameData::New(std::move(dmabuf_fds)));
- }
-#endif
-
std::vector<gpu::MailboxHolder> mailbox_holder(media::VideoFrame::kMaxPlanes);
DCHECK_LE(input->NumTextures(), mailbox_holder.size());
// STORAGE_GPU_MEMORY_BUFFER may carry meaningful or dummy mailboxes,
@@ -167,45 +150,6 @@ bool StructTraits<media::mojom::VideoFrameDataView,
shared_buffer_data.TakeFrameData(),
shared_buffer_data.frame_data_size(), std::move(offsets),
std::move(strides), timestamp);
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
- } else if (data.is_dmabuf_data()) {
- media::mojom::DmabufVideoFrameDataDataView dmabuf_data;
- data.GetDmabufDataDataView(&dmabuf_data);
-
- std::vector<mojo::PlatformHandle> dmabuf_fds_data;
- if (!dmabuf_data.ReadDmabufFds(&dmabuf_fds_data))
- return false;
-
- const size_t num_planes = media::VideoFrame::NumPlanes(format);
- std::vector<int> strides =
- media::VideoFrame::ComputeStrides(format, coded_size);
- if (num_planes != strides.size())
- return false;
- if (num_planes != dmabuf_fds_data.size())
- return false;
-
- std::vector<media::ColorPlaneLayout> planes(num_planes);
- for (size_t i = 0; i < num_planes; i++) {
- planes[i].stride = strides[i];
- planes[i].offset = 0;
- planes[i].size = static_cast<size_t>(
- media::VideoFrame::PlaneSize(format, i, coded_size).GetArea());
- }
-
- auto layout = media::VideoFrameLayout::CreateWithPlanes(format, coded_size,
- std::move(planes));
- if (!layout)
- return false;
-
- std::vector<base::ScopedFD> dmabuf_fds;
- dmabuf_fds.reserve(num_planes);
- for (size_t i = 0; i < num_planes; i++) {
- dmabuf_fds.push_back(dmabuf_fds_data[i].TakeFD());
- DCHECK(dmabuf_fds.back().is_valid());
- }
- frame = media::VideoFrame::WrapExternalDmabufs(
- *layout, visible_rect, natural_size, std::move(dmabuf_fds), timestamp);
-#endif
} else if (data.is_gpu_memory_buffer_data()) {
media::mojom::GpuMemoryBufferVideoFrameDataDataView gpu_memory_buffer_data;
data.GetGpuMemoryBufferDataDataView(&gpu_memory_buffer_data);
diff --git a/chromium/media/mojo/mojom/video_frame_mojom_traits_unittest.cc b/chromium/media/mojo/mojom/video_frame_mojom_traits_unittest.cc
index 1ac03ed08eb..d00e80d8693 100644
--- a/chromium/media/mojo/mojom/video_frame_mojom_traits_unittest.cc
+++ b/chromium/media/mojo/mojom/video_frame_mojom_traits_unittest.cc
@@ -24,11 +24,6 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
-#include <fcntl.h>
-#include <sys/stat.h>
-#endif
-
namespace media {
namespace {
@@ -102,41 +97,6 @@ TEST_F(VideoFrameStructTraitsTest, MojoSharedBufferVideoFrame) {
}
}
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
-TEST_F(VideoFrameStructTraitsTest, DmabufVideoFrame) {
- const size_t num_planes = media::VideoFrame::NumPlanes(PIXEL_FORMAT_NV12);
- std::vector<int> strides = {1280, 1280};
- std::vector<size_t> sizes = {1280 * 720, 1280 * 720 / 2};
- auto layout = media::VideoFrameLayout::CreateWithPlanes(
- PIXEL_FORMAT_NV12, gfx::Size(1280, 720),
- {media::ColorPlaneLayout(strides[0], 0, sizes[0]),
- media::ColorPlaneLayout(strides[1], 0, sizes[1])});
-
- // DMABUF needs device to create, use file fd instead.
- std::vector<int> fake_fds = {open("/dev/null", O_RDWR),
- open("/dev/zero", O_RDWR)};
- std::vector<base::ScopedFD> dmabuf_fds;
- dmabuf_fds.reserve(num_planes);
- for (size_t i = 0; i < num_planes; i++)
- dmabuf_fds.emplace_back(fake_fds[i]);
-
- scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalDmabufs(
- *layout, gfx::Rect(0, 0, 1280, 720), gfx::Size(1280, 720),
- std::move(dmabuf_fds), base::TimeDelta::FromSeconds(100));
-
- ASSERT_TRUE(RoundTrip(&frame));
- ASSERT_TRUE(frame);
- EXPECT_FALSE(frame->metadata().end_of_stream);
- EXPECT_EQ(frame->format(), PIXEL_FORMAT_NV12);
- EXPECT_EQ(frame->coded_size(), gfx::Size(1280, 720));
- EXPECT_EQ(frame->visible_rect(), gfx::Rect(0, 0, 1280, 720));
- EXPECT_EQ(frame->natural_size(), gfx::Size(1280, 720));
- EXPECT_EQ(frame->timestamp(), base::TimeDelta::FromSeconds(100));
- ASSERT_TRUE(frame->HasDmaBufs());
- ASSERT_EQ(frame->storage_type(), VideoFrame::STORAGE_DMABUFS);
-}
-#endif
-
TEST_F(VideoFrameStructTraitsTest, MailboxVideoFrame) {
gpu::Mailbox mailbox = gpu::Mailbox::Generate();
gpu::MailboxHolder mailbox_holder[VideoFrame::kMaxPlanes];
diff --git a/chromium/media/mojo/services/BUILD.gn b/chromium/media/mojo/services/BUILD.gn
index 5565b1ffdb8..3a87515b49c 100644
--- a/chromium/media/mojo/services/BUILD.gn
+++ b/chromium/media/mojo/services/BUILD.gn
@@ -141,6 +141,7 @@ component("services") {
deps += [ "//sandbox" ]
}
}
+
if (is_chromeos_ash) {
deps +=
[ "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_gpu" ]
@@ -152,6 +153,8 @@ component("services") {
"media_foundation_mojo_media_client.h",
"media_foundation_renderer_wrapper.cc",
"media_foundation_renderer_wrapper.h",
+ "media_foundation_service.cc",
+ "media_foundation_service.h",
]
deps += [ "//media/base/win:media_foundation_util" ]
}
diff --git a/chromium/media/mojo/services/cdm_service.cc b/chromium/media/mojo/services/cdm_service.cc
index 025dffbded5..9e1babd8287 100644
--- a/chromium/media/mojo/services/cdm_service.cc
+++ b/chromium/media/mojo/services/cdm_service.cc
@@ -66,16 +66,22 @@ class CdmFactoryImpl final : public DeferredDestroy<mojom::CdmFactory> {
auto* cdm_factory = GetCdmFactory();
if (!cdm_factory) {
- std::move(callback).Run(mojo::NullRemote(), base::nullopt,
- mojo::NullRemote(),
+ std::move(callback).Run(mojo::NullRemote(), nullptr,
"CDM Factory creation failed");
return;
}
- MojoCdmService::Create(
- cdm_factory, &cdm_service_context_, key_system, cdm_config,
- base::BindOnce(&CdmFactoryImpl::OnCdmServiceCreated,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+ auto mojo_cdm_service =
+ std::make_unique<MojoCdmService>(&cdm_service_context_);
+ auto* raw_mojo_cdm_service = mojo_cdm_service.get();
+ DCHECK(!pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
+ pending_mojo_cdm_services_[raw_mojo_cdm_service] =
+ std::move(mojo_cdm_service);
+ raw_mojo_cdm_service->Initialize(
+ cdm_factory, key_system, cdm_config,
+ base::BindOnce(&CdmFactoryImpl::OnCdmServiceInitialized,
+ weak_ptr_factory_.GetWeakPtr(), raw_mojo_cdm_service,
+ std::move(callback)));
}
// DeferredDestroy<mojom::CdmFactory> implemenation.
@@ -100,22 +106,27 @@ class CdmFactoryImpl final : public DeferredDestroy<mojom::CdmFactory> {
std::move(destroy_cb_).Run();
}
- void OnCdmServiceCreated(CreateCdmCallback callback,
- std::unique_ptr<MojoCdmService> cdm_service,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
- const std::string& error_message) {
- if (!cdm_service) {
- std::move(callback).Run(mojo::NullRemote(), base::nullopt,
- mojo::NullRemote(), error_message);
+ void OnCdmServiceInitialized(MojoCdmService* raw_mojo_cdm_service,
+ CreateCdmCallback callback,
+ mojom::CdmContextPtr cdm_context,
+ const std::string& error_message) {
+ DCHECK(raw_mojo_cdm_service);
+
+ // Remove pending MojoCdmService from the mapping in all cases.
+ DCHECK(pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
+ auto mojo_cdm_service =
+ std::move(pending_mojo_cdm_services_[raw_mojo_cdm_service]);
+ pending_mojo_cdm_services_.erase(raw_mojo_cdm_service);
+
+ if (!cdm_context) {
+ std::move(callback).Run(mojo::NullRemote(), nullptr, error_message);
return;
}
- auto cdm_id = cdm_service->cdm_id();
mojo::PendingRemote<mojom::ContentDecryptionModule> remote;
- cdm_receivers_.Add(std::move(cdm_service),
+ cdm_receivers_.Add(std::move(mojo_cdm_service),
remote.InitWithNewPipeAndPassReceiver());
- std::move(callback).Run(std::move(remote), cdm_id, std::move(decryptor),
- "");
+ std::move(callback).Run(std::move(remote), std::move(cdm_context), "");
}
// Must be declared before the receivers below because the bound objects might
@@ -129,6 +140,10 @@ class CdmFactoryImpl final : public DeferredDestroy<mojom::CdmFactory> {
std::unique_ptr<media::CdmFactory> cdm_factory_;
base::OnceClosure destroy_cb_;
+ // MojoCdmServices pending initialization.
+ std::map<MojoCdmService*, std::unique_ptr<MojoCdmService>>
+ pending_mojo_cdm_services_;
+
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<CdmFactoryImpl> weak_ptr_factory_{this};
diff --git a/chromium/media/mojo/services/cdm_service_unittest.cc b/chromium/media/mojo/services/cdm_service_unittest.cc
index 3386e888e04..6c43549c92c 100644
--- a/chromium/media/mojo/services/cdm_service_unittest.cc
+++ b/chromium/media/mojo/services/cdm_service_unittest.cc
@@ -10,6 +10,7 @@
#include "base/test/task_environment.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
+#include "media/base/mock_filters.h"
#include "media/cdm/default_cdm_factory.h"
#include "media/media_buildflags.h"
#include "media/mojo/services/cdm_service.h"
@@ -26,17 +27,46 @@ namespace {
using testing::_;
using testing::Invoke;
using testing::InvokeWithoutArgs;
+using testing::NiceMock;
+using testing::Return;
MATCHER_P(MatchesResult, success, "") {
return arg->success == success;
}
-const char kClearKeyKeySystem[] = "org.w3.clearkey";
-const char kInvalidKeySystem[] = "invalid.key.system";
+// MockCdmFactory treats any non-empty key system as valid and the empty key
+// system as invalid.
+const char kValidKeySystem[] = "org.w3.clearkey";
+const char kInvalidKeySystem[] = "";
+
+// Needed since MockCdmServiceClient needs to return unique_ptr of CdmFactory.
+class CdmFactoryWrapper : public CdmFactory {
+ public:
+ explicit CdmFactoryWrapper(CdmFactory* cdm_factory)
+ : cdm_factory_(cdm_factory) {}
+
+ // CdmFactory implementation.
+ void Create(const std::string& key_system,
+ const CdmConfig& cdm_config,
+ const SessionMessageCB& session_message_cb,
+ const SessionClosedCB& session_closed_cb,
+ const SessionKeysChangeCB& session_keys_change_cb,
+ const SessionExpirationUpdateCB& session_expiration_update_cb,
+ CdmCreatedCB cdm_created_cb) override {
+ cdm_factory_->Create(key_system, cdm_config, session_message_cb,
+ session_closed_cb, session_keys_change_cb,
+ session_expiration_update_cb,
+ std::move(cdm_created_cb));
+ }
+
+ private:
+ CdmFactory* const cdm_factory_;
+};
class MockCdmServiceClient : public media::CdmService::Client {
public:
- MockCdmServiceClient() = default;
+ explicit MockCdmServiceClient(CdmFactory* cdm_factory)
+ : cdm_factory_(cdm_factory) {}
~MockCdmServiceClient() override = default;
// media::CdmService::Client implementation.
@@ -44,12 +74,15 @@ class MockCdmServiceClient : public media::CdmService::Client {
std::unique_ptr<media::CdmFactory> CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces) override {
- return std::make_unique<media::DefaultCdmFactory>();
+ return std::make_unique<CdmFactoryWrapper>(cdm_factory_);
}
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
void AddCdmHostFilePaths(std::vector<media::CdmHostFilePath>*) override {}
#endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+
+ private:
+ CdmFactory* const cdm_factory_;
};
class CdmServiceTest : public testing::Test {
@@ -62,7 +95,11 @@ class CdmServiceTest : public testing::Test {
MOCK_METHOD0(CdmConnectionClosed, void());
void Initialize() {
- auto mock_cdm_service_client = std::make_unique<MockCdmServiceClient>();
+ EXPECT_CALL(*mock_cdm_, GetCdmContext())
+ .WillRepeatedly(Return(&cdm_context_));
+
+ auto mock_cdm_service_client =
+ std::make_unique<MockCdmServiceClient>(&mock_cdm_factory_);
mock_cdm_service_client_ = mock_cdm_service_client.get();
service_ = std::make_unique<CdmService>(
@@ -106,17 +143,21 @@ class CdmServiceTest : public testing::Test {
mojo::Remote<mojom::CdmFactory> cdm_factory_remote_;
mojo::Remote<mojom::ContentDecryptionModule> cdm_remote_;
+ // MojoCdmService will always create/use `mock_cdm_factory_` and `mock_cdm_`,
+ // so it's easier to set expectations on them.
+ scoped_refptr<MockCdm> mock_cdm_{new MockCdm()};
+ MockCdmFactory mock_cdm_factory_{mock_cdm_};
+ NiceMock<MockCdmContext> cdm_context_;
+
private:
void OnCdmCreated(bool expected_result,
mojo::PendingRemote<mojom::ContentDecryptionModule> remote,
- const base::Optional<base::UnguessableToken>& cdm_id,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
+ media::mojom::CdmContextPtr cdm_context,
const std::string& error_message) {
if (!expected_result) {
EXPECT_FALSE(remote);
- EXPECT_FALSE(decryptor);
+ EXPECT_FALSE(cdm_context);
EXPECT_TRUE(!error_message.empty());
- EXPECT_FALSE(cdm_id);
return;
}
EXPECT_TRUE(remote);
@@ -153,7 +194,7 @@ TEST_F(CdmServiceTest, LoadCdm) {
TEST_F(CdmServiceTest, InitializeCdm_Success) {
Initialize();
- InitializeCdm(kClearKeyKeySystem, true);
+ InitializeCdm(kValidKeySystem, true);
}
TEST_F(CdmServiceTest, InitializeCdm_InvalidKeySystem) {
@@ -163,9 +204,9 @@ TEST_F(CdmServiceTest, InitializeCdm_InvalidKeySystem) {
TEST_F(CdmServiceTest, DestroyAndRecreateCdm) {
Initialize();
- InitializeCdm(kClearKeyKeySystem, true);
+ InitializeCdm(kValidKeySystem, true);
cdm_remote_.reset();
- InitializeCdm(kClearKeyKeySystem, true);
+ InitializeCdm(kValidKeySystem, true);
}
// CdmFactory disconnection will cause the service to idle.
@@ -173,7 +214,7 @@ TEST_F(CdmServiceTest, DestroyCdmFactory) {
Initialize();
auto* service = cdm_service();
- InitializeCdm(kClearKeyKeySystem, true);
+ InitializeCdm(kValidKeySystem, true);
EXPECT_EQ(service->BoundCdmFactorySizeForTesting(), 1u);
EXPECT_EQ(service->UnboundCdmFactorySizeForTesting(), 0u);
@@ -185,9 +226,9 @@ TEST_F(CdmServiceTest, DestroyCdmFactory) {
}
// Destroy service will destroy the CdmFactory and all CDMs.
-TEST_F(CdmServiceTest, DestroyCdmService) {
+TEST_F(CdmServiceTest, DestroyCdmService_AfterCdmCreation) {
Initialize();
- InitializeCdm(kClearKeyKeySystem, true);
+ InitializeCdm(kValidKeySystem, true);
base::RunLoop run_loop;
// Ideally we should not care about order, and should only quit the loop when
@@ -199,4 +240,17 @@ TEST_F(CdmServiceTest, DestroyCdmService) {
run_loop.Run();
}
+// Before the CDM is fully created, CdmService has been destroyed. We should
+// fail gracefully instead of a crash. See crbug.com/1190319.
+TEST_F(CdmServiceTest, DestroyCdmService_DuringCdmCreation) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(*this, CdmFactoryConnectionClosed())
+ .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit));
+ mock_cdm_factory_.SetBeforeCreationCB(base::BindRepeating(
+ &CdmServiceTest::DestroyService, base::Unretained(this)));
+ Initialize();
+ InitializeCdm(kValidKeySystem, true);
+ run_loop.Run();
+}
+
} // namespace media
diff --git a/chromium/media/mojo/services/gpu_mojo_media_client.cc b/chromium/media/mojo/services/gpu_mojo_media_client.cc
index f11336e1a78..49eb8786b5f 100644
--- a/chromium/media/mojo/services/gpu_mojo_media_client.cc
+++ b/chromium/media/mojo/services/gpu_mojo_media_client.cc
@@ -54,8 +54,8 @@
#if defined(OS_ANDROID)
#include "media/mojo/services/android_mojo_util.h"
-using media::android_mojo_util::CreateProvisionFetcher;
using media::android_mojo_util::CreateMediaDrmStorage;
+using media::android_mojo_util::CreateProvisionFetcher;
#endif // defined(OS_ANDROID)
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -109,7 +109,7 @@ D3D11VideoDecoder::GetD3D11DeviceCB GetD3D11DeviceCallback() {
// use.
bool ShouldUseChromeOSDirectVideoDecoder(
const gpu::GpuPreferences& gpu_preferences) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
return gpu_preferences.enable_chromeos_direct_video_decoder;
#else
return false;
@@ -313,6 +313,10 @@ std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
if (!d3d11_supported_configs_)
GetSupportedVideoDecoderConfigs();
+ const bool enable_hdr =
+ gl::DirectCompositionSurfaceWin::IsHDRSupported() ||
+ base::FeatureList::IsEnabled(kD3D11VideoDecoderForceEnableHDR);
+
video_decoder = D3D11VideoDecoder::Create(
gpu_task_runner_, media_log->Clone(), gpu_preferences_,
gpu_workarounds_,
@@ -320,11 +324,10 @@ std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
media_gpu_channel_manager_,
command_buffer_id->channel_token,
command_buffer_id->route_id),
- GetD3D11DeviceCallback(), *d3d11_supported_configs_,
- gl::DirectCompositionSurfaceWin::IsHDRSupported());
+ GetD3D11DeviceCallback(), *d3d11_supported_configs_, enable_hdr);
}
#endif // defined(OS_WIN)
- break;
+ break;
}; // switch
// |video_decoder| may be null if we don't support |implementation|.
diff --git a/chromium/media/mojo/services/interface_factory_impl.cc b/chromium/media/mojo/services/interface_factory_impl.cc
index fbfbbd24cbc..093389972db 100644
--- a/chromium/media/mojo/services/interface_factory_impl.cc
+++ b/chromium/media/mojo/services/interface_factory_impl.cc
@@ -23,22 +23,18 @@
#include "media/mojo/services/mojo_video_decoder_service.h"
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
-#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
+#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER) || \
+ defined(OS_WIN)
#include "base/callback_helpers.h"
#include "media/base/renderer.h"
#include "media/mojo/services/mojo_renderer_service.h"
-#endif // BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
+#endif
#if BUILDFLAG(ENABLE_MOJO_CDM)
#include "media/base/cdm_factory.h"
#include "media/mojo/services/mojo_cdm_service.h"
#endif // BUILDFLAG(ENABLE_MOJO_CDM)
-#if defined(OS_WIN)
-#include "media/mojo/services/media_foundation_renderer_wrapper.h"
-#include "media/mojo/services/mojo_renderer_service.h"
-#endif // defined(OS_WIN)
-
namespace media {
InterfaceFactoryImpl::InterfaceFactoryImpl(
@@ -102,12 +98,7 @@ void InterfaceFactoryImpl::CreateDefaultRenderer(
return;
}
- std::unique_ptr<MojoRendererService> mojo_renderer_service =
- std::make_unique<MojoRendererService>(&cdm_service_context_,
- std::move(renderer));
-
- renderer_receivers_.Add(std::move(mojo_renderer_service),
- std::move(receiver));
+ AddRenderer(std::move(renderer), std::move(receiver));
#endif // BUILDFLAG(ENABLE_MOJO_RENDERER)
}
@@ -124,12 +115,7 @@ void InterfaceFactoryImpl::CreateCastRenderer(
return;
}
- std::unique_ptr<MojoRendererService> mojo_renderer_service =
- std::make_unique<MojoRendererService>(&cdm_service_context_,
- std::move(renderer));
-
- renderer_receivers_.Add(std::move(mojo_renderer_service),
- std::move(receiver));
+ AddRenderer(std::move(renderer), std::move(receiver));
}
#endif
@@ -157,13 +143,16 @@ void InterfaceFactoryImpl::CreateMediaFoundationRenderer(
mojo::PendingReceiver<media::mojom::Renderer> receiver,
mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension>
renderer_extension_receiver) {
- DVLOG(1) << __func__ << ": this=" << this;
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- base::ThreadTaskRunnerHandle::Get();
- CreateMediaFoundationRendererOnTaskRunner(
- std::move(task_runner), std::move(receiver),
+ DVLOG(2) << __func__;
+ auto renderer = mojo_media_client_->CreateMediaFoundationRenderer(
+ base::ThreadTaskRunnerHandle::Get(),
std::move(renderer_extension_receiver));
+ if (!renderer) {
+ DLOG(ERROR) << "MediaFoundationRenderer creation failed.";
+ return;
+ }
+
+ AddRenderer(std::move(renderer), std::move(receiver));
}
#endif // defined (OS_WIN)
@@ -174,17 +163,24 @@ void InterfaceFactoryImpl::CreateCdm(const std::string& key_system,
#if BUILDFLAG(ENABLE_MOJO_CDM)
CdmFactory* cdm_factory = GetCdmFactory();
if (!cdm_factory) {
- std::move(callback).Run(mojo::NullRemote(), base::nullopt,
- mojo::NullRemote(), "CDM Factory creation failed");
+ std::move(callback).Run(mojo::NullRemote(), nullptr,
+ "CDM Factory creation failed");
return;
}
- MojoCdmService::Create(
- cdm_factory, &cdm_service_context_, key_system, cdm_config,
- base::BindOnce(&InterfaceFactoryImpl::OnCdmServiceCreated,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+ auto mojo_cdm_service =
+ std::make_unique<MojoCdmService>(&cdm_service_context_);
+ auto* raw_mojo_cdm_service = mojo_cdm_service.get();
+ DCHECK(!pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
+ pending_mojo_cdm_services_[raw_mojo_cdm_service] =
+ std::move(mojo_cdm_service);
+ raw_mojo_cdm_service->Initialize(
+ cdm_factory, key_system, cdm_config,
+ base::BindOnce(&InterfaceFactoryImpl::OnCdmServiceInitialized,
+ weak_ptr_factory_.GetWeakPtr(), raw_mojo_cdm_service,
+ std::move(callback)));
#else // BUILDFLAG(ENABLE_MOJO_CDM)
- std::move(callback).Run(mojo::NullRemote(), base::nullopt, mojo::NullRemote(),
+ std::move(callback).Run(mojo::NullRemote(), nullptr,
"Mojo CDM not supported");
#endif
}
@@ -256,6 +252,18 @@ void InterfaceFactoryImpl::OnReceiverDisconnect() {
std::move(destroy_cb_).Run();
}
+#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER) || \
+ defined(OS_WIN)
+void InterfaceFactoryImpl::AddRenderer(
+ std::unique_ptr<media::Renderer> renderer,
+ mojo::PendingReceiver<mojom::Renderer> receiver) {
+ auto mojo_renderer_service = std::make_unique<MojoRendererService>(
+ &cdm_service_context_, std::move(renderer));
+ renderer_receivers_.Add(std::move(mojo_renderer_service),
+ std::move(receiver));
+}
+#endif
+
#if BUILDFLAG(ENABLE_MOJO_CDM)
CdmFactory* InterfaceFactoryImpl::GetCdmFactory() {
if (!cdm_factory_) {
@@ -266,53 +274,30 @@ CdmFactory* InterfaceFactoryImpl::GetCdmFactory() {
return cdm_factory_.get();
}
-void InterfaceFactoryImpl::OnCdmServiceCreated(
+void InterfaceFactoryImpl::OnCdmServiceInitialized(
+ MojoCdmService* raw_mojo_cdm_service,
CreateCdmCallback callback,
- std::unique_ptr<MojoCdmService> cdm_service,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
+ mojom::CdmContextPtr cdm_context,
const std::string& error_message) {
- if (!cdm_service) {
- std::move(callback).Run(mojo::NullRemote(), base::nullopt,
- mojo::NullRemote(), error_message);
+ DCHECK(raw_mojo_cdm_service);
+
+ // Remove pending MojoCdmService from the mapping in all cases.
+ DCHECK(pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
+ auto mojo_cdm_service =
+ std::move(pending_mojo_cdm_services_[raw_mojo_cdm_service]);
+ pending_mojo_cdm_services_.erase(raw_mojo_cdm_service);
+
+ if (!cdm_context) {
+ std::move(callback).Run(mojo::NullRemote(), nullptr, error_message);
return;
}
- auto cdm_id = cdm_service->cdm_id();
mojo::PendingRemote<mojom::ContentDecryptionModule> remote;
- cdm_receivers_.Add(std::move(cdm_service),
+ cdm_receivers_.Add(std::move(mojo_cdm_service),
remote.InitWithNewPipeAndPassReceiver());
- std::move(callback).Run(std::move(remote), cdm_id, std::move(decryptor), "");
+ std::move(callback).Run(std::move(remote), std::move(cdm_context), "");
}
#endif // BUILDFLAG(ENABLE_MOJO_CDM)
-#if defined(OS_WIN)
-void InterfaceFactoryImpl::CreateMediaFoundationRendererOnTaskRunner(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- mojo::PendingReceiver<media::mojom::Renderer> receiver,
- mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension>
- renderer_extension_receiver) {
- DVLOG(1) << __func__ << ": this=" << this;
-
- if (!task_runner->RunsTasksInCurrentSequence()) {
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(
- &InterfaceFactoryImpl::CreateMediaFoundationRendererOnTaskRunner,
- base::Unretained(this), task_runner, std::move(receiver),
- std::move(renderer_extension_receiver)));
- return;
- }
-
- DVLOG(1) << __func__ << ": this=" << this;
-
- auto renderer = std::make_unique<media::MediaFoundationRendererWrapper>(
- /*muted=*/false, std::move(task_runner),
- std::move(renderer_extension_receiver));
-
- media::MojoRendererService::Create(&cdm_service_context_, std::move(renderer),
- std::move(receiver));
-}
-#endif // defined(OS_WIN)
-
} // namespace media
diff --git a/chromium/media/mojo/services/interface_factory_impl.h b/chromium/media/mojo/services/interface_factory_impl.h
index be55cc55dd4..d238edb589c 100644
--- a/chromium/media/mojo/services/interface_factory_impl.h
+++ b/chromium/media/mojo/services/interface_factory_impl.h
@@ -33,6 +33,7 @@ namespace media {
class CdmFactory;
class MojoMediaClient;
+class Renderer;
class InterfaceFactoryImpl final
: public DeferredDestroy<mojom::InterfaceFactory> {
@@ -53,7 +54,7 @@ class InterfaceFactoryImpl final
#if BUILDFLAG(ENABLE_CAST_RENDERER)
void CreateCastRenderer(
const base::UnguessableToken& overlay_plane_id,
- mojo::PendingReceiver<media::mojom::Renderer> receiver) final;
+ mojo::PendingReceiver<mojom::Renderer> receiver) final;
#endif
#if defined(OS_ANDROID)
void CreateMediaPlayerRenderer(
@@ -70,8 +71,8 @@ class InterfaceFactoryImpl final
#endif // defined(OS_ANDROID)
#if defined(OS_WIN)
void CreateMediaFoundationRenderer(
- mojo::PendingReceiver<media::mojom::Renderer> receiver,
- mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension>
+ mojo::PendingReceiver<mojom::Renderer> receiver,
+ mojo::PendingReceiver<mojom::MediaFoundationRendererExtension>
renderer_extension_receiver) final;
#endif // defined(OS_WIN)
@@ -90,22 +91,22 @@ class InterfaceFactoryImpl final
void SetReceiverDisconnectHandler();
void OnReceiverDisconnect();
+#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER) || \
+ defined(OS_WIN)
+ // Creates MojoRendererService for `renderer`, bind it to `receiver` and add
+ // them to `renderer_receivers_`.
+ void AddRenderer(std::unique_ptr<media::Renderer> renderer,
+ mojo::PendingReceiver<mojom::Renderer> receiver);
+#endif
+
#if BUILDFLAG(ENABLE_MOJO_CDM)
CdmFactory* GetCdmFactory();
- void OnCdmServiceCreated(CreateCdmCallback callback,
- std::unique_ptr<MojoCdmService> cdm_service,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
- const std::string& error_message);
+ void OnCdmServiceInitialized(MojoCdmService* raw_mojo_cdm_service,
+ CreateCdmCallback callback,
+ mojom::CdmContextPtr cdm_context,
+ const std::string& error_message);
#endif // BUILDFLAG(ENABLE_MOJO_CDM)
-#if defined(OS_WIN)
- void CreateMediaFoundationRendererOnTaskRunner(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- mojo::PendingReceiver<media::mojom::Renderer> receiver,
- mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension>
- renderer_extension_receiver);
-#endif // defined(OS_WIN)
-
// Must be declared before the receivers below because the bound objects might
// take a raw pointer of |cdm_service_context_| and assume it's always
// available.
@@ -119,15 +120,20 @@ class InterfaceFactoryImpl final
mojo::UniqueReceiverSet<mojom::VideoDecoder> video_decoder_receivers_;
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
-#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
+#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER) || \
+ defined(OS_WIN)
// TODO(xhwang): Use MojoMediaLog for Renderer.
NullMediaLog media_log_;
mojo::UniqueReceiverSet<mojom::Renderer> renderer_receivers_;
-#endif // BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
+#endif
#if BUILDFLAG(ENABLE_MOJO_CDM)
std::unique_ptr<CdmFactory> cdm_factory_;
mojo::UniqueReceiverSet<mojom::ContentDecryptionModule> cdm_receivers_;
+
+ // MojoCdmServices pending initialization.
+ std::map<MojoCdmService*, std::unique_ptr<MojoCdmService>>
+ pending_mojo_cdm_services_;
#endif // BUILDFLAG(ENABLE_MOJO_CDM)
mojo::Remote<mojom::FrameInterfaceFactory> frame_interfaces_;
diff --git a/chromium/media/mojo/services/media_foundation_mojo_media_client.cc b/chromium/media/mojo/services/media_foundation_mojo_media_client.cc
index aa427c267db..27de9b14c14 100644
--- a/chromium/media/mojo/services/media_foundation_mojo_media_client.cc
+++ b/chromium/media/mojo/services/media_foundation_mojo_media_client.cc
@@ -4,22 +4,12 @@
#include "media/mojo/services/media_foundation_mojo_media_client.h"
-#include "media/base/audio_decoder.h"
#include "media/base/win/mf_helpers.h"
-#include "media/cdm/cdm_adapter_factory.h"
-#include "media/mojo/services/mojo_cdm_helper.h"
+#include "media/cdm/win/media_foundation_cdm_factory.h"
+#include "media/mojo/services/media_foundation_renderer_wrapper.h"
namespace media {
-namespace {
-
-std::unique_ptr<media::CdmAuxiliaryHelper> CreateCdmHelper(
- mojom::FrameInterfaceFactory* frame_interfaces) {
- return std::make_unique<media::MojoCdmHelper>(frame_interfaces);
-}
-
-} // namespace
-
MediaFoundationMojoMediaClient::MediaFoundationMojoMediaClient() {
DVLOG_FUNC(1);
}
@@ -28,17 +18,21 @@ MediaFoundationMojoMediaClient::~MediaFoundationMojoMediaClient() {
DVLOG_FUNC(1);
}
-// MojoMediaClient overrides.
+std::unique_ptr<Renderer>
+MediaFoundationMojoMediaClient::CreateMediaFoundationRenderer(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ mojo::PendingReceiver<mojom::MediaFoundationRendererExtension>
+ renderer_extension_receiver) {
+ DVLOG_FUNC(1);
+ return std::make_unique<MediaFoundationRendererWrapper>(
+ /*muted=*/false, std::move(task_runner),
+ std::move(renderer_extension_receiver));
+}
-std::unique_ptr<media::CdmFactory>
-MediaFoundationMojoMediaClient::CreateCdmFactory(
+std::unique_ptr<CdmFactory> MediaFoundationMojoMediaClient::CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces) {
DVLOG_FUNC(1);
-
- // TODO(frankli): consider to use MediaFoundationCdmFactory instead of
- // CdmAdapterFactory.
- return std::make_unique<media::CdmAdapterFactory>(
- base::BindRepeating(&CreateCdmHelper, frame_interfaces));
+ return std::make_unique<MediaFoundationCdmFactory>();
}
} // namespace media
diff --git a/chromium/media/mojo/services/media_foundation_mojo_media_client.h b/chromium/media/mojo/services/media_foundation_mojo_media_client.h
index e476f0be1b8..45286fb39b1 100644
--- a/chromium/media/mojo/services/media_foundation_mojo_media_client.h
+++ b/chromium/media/mojo/services/media_foundation_mojo_media_client.h
@@ -1,4 +1,4 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
+// Copyright 2021 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.
@@ -11,16 +11,20 @@
namespace media {
-// This class is the |mojo_media_client| parameter to create
-// media::MediaService. The MediaService itself is running in the mf_cdm utility
-// process to host MediaFoundationRenderer/Cdm.
-class MediaFoundationMojoMediaClient : public media::MojoMediaClient {
+// MediaFoundation-specific MojoMediaClient implementation for
+// MediaFoundationService running in the "Media Foundation Service" utility
+// process hosting MediaFoundationRenderer and MediaFoundationCdm.
+class MediaFoundationMojoMediaClient : public MojoMediaClient {
public:
MediaFoundationMojoMediaClient();
~MediaFoundationMojoMediaClient() final;
// MojoMediaClient implementation.
- std::unique_ptr<media::CdmFactory> CreateCdmFactory(
+ std::unique_ptr<Renderer> CreateMediaFoundationRenderer(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ mojo::PendingReceiver<mojom::MediaFoundationRendererExtension>
+ renderer_extension_receiver) final;
+ std::unique_ptr<CdmFactory> CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces) final;
private:
diff --git a/chromium/media/mojo/services/media_foundation_service.cc b/chromium/media/mojo/services/media_foundation_service.cc
new file mode 100644
index 00000000000..892cbd96381
--- /dev/null
+++ b/chromium/media/mojo/services/media_foundation_service.cc
@@ -0,0 +1,48 @@
+// Copyright 2021 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/mojo/services/media_foundation_service.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/check.h"
+#include "media/media_buildflags.h"
+#include "media/mojo/mojom/interface_factory.mojom.h"
+#include "media/mojo/services/interface_factory_impl.h"
+
+namespace media {
+
+MediaFoundationService::MediaFoundationService(
+ mojo::PendingReceiver<mojom::MediaFoundationService> receiver)
+ : receiver_(this, std::move(receiver)) {
+ mojo_media_client_.Initialize();
+}
+
+MediaFoundationService::~MediaFoundationService() = default;
+
+void MediaFoundationService::Initialize(const base::FilePath& cdm_path) {
+ // TODO(xhwang): Support loading MediaFoundation CDM and activating
+ // IMFContentDecryptionModuleFactory.
+ NOTIMPLEMENTED();
+}
+
+void MediaFoundationService::IsKeySystemSupported(
+ const std::string& key_system,
+ IsKeySystemSupportedCallback callback) {
+ // TODO(crbug.com/1115687): Implement MediaFoundation-based key system support
+ // query.
+ NOTIMPLEMENTED();
+}
+
+void MediaFoundationService::CreateInterfaceFactory(
+ mojo::PendingReceiver<mojom::InterfaceFactory> receiver,
+ mojo::PendingRemote<mojom::FrameInterfaceFactory> frame_interfaces) {
+ interface_factory_receivers_.Add(
+ std::make_unique<InterfaceFactoryImpl>(std::move(frame_interfaces),
+ &mojo_media_client_),
+ std::move(receiver));
+}
+
+} // namespace media
diff --git a/chromium/media/mojo/services/media_foundation_service.h b/chromium/media/mojo/services/media_foundation_service.h
new file mode 100644
index 00000000000..ad25361a377
--- /dev/null
+++ b/chromium/media/mojo/services/media_foundation_service.h
@@ -0,0 +1,48 @@
+// Copyright 2021 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_MOJO_SERVICES_MEDIA_FOUNDATION_SERVICE_H_
+#define MEDIA_MOJO_SERVICES_MEDIA_FOUNDATION_SERVICE_H_
+
+#include "build/build_config.h"
+#include "media/mojo/mojom/frame_interface_factory.mojom.h"
+#include "media/mojo/mojom/interface_factory.mojom.h"
+#include "media/mojo/mojom/media_foundation_service.mojom.h"
+#include "media/mojo/services/media_foundation_mojo_media_client.h"
+#include "media/mojo/services/media_mojo_export.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/unique_receiver_set.h"
+
+namespace media {
+
+// This class is similar to media::CdmService and media::MediaService, with
+// extra support for CDM preloading and key system support query.
+class MEDIA_MOJO_EXPORT MediaFoundationService final
+ : public mojom::MediaFoundationService {
+ public:
+ explicit MediaFoundationService(
+ mojo::PendingReceiver<mojom::MediaFoundationService> receiver);
+ MediaFoundationService(const MediaFoundationService&) = delete;
+ MediaFoundationService operator=(const MediaFoundationService&) = delete;
+ ~MediaFoundationService() final;
+
+ private:
+ // mojom::MediaFoundationService implementation:
+ void Initialize(const base::FilePath& cdm_path) final;
+ void IsKeySystemSupported(const std::string& key_system,
+ IsKeySystemSupportedCallback callback) final;
+ void CreateInterfaceFactory(
+ mojo::PendingReceiver<mojom::InterfaceFactory> receiver,
+ mojo::PendingRemote<mojom::FrameInterfaceFactory> frame_interfaces) final;
+
+ mojo::Receiver<mojom::MediaFoundationService> receiver_;
+ MediaFoundationMojoMediaClient mojo_media_client_;
+ mojo::UniqueReceiverSet<mojom::InterfaceFactory> interface_factory_receivers_;
+};
+
+} // namespace media
+
+#endif // MEDIA_MOJO_SERVICES_MEDIA_FOUNDATION_SERVICE_H_
diff --git a/chromium/media/mojo/services/media_metrics_provider_unittest.cc b/chromium/media/mojo/services/media_metrics_provider_unittest.cc
index d22d954904e..972f79d7dee 100644
--- a/chromium/media/mojo/services/media_metrics_provider_unittest.cc
+++ b/chromium/media/mojo/services/media_metrics_provider_unittest.cc
@@ -68,7 +68,7 @@ class MediaMetricsProviderTest : public testing::Test {
void ResetMetricRecorders() {
// Ensure cleared global before attempting to create a new TestUkmReporter.
test_recorder_.reset();
- test_recorder_.reset(new ukm::TestAutoSetUkmRecorder());
+ test_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
protected:
diff --git a/chromium/media/mojo/services/media_service_factory.cc b/chromium/media/mojo/services/media_service_factory.cc
index 27ebebc83e6..cf221050482 100644
--- a/chromium/media/mojo/services/media_service_factory.cc
+++ b/chromium/media/mojo/services/media_service_factory.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/notreached.h"
-#include "build/build_config.h"
#include "media/mojo/buildflags.h"
#include "media/mojo/services/gpu_mojo_media_client.h"
#include "media/mojo/services/media_service.h"
@@ -28,11 +27,6 @@ std::unique_ptr<MediaService> CreateMediaService(
#if defined(OS_ANDROID)
return std::make_unique<MediaService>(
std::make_unique<AndroidMojoMediaClient>(), std::move(receiver));
-#elif defined(OS_WIN)
- DVLOG(1) << "Create MediaService with MediaFoundationMojoMediaClient";
- return std::make_unique<MediaService>(
- std::make_unique<media::MediaFoundationMojoMediaClient>(),
- std::move(receiver));
#else
NOTREACHED() << "No MediaService implementation available.";
return nullptr;
diff --git a/chromium/media/mojo/services/media_service_factory.h b/chromium/media/mojo/services/media_service_factory.h
index d0052bf2acf..7b613d7c803 100644
--- a/chromium/media/mojo/services/media_service_factory.h
+++ b/chromium/media/mojo/services/media_service_factory.h
@@ -10,6 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "build/build_config.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
diff --git a/chromium/media/mojo/services/media_service_unittest.cc b/chromium/media/mojo/services/media_service_unittest.cc
index 9f8855a991e..ac1cba2aa34 100644
--- a/chromium/media/mojo/services/media_service_unittest.cc
+++ b/chromium/media/mojo/services/media_service_unittest.cc
@@ -138,8 +138,8 @@ class MediaServiceTest : public testing::Test {
video_stream_.set_video_decoder_config(video_config);
mojo::PendingRemote<mojom::DemuxerStream> video_stream_proxy;
- mojo_video_stream_.reset(new MojoDemuxerStreamImpl(
- &video_stream_, video_stream_proxy.InitWithNewPipeAndPassReceiver()));
+ mojo_video_stream_ = std::make_unique<MojoDemuxerStreamImpl>(
+ &video_stream_, video_stream_proxy.InitWithNewPipeAndPassReceiver());
mojo::PendingAssociatedRemote<mojom::RendererClient> client_remote;
renderer_client_receiver_.Bind(
@@ -162,14 +162,12 @@ class MediaServiceTest : public testing::Test {
protected:
void OnCdmCreated(bool expected_result,
mojo::PendingRemote<mojom::ContentDecryptionModule> remote,
- const base::Optional<base::UnguessableToken>& cdm_id,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
+ media::mojom::CdmContextPtr cdm_context,
const std::string& error_message) {
if (!expected_result) {
EXPECT_FALSE(remote);
- EXPECT_FALSE(decryptor);
+ EXPECT_FALSE(cdm_context);
EXPECT_TRUE(!error_message.empty());
- EXPECT_FALSE(cdm_id);
return;
}
EXPECT_TRUE(remote);
diff --git a/chromium/media/mojo/services/mojo_audio_decoder_service.cc b/chromium/media/mojo/services/mojo_audio_decoder_service.cc
index 589bce46a40..90f071bb723 100644
--- a/chromium/media/mojo/services/mojo_audio_decoder_service.cc
+++ b/chromium/media/mojo/services/mojo_audio_decoder_service.cc
@@ -4,6 +4,7 @@
#include "media/mojo/services/mojo_audio_decoder_service.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -83,8 +84,8 @@ void MojoAudioDecoderService::SetDataSource(
mojo::ScopedDataPipeConsumerHandle receive_pipe) {
DVLOG(1) << __func__;
- mojo_decoder_buffer_reader_.reset(
- new MojoDecoderBufferReader(std::move(receive_pipe)));
+ mojo_decoder_buffer_reader_ =
+ std::make_unique<MojoDecoderBufferReader>(std::move(receive_pipe));
}
void MojoAudioDecoderService::Decode(mojom::DecoderBufferPtr buffer,
@@ -110,8 +111,9 @@ void MojoAudioDecoderService::OnInitialized(InitializeCallback callback,
if (!status.is_ok()) {
// Do not call decoder_->NeedsBitstreamConversion() if init failed.
- std::move(callback).Run(std::move(status), false,
- AudioDecoderType::kUnknown);
+ std::move(callback).Run(
+ std::move(status), false,
+ decoder_ ? decoder_->GetDecoderType() : AudioDecoderType::kUnknown);
return;
}
diff --git a/chromium/media/mojo/services/mojo_cdm_service.cc b/chromium/media/mojo/services/mojo_cdm_service.cc
index 8352f58df35..785f2c96289 100644
--- a/chromium/media/mojo/services/mojo_cdm_service.cc
+++ b/chromium/media/mojo/services/mojo_cdm_service.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
+#include "build/build_config.h"
#include "media/base/cdm_config.h"
#include "media/base/cdm_context.h"
#include "media/base/cdm_factory.h"
@@ -32,46 +33,39 @@ using NewSessionMojoCdmPromise =
MojoCdmPromise<void(mojom::CdmPromiseResultPtr, const std::string&),
std::string>;
-// static
-void MojoCdmService::Create(CdmFactory* cdm_factory,
- MojoCdmServiceContext* context,
- const std::string& key_system,
- const CdmConfig& cdm_config,
- CdmServiceCreatedCB callback) {
- std::unique_ptr<MojoCdmService> mojo_cdm_service(
- new MojoCdmService(cdm_factory, context));
- auto weak_this = mojo_cdm_service->weak_factory_.GetWeakPtr();
- cdm_factory->Create(
- key_system, cdm_config,
- base::BindRepeating(&MojoCdmService::OnSessionMessage, weak_this),
- base::BindRepeating(&MojoCdmService::OnSessionClosed, weak_this),
- base::BindRepeating(&MojoCdmService::OnSessionKeysChange, weak_this),
- base::BindRepeating(&MojoCdmService::OnSessionExpirationUpdate,
- weak_this),
- base::BindOnce(&MojoCdmService::OnCdmCreated, weak_this,
- std::move(mojo_cdm_service),
- mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(callback), nullptr, mojo::NullRemote(),
- "Mojo CDM Service creation failure")));
-}
-
-MojoCdmService::MojoCdmService(CdmFactory* cdm_factory,
- MojoCdmServiceContext* context)
- : cdm_factory_(cdm_factory), context_(context) {
+MojoCdmService::MojoCdmService(MojoCdmServiceContext* context)
+ : context_(context) {
DVLOG(1) << __func__;
- DCHECK(cdm_factory_);
- // |context_| can be null.
+ DCHECK(context_);
}
MojoCdmService::~MojoCdmService() {
DVLOG(1) << __func__;
- if (!context_ || !cdm_id_)
+ if (!cdm_id_)
return;
context_->UnregisterCdm(cdm_id_.value());
}
+void MojoCdmService::Initialize(CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const CdmConfig& cdm_config,
+ InitializeCB init_cb) {
+ auto weak_this = weak_factory_.GetWeakPtr();
+ cdm_factory->Create(
+ key_system, cdm_config,
+ base::BindRepeating(&MojoCdmService::OnSessionMessage, weak_this),
+ base::BindRepeating(&MojoCdmService::OnSessionClosed, weak_this),
+ base::BindRepeating(&MojoCdmService::OnSessionKeysChange, weak_this),
+ base::BindRepeating(&MojoCdmService::OnSessionExpirationUpdate,
+ weak_this),
+ base::BindOnce(&MojoCdmService::OnCdmCreated, weak_this,
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ std::move(init_cb), nullptr,
+ "Mojo CDM Service creation aborted")));
+}
+
void MojoCdmService::SetClient(
mojo::PendingAssociatedRemote<mojom::ContentDecryptionModuleClient>
client) {
@@ -143,51 +137,58 @@ scoped_refptr<ContentDecryptionModule> MojoCdmService::GetCdm() {
}
void MojoCdmService::OnCdmCreated(
- std::unique_ptr<MojoCdmService> mojo_cdm_service,
- CdmServiceCreatedCB callback,
+ InitializeCB init_cb,
const scoped_refptr<::media::ContentDecryptionModule>& cdm,
const std::string& error_message) {
- DVLOG(2) << __func__ << ": error_message=" << error_message;
-
// TODO(xhwang): This should not happen when KeySystemInfo is properly
// populated. See http://crbug.com/469366
if (!cdm) {
// Make sure the error string is non-empty on failure.
- std::move(callback).Run(
- nullptr, mojo::NullRemote(),
- error_message.empty() ? "CDM initialization failed" : error_message);
+ auto non_empty_error_message =
+ error_message.empty() ? "CDM creation failed" : error_message;
+ DVLOG(1) << __func__ << ": " << non_empty_error_message;
+ std::move(init_cb).Run(nullptr, non_empty_error_message);
return;
}
cdm_ = cdm;
+ cdm_id_ = context_->RegisterCdm(this);
+ DVLOG(1) << __func__ << ": CDM successfully registered with ID "
+ << CdmContext::CdmIdToString(base::OptionalOrNullptr(cdm_id_));
- if (context_) {
- cdm_id_ = context_->RegisterCdm(this);
- DVLOG(1) << __func__ << ": CDM successfully registered with ID "
- << CdmContext::CdmIdToString(base::OptionalOrNullptr(cdm_id_));
- }
+ auto mojo_cdm_context = mojom::CdmContext::New();
+ mojo_cdm_context->cdm_id = cdm_id();
- // If |cdm| has a decryptor, create the MojoDecryptorService
- // and pass the connection back to the client.
- mojo::PendingRemote<mojom::Decryptor> decryptor_remote;
CdmContext* const cdm_context = cdm_->GetCdmContext();
- if (cdm_context && cdm_context->GetDecryptor()) {
- DVLOG(2) << __func__ << ": CDM supports Decryptor.";
- // Both |cdm_| and |decryptor_| are owned by |this|, so we don't need to
- // pass in a CdmContextRef.
- decryptor_.reset(
- new MojoDecryptorService(cdm_context->GetDecryptor(), nullptr));
- decryptor_receiver_ = std::make_unique<mojo::Receiver<mojom::Decryptor>>(
- decryptor_.get(), decryptor_remote.InitWithNewPipeAndPassReceiver());
- // base::Unretained is safe because |decryptor_receiver_| is owned by
- // |this|. If |this| is destructed, |decryptor_receiver_| will be destructed
- // as well and the error handler should never be called.
- decryptor_receiver_->set_disconnect_handler(base::BindOnce(
- &MojoCdmService::OnDecryptorConnectionError, base::Unretained(this)));
+ if (cdm_context) {
+ // If |cdm| has a decryptor, create the MojoDecryptorService
+ // and pass the connection back to the client.
+ if (cdm_context->GetDecryptor()) {
+ DVLOG(2) << __func__ << ": CDM supports Decryptor.";
+ mojo::PendingRemote<mojom::Decryptor> decryptor_remote;
+ // Both |cdm_| and |decryptor_| are owned by |this|, so we don't need to
+ // pass in a CdmContextRef.
+ decryptor_ = std::make_unique<MojoDecryptorService>(
+ cdm_context->GetDecryptor(), /*cdm_context_ref=*/nullptr);
+ decryptor_receiver_ = std::make_unique<mojo::Receiver<mojom::Decryptor>>(
+ decryptor_.get(), decryptor_remote.InitWithNewPipeAndPassReceiver());
+ // base::Unretained is safe because |decryptor_receiver_| is owned by
+ // |this|. If |this| is destructed, |decryptor_receiver_| will be
+ // destructed as well and the error handler should never be called.
+ // The disconnection can happen due to race conditions during render
+ // process teardown or crash.
+ decryptor_receiver_->set_disconnect_handler(base::BindOnce(
+ &MojoCdmService::OnDecryptorConnectionError, base::Unretained(this)));
+ mojo_cdm_context->decryptor = std::move(decryptor_remote);
+ }
+
+#if defined(OS_WIN)
+ mojo_cdm_context->requires_media_foundation_renderer =
+ cdm_context->RequiresMediaFoundationRenderer();
+#endif // defined(OS_WIN)
}
- std::move(callback).Run(std::move(mojo_cdm_service),
- std::move(decryptor_remote), "");
+ std::move(init_cb).Run(std::move(mojo_cdm_context), "");
}
void MojoCdmService::OnSessionMessage(const std::string& session_id,
@@ -230,7 +231,8 @@ void MojoCdmService::OnDecryptorConnectionError() {
DVLOG(2) << __func__;
// MojoDecryptorService has lost connectivity to it's client, so it can be
- // freed.
+ // freed. This could happen due to render process teardown or crash. No need
+ // for recovery.
decryptor_.reset();
}
diff --git a/chromium/media/mojo/services/mojo_cdm_service.h b/chromium/media/mojo/services/mojo_cdm_service.h
index ec27caa040d..18195fb1c73 100644
--- a/chromium/media/mojo/services/mojo_cdm_service.h
+++ b/chromium/media/mojo/services/mojo_cdm_service.h
@@ -35,25 +35,23 @@ class CdmFactory;
class MEDIA_MOJO_EXPORT MojoCdmService final
: public mojom::ContentDecryptionModule {
public:
- using CdmServiceCreatedCB =
- base::OnceCallback<void(std::unique_ptr<MojoCdmService> mojo_cdm_service,
- mojo::PendingRemote<mojom::Decryptor> decryptor,
+ // Callback for Initialize(). Non-null `cdm_context` indicates success. Null
+ // `cdm_context` indicates failure and the `error_message` provides a reason.
+ using InitializeCB =
+ base::OnceCallback<void(mojom::CdmContextPtr cdm_context,
const std::string& error_message)>;
- // Creates a MojoCdmService. Callback will have |mojo_cdm_service| be non-null
- // on success, on failure it will be null and the |error_message| will
- // indicate a reason.
- // - |cdm_factory| is used to create CDM instances. Must not be null.
- // - |context| is used to keep track of all CDM instances such that we can
- // connect the CDM with a media player (e.g. decoder). Can be null if the
- // CDM does not need to be connected with any media player in this process.
- static void Create(CdmFactory* cdm_factory,
- MojoCdmServiceContext* context,
- const std::string& key_system,
- const CdmConfig& cdm_config,
- CdmServiceCreatedCB callback);
-
+ explicit MojoCdmService(MojoCdmServiceContext* context);
~MojoCdmService() final;
+
+ // Initialize the MojoCdmService, including creating the real CDM using the
+ // `cdm_factory`, which must not be null. The MojoCdmService should NOT be
+ // used before the `init_cb` is returned.
+ void Initialize(CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const CdmConfig& cdm_config,
+ InitializeCB init_cb);
+
// mojom::ContentDecryptionModule implementation.
void SetClient(
mojo::PendingAssociatedRemote<mojom::ContentDecryptionModuleClient>
@@ -82,14 +80,11 @@ class MEDIA_MOJO_EXPORT MojoCdmService final
scoped_refptr<::media::ContentDecryptionModule> GetCdm();
// Gets the remote ID of the CDM this is holding.
- base::Optional<base::UnguessableToken> cdm_id() const { return cdm_id_; }
+ base::UnguessableToken cdm_id() const { return cdm_id_.value(); }
private:
- MojoCdmService(CdmFactory* cdm_factory, MojoCdmServiceContext* context);
-
// Callback for CdmFactory::Create().
- void OnCdmCreated(std::unique_ptr<MojoCdmService> mojo_cdm_service,
- CdmServiceCreatedCB callback,
+ void OnCdmCreated(InitializeCB callback,
const scoped_refptr<::media::ContentDecryptionModule>& cdm,
const std::string& error_message);
@@ -107,8 +102,7 @@ class MEDIA_MOJO_EXPORT MojoCdmService final
// Callback for when |decryptor_| loses connectivity.
void OnDecryptorConnectionError();
- CdmFactory* cdm_factory_;
- MojoCdmServiceContext* const context_ = nullptr;
+ MojoCdmServiceContext* const context_;
scoped_refptr<::media::ContentDecryptionModule> cdm_;
// MojoDecryptorService is passed the Decryptor from |cdm_|, so
diff --git a/chromium/media/mojo/services/mojo_decryptor_service.cc b/chromium/media/mojo/services/mojo_decryptor_service.cc
index d113b425667..96b757d0697 100644
--- a/chromium/media/mojo/services/mojo_decryptor_service.cc
+++ b/chromium/media/mojo/services/mojo_decryptor_service.cc
@@ -4,6 +4,7 @@
#include "media/mojo/services/mojo_decryptor_service.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -78,14 +79,14 @@ void MojoDecryptorService::Initialize(
}
has_initialize_been_called_ = true;
- audio_buffer_reader_.reset(
- new MojoDecoderBufferReader(std::move(audio_pipe)));
- video_buffer_reader_.reset(
- new MojoDecoderBufferReader(std::move(video_pipe)));
- decrypt_buffer_reader_.reset(
- new MojoDecoderBufferReader(std::move(decrypt_pipe)));
- decrypted_buffer_writer_.reset(
- new MojoDecoderBufferWriter(std::move(decrypted_pipe)));
+ audio_buffer_reader_ =
+ std::make_unique<MojoDecoderBufferReader>(std::move(audio_pipe));
+ video_buffer_reader_ =
+ std::make_unique<MojoDecoderBufferReader>(std::move(video_pipe));
+ decrypt_buffer_reader_ =
+ std::make_unique<MojoDecoderBufferReader>(std::move(decrypt_pipe));
+ decrypted_buffer_writer_ =
+ std::make_unique<MojoDecoderBufferWriter>(std::move(decrypted_pipe));
}
void MojoDecryptorService::Decrypt(StreamType stream_type,
diff --git a/chromium/media/mojo/services/mojo_demuxer_stream_adapter.cc b/chromium/media/mojo/services/mojo_demuxer_stream_adapter.cc
index accafab8e28..d9f40c7eefc 100644
--- a/chromium/media/mojo/services/mojo_demuxer_stream_adapter.cc
+++ b/chromium/media/mojo/services/mojo_demuxer_stream_adapter.cc
@@ -5,6 +5,8 @@
#include "media/mojo/services/mojo_demuxer_stream_adapter.h"
#include <stdint.h>
+
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -76,8 +78,8 @@ void MojoDemuxerStreamAdapter::OnStreamReady(
type_ = type;
- mojo_decoder_buffer_reader_.reset(
- new MojoDecoderBufferReader(std::move(consumer_handle)));
+ mojo_decoder_buffer_reader_ =
+ std::make_unique<MojoDecoderBufferReader>(std::move(consumer_handle));
UpdateConfig(std::move(audio_config), std::move(video_config));
diff --git a/chromium/media/mojo/services/mojo_media_client.cc b/chromium/media/mojo/services/mojo_media_client.cc
index b9f53ad90c5..70303624d74 100644
--- a/chromium/media/mojo/services/mojo_media_client.cc
+++ b/chromium/media/mojo/services/mojo_media_client.cc
@@ -57,6 +57,15 @@ std::unique_ptr<Renderer> MojoMediaClient::CreateCastRenderer(
}
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
+#if defined(OS_WIN)
+std::unique_ptr<Renderer> MojoMediaClient::CreateMediaFoundationRenderer(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ mojo::PendingReceiver<mojom::MediaFoundationRendererExtension>
+ renderer_extension_receiver) {
+ return nullptr;
+}
+#endif // defined(OS_WIN)
+
std::unique_ptr<CdmFactory> MojoMediaClient::CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces) {
return nullptr;
diff --git a/chromium/media/mojo/services/mojo_media_client.h b/chromium/media/mojo/services/mojo_media_client.h
index 8d0ff976a04..cba23037f32 100644
--- a/chromium/media/mojo/services/mojo_media_client.h
+++ b/chromium/media/mojo/services/mojo_media_client.h
@@ -17,6 +17,7 @@
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"
#include "media/mojo/mojom/frame_interface_factory.mojom.h"
+#include "media/mojo/mojom/renderer_extensions.mojom.h"
#include "media/mojo/mojom/video_decoder.mojom.h"
#include "media/mojo/services/media_mojo_export.h"
@@ -91,9 +92,16 @@ class MEDIA_MOJO_EXPORT MojoMediaClient {
const base::UnguessableToken& overlay_plane_id);
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
- // Returns the CdmFactory to be used by MojoCdmService. |frame_interfaces| can
- // be used to request interfaces provided remotely by the host. It may be a
- // nullptr if the host chose not to bind the InterfacePtr.
+#if defined(OS_WIN)
+ virtual std::unique_ptr<Renderer> CreateMediaFoundationRenderer(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ mojo::PendingReceiver<mojom::MediaFoundationRendererExtension>
+ renderer_extension_receiver);
+#endif // defined(OS_WIN)
+
+ // Returns the CdmFactory to be used by MojoCdmService. |frame_interfaces|
+ // can be used to request interfaces provided remotely by the host. It may
+ // be a nullptr if the host chose not to bind the InterfacePtr.
virtual std::unique_ptr<CdmFactory> CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces);
diff --git a/chromium/media/mojo/services/mojo_renderer_service.cc b/chromium/media/mojo/services/mojo_renderer_service.cc
index 102932c7b5e..5fbf6cf0e4c 100644
--- a/chromium/media/mojo/services/mojo_renderer_service.cc
+++ b/chromium/media/mojo/services/mojo_renderer_service.cc
@@ -4,6 +4,7 @@
#include "media/mojo/services/mojo_renderer_service.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -73,10 +74,10 @@ void MojoRendererService::Initialize(
}
DCHECK(!media_url_params->media_url.is_empty());
- media_resource_.reset(new MediaUrlDemuxer(
+ media_resource_ = std::make_unique<MediaUrlDemuxer>(
nullptr, media_url_params->media_url, media_url_params->site_for_cookies,
media_url_params->top_frame_origin, media_url_params->allow_credentials,
- media_url_params->is_hls));
+ media_url_params->is_hls);
renderer_->Initialize(
media_resource_.get(), this,
base::BindOnce(&MojoRendererService::OnRendererInitializeDone, weak_this_,
diff --git a/chromium/media/mojo/services/mojo_video_decoder_service.cc b/chromium/media/mojo/services/mojo_video_decoder_service.cc
index 450d27ecd64..19e7d34f60a 100644
--- a/chromium/media/mojo/services/mojo_video_decoder_service.cc
+++ b/chromium/media/mojo/services/mojo_video_decoder_service.cc
@@ -4,15 +4,19 @@
#include "media/mojo/services/mojo_video_decoder_service.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/elapsed_timer.h"
#include "media/base/decoder_buffer.h"
#include "media/base/simple_sync_token_client.h"
#include "media/base/video_decoder.h"
@@ -43,6 +47,18 @@ const char kInitializeTraceName[] = "MojoVideoDecoderService::Initialize";
const char kDecodeTraceName[] = "MojoVideoDecoderService::Decode";
const char kResetTraceName[] = "MojoVideoDecoderService::Reset";
+void RecordTimingHistogram(VideoDecoderImplementation impl,
+ const char* method,
+ base::TimeDelta elapsed) {
+ base::UmaHistogramTimes(
+ base::StringPrintf("Media.MojoVideoDecoderServiceTiming.%s.%s",
+ impl == VideoDecoderImplementation::kDefault
+ ? "Default"
+ : "Alternate",
+ method),
+ elapsed);
+}
+
} // namespace
class VideoFrameHandleReleaserImpl final
@@ -99,6 +115,7 @@ MojoVideoDecoderService::MojoVideoDecoderService(
MojoVideoDecoderService::~MojoVideoDecoderService() {
DVLOG(1) << __func__;
+ base::ElapsedTimer elapsed;
if (init_cb_) {
OnDecoderInitialized(
@@ -111,6 +128,14 @@ MojoVideoDecoderService::~MojoVideoDecoderService() {
if (is_active_instance_)
g_num_active_mvd_instances--;
+
+ // Destruct the VideoDecoder here so its destruction duration is included by
+ // the histogram timer below.
+ weak_factory_.InvalidateWeakPtrs();
+ decoder_.reset();
+
+ if (implementation_)
+ RecordTimingHistogram(*implementation_, "Destruct", elapsed.Elapsed());
}
void MojoVideoDecoderService::GetSupportedConfigs(
@@ -139,6 +164,9 @@ void MojoVideoDecoderService::Construct(
return;
}
+ base::ElapsedTimer elapsed;
+ implementation_ = implementation;
+
client_.Bind(std::move(client));
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
@@ -151,8 +179,8 @@ void MojoVideoDecoderService::Construct(
std::make_unique<VideoFrameHandleReleaserImpl>(),
std::move(video_frame_handle_releaser_receiver));
- mojo_decoder_buffer_reader_.reset(
- new MojoDecoderBufferReader(std::move(decoder_buffer_pipe)));
+ mojo_decoder_buffer_reader_ =
+ std::make_unique<MojoDecoderBufferReader>(std::move(decoder_buffer_pipe));
decoder_ = mojo_media_client_->CreateVideoDecoder(
task_runner, media_log_.get(), std::move(command_buffer_id),
@@ -160,6 +188,8 @@ void MojoVideoDecoderService::Construct(
base::BindRepeating(
&MojoVideoDecoderService::OnDecoderRequestedOverlayInfo, weak_this_),
target_color_space);
+
+ RecordTimingHistogram(*implementation_, "Construct", elapsed.Elapsed());
}
void MojoVideoDecoderService::Initialize(
@@ -281,7 +311,9 @@ void MojoVideoDecoderService::OnDecoderInitialized(Status status) {
status.code());
if (!status.is_ok()) {
- std::move(init_cb_).Run(status, false, 1, VideoDecoderType::kUnknown);
+ std::move(init_cb_).Run(
+ status, false, 1,
+ decoder_ ? decoder_->GetDecoderType() : VideoDecoderType::kUnknown);
return;
}
std::move(init_cb_).Run(status, decoder_->NeedsBitstreamConversion(),
diff --git a/chromium/media/mojo/services/mojo_video_decoder_service.h b/chromium/media/mojo/services/mojo_video_decoder_service.h
index da0ff47e90f..d04d177d3bf 100644
--- a/chromium/media/mojo/services/mojo_video_decoder_service.h
+++ b/chromium/media/mojo/services/mojo_video_decoder_service.h
@@ -86,6 +86,9 @@ class MEDIA_MOJO_EXPORT MojoVideoDecoderService final
bool restart_for_transitions,
ProvideOverlayInfoCB provide_overlay_info_cb);
+ // Implementation value provided at the time of Construct().
+ base::Optional<VideoDecoderImplementation> implementation_;
+
// Whether this instance is active (Decode() was called at least once).
bool is_active_instance_ = false;
diff --git a/chromium/media/mojo/services/test_mojo_media_client.cc b/chromium/media/mojo/services/test_mojo_media_client.cc
index 7d51f3db006..8a9a71f4d29 100644
--- a/chromium/media/mojo/services/test_mojo_media_client.cc
+++ b/chromium/media/mojo/services/test_mojo_media_client.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/callback_helpers.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -56,7 +57,7 @@ std::unique_ptr<Renderer> TestMojoMediaClient::CreateRenderer(
const std::string& /* audio_device_id */) {
// If called the first time, do one time initialization.
if (!decoder_factory_) {
- decoder_factory_.reset(new media::DefaultDecoderFactory(nullptr));
+ decoder_factory_ = std::make_unique<media::DefaultDecoderFactory>(nullptr);
}
if (!renderer_factory_) {
diff --git a/chromium/media/mojo/services/video_decode_perf_history_unittest.cc b/chromium/media/mojo/services/video_decode_perf_history_unittest.cc
index a475f85b295..e6eeddb2364 100644
--- a/chromium/media/mojo/services/video_decode_perf_history_unittest.cc
+++ b/chromium/media/mojo/services/video_decode_perf_history_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <map>
+#include <memory>
#include <string>
#include "base/bind.h"
@@ -302,7 +303,7 @@ class VideoDecodePerfHistoryTest : public testing::Test {
past_is_efficient);
// Zero it out to make verification readable.
if (!old_stats)
- old_stats.reset(new DecodeStatsEntry(0, 0, 0));
+ old_stats = std::make_unique<DecodeStatsEntry>(0, 0, 0);
EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesDecodedName,
old_stats->frames_decoded);
EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesDroppedName,
diff --git a/chromium/media/mojo/services/video_decode_stats_recorder_unittest.cc b/chromium/media/mojo/services/video_decode_stats_recorder_unittest.cc
index 7c63a2d65b9..8e3831b5d12 100644
--- a/chromium/media/mojo/services/video_decode_stats_recorder_unittest.cc
+++ b/chromium/media/mojo/services/video_decode_stats_recorder_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
#include <string>
#include "base/bind.h"
@@ -57,10 +58,10 @@ class VideoDecodeStatsRecorderTest : public ::testing::Test {
learning::FeatureValue origin,
bool is_top_frame,
uint64_t player_id) {
- recorder_.reset(new VideoDecodeStatsRecorder(
+ recorder_ = std::make_unique<VideoDecodeStatsRecorder>(
base::BindRepeating(&VideoDecodeStatsRecorderTest::PrintSavePerfRecord,
base::Unretained(this)),
- source_id, origin, is_top_frame, player_id));
+ source_id, origin, is_top_frame, player_id);
}
void PrintSavePerfRecord(ukm::SourceId source_id,
diff --git a/chromium/media/mojo/services/watch_time_recorder_unittest.cc b/chromium/media/mojo/services/watch_time_recorder_unittest.cc
index 82597c9dd1d..08467f09fef 100644
--- a/chromium/media/mojo/services/watch_time_recorder_unittest.cc
+++ b/chromium/media/mojo/services/watch_time_recorder_unittest.cc
@@ -171,10 +171,10 @@ class WatchTimeRecorderTest : public testing::Test {
}
void ResetMetricRecorders() {
- histogram_tester_.reset(new base::HistogramTester());
+ histogram_tester_ = std::make_unique<base::HistogramTester>();
// Ensure cleared global before attempting to create a new TestUkmReporter.
test_recorder_.reset();
- test_recorder_.reset(new ukm::TestAutoSetUkmRecorder());
+ test_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
test_recorder_->UpdateSourceURL(source_id_, GURL(kTestOrigin));
}