1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
media / fuchsia / common / decrypting_sysmem_buffer_stream.cc [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/fuchsia/common/decrypting_sysmem_buffer_stream.h"
#include "media/base/callback_registry.h"
#include "media/base/decoder_buffer.h"
namespace media {
DecryptingSysmemBufferStream::DecryptingSysmemBufferStream(
SysmemAllocatorClient* sysmem_allocator,
CdmContext* cdm_context,
Decryptor::StreamType stream_type)
: passthrough_stream_(sysmem_allocator),
decryptor_(cdm_context->GetDecryptor()),
stream_type_(stream_type) {
DCHECK(decryptor_);
event_cb_registration_ = cdm_context->RegisterEventCB(
base::BindRepeating(&DecryptingSysmemBufferStream::OnCdmContextEvent,
weak_factory_.GetWeakPtr()));
}
DecryptingSysmemBufferStream::~DecryptingSysmemBufferStream() = default;
void DecryptingSysmemBufferStream::Initialize(Sink* sink,
size_t min_buffer_size,
size_t min_buffer_count) {
sink_ = sink;
passthrough_stream_.Initialize(sink, min_buffer_size, min_buffer_count);
}
void DecryptingSysmemBufferStream::EnqueueBuffer(
scoped_refptr<DecoderBuffer> buffer) {
buffer_queue_.push_back(std::move(buffer));
DecryptNextBuffer();
}
void DecryptingSysmemBufferStream::Reset() {
buffer_queue_.clear();
if (state_ == State::kDecryptPending) {
decryptor_->CancelDecrypt(stream_type_);
}
state_ = State::kIdle;
retry_on_no_key_ = false;
}
void DecryptingSysmemBufferStream::OnCdmContextEvent(CdmContext::Event event) {
if (event != CdmContext::Event::kHasAdditionalUsableKey)
return;
switch (state_) {
case State::kIdle:
break;
case State::kDecryptPending:
retry_on_no_key_ = true;
break;
case State::kWaitingKey:
state_ = State::kIdle;
DecryptNextBuffer();
break;
}
}
void DecryptingSysmemBufferStream::DecryptNextBuffer() {
if (buffer_queue_.empty() || state_ != State::kIdle)
return;
if (buffer_queue_.front()->end_of_stream()) {
scoped_refptr<DecoderBuffer> buffer = std::move(buffer_queue_.front());
buffer_queue_.pop_front();
DCHECK(buffer_queue_.empty());
passthrough_stream_.EnqueueBuffer(std::move(buffer));
return;
}
state_ = State::kDecryptPending;
decryptor_->Decrypt(
stream_type_, buffer_queue_.front(),
base::BindOnce(&DecryptingSysmemBufferStream::OnBufferDecrypted,
weak_factory_.GetWeakPtr()));
}
void DecryptingSysmemBufferStream::OnBufferDecrypted(
Decryptor::Status status,
scoped_refptr<DecoderBuffer> decrypted_buffer) {
DCHECK(state_ == State::kDecryptPending);
state_ = State::kIdle;
switch (status) {
case Decryptor::kError:
sink_->OnSysmemBufferStreamError();
return;
case Decryptor::kNoKey:
if (retry_on_no_key_) {
retry_on_no_key_ = false;
DecryptNextBuffer();
} else {
state_ = State::kWaitingKey;
sink_->OnSysmemBufferStreamNoKey();
}
return;
case Decryptor::kNeedMoreData:
break;
case Decryptor::kSuccess:
passthrough_stream_.EnqueueBuffer(std::move(decrypted_buffer));
}
buffer_queue_.pop_front();
DecryptNextBuffer();
}
} // namespace media