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 
30 using namespace fawkes;
31 using 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. */
39 ImageRestApi::ImageRestApi() : Thread("ImageRestApi", Thread::OPMODE_WAITFORWAKEUP)
40 {
41 }
42 
43 /** Destructor. */
45 {
46 }
47 
48 void
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 
60 void
62 {
64  delete rest_api_;
65  for (auto &s : streams_) {
66  thread_collector->remove(&*s.second);
67  }
68  streams_.clear();
69 }
70 
71 void
73 {
74 }
75 
77 ImageRestApi::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 
99 std::shared_ptr<fawkes::WebviewJpegStreamProducer>
100 ImageRestApi::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 
153 std::unique_ptr<WebReply>
154 ImageRestApi::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 }
fawkes::WebviewJpegStreamProducer::wait_for_next_frame
std::shared_ptr< Buffer > wait_for_next_frame()
Blocks caller until new thread is available.
Definition: jpeg_stream_producer.cpp:140
fawkes::ThreadCollector::remove
virtual void remove(ThreadList &tl)=0
Remove multiple threads.
WebviewRestArray::push_back
void push_back(M &m)
Add item at the back of the container.
Definition: rest_array.h:123
fawkes::WebviewRestApiManager::unregister_api
void unregister_api(WebviewRestApi *api)
Remove a request processor.
Definition: rest_api_manager.cpp:67
ImageRestApi::finalize
virtual void finalize()
Finalize the thread.
Definition: image-rest-api.cpp:61
fawkes::Configuration::get_bool
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
fawkes::WebviewRestApiManager::register_api
void register_api(WebviewRestApi *api)
Add a REST API.
Definition: rest_api_manager.cpp:54
fawkes::ThreadCollector::add
virtual void add(ThreadList &tl)=0
Add multiple threads.
ImageRestApi::~ImageRestApi
~ImageRestApi()
Destructor.
Definition: image-rest-api.cpp:44
ImageInfo::set_id
void set_id(const std::string &id)
Set id value.
Definition: ImageInfo.h:135
ImageRestApi::init
virtual void init()
Initialize the thread.
Definition: image-rest-api.cpp:49
ImageRestApi::ImageRestApi
ImageRestApi()
Constructor.
Definition: image-rest-api.cpp:39
fawkes::WebviewJpegStreamProducer::Buffer::data
const unsigned char * data() const
Get data buffer.
Definition: jpeg_stream_producer.h:55
fawkes::LoggingAspect::logger
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
ImageInfo::set_height
void set_height(const int64_t &height)
Set height value.
Definition: ImageInfo.h:203
fawkes::ThreadProducerAspect::thread_collector
ThreadCollector * thread_collector
Thread collector.
Definition: thread_producer.h:41
fawkes
Fawkes library namespace.
fawkes::WebviewAspect::webview_rest_api_manager
WebviewRestApiManager * webview_rest_api_manager
Webview REST API manager.
Definition: webview.h:55
ImageInfo::set_apiVersion
void set_apiVersion(const std::string &apiVersion)
Set apiVersion value.
Definition: ImageInfo.h:118
fawkes::Logger::log_warn
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
WebviewRestArray
Container to return array via REST.
Definition: rest_array.h:36
ImageRestApi::loop
virtual void loop()
Code to execute in the thread.
Definition: image-rest-api.cpp:72
fawkes::ConfigurableAspect::config
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
fawkes::WebviewRestParams
REST parameters to pass to handlers.
Definition: rest_api.h:125
ImageInfo::set_frame
void set_frame(const std::string &frame)
Set frame value.
Definition: ImageInfo.h:169
ImageInfo::set_kind
void set_kind(const std::string &kind)
Set kind value.
Definition: ImageInfo.h:101
fawkes::WebviewRestApi
Webview REST API component.
Definition: rest_api.h:221
fawkes::Configuration::get_float
virtual float get_float(const char *path)=0
Get value from configuration which is of type float.
fawkes::Thread
Thread class encapsulation of pthreads.
Definition: thread.h:46
fawkes::WebviewRestParams::path_arg
std::string path_arg(const std::string &what)
Get a path argument.
Definition: rest_api.h:142
ImageInfo::set_width
void set_width(const int64_t &width)
Set width value.
Definition: ImageInfo.h:186
fawkes::Configuration::get_uint
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
fawkes::WebviewJpegStreamProducer::Buffer::size
size_t size() const
Get buffer size.
Definition: jpeg_stream_producer.h:63
ImageInfo::set_colorspace
void set_colorspace(const std::string &colorspace)
Set colorspace value.
Definition: ImageInfo.h:152
ImageInfo
ImageInfo representation for JSON transfer.
Definition: ImageInfo.h:28
ImageInfo::set_mem_size
void set_mem_size(const int64_t &mem_size)
Set mem_size value.
Definition: ImageInfo.h:220
fawkes::WebviewRestApi::add_handler
void add_handler(WebRequest::Method method, std::string path, Handler handler)
Add handler function.
Definition: rest_api.cpp:85
ImageInfo::api_version
static std::string api_version()
Get version of implemented API.
Definition: ImageInfo.h:48
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36