CVB++ 15.0
recorder.hpp
1#pragma once
2
3#include <memory>
4
5#include "../global.hpp"
6#include "../exception.hpp"
7#include "../string.hpp"
8#include "../size_2d.hpp"
9
10#include "../image.hpp"
11
12#include "movie2.hpp"
13#include "recording_settings.hpp"
14
15#include "_detail/detail_recording_engine.hpp"
16
17namespace Cvb
18{
19
20 CVB_BEGIN_INLINE_NS
21
22 template <>
23 inline HandleGuard<Movie2::Recorder>::HandleGuard(void *handle) noexcept
24 : HandleGuard<Movie2::Recorder>(handle, [](void *handle) { CVB_CALL_CAPI(ReleaseObject(handle)); })
25 {
26 }
27
28 namespace Movie2
29 {
30
32
66 class Recorder
67 {
68
69 public:
71
78 static RecorderPtr FromHandle(HandleGuard<Recorder> &&guard)
79 {
80 if (!guard.Handle())
81 throw std::runtime_error("handle must not be null");
82
83 return std::unique_ptr<Recorder>(new Recorder(std::move(guard)));
84 }
85
87
96 const RecordingSettings &settings)
97 {
98 return Create(path, size, pixelFormat, Private::RecordingEngine::Create(settings));
99 }
100
103
111 {
112 return Create(path, size, pixelFormat, Private::RecordingEngine::Create(DirectShowSettings()));
113 }
114
116
122 void *Handle() const noexcept
123 {
124 return handle_.Handle();
125 }
126
128
133 void Write(const Image &image, const String &metaData = String())
134 {
135 metaData_ = metaData;
136
137 auto res = CVB_CALL_CAPI(Movie2SetImage(Handle(), image.Handle()));
138 if (res != CExports::CVC_E_OK)
139 Utilities::SystemInfo::ThrowLastError();
140
141 res = CVB_CALL_CAPI(Movie2AddFrame(Handle()));
142 if (res != CExports::CVC_E_OK)
143 Utilities::SystemInfo::ThrowLastError();
144 }
145
146 virtual ~Recorder()
147 {
148 if (Handle())
149 {
150 CExports::Movie2StopRecording(Handle());
151 }
152 }
153
154 Recorder(HandleGuard<Recorder> &&guard) noexcept
155 : handle_(std::move(guard))
156 {
157 }
158
159 private:
160 Recorder(Recorder &&other) noexcept
161 : handle_(std::move(other.handle_))
162 {
163 }
164
165 Recorder(const String &path, Size2D<int> size, RecorderPixelFormat pixelFormat,
166 Private::RecordingEnginePtr engine)
167 : Recorder(std::move(*CreateRecorder(size, pixelFormat, engine)))
168 {
169 // After creating recorder
170 // configure the engine
171 ConfigureEngine(engine);
172 // and start recording
173 Record(path);
174 }
175
176 static std::unique_ptr<Recorder> Create(const String &path, Size2D<int> size, RecorderPixelFormat pixelFormat,
177 Private::RecordingEnginePtr engine)
178 {
179 return std::unique_ptr<Recorder>(new Recorder(path, size, pixelFormat, engine));
180 }
181
182 static RecorderPtr CreateRecorder(Size2D<int> size, RecorderPixelFormat pixelFormat,
183 Private::RecordingEnginePtr engine)
184 {
185 intptr_t dummyBuffer = 0;
186 auto dummyImage =
187 (pixelFormat == RecorderPixelFormat::Mono)
188 ? WrappedImage::FromGreyPixels(&dummyBuffer, size.Width() * size.Height(), size.Width(), size.Height(),
189 DataType::Int8BppUnsigned(), 1, size.Width())
190 : WrappedImage::FromRgbPixels(&dummyBuffer, size.Width() * size.Height() * 3, size.Width(),
191 size.Height(), DataType::Int8BppUnsigned(), 3, size.Width() * 3, 1);
192
193 HandleGuard<Recorder> guard(CExports::CreateMovie2RecorderEx(
194 static_cast<CExports::Movie2_RecordingEngine>(engine->Settings().EngineType()), dummyImage->Handle()));
195 if (!guard.Handle())
196 throw std::runtime_error("failed to create movie recorder");
197
198 return std::make_unique<Recorder>(std::move(guard));
199 }
200
201 void ConfigureEngine(Private::RecordingEnginePtr engine)
202 {
203 engine_ = engine;
204
205 if (engine_->Settings().EngineType() == RecordingEngineType::DirectShow)
206 ConfigureDirectShowEngine();
207 else if (engine_->Settings().EngineType() == RecordingEngineType::RawVideo)
208 ConfigureRawVideoEngine();
209 }
210
211 void ConfigureDirectShowEngine()
212 {
213 auto directShowEngine = std::dynamic_pointer_cast<Private::DirectShowEngine>(engine_);
214 const auto &settings = directShowEngine->Settings();
215
216 CVB_CALL_CAPI(Movie2SetSyncMode(Handle(), CExports::Movie2_SyncAfterCopy));
217 CVB_CALL_CAPI(Movie2SetAcqMode(Handle(), CExports::Movie2_AcqAddFrame));
218 CVB_CALL_CAPI(Movie2SetCompressorIndex(Handle(), static_cast<CExports::cvbval_t>(settings.CodecIndex())));
219 CVB_CALL_CAPI(Movie2SetFrameRate(Handle(), settings.FrameRate()));
220 CVB_CALL_CAPI(Movie2SetUseMetadata(Handle(), (settings.UseMetaData()) ? 1 : 0));
221
222 if (settings.UseMetaData())
223 {
224 Internal::DoResCall([&]() {
225 CExports::pfMovie2ProvideMetaData metaDataCallback = [](CExports::MOVIE2RECORDER, char *szMetaData,
226 CExports::cvbval_t BufferSize, void *pUserData) {
227 if (szMetaData && BufferSize > 0)
228 {
229 auto recorder = reinterpret_cast<Cvb::Movie2::Recorder *>(pUserData);
230 auto metaData = recorder->metaData_;
231
232 std::string metaDataAscii(Internal::CastToAscii(metaData));
233 size_t charsToCopy = std::min(metaData.size(), static_cast<std::size_t>(BufferSize) - 1);
234 std::copy_n(metaDataAscii.begin(), charsToCopy, szMetaData);
235 szMetaData[charsToCopy] = 0;
236 }
237 };
238
239 CExports::cvbval_t dummy = 0;
240 return CVB_CALL_CAPI(Movie2RegisterMetaDataCallback(Handle(), metaDataCallback, this, dummy));
241 });
242 }
243 }
244
245 void ConfigureRawVideoEngine()
246 {
247 const auto &settings = engine_->Settings();
248 CVB_CALL_CAPI(Movie2SetSyncMode(Handle(), CExports::Movie2_SyncAfterCopy));
249 CVB_CALL_CAPI(Movie2SetAcqMode(Handle(), CExports::Movie2_AcqAddFrame));
250 Internal::DoResCall([&]() { return CVB_CALL_CAPI(Movie2SetFrameRate(Handle(), settings.FrameRate())); });
251 }
252
253 void Record(const String &path)
254 {
255 auto res = CExports::Movie2SetTargetFileNameTyped(Handle(), path.c_str());
256 if (res != CExports::CVC_E_OK)
257 Utilities::SystemInfo::ThrowLastError();
258
259 Internal::DoResCall([&]() { return CVB_CALL_CAPI(Movie2StartRecording(Handle())); });
260 }
261
262 private:
263 HandleGuard<Recorder> handle_;
264 Private::RecordingEnginePtr engine_;
265 String metaData_;
266 };
267
268 } // namespace Movie2
269
270 CVB_END_INLINE_NS
271
272} // namespace Cvb
static DataType Int8BppUnsigned() noexcept
Represents 8-bit unsigned integer pixels (bytes).
Definition data_type.hpp:41
The Common Vision Blox image.
Definition decl_image.hpp:50
void * Handle() const noexcept
Classic API image handle.
Definition decl_image.hpp:237
Settings for initializing a direct show engine recorder.
Definition recording_settings.hpp:87
Movie recorder for writing video files to disk.
Definition recorder.hpp:67
static RecorderPtr FromHandle(HandleGuard< Recorder > &&guard)
Creates a recorder from a classic API handle.
Definition recorder.hpp:78
static std::unique_ptr< Recorder > Create(const String &path, Size2D< int > size, RecorderPixelFormat pixelFormat)
Creates a recorder object writing video streams with the given pixel format. Uses the DirectShowEngin...
Definition recorder.hpp:110
static std::unique_ptr< Recorder > Create(const String &path, Size2D< int > size, RecorderPixelFormat pixelFormat, const RecordingSettings &settings)
Creates a recorder object writing video streams with the given pixel format and recording engine.
Definition recorder.hpp:95
void Write(const Image &image, const String &metaData=String())
Writes the given image into the stream.
Definition recorder.hpp:133
void * Handle() const noexcept
Classic API classifier handle.
Definition recorder.hpp:122
Settings for initializing a recorder.
Definition recording_settings.hpp:21
Stores a pair of numbers that represents the width and the height of a subject, typically a rectangle...
Definition size_2d.hpp:20
static std::unique_ptr< WrappedImage > FromRgbPixels(void *buffer, int bufferSize, int width, int height, DataType dataType, int pixelStride, int lineStride, int planeStride)
Wraps, without copying, the given RGB pixel buffer in a CvbImage.
Definition decl_wrapped_image.hpp:81
static std::unique_ptr< WrappedImage > FromGreyPixels(void *buffer, int bufferSize, int width, int height, DataType dataType, int pixelStride, int lineStride)
Wraps, without copying, the given monochrome pixel buffer in an image.
Definition decl_wrapped_image.hpp:46
cvbbool_t ReleaseObject(OBJ &Object)
T move(T... args)
Record movies with classes from this tool.
Definition detail_recording_engine.hpp:15
std::shared_ptr< Recorder > RecorderPtr
Convenience shared pointer for Recorder.
Definition movie2.hpp:18
RecorderPixelFormat
Defines whether the recorder object writes color or mono data.
Definition movie2.hpp:22
@ Mono
Recorder writes single-plane monochrome data.
Definition movie2.hpp:24
@ DirectShow
Use DirectShow framework for recording AVI files.
Definition movie2.hpp:36
@ RawVideo
Use RawVideo for recording raw video.
Definition movie2.hpp:38
Root namespace for the Image Manager interface.
Definition c_bayer_to_rgb.h:17
std::string String
String for wide characters or unicode characters.
Definition string.hpp:49