@@ -58,6 +58,20 @@ const char *camera_get_error() {
5858 return errbuf;
5959}
6060
61+ static long timespec_sub (struct timespec *a, struct timespec *b) {
62+ return ((a->tv_sec * 1000000000L ) + a->tv_nsec ) -
63+ ((b->tv_sec * 1000000000L ) + b->tv_nsec );
64+ }
65+
66+ static void timespec_add (struct timespec *a, long nanosecs) {
67+ a->tv_nsec += nanosecs;
68+
69+ while (a->tv_nsec > 1000000000L ) {
70+ a->tv_sec ++;
71+ a->tv_nsec -= 1000000000L ;
72+ }
73+ };
74+
6175// https://github.com/raspberrypi/rpicam-apps/blob/6de1ab6a899df35f929b2a15c0831780bd8e750e/core/dma_heaps.cpp
6276static int create_dma_allocator () {
6377 static const char *heap_positions[] = {
@@ -132,14 +146,17 @@ struct CameraPriv {
132146 const parameters_t *params;
133147 camera_frame_cb frame_cb;
134148 camera_error_cb error_cb;
149+ long secondary_deltat;
135150 std::unique_ptr<CameraManager> camera_manager;
136151 std::shared_ptr<Camera> camera;
137152 Stream *video_stream;
153+ Stream *secondary_stream;
138154 std::vector<std::unique_ptr<Request>> requests;
139155 std::mutex ctrls_mutex;
140156 std::unique_ptr<ControlList> ctrls;
141157 std::vector<std::unique_ptr<FrameBuffer>> frame_buffers;
142158 std::map<FrameBuffer *, uint8_t *> mapped_buffers;
159+ struct timespec last_secondary_frame_time;
143160 bool in_error;
144161};
145162
@@ -194,14 +211,19 @@ bool camera_create(
194211 if (params->mode != NULL ) {
195212 stream_roles.push_back (StreamRole::Raw);
196213 }
214+ if (params->secondary_width != 0 ) {
215+ stream_roles.push_back (StreamRole::Viewfinder);
216+ }
197217
198218 std::unique_ptr<CameraConfiguration> conf = camp->camera ->generateConfiguration (stream_roles);
199219 if (conf == NULL ) {
200220 set_error (" Camera.generateConfiguration() failed" );
201221 return false ;
202222 }
203223
204- StreamConfiguration &video_stream_conf = conf->at (0 );
224+ int cur_stream = 0 ;
225+
226+ StreamConfiguration &video_stream_conf = conf->at (cur_stream++);
205227 video_stream_conf.size = Size (params->width , params->height );
206228 video_stream_conf.pixelFormat = formats::YUV420;
207229 video_stream_conf.bufferCount = params->buffer_count ;
@@ -212,12 +234,19 @@ bool camera_create(
212234 }
213235
214236 if (params->mode != NULL ) {
215- StreamConfiguration &raw_stream_conf = conf->at (1 );
237+ StreamConfiguration &raw_stream_conf = conf->at (cur_stream++ );
216238 raw_stream_conf.size = Size (params->mode ->width , params->mode ->height );
217239 raw_stream_conf.pixelFormat = mode_to_pixel_format (params->mode );
218240 raw_stream_conf.bufferCount = video_stream_conf.bufferCount ;
219241 }
220242
243+ if (params->secondary_width != 0 ) {
244+ StreamConfiguration &secondary_stream_conf = conf->at (cur_stream++);
245+ secondary_stream_conf.size = Size (params->secondary_width , params->secondary_height );
246+ secondary_stream_conf.bufferCount = video_stream_conf.bufferCount ;
247+ secondary_stream_conf.pixelFormat = formats::YUV420;
248+ }
249+
221250 conf->orientation = Orientation::Rotate0;
222251 if (params->h_flip ) {
223252 conf->orientation = conf->orientation * Transform::HFlip;
@@ -240,6 +269,11 @@ bool camera_create(
240269
241270 camp->video_stream = video_stream_conf.stream ();
242271
272+ if (params->secondary_width != 0 ) {
273+ StreamConfiguration &secondary_stream_conf = conf->at (cur_stream - 1 );
274+ camp->secondary_stream = secondary_stream_conf.stream ();
275+ }
276+
243277 for (unsigned int i = 0 ; i < params->buffer_count ; i++) {
244278 std::unique_ptr<Request> request = camp->camera ->createRequest ((uint64_t )camp.get ());
245279 if (request == NULL ) {
@@ -282,8 +316,7 @@ bool camera_create(
282316 camp->frame_buffers .push_back (std::make_unique<FrameBuffer>(plane));
283317 FrameBuffer *fb = camp->frame_buffers .back ().get ();
284318
285- // map buffers of the video stream only
286- if (stream == video_stream_conf.stream ()) {
319+ if (stream == camp->video_stream || stream == camp->secondary_stream ) {
287320 camp->mapped_buffers [fb] = (uint8_t *)mmap (NULL , stream_conf.frameSize , PROT_READ | PROT_WRITE, MAP_SHARED, plane[0 ].fd .get (), 0 );
288321 }
289322
@@ -300,6 +333,8 @@ bool camera_create(
300333 camp->params = params;
301334 camp->frame_cb = frame_cb;
302335 camp->error_cb = error_cb;
336+ camp->secondary_deltat = (long )(1000000000.0 / params->secondary_fps );
337+ clock_gettime (CLOCK_MONOTONIC, &camp->last_secondary_frame_time );
303338 *cam = camp.release ();
304339
305340 return true ;
@@ -328,11 +363,26 @@ static void on_request_complete(Request *request) {
328363
329364 FrameBuffer *buffer = request->buffers ().at (camp->video_stream );
330365
366+ uint8_t *secondary_buffer_mapped = NULL ;
367+ if (camp->secondary_stream != NULL ) {
368+ struct timespec now;
369+ clock_gettime (CLOCK_MONOTONIC, &now);
370+
371+ long diff = timespec_sub (&now, &camp->last_secondary_frame_time );
372+
373+ if (diff >= camp->secondary_deltat ) {
374+ timespec_add (&camp->last_secondary_frame_time , camp->secondary_deltat );
375+ FrameBuffer *secondary_buffer = request->buffers ().at (camp->secondary_stream );
376+ secondary_buffer_mapped = camp->mapped_buffers .at (secondary_buffer);
377+ }
378+ }
379+
331380 camp->frame_cb (
332381 camp->mapped_buffers .at (buffer),
333382 buffer->planes ()[0 ].fd .get (),
334383 buffer_size (buffer->planes ()),
335- buffer->metadata ().timestamp / 1000 );
384+ buffer->metadata ().timestamp / 1000 ,
385+ secondary_buffer_mapped);
336386
337387 request->reuse (Request::ReuseFlag::ReuseBuffers);
338388
@@ -350,6 +400,11 @@ int camera_get_stride(camera_t *cam) {
350400 return camp->video_stream ->configuration ().stride ;
351401}
352402
403+ int camera_get_secondary_stride (camera_t *cam) {
404+ CameraPriv *camp = (CameraPriv *)cam;
405+ return camp->secondary_stream ->configuration ().stride ;
406+ }
407+
353408int camera_get_colorspace (camera_t *cam) {
354409 CameraPriv *camp = (CameraPriv *)cam;
355410 return get_v4l2_colorspace (camp->video_stream ->configuration ().colorSpace );
0 commit comments