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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
media / cdm / win / test / media_foundation_clear_key_decryptor.h [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CDM_WIN_TEST_MEDIA_FOUNDATION_CLEAR_KEY_DECRYPTOR_H_
#define MEDIA_CDM_WIN_TEST_MEDIA_FOUNDATION_CLEAR_KEY_DECRYPTOR_H_
#include <mferror.h>
#include <mfidl.h>
#include <wrl/implements.h>
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "media/base/decoder_buffer.h"
#include "media/cdm/aes_decryptor.h"
namespace media {
enum class StreamType { kUnknown, kVideo, kAudio };
// This transform (decryptor) decrypts the encrypted content or bypasses the
// clear content. An instance for audio or video gets created by
// `IMFInputTrustAuthority::GetDecrypter()`.
// - Once an instance is created and the streaming is about to start, a set of
// Set and Get interfaces (i.e., `SetInputType`, `GetOutputAvailableType`,
// `SetOutputType`, `GetStreamCount`, `GetStreamIDs` and etc) are getting called
// to set up the transform to be ready for processing the stream data.
// - `ProcessMessage()` receives `MFT_MESSAGE_NOTIFY_START_OF_STREAM` when the
// streaming begins.
// - The input samples are getting fed into `ProcessInput()` while
// `MediaFoundationStreamWrapper` produces the input stream data.
// - As a synchronous MFT decryptor, the input sample is simply stored for
// `ProcessOutput()` to process it later. Note that `ProcessOutput()` can be
// called first before `ProcessInput()`. In this case it should return
// `MF_E_TRANSFORM_NEED_MORE_INPUT` saying the transform cannot produce output
// data until it receives more input data.
// `ProcessMessage()` receives `MFT_MESSAGE_NOTIFY_END_OF_STREAM` message once
// the stream reaches the end of stream.
class MediaFoundationClearKeyDecryptor final
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
IMFTransform,
Microsoft::WRL::CloakedIid<IMFShutdown>,
Microsoft::WRL::FtmBase> {
public:
MediaFoundationClearKeyDecryptor();
~MediaFoundationClearKeyDecryptor() override;
HRESULT RuntimeClassInitialize(
_In_ scoped_refptr<AesDecryptor> aes_decryptor);
// IMFTransform
STDMETHODIMP GetStreamLimits(_Out_ DWORD* input_minimum,
_Out_ DWORD* input_maximum,
_Out_ DWORD* output_minimum,
_Out_ DWORD* output_maximum) override;
STDMETHODIMP GetStreamCount(_Out_ DWORD* input_streams,
_Out_ DWORD* output_streams) override;
STDMETHODIMP GetStreamIDs(_In_ DWORD input_ids_size,
_Out_ DWORD* input_ids,
_In_ DWORD output_ids_size,
_Out_ DWORD* output_ids) override;
STDMETHODIMP GetInputStreamInfo(
_In_ DWORD input_stream_id,
_Out_ MFT_INPUT_STREAM_INFO* stream_info) override;
STDMETHODIMP GetOutputStreamInfo(
_In_ DWORD output_stream_id,
_Out_ MFT_OUTPUT_STREAM_INFO* stream_info) override;
STDMETHODIMP GetAttributes(_COM_Outptr_ IMFAttributes** attributes) override;
STDMETHODIMP GetInputStreamAttributes(
_In_ DWORD input_stream_id,
_COM_Outptr_ IMFAttributes** attributes) override;
STDMETHODIMP GetOutputStreamAttributes(
_In_ DWORD output_stream_id,
_COM_Outptr_ IMFAttributes** attributes) override;
STDMETHODIMP DeleteInputStream(_In_ DWORD stream_id) override;
STDMETHODIMP AddInputStreams(_In_ DWORD streams_count,
_In_count_(streams_count)
DWORD* stream_ids) override;
STDMETHODIMP GetInputAvailableType(_In_ DWORD input_stream_index,
_In_ DWORD type_index,
_COM_Outptr_ IMFMediaType** type) override;
STDMETHODIMP GetOutputAvailableType(
_In_ DWORD output_stream_index,
_In_ DWORD type_index,
_COM_Outptr_ IMFMediaType** type) override;
STDMETHODIMP SetInputType(_In_ DWORD input_stream_index,
_In_ IMFMediaType* type,
_In_ DWORD flags) override;
STDMETHODIMP SetOutputType(_In_ DWORD output_stream_index,
_In_ IMFMediaType* type,
_In_ DWORD flags) override;
STDMETHODIMP GetInputCurrentType(_In_ DWORD input_stream_index,
_COM_Outptr_ IMFMediaType** ptype) override;
STDMETHODIMP GetOutputCurrentType(_In_ DWORD output_stream_index,
_COM_Outptr_ IMFMediaType** ptype) override;
STDMETHODIMP GetInputStatus(_In_ DWORD input_stream_index,
_Out_ DWORD* flags) override;
STDMETHODIMP GetOutputStatus(_Out_ DWORD* flags) override;
STDMETHODIMP SetOutputBounds(_In_ LONGLONG lower_bound,
_In_ LONGLONG upper_bound) override;
STDMETHODIMP ProcessEvent(_In_ DWORD input_stream_id,
_In_ IMFMediaEvent* event) override;
STDMETHODIMP ProcessMessage(_In_ MFT_MESSAGE_TYPE message,
_In_ ULONG_PTR param) override;
STDMETHODIMP ProcessInput(_In_ DWORD input_stream_index,
_In_ IMFSample* sample,
_In_ DWORD flags) override;
STDMETHODIMP ProcessOutput(_In_ DWORD flags,
_In_ DWORD output_samples_count,
_Inout_count_(output_samples_count)
MFT_OUTPUT_DATA_BUFFER* output_samples,
_Out_ DWORD* status) override;
// IMFShutdown
STDMETHODIMP Shutdown() override;
STDMETHODIMP GetShutdownStatus(_Out_ MFSHUTDOWN_STATUS* status) override;
private:
HRESULT GetShutdownStatus() {
base::AutoLock lock(lock_);
return (is_shutdown_) ? MF_E_SHUTDOWN : S_OK;
}
// Generates a DecoderBuffer from a Media Foundation sample.
HRESULT GenerateDecoderBufferFromSample(
IMFSample* mf_sample,
GUID* key_id,
scoped_refptr<DecoderBuffer>* buffer_out);
// Flushes all stored data as the transform receives a flush command or a
// request to release all resources.
void FlushAllStoredData();
// For IMFShutdown
bool is_shutdown_ GUARDED_BY(lock_) = false;
// AES decryptor
scoped_refptr<AesDecryptor> aes_decryptor_;
// The media type for an input stream on the transform.
Microsoft::WRL::ComPtr<IMFMediaType> input_media_type_ GUARDED_BY(lock_);
// The media type for an output stream on the transform.
Microsoft::WRL::ComPtr<IMFMediaType> output_media_type_ GUARDED_BY(lock_);
// The available media type for an output stream on the transform.
Microsoft::WRL::ComPtr<IMFMediaType> available_output_media_type_
GUARDED_BY(lock_);
// The input sample data to the input stream on the transform.
Microsoft::WRL::ComPtr<IMFSample> sample_ GUARDED_BY(lock_);
// The input stream type (either Audio or Video).
StreamType stream_type_ GUARDED_BY(lock_) = StreamType::kUnknown;
// To protect access to data from multiple threads. GetAttributes,
// GetInputCurrentType, GetOutputCurrentType, GetStreamCount, GetStreamIDs,
// GetOutputStreamInfo, GetInputAvailableType, GetOutputAvailableType,
// SetInputType, SetOutputType, ProcessMessage ProcessInput and ProcessOutput
// methods can run from MF work queue threads.
base::Lock lock_;
};
} // namespace media
#endif // MEDIA_CDM_WIN_TEST_MEDIA_FOUNDATION_CLEAR_KEY_DECRYPTOR_H_