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
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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
|