// Copyright 2017 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_FILTERS_OFFLOADING_VIDEO_DECODER_H_ #define MEDIA_FILTERS_OFFLOADING_VIDEO_DECODER_H_ #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "media/base/video_codecs.h" #include "media/base/video_decoder.h" #include "media/base/video_decoder_config.h" namespace base { class SequencedTaskRunner; } // namespace base namespace media { class CancellationHelper; // OffloadableVideoDecoder implementations must have synchronous execution of // Reset() and Decode() (true for all current software decoders); this allows // for serializing these operations on the offloading sequence. With // serializing, multiple Decode() events can be queued on the offload thread, // and Reset() does not need to wait for |reset_cb| to return. class MEDIA_EXPORT OffloadableVideoDecoder : public VideoDecoder { … }; // Wrapper for OffloadableVideoDecoder implementations that runs the wrapped // decoder on a task pool other than the caller's thread. // // Offloading allows us to avoid blocking the media sequence for Decode() when // it's known that decoding may take a long time; e.g., high-resolution VP9 // decodes may occasionally take upwards of > 100ms per frame, which is enough // to exhaust the audio buffer and lead to underflow in some circumstances. // // Offloading also allows better pipelining of Decode() calls. The normal decode // sequence is Decode(buffer) -> DecodeComplete() -> WaitFor(buffer)-> (repeat); // this sequence generally involves thread hops as well. When offloading we can // take advantage of the serialization of operations on the offloading sequence // to make this Decode(buffer) -> DecodeComplete() -> Decode(buffer) by queuing // the next Decode(buffer) before the previous one completes. // // I.e., we are no longer wasting cycles waiting for the recipient of the // decoded frame to acknowledge that receipt, request the next muxed buffer, and // then queue the next decode. Those operations now happen in parallel with the // decoding of the previous buffer on the offloading sequence. Improving the // total throughput that a decode can achieve. // // E.g., without parallel offloading, over 4000 frames, a 4K60 VP9 clip spent // ~11.7 seconds of aggregate time just waiting for frames. With parallel // offloading the same clip spent only ~3.4 seconds. // // Optionally decoders which are aware of the wrapping may choose to not rebind // callbacks to the offloaded thread since they will already be bound by the // OffloadingVideoDecoder; this simply avoids extra hops for completed tasks. class MEDIA_EXPORT OffloadingVideoDecoder : public VideoDecoder { … }; } // namespace media #endif // MEDIA_FILTERS_OFFLOADING_VIDEO_DECODER_H_