| // Copyright (c) 2020 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_ASYNC_DESTROY_VIDEO_DECODER_H_ |
| #define MEDIA_BASE_ASYNC_DESTROY_VIDEO_DECODER_H_ |
| |
| #include <memory> |
| #include <type_traits> |
| #include "media/base/video_decoder.h" |
| |
| namespace media { |
| |
| // Some VideoDecoder implementations must do non-synchronous cleanup before |
| // they are destroyed. This wrapper implementation allows a VideoDecoder |
| // to schedule its own cleanup tasks before its memory is released. |
| // The underlying type must implement a static |
| // `DestroyAsync(std::unique_ptr<T>)` function which fires any pending |
| // callbacks, stops and destroys the decoder. After this call, external |
| // resources (e.g. raw pointers) held by the decoder might be invalidated |
| // immediately. So if the decoder is destroyed asynchronously (e.g. DeleteSoon), |
| // external resources must be released in this call. |
| template <typename T> |
| class AsyncDestroyVideoDecoder final : public VideoDecoder { |
| public: |
| explicit AsyncDestroyVideoDecoder(std::unique_ptr<T> wrapped_decoder) |
| : wrapped_decoder_(std::move(wrapped_decoder)) { |
| static_assert(std::is_base_of<VideoDecoder, T>::value, |
| "T must implement 'media::VideoDecoder'"); |
| DCHECK(wrapped_decoder_); |
| } |
| |
| ~AsyncDestroyVideoDecoder() override { |
| if (wrapped_decoder_) |
| T::DestroyAsync(std::move(wrapped_decoder_)); |
| } |
| |
| VideoDecoderType GetDecoderType() const override { |
| DCHECK(wrapped_decoder_); |
| return wrapped_decoder_->GetDecoderType(); |
| } |
| |
| bool IsPlatformDecoder() const override { |
| DCHECK(wrapped_decoder_); |
| return wrapped_decoder_->IsPlatformDecoder(); |
| } |
| |
| void Initialize(const VideoDecoderConfig& config, |
| bool low_delay, |
| CdmContext* cdm_context, |
| InitCB init_cb, |
| const OutputCB& output_cb, |
| const WaitingCB& waiting_cb) override { |
| DCHECK(wrapped_decoder_); |
| wrapped_decoder_->Initialize(config, low_delay, cdm_context, |
| std::move(init_cb), output_cb, waiting_cb); |
| } |
| |
| void Decode(scoped_refptr<DecoderBuffer> buffer, |
| DecodeCB decode_cb) override { |
| DCHECK(wrapped_decoder_); |
| wrapped_decoder_->Decode(std::move(buffer), std::move(decode_cb)); |
| } |
| |
| void Reset(base::OnceClosure closure) override { |
| DCHECK(wrapped_decoder_); |
| wrapped_decoder_->Reset(std::move(closure)); |
| } |
| |
| bool NeedsBitstreamConversion() const override { |
| DCHECK(wrapped_decoder_); |
| return wrapped_decoder_->NeedsBitstreamConversion(); |
| } |
| |
| bool CanReadWithoutStalling() const override { |
| DCHECK(wrapped_decoder_); |
| return wrapped_decoder_->CanReadWithoutStalling(); |
| } |
| |
| int GetMaxDecodeRequests() const override { |
| DCHECK(wrapped_decoder_); |
| return wrapped_decoder_->GetMaxDecodeRequests(); |
| } |
| |
| private: |
| std::unique_ptr<T> wrapped_decoder_; |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_BASE_ASYNC_DESTROY_VIDEO_DECODER_H_ |