summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/wrappers/FuzzingWrapper.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/platforms/wrappers/FuzzingWrapper.h')
-rw-r--r--dom/media/platforms/wrappers/FuzzingWrapper.h124
1 files changed, 124 insertions, 0 deletions
diff --git a/dom/media/platforms/wrappers/FuzzingWrapper.h b/dom/media/platforms/wrappers/FuzzingWrapper.h
new file mode 100644
index 000000000..c2b737520
--- /dev/null
+++ b/dom/media/platforms/wrappers/FuzzingWrapper.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined(FuzzingWrapper_h_)
+#define FuzzingWrapper_h_
+
+#include "mozilla/Pair.h"
+#include "PlatformDecoderModule.h"
+
+#include <deque>
+
+namespace mozilla {
+
+// Fuzzing wrapper for media decoders.
+//
+// DecoderFuzzingWrapper owns the DecoderCallbackFuzzingWrapper, and inserts
+// itself between the reader and the decoder.
+// DecoderCallbackFuzzingWrapper inserts itself between a decoder and its
+// callback.
+// Together they are used to introduce some fuzzing, (e.g. delay output).
+//
+// Normally:
+// ====================================>
+// reader decoder
+// <------------------------------------
+//
+// With fuzzing:
+// ======> DecoderFuzzingWrapper ======>
+// reader v decoder
+// <-- DecoderCallbackFuzzingWrapper <--
+//
+// Creation order should be:
+// 1. Create DecoderCallbackFuzzingWrapper, give the expected callback target.
+// 2. Create actual decoder, give DecoderCallbackFuzzingWrapper as callback.
+// 3. Create DecoderFuzzingWrapper, give decoder and DecoderCallbackFuzzingWrapper.
+// DecoderFuzzingWrapper is what the reader sees as decoder, it owns the
+// real decoder and the DecoderCallbackFuzzingWrapper.
+
+class DecoderCallbackFuzzingWrapper : public MediaDataDecoderCallback
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecoderCallbackFuzzingWrapper)
+
+ explicit DecoderCallbackFuzzingWrapper(MediaDataDecoderCallback* aCallback);
+
+ // Enforce a minimum interval between output frames (i.e., limit frame rate).
+ // Of course, if the decoder is even slower, this won't have any effect.
+ void SetVideoOutputMinimumInterval(TimeDuration aFrameOutputMinimumInterval);
+ // If false (default), if frames are delayed, any InputExhausted is delayed to
+ // be later sent after the corresponding delayed frame.
+ // If true, InputExhausted are passed through immediately; This could result
+ // in lots of frames being decoded and queued for delayed output!
+ void SetDontDelayInputExhausted(bool aDontDelayInputExhausted);
+
+private:
+ virtual ~DecoderCallbackFuzzingWrapper();
+
+ // MediaDataDecoderCallback implementation.
+ void Output(MediaData* aData) override;
+ void Error(const MediaResult& aError) override;
+ void InputExhausted() override;
+ void DrainComplete() override;
+ void ReleaseMediaResources() override;
+ bool OnReaderTaskQueue() override;
+
+ MediaDataDecoderCallback* mCallback;
+
+ // Settings for minimum frame output interval & InputExhausted,
+ // should be set during init and then only read on mTaskQueue.
+ TimeDuration mFrameOutputMinimumInterval;
+ bool mDontDelayInputExhausted;
+ // Members for minimum frame output interval & InputExhausted,
+ // should only be accessed on mTaskQueue.
+ TimeStamp mPreviousOutput;
+ // First member is the frame to be delayed.
+ // Second member is true if an 'InputExhausted' arrived after that frame; in
+ // which case an InputExhausted will be sent after finally outputting the frame.
+ typedef Pair<RefPtr<MediaData>, bool> MediaDataAndInputExhausted;
+ std::deque<MediaDataAndInputExhausted> mDelayedOutput;
+ RefPtr<MediaTimer> mDelayedOutputTimer;
+ MozPromiseRequestHolder<MediaTimerPromise> mDelayedOutputRequest;
+ // If draining, a 'DrainComplete' will be sent after all delayed frames have
+ // been output.
+ bool mDraining;
+ // All callbacks are redirected through this task queue, both to avoid locking
+ // and to have a consistent sequencing of callbacks.
+ RefPtr<TaskQueue> mTaskQueue;
+ void ScheduleOutputDelayedFrame();
+ void OutputDelayedFrame();
+public: // public for the benefit of DecoderFuzzingWrapper.
+ void ClearDelayedOutput();
+ void Shutdown();
+};
+
+class DecoderFuzzingWrapper : public MediaDataDecoder
+{
+public:
+ DecoderFuzzingWrapper(already_AddRefed<MediaDataDecoder> aDecoder,
+ already_AddRefed<DecoderCallbackFuzzingWrapper> aCallbackWrapper);
+
+ // MediaDataDecoder implementation.
+ RefPtr<InitPromise> Init() override;
+ void Input(MediaRawData* aSample) override;
+ void Flush() override;
+ void Drain() override;
+ void Shutdown() override;
+ bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
+ const char* GetDescriptionName() const override
+ {
+ return mDecoder->GetDescriptionName();
+ }
+
+private:
+ virtual ~DecoderFuzzingWrapper();
+ RefPtr<MediaDataDecoder> mDecoder;
+ RefPtr<DecoderCallbackFuzzingWrapper> mCallbackWrapper;
+};
+
+} // namespace mozilla
+
+#endif