Commit a80616b7 authored by Xiaohan Wang's avatar Xiaohan Wang Committed by Commit Bot

media: Support NewKeyCB registration in CdmContext

All players/decoders handling encrypted media should implement the logic
to suspend playback when the decryption key is not available, and then
resume playback when a new usable decryption key is added. Hence,
there's a common need for the players/decoders to be notified when such
an event (new usable key) happens.

Since CdmContext is the common interface bridging players/decoders and
the CDM, this CL adds RegisterNewKeyCB() to CdmContext.

To facilitate the implementation of RegisterNewKeyCB() in various CDMs
and CdmProxies, CallbackRegistry is also introduced, which can manage
callback registration, notification and unregistration. Note that
there's base::CallbackList which is similar, but that class is not as
simple and is not thread-safe.

This CL also updates D3D11CdmProxy to use CallbackRegistry to manage
new key callbacks. D3D11VideoDecoderImpl is also updated to be able to
register new key callbacks.

Bug: 821288
Test: Covered by existing tests.
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I0380f934efb63d3b3c893d909e0d78f5f8e082f4
Reviewed-on: https://chromium-review.googlesource.com/1014245
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551468}
parent 7951767c
...@@ -81,6 +81,7 @@ source_set("base") { ...@@ -81,6 +81,7 @@ source_set("base") {
"byte_queue.cc", "byte_queue.cc",
"byte_queue.h", "byte_queue.h",
"callback_holder.h", "callback_holder.h",
"callback_registry.h",
"cdm_callback_promise.cc", "cdm_callback_promise.cc",
"cdm_callback_promise.h", "cdm_callback_promise.h",
"cdm_config.h", "cdm_config.h",
...@@ -456,6 +457,7 @@ source_set("unit_tests") { ...@@ -456,6 +457,7 @@ source_set("unit_tests") {
"bind_to_current_loop_unittest.cc", "bind_to_current_loop_unittest.cc",
"bit_reader_unittest.cc", "bit_reader_unittest.cc",
"callback_holder_unittest.cc", "callback_holder_unittest.cc",
"callback_registry_unittest.cc",
"channel_mixer_unittest.cc", "channel_mixer_unittest.cc",
"channel_mixing_matrix_unittest.cc", "channel_mixing_matrix_unittest.cc",
"container_names_unittest.cc", "container_names_unittest.cc",
......
// 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.
#ifndef MEDIA_BASE_CALLBACK_REGISTRY_H_
#define MEDIA_BASE_CALLBACK_REGISTRY_H_
#include <stdint.h>
#include <map>
#include <memory>
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "media/base/bind_to_current_loop.h"
namespace media {
// A class that keeps a callback registered. The callback will be unregistered
// upon destruction of this object.
class CallbackRegistration {
public:
CallbackRegistration() = default;
virtual ~CallbackRegistration() = default;
private:
DISALLOW_COPY_AND_ASSIGN(CallbackRegistration);
};
template <typename Sig>
class CallbackRegistry;
// A helper class that can register, unregister callbacks, and notify registered
// callbacks. This class is thread safe: all methods can be called on any
// thread. The CallbackRegistry must outlive all CallbackRegistrations returned
// by Register().
// TODO(xhwang): This class is similar to base::CallbackList, but is simpler,
// and provides thread safty. Consider merging these two.
template <typename... Args>
class CallbackRegistry<void(Args...)> {
public:
using CallbackType = base::RepeatingCallback<void(Args...)>;
CallbackRegistry() = default;
~CallbackRegistry() = default;
std::unique_ptr<CallbackRegistration> Register(CallbackType cb)
WARN_UNUSED_RESULT {
base::AutoLock lock(lock_);
DCHECK(cb);
uint32_t registration_id = ++next_registration_id_;
DVLOG(1) << __func__ << ": registration_id = " << registration_id;
// Use BindToCurrentLoop so that the callbacks are always posted to the
// thread where Register() is called. Also, this helps avoid reentrancy
// and deadlock issues, e.g. Register() is called in one of the callbacks.
callbacks_[registration_id] = BindToCurrentLoop(std::move(cb));
return std::make_unique<RegistrationImpl>(this, registration_id);
}
void Notify(Args&&... args) {
DVLOG(1) << __func__;
base::AutoLock lock(lock_);
for (auto const& entry : callbacks_)
entry.second.Run(std::forward<Args>(args)...);
}
private:
class RegistrationImpl : public CallbackRegistration {
public:
RegistrationImpl(CallbackRegistry<void(Args...)>* registry,
uint32_t registration_id)
: registry_(registry), registration_id_(registration_id) {}
~RegistrationImpl() override { registry_->Unregister(registration_id_); }
private:
CallbackRegistry<void(Args...)>* registry_ = nullptr;
uint32_t registration_id_ = 0;
DISALLOW_COPY_AND_ASSIGN(RegistrationImpl);
};
void Unregister(uint32_t registration_id) {
DVLOG(1) << __func__ << ": registration_id = " << registration_id;
base::AutoLock lock(lock_);
size_t num_callbacks_removed = callbacks_.erase(registration_id);
DCHECK_EQ(num_callbacks_removed, 1u);
}
base::Lock lock_;
uint32_t next_registration_id_ = 0;
std::map<uint32_t, CallbackType> callbacks_;
DISALLOW_COPY_AND_ASSIGN(CallbackRegistry);
};
using ClosureRegistry = CallbackRegistry<void()>;
} // namespace media
#endif // MEDIA_BASE_CALLBACK_REGISTRY_H_
// 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.
#include "media/base/callback_registry.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
namespace {
using ::testing::_;
using ::testing::Invoke;
using ::testing::IsNull;
class CallbackRegistryTest : public testing::Test {
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
};
TEST_F(CallbackRegistryTest, RegisterWithNoParam) {
ClosureRegistry registry;
base::MockCallback<base::RepeatingCallback<void()>> callback;
auto registration = registry.Register(callback.Get());
EXPECT_TRUE(registration);
EXPECT_CALL(callback, Run());
registry.Notify();
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterWithOneParam) {
CallbackRegistry<void(int)> registry;
base::MockCallback<base::RepeatingCallback<void(int)>> callback;
auto registration = registry.Register(callback.Get());
EXPECT_TRUE(registration);
EXPECT_CALL(callback, Run(1));
registry.Notify(1);
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterWithTwoParams) {
CallbackRegistry<void(int, int)> registry;
base::MockCallback<base::RepeatingCallback<void(int, int)>> callback;
auto registration = registry.Register(callback.Get());
EXPECT_TRUE(registration);
EXPECT_CALL(callback, Run(1, 2));
registry.Notify(1, 2);
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterWithMoveOnlyParam) {
CallbackRegistry<void(std::unique_ptr<int>)> registry;
base::MockCallback<base::RepeatingCallback<void(std::unique_ptr<int>)>>
callback;
auto registration = registry.Register(callback.Get());
EXPECT_TRUE(registration);
EXPECT_CALL(callback, Run(_));
registry.Notify(std::make_unique<int>(1));
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterWithPointerParam) {
CallbackRegistry<void(int*)> registry;
base::MockCallback<base::RepeatingCallback<void(int*)>> callback;
auto registration = registry.Register(callback.Get());
EXPECT_TRUE(registration);
EXPECT_CALL(callback, Run(IsNull()));
registry.Notify(nullptr);
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterWithReferenceParam) {
CallbackRegistry<void(const int&)> registry;
base::MockCallback<base::RepeatingCallback<void(const int&)>> callback;
auto registration = registry.Register(callback.Get());
EXPECT_TRUE(registration);
int i = 1;
EXPECT_CALL(callback, Run(i));
registry.Notify(i);
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterAfterNotify) {
ClosureRegistry registry;
base::MockCallback<base::RepeatingClosure> callback_1;
auto registration_1 = registry.Register(callback_1.Get());
EXPECT_TRUE(registration_1);
EXPECT_CALL(callback_1, Run());
registry.Notify();
scoped_task_environment_.RunUntilIdle();
base::MockCallback<base::RepeatingClosure> callback_2;
auto registration_2 = registry.Register(callback_2.Get());
EXPECT_TRUE(registration_2);
EXPECT_CALL(callback_1, Run());
EXPECT_CALL(callback_2, Run());
registry.Notify();
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, EmptyRegistry) {
ClosureRegistry registry;
registry.Notify();
}
TEST_F(CallbackRegistryTest, UnregisterCallback) {
ClosureRegistry registry;
base::MockCallback<base::RepeatingClosure> callback_1;
base::MockCallback<base::RepeatingClosure> callback_2;
auto registration_1 = registry.Register(callback_1.Get());
auto registration_2 = registry.Register(callback_2.Get());
EXPECT_TRUE(registration_1);
EXPECT_TRUE(registration_2);
EXPECT_CALL(callback_1, Run());
EXPECT_CALL(callback_2, Run());
registry.Notify();
scoped_task_environment_.RunUntilIdle();
registration_1.reset();
EXPECT_CALL(callback_2, Run());
registry.Notify();
scoped_task_environment_.RunUntilIdle();
registration_2.reset();
registry.Notify();
scoped_task_environment_.RunUntilIdle();
}
TEST_F(CallbackRegistryTest, RegisterDuringNotification) {
ClosureRegistry registry;
base::MockCallback<base::RepeatingClosure> callback_1;
base::MockCallback<base::RepeatingClosure> callback_2;
auto registration_1 = registry.Register(callback_1.Get());
std::unique_ptr<CallbackRegistration> registration_2;
EXPECT_TRUE(registration_1);
// Register callback_2 during callback_1's notification run.
EXPECT_CALL(callback_1, Run()).WillOnce(Invoke([&]() {
registration_2 = registry.Register(callback_2.Get());
}));
registry.Notify();
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(registration_2);
EXPECT_CALL(callback_1, Run());
EXPECT_CALL(callback_2, Run());
registry.Notify();
scoped_task_environment_.RunUntilIdle();
}
} // namespace
} // namespace media
...@@ -4,12 +4,19 @@ ...@@ -4,12 +4,19 @@
#include "media/base/cdm_context.h" #include "media/base/cdm_context.h"
#include "media/base/callback_registry.h"
namespace media { namespace media {
CdmContext::CdmContext() = default; CdmContext::CdmContext() = default;
CdmContext::~CdmContext() = default; CdmContext::~CdmContext() = default;
std::unique_ptr<CallbackRegistration> CdmContext::RegisterNewKeyCB(
base::RepeatingClosure new_key_cb) {
return nullptr;
}
Decryptor* CdmContext::GetDecryptor() { Decryptor* CdmContext::GetDecryptor() {
return nullptr; return nullptr;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
namespace media { namespace media {
class CallbackRegistration;
class CdmProxyContext; class CdmProxyContext;
class Decryptor; class Decryptor;
class MediaCryptoContext; class MediaCryptoContext;
...@@ -35,6 +36,20 @@ class MEDIA_EXPORT CdmContext { ...@@ -35,6 +36,20 @@ class MEDIA_EXPORT CdmContext {
virtual ~CdmContext(); virtual ~CdmContext();
// Registers a callback which will be called when an additional usable key is
// available in the CDM. Can be called multiple times to register multiple
// callbacks, all of which will be called when a new usable key is available.
// Lifetime: The caller should keep the returned CallbackRegistration object
// to keep the callback registered. The callback will be unregistered upon the
// destruction of the returned CallbackRegistration object. The returned
// CallbackRegistration object can be destructed on any thread.
// Thread Model: Can be called on any thread. The registered callback will
// always be called on the thread where RegisterNewKeyCB() is called.
// TODO(xhwang): We are not using base::CallbackList because it is not thread-
// safe. Consider refactoring base::CallbackList to avoid code duplication.
virtual std::unique_ptr<CallbackRegistration> RegisterNewKeyCB(
base::RepeatingClosure new_key_cb);
// Gets the Decryptor object associated with the CDM. Returns nullptr if the // Gets the Decryptor object associated with the CDM. Returns nullptr if the
// CDM does not support a Decryptor (i.e. platform-based CDMs where decryption // CDM does not support a Decryptor (i.e. platform-based CDMs where decryption
// occurs implicitly along with decoding). // occurs implicitly along with decoding).
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "crypto/encryptor.h" #include "crypto/encryptor.h"
#include "crypto/symmetric_key.h" #include "crypto/symmetric_key.h"
#include "media/base/audio_decoder_config.h" #include "media/base/audio_decoder_config.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_promise.h" #include "media/base/cdm_promise.h"
#include "media/base/decoder_buffer.h" #include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h" #include "media/base/decrypt_config.h"
...@@ -147,10 +148,7 @@ void AesDecryptor::SessionIdDecryptionKeyMap::Erase( ...@@ -147,10 +148,7 @@ void AesDecryptor::SessionIdDecryptionKeyMap::Erase(
key_list_.erase(position); key_list_.erase(position);
} }
enum ClearBytesBufferSel { enum ClearBytesBufferSel { kSrcContainsClearBytes, kDstContainsClearBytes };
kSrcContainsClearBytes,
kDstContainsClearBytes
};
static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples,
const ClearBytesBufferSel sel, const ClearBytesBufferSel sel,
...@@ -554,6 +552,12 @@ CdmContext* AesDecryptor::GetCdmContext() { ...@@ -554,6 +552,12 @@ CdmContext* AesDecryptor::GetCdmContext() {
return this; return this;
} }
std::unique_ptr<CallbackRegistration> AesDecryptor::RegisterNewKeyCB(
base::RepeatingClosure new_key_cb) {
NOTIMPLEMENTED();
return nullptr;
}
Decryptor* AesDecryptor::GetDecryptor() { Decryptor* AesDecryptor::GetDecryptor() {
return this; return this;
} }
...@@ -585,8 +589,8 @@ void AesDecryptor::Decrypt(StreamType stream_type, ...@@ -585,8 +589,8 @@ void AesDecryptor::Decrypt(StreamType stream_type,
scoped_refptr<DecoderBuffer> decrypted; scoped_refptr<DecoderBuffer> decrypted;
if (!encrypted->decrypt_config()->is_encrypted()) { if (!encrypted->decrypt_config()->is_encrypted()) {
decrypted = DecoderBuffer::CopyFrom(encrypted->data(), decrypted =
encrypted->data_size()); DecoderBuffer::CopyFrom(encrypted->data(), encrypted->data_size());
} else { } else {
const std::string& key_id = encrypted->decrypt_config()->key_id(); const std::string& key_id = encrypted->decrypt_config()->key_id();
base::AutoLock auto_lock(key_map_lock_); base::AutoLock auto_lock(key_map_lock_);
...@@ -757,8 +761,7 @@ CdmKeysInfo AesDecryptor::GenerateKeysInfoList( ...@@ -757,8 +761,7 @@ CdmKeysInfo AesDecryptor::GenerateKeysInfoList(
} }
AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret) AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret)
: secret_(secret) { : secret_(secret) {}
}
AesDecryptor::DecryptionKey::~DecryptionKey() = default; AesDecryptor::DecryptionKey::~DecryptionKey() = default;
......
...@@ -61,6 +61,8 @@ class MEDIA_EXPORT AesDecryptor : public ContentDecryptionModule, ...@@ -61,6 +61,8 @@ class MEDIA_EXPORT AesDecryptor : public ContentDecryptionModule,
CdmContext* GetCdmContext() override; CdmContext* GetCdmContext() override;
// CdmContext implementation. // CdmContext implementation.
std::unique_ptr<CallbackRegistration> RegisterNewKeyCB(
base::RepeatingClosure new_key_cb) override;
Decryptor* GetDecryptor() override; Decryptor* GetDecryptor() override;
int GetCdmId() const override; int GetCdmId() const override;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "components/crash/core/common/crash_key.h" #include "components/crash/core/common/crash_key.h"
#include "media/base/audio_decoder_config.h" #include "media/base/audio_decoder_config.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_initialized_promise.h" #include "media/base/cdm_initialized_promise.h"
#include "media/base/cdm_key_information.h" #include "media/base/cdm_key_information.h"
#include "media/base/channel_layout.h" #include "media/base/channel_layout.h"
...@@ -684,6 +685,12 @@ CdmContext* CdmAdapter::GetCdmContext() { ...@@ -684,6 +685,12 @@ CdmContext* CdmAdapter::GetCdmContext() {
return this; return this;
} }
std::unique_ptr<CallbackRegistration> CdmAdapter::RegisterNewKeyCB(
base::RepeatingClosure new_key_cb) {
NOTIMPLEMENTED();
return nullptr;
}
Decryptor* CdmAdapter::GetDecryptor() { Decryptor* CdmAdapter::GetDecryptor() {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
return this; return this;
......
...@@ -86,6 +86,8 @@ class MEDIA_EXPORT CdmAdapter : public ContentDecryptionModule, ...@@ -86,6 +86,8 @@ class MEDIA_EXPORT CdmAdapter : public ContentDecryptionModule,
CdmContext* GetCdmContext() final; CdmContext* GetCdmContext() final;
// CdmContext implementation. // CdmContext implementation.
std::unique_ptr<CallbackRegistration> RegisterNewKeyCB(
base::RepeatingClosure new_key_cb) final;
Decryptor* GetDecryptor() final; Decryptor* GetDecryptor() final;
int GetCdmId() const final; int GetCdmId() const final;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/logging.h" #include "base/logging.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_context.h" #include "media/base/cdm_context.h"
#include "media/base/cdm_proxy_context.h" #include "media/base/cdm_proxy_context.h"
...@@ -105,11 +106,18 @@ class D3D11CdmContext : public CdmContext { ...@@ -105,11 +106,18 @@ class D3D11CdmContext : public CdmContext {
} }
// CdmContext implementation. // CdmContext implementation.
std::unique_ptr<CallbackRegistration> RegisterNewKeyCB(
base::RepeatingClosure new_key_cb) override {
return new_key_callbacks_.Register(std::move(new_key_cb));
}
CdmProxyContext* GetCdmProxyContext() override { return &cdm_proxy_context_; } CdmProxyContext* GetCdmProxyContext() override { return &cdm_proxy_context_; }
private: private:
D3D11CdmProxyContext cdm_proxy_context_; D3D11CdmProxyContext cdm_proxy_context_;
// TODO(rkuroiwa): Call Notify() when new usable key is available.
ClosureRegistry new_key_callbacks_;
base::WeakPtrFactory<D3D11CdmContext> weak_factory_; base::WeakPtrFactory<D3D11CdmContext> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(D3D11CdmContext); DISALLOW_COPY_AND_ASSIGN(D3D11CdmContext);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "media/base/bind_to_current_loop.h" #include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_buffer.h" #include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h" #include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
...@@ -160,6 +161,13 @@ void D3D11VideoDecoderImpl::Initialize( ...@@ -160,6 +161,13 @@ void D3D11VideoDecoderImpl::Initialize(
std::make_unique<H264Decoder>(std::make_unique<D3D11H264Accelerator>( std::make_unique<H264Decoder>(std::make_unique<D3D11H264Accelerator>(
this, video_decoder, video_device_, video_context_)); this, video_decoder, video_device_, video_context_));
// |cdm_context| could be null for clear playback.
if (cdm_context) {
new_key_callback_registration_ =
cdm_context->RegisterNewKeyCB(base::BindRepeating(
&D3D11VideoDecoderImpl::NotifyNewKey, weak_factory_.GetWeakPtr()));
}
state_ = State::kRunning; state_ = State::kRunning;
std::move(init_cb_).Run(true); std::move(init_cb_).Run(true);
} }
...@@ -370,6 +378,11 @@ base::WeakPtr<D3D11VideoDecoderImpl> D3D11VideoDecoderImpl::GetWeakPtr() { ...@@ -370,6 +378,11 @@ base::WeakPtr<D3D11VideoDecoderImpl> D3D11VideoDecoderImpl::GetWeakPtr() {
return weak_factory_.GetWeakPtr(); return weak_factory_.GetWeakPtr();
} }
void D3D11VideoDecoderImpl::NotifyNewKey() {
// TODO(rkuroiwa): Implement this method.
NOTIMPLEMENTED();
}
void D3D11VideoDecoderImpl::NotifyError(const char* reason) { void D3D11VideoDecoderImpl::NotifyError(const char* reason) {
state_ = State::kError; state_ = State::kError;
DLOG(ERROR) << reason; DLOG(ERROR) << reason;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "gpu/ipc/service/command_buffer_stub.h" #include "gpu/ipc/service/command_buffer_stub.h"
#include "media/base/callback_registry.h"
#include "media/base/video_decoder.h" #include "media/base/video_decoder.h"
#include "media/gpu/gles2_decoder_helper.h" #include "media/gpu/gles2_decoder_helper.h"
#include "media/gpu/media_gpu_export.h" #include "media/gpu/media_gpu_export.h"
...@@ -27,7 +28,7 @@ namespace media { ...@@ -27,7 +28,7 @@ namespace media {
class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder, class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder,
public D3D11VideoDecoderClient { public D3D11VideoDecoderClient {
public: public:
D3D11VideoDecoderImpl( explicit D3D11VideoDecoderImpl(
base::RepeatingCallback<gpu::CommandBufferStub*()> get_stub_cb); base::RepeatingCallback<gpu::CommandBufferStub*()> get_stub_cb);
~D3D11VideoDecoderImpl() override; ~D3D11VideoDecoderImpl() override;
...@@ -72,6 +73,9 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder, ...@@ -72,6 +73,9 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder,
void OnMailboxReleased(scoped_refptr<D3D11PictureBuffer> buffer, void OnMailboxReleased(scoped_refptr<D3D11PictureBuffer> buffer,
const gpu::SyncToken& sync_token); const gpu::SyncToken& sync_token);
// Callback to notify that new usable key is available.
void NotifyNewKey();
// Enter the kError state. This will fail any pending |init_cb_| and / or // Enter the kError state. This will fail any pending |init_cb_| and / or
// pending decode as well. // pending decode as well.
void NotifyError(const char* reason); void NotifyError(const char* reason);
...@@ -104,6 +108,9 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder, ...@@ -104,6 +108,9 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder,
State state_ = State::kInitializing; State state_ = State::kInitializing;
// Callback registration to keep the new key callback registered.
std::unique_ptr<CallbackRegistration> new_key_callback_registration_;
base::WeakPtrFactory<D3D11VideoDecoderImpl> weak_factory_; base::WeakPtrFactory<D3D11VideoDecoderImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(D3D11VideoDecoderImpl); DISALLOW_COPY_AND_ASSIGN(D3D11VideoDecoderImpl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment