| // Copyright (c) 2012 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_FILTERS_DECRYPTING_DEMUXER_STREAM_H_ |
| #define MEDIA_FILTERS_DECRYPTING_DEMUXER_STREAM_H_ |
| |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/sequence_checker.h" |
| #include "media/base/audio_decoder_config.h" |
| #include "media/base/callback_registry.h" |
| #include "media/base/cdm_context.h" |
| #include "media/base/decryptor.h" |
| #include "media/base/demuxer_stream.h" |
| #include "media/base/pipeline_status.h" |
| #include "media/base/video_decoder_config.h" |
| #include "media/base/waiting.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace base { |
| class SequencedTaskRunner; |
| } |
| |
| namespace media { |
| |
| class CdmContext; |
| class DecoderBuffer; |
| class MediaLog; |
| |
| // Decryptor-based DemuxerStream implementation that converts a potentially |
| // encrypted demuxer stream to a clear demuxer stream. |
| // All public APIs and callbacks are trampolined to the |task_runner_| so |
| // that no locks are required for thread safety. |
| class MEDIA_EXPORT DecryptingDemuxerStream : public DemuxerStream { |
| public: |
| DecryptingDemuxerStream( |
| const scoped_refptr<base::SequencedTaskRunner>& task_runner, |
| MediaLog* media_log, |
| const WaitingCB& waiting_cb); |
| |
| DecryptingDemuxerStream(const DecryptingDemuxerStream&) = delete; |
| DecryptingDemuxerStream& operator=(const DecryptingDemuxerStream&) = delete; |
| |
| // Cancels all pending operations immediately and fires all pending callbacks. |
| ~DecryptingDemuxerStream() override; |
| |
| // |stream| must be encrypted and |cdm_context| must be non-null. |
| void Initialize(DemuxerStream* stream, |
| CdmContext* cdm_context, |
| PipelineStatusCallback status_cb); |
| |
| // Cancels all pending operations and fires all pending callbacks. If in |
| // kPendingDemuxerRead or kPendingDecrypt state, waits for the pending |
| // operation to finish before satisfying |closure|. Sets the state to |
| // kUninitialized if |this| hasn't been initialized, or to kIdle otherwise. |
| void Reset(base::OnceClosure closure); |
| |
| // Returns the name of this class for logging purpose. |
| std::string GetDisplayName() const; |
| |
| // DemuxerStream implementation. |
| void Read(ReadCB read_cb) override; |
| AudioDecoderConfig audio_decoder_config() override; |
| VideoDecoderConfig video_decoder_config() override; |
| Type type() const override; |
| Liveness liveness() const override; |
| void EnableBitstreamConverter() override; |
| bool SupportsConfigChanges() override; |
| |
| // Returns whether the stream has clear lead. |
| bool HasClearLead() const; |
| |
| private: |
| // See this link for a detailed state diagram: http://shortn/_1nXgoVIrps |
| // Each line has a number that corresponds to an action, status or function |
| // that results in a state change. These actions, etc are all listed below. |
| // NOTE: invoking Reset() will cause a transition from any state except |
| // kUninitialized to the kIdle state. |
| // |
| // +----------------+ +---------------------------------+ |
| // | kUninitialized | | Any State Except kUninitialized | |
| // +----------------+ +---------------------------------+ |
| // | | |
| // 0 7 |
| // v v |
| // +-------+ +-------+ |
| // | kIdle |<-------+-+ | kIdle | |
| // +-------+ | | +-------+ |
| // | | | |
| // 1 4 5 |
| // v | | |
| // +---------------------+ | | |
| // | kPendingDemuxerRead |-+ | |
| // +---------------------+ | |
| // | | |
| // 2 | |
| // v | |
| // +-----------------+ | |
| // +->| kPendingDecrypt |-----+ |
| // | +-----------------+ |
| // | | |
| // 6 3 |
| // | v |
| // | +----------------+ |
| // +---| kWaitingForKey | |
| // +----------------+ |
| // |
| // 1) Read() |
| // 2) Has encrypted buffer |
| // 3) kNoKey |
| // 4) kConfigChanged, kAborted, has clear buffer or end of stream |
| // 5) kSuccess or kAborted |
| // 6) OnKeyAdded() |
| // 7) Reset() |
| |
| enum State { |
| kUninitialized = 0, |
| kIdle, |
| kPendingDemuxerRead, |
| kPendingDecrypt, |
| kWaitingForKey |
| }; |
| |
| // Callback for DemuxerStream::Read(). |
| void OnBufferReadFromDemuxerStream(DemuxerStream::Status status, |
| scoped_refptr<DecoderBuffer> buffer); |
| |
| void DecryptPendingBuffer(); |
| |
| // Callback for Decryptor::Decrypt(). |
| void OnBufferDecrypted(Decryptor::Status status, |
| scoped_refptr<DecoderBuffer> decrypted_buffer); |
| |
| // Callback for the CDM to notify |this|. |
| void OnCdmContextEvent(CdmContext::Event event); |
| |
| // Resets decoder and calls |reset_cb_|. |
| void DoReset(); |
| |
| // Returns Decryptor::StreamType converted from |stream_type_|. |
| Decryptor::StreamType GetDecryptorStreamType() const; |
| |
| // Creates and initializes either |audio_config_| or |video_config_| based on |
| // |demuxer_stream_|. |
| void InitializeDecoderConfig(); |
| |
| // Completes traces for various pending states. |
| void CompletePendingDecrypt(Decryptor::Status status); |
| void CompleteWaitingForDecryptionKey(); |
| |
| void LogMetadata(); |
| |
| scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| SEQUENCE_CHECKER(sequence_checker_); |
| MediaLog* const media_log_; |
| WaitingCB waiting_cb_; |
| |
| State state_ = kUninitialized; |
| |
| PipelineStatusCallback init_cb_; |
| ReadCB read_cb_; |
| base::OnceClosure reset_cb_; |
| |
| // Pointer to the input demuxer stream that will feed us encrypted buffers. |
| DemuxerStream* demuxer_stream_ = nullptr; |
| |
| AudioDecoderConfig audio_config_; |
| VideoDecoderConfig video_config_; |
| |
| Decryptor* decryptor_ = nullptr; |
| |
| absl::optional<bool> has_clear_lead_; |
| |
| // The buffer returned by the demuxer that needs to be decrypted. |
| scoped_refptr<media::DecoderBuffer> pending_buffer_to_decrypt_; |
| |
| // Indicates the situation where new key is added during pending decryption |
| // (in other words, this variable can only be set in state kPendingDecrypt). |
| // If this variable is true and kNoKey is returned then we need to try |
| // decrypting again in case the newly added key is the correct decryption key. |
| bool key_added_while_decrypt_pending_ = false; |
| |
| // To keep the CdmContext event callback registered. |
| std::unique_ptr<CallbackRegistration> event_cb_registration_; |
| |
| base::WeakPtrFactory<DecryptingDemuxerStream> weak_factory_{this}; |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_FILTERS_DECRYPTING_DEMUXER_STREAM_H_ |