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
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm
#include "exprProcessor.hpp"
#include "gridProcessor.hpp"
#include "tintProcessor.hpp"
#include "maskProcessor.hpp"
#include "libvideostitch/parse.hpp"
#include "libvideostitch/logging.hpp"
#include "libvideostitch/preprocessor.hpp"
#include "libvideostitch/ptv.hpp"
#include <memory>
namespace VideoStitch {
namespace Core {
namespace {
/**
* A PreProcessor that just chains several PreProcessors.
*/
class MultiPreProcessor : public PreProcessor {
public:
~MultiPreProcessor() {
for (auto preprocessor = preprocessors.begin(); preprocessor != preprocessors.end(); ++preprocessor) {
delete *preprocessor;
}
}
void add(PreProcessor* preprocessor) { preprocessors.push_back(preprocessor); }
Status process(frameid_t frame, GPU::Surface& devBuffer, int64_t width, int64_t height, readerid_t inputId,
GPU::Stream& stream) const {
Status s;
for (auto preprocessor = preprocessors.begin(); preprocessor != preprocessors.end(); ++preprocessor) {
Status processingStatus = (*preprocessor)->process(frame, devBuffer, width, height, inputId, stream);
if (processingStatus.ok()) {
s = processingStatus;
}
}
return s;
}
void getDisplayName(std::ostream& os) const {
for (auto preprocessor = preprocessors.begin(); preprocessor != preprocessors.end(); ++preprocessor) {
(*preprocessor)->getDisplayName(os);
os << ", ";
}
}
private:
std::vector<PreProcessor*> preprocessors;
};
} // namespace
Potential<PreProcessor> PreProcessor::create(const Ptv::Value& config, Util::OpaquePtr** /*ctx*/) {
// We accept either lists of processors or single objects.
if (config.getType() == Ptv::Value::LIST) {
if (config.asList().size() == 0) {
return {Origin::PreProcessor, ErrType::InvalidConfiguration, "Configuration is empty"};
} else if (config.asList().size() == 1) {
return create(*config.asList()[0]);
} else {
std::unique_ptr<MultiPreProcessor> multiPreprocessor(new MultiPreProcessor());
for (auto subConfig = config.asList().begin(); subConfig != config.asList().end(); ++subConfig) {
Potential<PreProcessor> preprocessor = PreProcessor::create(*(*subConfig));
FAIL_RETURN(preprocessor.status());
multiPreprocessor->add(preprocessor.release());
}
return Potential<PreProcessor>(multiPreprocessor.release());
}
}
if (!Parse::checkType("PreProcessor", config, Ptv::Value::OBJECT)) {
return {Origin::PreProcessor, ErrType::InvalidConfiguration, "Invalid configuration type for 'PreProcessor'"};
}
std::string strType;
if (Parse::populateString("PreProcessor", config, "type", strType, true) == Parse::PopulateResult_WrongType) {
return {Origin::PreProcessor, ErrType::InvalidConfiguration,
"Invalid configuration type for 'PreProcessor', expected string"};
}
if (strType == "expr") {
return Potential<PreProcessor>(ExprProcedure::create(config));
} else if (strType == "tint") {
return Potential<PreProcessor>(TintPreProcessor::create(config));
} else if (strType == "mask") {
return Potential<PreProcessor>(MaskPreProcessor::create(config));
}
return {Origin::PreProcessor, ErrType::InvalidConfiguration, "No such pre-processor: '" + strType + "'"};
}
} // namespace Core
} // namespace VideoStitch