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_