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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm
#pragma once
#include "inputControllerImpl.hpp"
#include "audio/audioPipeline.hpp"
#include "exposure/metadataProcessor.hpp"
#include "libvideostitch/orah/imuStabilization.hpp"
#include "libvideostitch/controller.hpp"
#include "libvideostitch/preprocessor.hpp"
#include "libvideostitch/postprocessor.hpp"
#include <list>
#include <mutex>
#ifdef ANDROID__GNUSTL
#define timed_mutex mutex
#define try_lock_for(a) try_lock()
#endif
#ifdef _MSC_VER
#pragma warning(push)
// using virtual inheritance of InputController on purpose
#pragma warning(disable : 4250)
#endif
namespace VideoStitch {
namespace Core {
class ImageMergerFactory;
class Mutex;
class PreProcessor;
/**
* @brief Controller implementation.
*/
template <typename VideoPipeline>
class ControllerImpl
: public InputControllerImpl,
public StitcherController<typename VideoPipeline::Output, typename VideoPipeline::DeviceDefinition> {
using typename StitcherController<typename VideoPipeline::Output, typename VideoPipeline::DeviceDefinition>::Output;
using typename StitcherController<typename VideoPipeline::Output,
typename VideoPipeline::DeviceDefinition>::DeviceDefinition;
typedef typename Output::Writer Writer;
using typename StitcherController<Output, DeviceDefinition>::PotentialOutput;
using typename StitcherController<Output, DeviceDefinition>::PotentialController;
public:
/**
* Factory function to create a Controller with the @pano PanoDefinition and the @readerFactory input ReaderFactory.
* @param pano The panorama to stitch.
* @param mergerFactory Factory to create mergers.
* @param readerFactory The factory for reader. We take ownership.
* @param preprocessors Vector of the preprocessors.
* @param rig Stereo rig definition.
*/
static PotentialController create(const PanoDefinition& pano, const AudioPipeDefinition& audioPipe,
const ImageMergerFactory& mergerFactory, const ImageWarperFactory& warperFactory,
const ImageFlowFactory& flowFactory, Input::ReaderFactory* readerFactory,
const StereoRigDefinition* rig = nullptr);
virtual ~ControllerImpl();
virtual Status createStitcher() override;
virtual void deleteStitcher() override;
virtual bool addAudioOutput(std::shared_ptr<VideoStitch::Output::AudioWriter>) override;
virtual bool removeAudioOutput(const std::string&) override;
virtual void setAudioInput(const std::string& inputName) override;
virtual Potential<ExtractOutput> createBlockingExtractOutput(
int source, std::shared_ptr<SourceSurface>, std::shared_ptr<SourceRenderer> renderer,
std::shared_ptr<VideoStitch::Output::VideoWriter> writer) override;
virtual Potential<ExtractOutput> createAsyncExtractOutput(
int source, const std::vector<std::shared_ptr<SourceSurface>>&, std::shared_ptr<SourceRenderer> renderer,
std::shared_ptr<VideoStitch::Output::VideoWriter> writer) const override;
virtual PotentialOutput createBlockingStitchOutput(std::shared_ptr<PanoSurface>,
const std::vector<std::shared_ptr<PanoRenderer>>& renderer,
const std::vector<std::shared_ptr<Writer>>& writers) override;
virtual PotentialOutput createAsyncStitchOutput(const std::vector<std::shared_ptr<PanoSurface>>&,
const std::vector<std::shared_ptr<PanoRenderer>>& renderer,
const std::vector<std::shared_ptr<Writer>>& writers) const override;
virtual ControllerStatus stitch(Output* output, bool readFrame) override;
virtual ControllerStatus extract(ExtractOutput* output, bool readFrame) override;
virtual ControllerStatus extract(std::vector<ExtractOutput*> extracts, AlgorithmOutput* algo,
bool readFrame) override;
virtual ControllerStatus stitchAndExtract(Output* output, std::vector<ExtractOutput*> extracts, AlgorithmOutput* algo,
bool readFrame) override;
virtual const PanoDefinition& getPano() const override { return *pano; }
virtual const StereoRigDefinition* getRig() const override { return rig; }
virtual bool isPanoChangeCompatible(const PanoDefinition& newPano) const override;
virtual const ImageMergerFactory& getMergerFactory() const override { return *mergerFactory; }
virtual const ImageWarperFactory& getWarperFactory() const override { return *warperFactory; }
virtual const ImageFlowFactory& getFlowFactory() const override { return *flowFactory; }
virtual int getCurrentFrame() const override { return readerController->getCurrentFrame(); }
virtual Status updatePanorama(
const std::function<Potential<PanoDefinition>(const PanoDefinition&)>& panoramaUpdater) override;
virtual Status updatePanorama(const PanoDefinition& panorama) override;
virtual Status resetRig(const StereoRigDefinition& newRig) override;
virtual Status applyAudioProcessorParam(const AudioPipeDefinition& newAudioPipe) override;
virtual Status resetMergerFactory(const ImageMergerFactory& newMergerFactory, bool redoSetupNow) override;
virtual Status resetWarperFactory(const ImageWarperFactory& newWarperFactory, bool redoSetupNow) override;
virtual Status resetFlowFactory(const ImageFlowFactory& newFlowFactory, bool redoSetupNow) override;
virtual void applyRotation(double yaw, double pitch, double roll) override;
virtual void resetRotation() override;
virtual Quaternion<double> getRotation() const override;
virtual void setSphereScale(const double sphereScale) override;
ReaderController& getReaderCtrl() const { return *readerController; }
std::vector<PreProcessor*> getPreProcessors() const { return preprocessors; }
/**
* Preprocessor accessor.
* @returns The i-th preprocessor, or NULL if no preprocessor.
* @note Inputs must be locked by the calling thread.
*/
PreProcessor* getPreProcessor(int i) const;
/**
* Preprocessor setter.
* @note Inputs must be locked by the calling thread.
* @note The current i-th preprocessor will be deleted and replaced by @p.
* @note @p ownership is tranferred to the ControllerImpl.
*/
void setPreProcessor(int i, PreProcessor* p) override;
/**
* @brief enablePreProcessing
* @param value enables preprocessing according to boolean value
*/
void enablePreProcessing(bool value) override;
/**
* Enables/disables metadata processing.
*/
virtual void enableMetadataProcessing(bool value) override;
/**
* Postprocessor accessor.
*/
PostProcessor* getPostProcessor() const;
/**
* Returns true if preprocessing is enabled.
*/
bool isPreProcessingEnabled() const { return preProcessingEnabled; }
/**
* Postprocessor setter.
* @note The current postprocessor will be deleted and replaced by @p.
* @note @p ownership is tranferred to the ControllerImpl.
*/
void setPostProcessor(PostProcessor* p) override;
/**
* AudioPreprocessor setter.
* @param name Name of the audio preprocessor to setup.
* @param gr Group id of the audio preprocessor to be applied.
*/
void setAudioPreProcessor(const std::string& name, groupid_t gr) override {
readerController->setupAudioPreProc(name, gr);
}
/**
* Audio accessors.
*/
bool hasAudio() const override { return audioPipe->hasAudio(); }
Status seekFrame(frameid_t date) override { return readerController->seekFrame(date); }
virtual bool hasVuMeter(const std::string& inputName) const override;
virtual std::vector<double> getPeakValues(const std::string& inputName) const override;
virtual std::vector<double> getRMSValues(const std::string& inputName) const override;
virtual Status setAudioDelay(double delay_ms) override;
/**
* IMU Stabilization accessors
*/
const Quaternion<double> getUserOrientation() override;
void setUserOrientation(const Quaternion<double>& q) override;
void updateUserOrientation(const Quaternion<double>& q) override;
void resetUserOrientation() override;
/**
* @brief enables (true) or disables (false) the IMU stabilization
* It always resets previous user defined orientation
*/
void enableStabilization(bool value) override;
virtual bool isStabilizationEnabled() override;
Stab::IMUStabilization& getStabilizationIMU() override;
virtual mtime_t getLatency() const override;
virtual Status addSink(const Ptv::Value* config) override;
virtual void removeSink() override;
protected:
/**
* Create a controller. Call init() after creation.
* @param pano The panorama to stitch.
* @param mergerFactory The factory for mergers.
* @param readers Vector of the intput readers.
* @param preprocessors Vector of the preprocessors.
* @param maxStitchers Maximum number of stitchers that can live in parallel.
* @param options controller options.
* @param frameid_t Initial frame offset.
*/
ControllerImpl(const PanoDefinition& pano, Audio::AudioPipeline* audioPipe, const ImageMergerFactory& mergerFactory,
const ImageWarperFactory& warperFactory, const ImageFlowFactory& flowFactory,
ReaderController* readerController, std::vector<PreProcessor*> preprocessors, PostProcessor* postproc,
const StereoRigDefinition*);
virtual Status resetPano(const PanoDefinition& newPano) override;
private:
PanoDefinition* pano;
const StereoRigDefinition* rig;
std::timed_mutex panoramaUpdateLock;
const ImageMergerFactory* mergerFactory;
const ImageWarperFactory* warperFactory;
const ImageFlowFactory* flowFactory;
bool setupPending;
std::vector<PreProcessor*> preprocessors;
std::atomic<bool> preProcessingEnabled;
std::atomic<bool> metadataProcessingEnabled;
PostProcessor* postprocessor;
mutable std::mutex stitcherMutex; // protects pipeline.
Audio::AudioPipeline* audioPipe;
VideoPipeline* videoPipe;
Stab::IMUStabilization stabilizationAlgorithm;
Quaternion<double> qUserOrientation;
bool stabilizationEnabled;
Exposure::MetadataProcessor exposureProcessor;
};
#define PROPAGATE_CONTROLLER_FAILURE_STATUS(call) \
{ \
const ControllerStatus status = (call); \
if (!status.ok()) { \
return status; \
} \
}
#define FAIL_CONTROLLER_RETURN PROPAGATE_CONTROLLER_FAILURE_STATUS
} // namespace Core
} // namespace VideoStitch
#ifdef _MSC_VER
#pragma warning(pop)
#endif