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
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm
#pragma once
#include "../../image/colorArray.hpp"
#include "gpu/2dBuffer.hpp"
#include "gpu/uniqueBuffer.hpp"
#include "gpu/stream.hpp"
#include "gpu/allocator.hpp"
#include "libvideostitch/output.hpp"
#include "libvideostitch/profile.hpp"
#include "libvideostitch/logging.hpp"
#include "libvideostitch/gpu_device.hpp"
#include "libvideostitch/stitchOutput.hpp"
#include <condition_variable>
#include <map>
#include <mutex>
#include <vector>
namespace VideoStitch {
namespace Core {
/**
* Represents the data for a single format.
*/
struct FormatBuffer;
/**
* A frame buffer.
*
* Can be host- or device- backed.
* Currently instantiated for 32 bits RGBA, with 2 variants:
* - 2 alpha, 10 color bits for panorama internal format.
* - 8 bits for each components for source frames.
* Can represent either panorama or input frames.
*
* Possible output formats are:
* - RGBA
* - RGB
* - planarYV12
*
* fill() marks the end of commands queueing.
* The frame can then be synchronized and presented to the user's callback.
* Thread-safe.
*/
template <typename Writer, typename Surface>
class FrameBuffer {
public:
typedef PanoOpenGLSurface GLSurface;
static Potential<FrameBuffer<Writer, Surface>> create(std::shared_ptr<Surface> surf,
const std::vector<std::shared_ptr<Writer>>& writers);
static Potential<FrameBuffer<Writer, Surface>> create(std::shared_ptr<Surface> surf, std::shared_ptr<Writer> writer);
static Potential<FrameBuffer<Writer, Surface>> create(std::shared_ptr<Surface> surf);
FrameBuffer& operator=(FrameBuffer&&);
virtual ~FrameBuffer();
/**
* Fills the buffer asynchronously.
*/
Status pushVideo();
Status registerWriters(const std::vector<std::shared_ptr<Writer>>& writers) {
for (auto w : writers) {
FAIL_RETURN(registerWriter(w));
}
return Status::OK();
}
Status registerWriter(std::shared_ptr<Writer>);
void streamSynchronize() {
surf->pimpl->releaseWriter();
if (!surf->pimpl->stream.synchronize().ok()) {
Logger::get(Logger::Error) << "GPU error when stitching frame at " << date << " useconds " << std::endl;
} else {
const uint64_t duration = timer.elapsed();
Logger::get(Logger::Verbose) << "stitched frame at " << date << " useconds "
<< " : " << duration / 1000 << " ms" << std::endl;
date = -1;
}
}
std::shared_ptr<Surface> getSurface() const { return surf; }
std::shared_ptr<GLSurface> getOpenGLSurface() {
if (oglSurf == nullptr) {
Potential<PanoOpenGLSurface> osurf = OpenGLAllocator::createPanoSurface(
surf->getWidth(), surf->getHeight(), OpenGLAllocator::BufferAllocType::ReadOnly);
if (osurf.ok()) {
oglSurf = std::shared_ptr<GLSurface>(osurf.release());
} else {
Logger::get(Logger::Error) << "Can not allocate OpenGL shared buffer on GPU." << std::endl;
}
}
return oglSurf;
}
void streamOpenGLSynchronize() {
oglSurf->pimpl->releaseWriter();
if (!oglSurf->pimpl->stream.synchronize().ok()) {
Logger::get(Logger::Error) << "GPU error when stitching frame at " << date << " useconds " << std::endl;
} else {
const uint64_t duration = timer.elapsed();
Logger::get(Logger::Verbose) << "stitched frame at " << date << " useconds "
<< " : " << duration / 1000 << " ms" << std::endl;
date = -1;
}
}
Frame getFrame(PixelFormat, AddressSpace, size_t);
void releaseFrame() {
surf->pimpl->releaseWriter();
surf->pimpl->release();
}
protected:
explicit FrameBuffer(std::shared_ptr<Surface>);
FrameBuffer(FrameBuffer<Writer, Surface>&&);
mtime_t date;
Util::SimpleTimer timer;
mutable std::mutex mutex; // Protect formatBuffers
typedef std::map<VideoStitch::PixelFormat, FormatBuffer*> FormatBufferMap;
FormatBufferMap formatBuffers;
std::shared_ptr<Surface> surf;
std::shared_ptr<GLSurface> oglSurf;
};
class SourceFrameBuffer : public FrameBuffer<Output::VideoWriter, SourceSurface> {
public:
typedef SourceSurface Surface;
typedef SourceOpenGLSurface GLSurface;
typedef SourceRenderer Renderer;
static Potential<SourceFrameBuffer> create(std::shared_ptr<SourceSurface> surf,
const std::vector<std::shared_ptr<Output::VideoWriter>>& writers);
static Potential<SourceFrameBuffer> create(std::shared_ptr<SourceSurface> surf,
std::shared_ptr<Output::VideoWriter> writer);
static Potential<SourceFrameBuffer> create(std::shared_ptr<SourceSurface> surf);
SourceFrameBuffer& operator=(SourceFrameBuffer&&);
virtual ~SourceFrameBuffer() {}
GPU::Surface& acquireFrame(mtime_t d, GPU::Stream& str) {
if (date == -1) {
date = d;
timer.reset();
}
surf->pimpl->acquireWriter();
surf->pimpl->acquire();
str = surf->pimpl->stream;
return *surf->pimpl->surface;
}
// Fills the buffer asynchronously.
Status pushVideo();
Status pushOpenGLVideo();
private:
explicit SourceFrameBuffer(std::shared_ptr<SourceSurface> s) : FrameBuffer(s) {}
SourceFrameBuffer(SourceFrameBuffer&&);
};
template <typename Writer>
class StitchFrameBuffer : public FrameBuffer<Writer, PanoSurface> {
public:
typedef PanoSurface Surface;
typedef PanoOpenGLSurface GLSurface;
typedef PanoRenderer Renderer;
static Potential<StitchFrameBuffer> create(std::shared_ptr<PanoSurface> surf,
const std::vector<std::shared_ptr<Writer>>& writers);
static Potential<StitchFrameBuffer> create(std::shared_ptr<PanoSurface> surf, std::shared_ptr<Writer> writer);
static Potential<StitchFrameBuffer> create(std::shared_ptr<PanoSurface> surf);
StitchFrameBuffer& operator=(StitchFrameBuffer&&);
virtual ~StitchFrameBuffer() {}
PanoSurface& acquireFrame(mtime_t d) {
if (this->date == -1) {
this->date = d;
this->timer.reset();
}
this->surf->pimpl->acquireWriter();
this->surf->pimpl->acquire();
return *this->surf;
}
// Fills the frame buffer asynchronously.
Status pushVideo();
Status pushOpenGLVideo();
private:
explicit StitchFrameBuffer(std::shared_ptr<PanoSurface> s) : FrameBuffer<Writer, PanoSurface>(s) {}
StitchFrameBuffer(StitchFrameBuffer&&);
};
typedef StitchFrameBuffer<Output::VideoWriter> PanoFrameBuffer;
typedef StitchFrameBuffer<Output::StereoWriter> StereoFrameBuffer;
} // namespace Core
} // namespace VideoStitch