Fawkes API Fawkes Development Version
jpeg_stream_producer.cpp
1
2/***************************************************************************
3 * jpeg_stream_producer.cpp - Image JPEG stream producer
4 *
5 * Created: Thu Feb 06 13:04:53 2014
6 * Copyright 2006-2014 Tim Niemueller [www.niemueller.de]
7 ****************************************************************************/
8
9/* This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Library General Public License for more details.
18 *
19 * Read the full text in the LICENSE.GPL file in the doc directory.
20 */
21
22#include "jpeg_stream_producer.h"
23
24#include <core/threading/mutex.h>
25#include <core/threading/mutex_locker.h>
26#include <core/threading/wait_condition.h>
27#include <fvcams/shmem.h>
28#include <fvutils/color/conversions.h>
29#include <fvutils/compression/jpeg_compressor.h>
30#include <utils/time/wait.h>
31
32#include <cstdlib>
33
34using namespace firevision;
35
36namespace fawkes {
37
38/** @class WebviewJpegStreamProducer::Buffer "jpeg_stream_producer.h"
39 * Image buffer passed to stream subscribers.
40 */
41
42/** Constructor.
43 * @param data data buffer
44 * @param size size in bytes of @p data
45 */
46WebviewJpegStreamProducer::Buffer::Buffer(unsigned char *data, size_t size)
47: data_(data), size_(size)
48{
49}
50
51/** Destructor. */
53{
54 free(data_);
55}
56
57/** @class WebviewJpegStreamProducer::Subscriber "jpeg_stream_producer.h"
58 * JPEG stream subscriber.
59 *
60 * @fn void WebviewJpegStreamProducer::Subscriber::handle_buffer(std::shared_ptr<Buffer> buffer) noexcept = 0
61 * Notification if a new buffer is available.
62 * @param buffer new buffer
63 */
64
65/** Destructor. */
67{
68}
69
70/** @class WebviewJpegStreamProducer "jpeg_stream_producer.h"
71 * JPEG stream producer.
72 * This class takes an image ID and some parameters and then creates a stream
73 * of JPEG buffers that is either passed to subscribers or can be queried
74 * using the wait_for_next_frame() method.
75 * @author Tim Niemueller
76 */
77
78/** Constructor.
79 * @param image_id ID of the shared memory image buffer to get the input image from
80 * @param quality JPEG quality value, depends on used compressor (system default)
81 * @param fps frames per second to achieve
82 * @param vflip true to enable vertical flipping, false to disable
83 */
85 unsigned int quality,
86 float fps,
87 bool vflip)
88: Thread("WebviewJpegStreamProducer", Thread::OPMODE_WAITFORWAKEUP)
89{
92 set_name("WebviewJpegStreamProducer[%s]", image_id.c_str());
93
94 last_buf_mutex_ = new Mutex();
95 last_buf_waitcond_ = new WaitCondition(last_buf_mutex_);
96
97 quality_ = quality;
98 image_id_ = image_id;
99 fps_ = fps;
100 vflip_ = vflip;
101}
102
103/** Destructor. */
105{
106 delete last_buf_mutex_;
107 delete last_buf_waitcond_;
108}
109
110/** Add a subscriber.
111 * @param subscriber subscriber to add, must be valid until removed or as long
112 * as this instance is valid.
113 */
114void
116{
117 subs_.lock();
118 subs_.push_back(subscriber);
119 subs_.sort();
120 subs_.unique();
121 subs_.unlock();
122 wakeup();
123}
124
125/** Remove a subscriber.
126 * @param subscriber subscriber to remove
127 */
128void
130{
131 subs_.lock();
132 subs_.remove(subscriber);
133 subs_.unlock();
134}
135
136/** Blocks caller until new thread is available.
137 * @return newest available buffer once it becomes available
138 */
139std::shared_ptr<WebviewJpegStreamProducer::Buffer>
141{
142 MutexLocker lock(last_buf_mutex_);
143 wakeup();
144 while (!last_buf_) {
145 last_buf_waitcond_->wait();
146 }
147 return last_buf_;
148}
149
150void
152{
153 cam_ = new SharedMemoryCamera(image_id_.c_str(), /* deep copy */ false);
154 jpeg_ = new JpegImageCompressor(quality_);
155 jpeg_->set_image_dimensions(cam_->pixel_width(), cam_->pixel_height());
156 jpeg_->set_compression_destination(ImageCompressor::COMP_DEST_MEM);
157 if (jpeg_->supports_vflip())
158 jpeg_->set_vflip(vflip_);
159
160 in_buffer_ = malloc_buffer(YUV422_PLANAR, cam_->pixel_width(), cam_->pixel_height());
161 jpeg_->set_image_buffer(YUV422_PLANAR, in_buffer_);
162
163 long int loop_time = (long int)roundf((1. / fps_) * 1000000.);
164 timewait_ = new TimeWait(clock, loop_time);
165}
166
167void
169{
170 last_buf_mutex_->lock();
171 last_buf_.reset();
172 last_buf_mutex_->unlock();
173
174 timewait_->mark_start();
175
176 size_t size = jpeg_->recommended_compressed_buffer_size();
177 unsigned char *buffer = (unsigned char *)malloc(size);
178 jpeg_->set_destination_buffer(buffer, size);
179
180 cam_->lock_for_read();
181 cam_->capture();
182 firevision::convert(cam_->colorspace(),
183 YUV422_PLANAR,
184 cam_->buffer(),
185 in_buffer_,
186 cam_->pixel_width(),
187 cam_->pixel_height());
188 jpeg_->compress();
189 cam_->dispose_buffer();
190 cam_->unlock();
191
192 std::shared_ptr<Buffer> shared_buf = std::make_shared<Buffer>(buffer, jpeg_->compressed_size());
193 subs_.lock();
194#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) > 40600
195 for (auto &s : subs_) {
196#else
198 for (si = subs_.begin(); si != subs_.end(); ++si) {
199 Subscriber *s = *si;
200#endif
201 s->handle_buffer(shared_buf);
202 }
203 bool go_on = !subs_.empty();
204 subs_.unlock();
205
206 last_buf_mutex_->lock();
207 last_buf_ = shared_buf;
208 last_buf_waitcond_->wake_all();
209 last_buf_mutex_->unlock();
210
211 if (go_on) {
212 timewait_->wait_systime();
213 wakeup();
214 }
215}
216
217void
219{
220 delete jpeg_;
221 delete cam_;
222 delete timewait_;
223 free(in_buffer_);
224}
225
226} // end namespace fawkes
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:42
List with a lock.
Definition: lock_list.h:45
Mutex locking helper.
Definition: mutex_locker.h:34
Mutex mutual exclusion lock.
Definition: mutex.h:33
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
Thread class encapsulation of pthreads.
Definition: thread.h:46
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
Definition: thread.cpp:716
void set_name(const char *format,...)
Set name of thread.
Definition: thread.cpp:748
void wakeup()
Wake up thread.
Definition: thread.cpp:995
@ OPMODE_WAITFORWAKEUP
operate in wait-for-wakeup mode
Definition: thread.h:58
void set_coalesce_wakeups(bool coalesce=true)
Set wakeup coalescing.
Definition: thread.cpp:729
Time wait utility.
Definition: wait.h:33
void mark_start()
Mark start of loop.
Definition: wait.cpp:68
void wait_systime()
Wait until minimum loop time has been reached in real time.
Definition: wait.cpp:96
Wait until a given condition holds.
void wait()
Wait for the condition forever.
void wake_all()
Wake up all waiting threads.
Buffer(unsigned char *data, size_t size)
Constructor.
virtual void handle_buffer(std::shared_ptr< Buffer > buffer)=0
Notification if a new buffer is available.
void add_subscriber(Subscriber *subscriber)
Add a subscriber.
virtual void loop()
Code to execute in the thread.
std::shared_ptr< Buffer > wait_for_next_frame()
Blocks caller until new thread is available.
virtual void finalize()
Finalize the thread.
virtual void init()
Initialize the thread.
void remove_subscriber(Subscriber *subscriber)
Remove a subscriber.
WebviewJpegStreamProducer(const std::string &image_id, unsigned int quality, float fps, bool vflip)
Constructor.
Jpeg image compressor.
virtual void compress()
Compress image.
virtual size_t compressed_size()
Get compressed size.
virtual bool supports_vflip()
Check if image compressor can do vflip during compress.
virtual size_t recommended_compressed_buffer_size()
Get the recommended size for the compressed buffer.
virtual void set_image_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer to compress.
virtual void set_compression_destination(ImageCompressor::CompressionDestination cd)
Set compression destination.
virtual void set_destination_buffer(unsigned char *buf, unsigned int buf_size)
Set destination buffer (if compressing to memory).
virtual void set_vflip(bool enable)
Enable or disable vflipping.
virtual void set_image_dimensions(unsigned int width, unsigned int height)
Set dimensions of image to compress.
Shared memory camera.
Definition: shmem.h:36
virtual unsigned int pixel_width()
Width of image in pixels.
Definition: shmem.cpp:193
virtual void lock_for_read()
Lock image for reading.
Definition: shmem.cpp:246
virtual colorspace_t colorspace()
Colorspace of returned image.
Definition: shmem.cpp:205
virtual void dispose_buffer()
Dispose current buffer.
Definition: shmem.cpp:188
virtual void unlock()
Unlock buffer.
Definition: shmem.cpp:280
virtual void capture()
Capture an image.
Definition: shmem.cpp:153
virtual unsigned char * buffer()
Get access to current image buffer.
Definition: shmem.cpp:165
virtual unsigned int pixel_height()
Height of image in pixels.
Definition: shmem.cpp:199
Fawkes library namespace.