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
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm
#include "libvideostitch/input.hpp"
#include "image/unpack.hpp"
#include <mutex>
#include <sstream>
// TODO: enable thread safety annotations.
#define GUARDED_BY(mutex)
namespace VideoStitch {
namespace Input {
Reader::Reader(readerid_t id) : id(id), latency(0) {}
Reader::~Reader() {}
VideoReader::~VideoReader() {}
frameid_t VideoReader::getFirstFrame() const { return firstFrame; }
frameid_t VideoReader::getLastFrame() const { return lastFrame; }
int64_t VideoReader::getWidth() const { return spec.width; }
int64_t VideoReader::getHeight() const { return spec.height; }
int64_t VideoReader::getFrameDataSize() const { return spec.frameDataSize; }
const VideoReader::Spec& VideoReader::getSpec() const { return spec; }
VideoReader::Spec& VideoReader::getSpec() { return spec; }
VideoReader* Reader::getVideoReader() const { return dynamic_cast<VideoReader*>(const_cast<Reader*>(this)); }
AudioReader::~AudioReader() {}
const AudioReader::Spec& AudioReader::getSpec() const { return spec; }
AudioReader::Spec& AudioReader::getSpec() { return spec; }
AudioReader* Reader::getAudioReader() const {
AudioReader* audio = dynamic_cast<AudioReader*>(const_cast<Reader*>(this));
if (audio) {
AudioReader::Spec spec = audio->getSpec();
if (spec.layout != Audio::UNKNOWN && spec.sampleRate != Audio::SamplingRate::SR_NONE &&
spec.sampleDepth != Audio::SamplingDepth::SD_NONE) {
return audio;
}
}
return nullptr;
}
MetadataReader::~MetadataReader() {}
MetadataReader* Reader::getMetadataReader() const { return dynamic_cast<MetadataReader*>(const_cast<Reader*>(this)); }
SinkReader* Reader::getSinkReader() const { return dynamic_cast<SinkReader*>(const_cast<Reader*>(this)); }
mtime_t Reader::getLatency() {
std::lock_guard<std::mutex> lock(this->latencyMutex);
return this->latency;
}
void Reader::setLatency(mtime_t value) {
std::lock_guard<std::mutex> lock(this->latencyMutex);
this->latency = value;
}
bool Reader::updateLatency(mtime_t value) {
std::lock_guard<std::mutex> lock(this->latencyMutex);
if (value > this->latency) {
this->latency = value;
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////
class VideoReader::Spec::Impl {
friend class VideoReader;
/**
* A mutex that guards the mutable properties.
*/
std::mutex mutex;
/**
* The display name.
*/
std::string displayName GUARDED_BY(mutex);
};
class AudioReader::Spec::Impl {
friend class AudioReader;
/**
* A mutex that guards the mutable properties.
*/
std::mutex mutex;
/**
* The display name.
*/
std::string displayName GUARDED_BY(mutex);
};
class MetadataReader::Spec::Impl {
friend class MetadataReader;
/**
* A mutex that guards the mutable properties
*/
std::mutex mutex;
/**
* The display name
*/
std::string displayName GUARDED_BY(mutex);
};
///////////////////////////////////////////
VideoReader::Spec::Spec(int64_t width, int64_t height, int64_t frameDataSize, VideoStitch::PixelFormat format,
AddressSpace addressSpace, int frameNum, FrameRate frameRate, bool frameRateIsProcedural,
const unsigned char* maskHostBuffer, int flags)
: width(width),
height(height),
frameDataSize(frameDataSize),
format(format),
addressSpace(addressSpace),
frameNum(frameNum),
frameRate(frameRate),
frameRateIsProcedural(frameRateIsProcedural),
flags(flags),
maskHostBuffer(maskHostBuffer),
pimpl(new Impl()) {}
AudioReader::Spec::Spec(Audio::ChannelLayout layout, Audio::SamplingRate sampleRate, Audio::SamplingDepth sampleDepth)
: layout(layout), sampleRate(sampleRate), sampleDepth(sampleDepth), pimpl(new Impl()) {}
MetadataReader::Spec::Spec(FrameRate framerate) : frameRate(framerate), pimpl(new Impl()) {}
///////////////////////////////////////////
VideoReader::Spec::Spec()
: width(0),
height(0),
frameDataSize(0),
format(VideoStitch::RGBA),
addressSpace(Host),
frameNum(0),
frameRate({-1, 1} /* Unknown */),
frameRateIsProcedural(true),
flags(0),
maskHostBuffer(NULL),
pimpl(new Impl()) {}
AudioReader::Spec::Spec()
: layout(Audio::UNKNOWN),
sampleRate(Audio::SamplingRate::SR_NONE),
sampleDepth(Audio::SamplingDepth::SD_NONE),
pimpl(new Impl()) {}
MetadataReader::Spec::Spec() : frameRate({-1, 1} /* Unknown */), pimpl(new Impl()) {}
///////////////////////////////////////////
VideoReader::Spec::~Spec() { delete pimpl; }
AudioReader::Spec::~Spec() { delete pimpl; }
MetadataReader::Spec::~Spec() { delete pimpl; }
///////////////////////////////////////////
VideoReader::Spec::Spec(const Spec& o)
: width(o.width),
height(o.height),
frameDataSize(o.frameDataSize),
format(o.format),
addressSpace(o.addressSpace),
frameNum(o.frameNum),
frameRate(o.frameRate),
frameRateIsProcedural(o.frameRateIsProcedural),
flags(o.flags),
maskHostBuffer(o.maskHostBuffer),
pimpl(new Impl()) {}
AudioReader::Spec::Spec(const Spec& o)
: layout(o.layout), sampleRate(o.sampleRate), sampleDepth(o.sampleDepth), pimpl(new Impl()) {}
MetadataReader::Spec::Spec(const Spec& o) : frameRate(o.frameRate), pimpl(new Impl()) {}
///////////////////////////////////////////
void VideoReader::Spec::setDisplayName(const char* name) { pimpl->displayName = name; }
void AudioReader::Spec::setDisplayName(const char* name) { pimpl->displayName = name; }
void MetadataReader::Spec::setDisplayName(const char* name) { pimpl->displayName = name; }
///////////////////////////////////////////
void VideoReader::Spec::getDisplayName(std::ostream& os) const { os << pimpl->displayName; }
void AudioReader::Spec::getDisplayName(std::ostream& os) const { os << pimpl->displayName; }
void MetadataReader::Spec::getDisplayName(std::ostream& os) const { os << pimpl->displayName; }
///////////////////////////////////////////
VideoReader::VideoReader(int64_t width, int64_t height, int64_t frameDataSize, VideoStitch::PixelFormat format,
AddressSpace addressSpace, FrameRate frameRate, int firstFrame, int lastFrame,
bool isProcedural, const unsigned char* maskHostBuffer,
int flags)
: Reader(-1), // never called : https://isocpp.org/wiki/faq/multiple-inheritance#virtual-inheritance-ctors
firstFrame(firstFrame),
lastFrame(lastFrame),
spec(width, height, frameDataSize, format, addressSpace, lastFrame - firstFrame + 1, frameRate, isProcedural,
maskHostBuffer, flags) {
getSpec().setDisplayName("[unknown input]");
}
AudioReader::AudioReader(Audio::ChannelLayout layout, Audio::SamplingRate sampleRate,
Audio::SamplingDepth sampleDepth)
: Reader(-1), // never called : https://isocpp.org/wiki/faq/multiple-inheritance#virtual-inheritance-ctors
spec(layout, sampleRate, sampleDepth) {}
MetadataReader::MetadataReader(FrameRate framerate)
: Reader(-1), // never called : https://isocpp.org/wiki/faq/multiple-inheritance#virtual-inheritance-ctors
spec(framerate) {}
SinkReader::SinkReader()
: Reader(-1) {} // never called : https://isocpp.org/wiki/faq/multiple-inheritance#virtual-inheritance-ctors
///////////////////////////////////////////
Status VideoReader::perThreadInit() { return Status::OK(); }
void VideoReader::perThreadCleanup() {}
Status VideoReader::unpackDevBuffer(GPU::Surface& dst, const GPU::Buffer<const unsigned char>& src,
GPU::Stream& stream) const {
return Image::unpackCommonPixelFormat(spec.format, dst, src, spec.width, spec.height, stream);
}
Status VideoReader::unpackDevBuffer(VideoStitch::PixelFormat fmt, GPU::Surface& dst,
const GPU::Buffer<const unsigned char>& src, uint64_t width, uint64_t height,
GPU::Stream& stream) {
return Image::unpackCommonPixelFormat(fmt, dst, src, width, height, stream);
}
} // namespace Input
} // namespace VideoStitch