Fawkes API Fawkes Development Version
image-rest-api.cpp
1
2/***************************************************************************
3 * image-rest-api.cpp - Image REST API
4 *
5 * Created: Sat Apr 07 23:06:51 2018
6 * Copyright 2006-2018 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 "image-rest-api.h"
23
24#include "jpeg_stream_producer.h"
25#include "mjpeg_reply.h"
26
27#include <fvutils/ipc/shm_image.h>
28#include <webview/rest_api_manager.h>
29
30using namespace fawkes;
31using namespace firevision;
32
33/** @class ImageRestApi "skiller-rest-api.h"
34 * REST API backend for the image.
35 * @author Tim Niemueller
36 */
37
38/** Constructor. */
39ImageRestApi::ImageRestApi() : Thread("ImageRestApi", Thread::OPMODE_WAITFORWAKEUP)
40{
41}
42
43/** Destructor. */
45{
46}
47
48void
50{
51 rest_api_ = new WebviewRestApi("images", logger);
53 WebRequest::METHOD_GET, "/?", std::bind(&ImageRestApi::cb_list_images, this));
54 rest_api_->add_handler(WebRequest::METHOD_GET,
55 "/{id+}",
56 std::bind(&ImageRestApi::cb_get_image, this, std::placeholders::_1));
58}
59
60void
62{
64 delete rest_api_;
65 for (auto &s : streams_) {
66 thread_collector->remove(&*s.second);
67 }
68 streams_.clear();
69}
70
71void
73{
74}
75
77ImageRestApi::cb_list_images()
78{
80
81 std::list<SharedMemoryImageBufferMetaData> meta_data = SharedMemoryImageBuffer::list_meta_data();
82
83 for (auto &m : meta_data) {
84 ImageInfo image;
85 image.set_kind("ImageInfo");
87 image.set_id(m.image_id);
88 image.set_colorspace(colorspace_to_string(m.colorspace));
89 image.set_frame(m.frame_id);
90 image.set_width(m.width);
91 image.set_height(m.height);
92 image.set_mem_size(m.mem_size);
93 rv.push_back(std::move(image));
94 }
95
96 return rv;
97}
98
99std::shared_ptr<fawkes::WebviewJpegStreamProducer>
100ImageRestApi::get_stream(const std::string &image_id)
101{
102 if (streams_.find(image_id) == streams_.end()) {
103 try {
104 std::string cfg_prefix = "/webview/images/" + image_id + "/";
105 unsigned int quality = 80;
106 float fps = 15;
107 bool vflip = false;
108 // Read default values if set
109 try {
110 quality = config->get_uint("/webview/images/default/jpeg-quality");
111 } catch (Exception &e) {
112 } // ignored, use default
113 try {
114 fps = config->get_float("/webview/images/default/mjpeg-fps");
115 } catch (Exception &e) {
116 } // ignored, use default
117 try {
118 vflip = config->get_bool("/webview/images/default/jpeg-vflip");
119 } catch (Exception &e) {
120 } // ignored, use default
121 // Set camera-specific values
122 try {
123 quality = config->get_uint((cfg_prefix + "jpeg-quality").c_str());
124 } catch (Exception &e) {
125 } // ignored, use default
126 try {
127 fps = config->get_float((cfg_prefix + "mjpeg-fps").c_str());
128 } catch (Exception &e) {
129 } // ignored, use default
130 try {
131 vflip = config->get_bool((cfg_prefix + "jpeg-vflip").c_str());
132 } catch (Exception &e) {
133 } // ignored, use default
134
135 auto stream = std::make_shared<WebviewJpegStreamProducer>(image_id, quality, fps, vflip);
136
137 thread_collector->add(&*stream);
138
139 streams_[image_id] = stream;
140 } catch (Exception &e) {
141 logger->log_warn("ImageRestApi",
142 "Failed to open buffer '%s',"
143 " exception follows",
144 image_id.c_str());
145 logger->log_warn("ImageRestApi", e);
146 return NULL;
147 }
148 }
149
150 return streams_[image_id];
151}
152
153std::unique_ptr<WebReply>
154ImageRestApi::cb_get_image(WebviewRestParams &params)
155{
156 std::string image = params.path_arg("id");
157
158 std::string::size_type last_dot = image.rfind(".");
159 if (last_dot == std::string::npos) {
160 return std::make_unique<StaticWebReply>(WebReply::HTTP_NOT_FOUND, "Invalid stream ID");
161 }
162 std::string image_id = image.substr(0, last_dot);
163 std::string image_type = image.substr(last_dot + 1);
164
165 std::shared_ptr<WebviewJpegStreamProducer> stream = get_stream(image_id);
166 if (!stream) {
167 return std::make_unique<StaticWebReply>(WebReply::HTTP_NOT_FOUND, "Stream not found");
168 }
169
170 if (image_type == "jpeg" || image_type == "jpg") {
171 std::shared_ptr<WebviewJpegStreamProducer::Buffer> buf = stream->wait_for_next_frame();
172
173 //logger_->log_debug("WebImageReqProc", "Compressed buffer size: %zu", buf->size());
174 std::string body((char *)buf->data(), buf->size());
175 auto reply = std::make_unique<StaticWebReply>(WebReply::HTTP_OK, body);
176 reply->add_header("Content-type", "image/jpeg");
177 reply->set_caching(false);
178 return reply;
179 } else if (image_type == "mjpeg" || image_type == "mjpg") {
180 return std::make_unique<DynamicMJPEGStreamWebReply>(stream);
181 } else {
182 return std::make_unique<StaticWebReply>(WebReply::HTTP_NOT_FOUND, "Unknown image format");
183 }
184}
ImageInfo representation for JSON transfer.
Definition: ImageInfo.h:28
void set_colorspace(const std::string &colorspace)
Set colorspace value.
Definition: ImageInfo.h:152
void set_kind(const std::string &kind)
Set kind value.
Definition: ImageInfo.h:101
void set_frame(const std::string &frame)
Set frame value.
Definition: ImageInfo.h:169
void set_height(const int64_t &height)
Set height value.
Definition: ImageInfo.h:203
void set_width(const int64_t &width)
Set width value.
Definition: ImageInfo.h:186
void set_mem_size(const int64_t &mem_size)
Set mem_size value.
Definition: ImageInfo.h:220
void set_id(const std::string &id)
Set id value.
Definition: ImageInfo.h:135
void set_apiVersion(const std::string &apiVersion)
Set apiVersion value.
Definition: ImageInfo.h:118
static std::string api_version()
Get version of implemented API.
Definition: ImageInfo.h:48
virtual void loop()
Code to execute in the thread.
virtual void init()
Initialize the thread.
~ImageRestApi()
Destructor.
ImageRestApi()
Constructor.
virtual void finalize()
Finalize the thread.
Container to return array via REST.
Definition: rest_array.h:36
void push_back(M &m)
Add item at the back of the container.
Definition: rest_array.h:123
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
virtual float get_float(const char *path)=0
Get value from configuration which is of type float.
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
virtual void add(ThreadList &tl)=0
Add multiple threads.
virtual void remove(ThreadList &tl)=0
Remove multiple threads.
ThreadCollector * thread_collector
Thread collector.
Thread class encapsulation of pthreads.
Definition: thread.h:46
WebviewRestApiManager * webview_rest_api_manager
Webview REST API manager.
Definition: webview.h:55
void unregister_api(WebviewRestApi *api)
Remove a request processor.
void register_api(WebviewRestApi *api)
Add a REST API.
Webview REST API component.
Definition: rest_api.h:221
void add_handler(WebRequest::Method method, std::string path, Handler handler)
Add handler function.
Definition: rest_api.cpp:85
REST parameters to pass to handlers.
Definition: rest_api.h:125
std::string path_arg(const std::string &what)
Get a path argument.
Definition: rest_api.h:142
Fawkes library namespace.