blob: 47e08563f1f0bab72b607730f92ac6bd35b314d0 [file] [log] [blame]
Parker Schuh90641112017-02-25 12:18:36 -08001#include "aos/vision/debug/debug_framework.h"
2
3#include <gtk/gtk.h>
4
John Park33858a32018-09-28 23:05:48 -07005#include "aos/logging/implementations.h"
6#include "aos/logging/logging.h"
Parker Schuh90641112017-02-25 12:18:36 -08007#include "aos/vision/blob/find_blob.h"
8#include "aos/vision/blob/stream_view.h"
Parker Schuh90641112017-02-25 12:18:36 -08009#include "aos/vision/events/epoll_events.h"
10#include "aos/vision/image/jpeg_routines.h"
11
12namespace aos {
13namespace vision {
14
Parker Schuhcd258b82017-04-09 16:28:29 -070015// Detect screen height on smaller monitors.
16int GetScreenHeight() {
17 fprintf(stderr, "gtk version_info: %d.%d.%d\n", gtk_get_major_version(),
18 gtk_get_minor_version(), gtk_get_micro_version());
19
20 GdkScreen *screen = gdk_screen_get_default();
21 GdkRectangle dimensions;
22// Deprecated in newer versions of GTK and missing from older versions.
23#if GTK_CHECK_VERSION(3, 22, 7)
24 GdkDisplay *display = gdk_screen_get_display(screen);
25 GdkMonitor *monitor = gdk_display_get_primary_monitor(display);
26 gdk_monitor_get_geometry(monitor, &dimensions);
27#else
28 dimensions.height = gdk_screen_get_height(screen);
29 dimensions.width = gdk_screen_get_width(screen);
30#endif
31 fprintf(stdout, "Monitor dimensions: %dx%d\n", dimensions.width,
32 dimensions.height);
33 return dimensions.height;
34}
35
Parker Schuh90641112017-02-25 12:18:36 -080036bool DecodeJpeg(aos::vision::DataRef data,
37 aos::vision::BlobStreamViewer *view) {
38 auto fmt = aos::vision::GetFmt(data);
39 auto value = view->img();
40 if (!value.fmt().Equals(fmt)) {
41 view->SetFormatAndClear(fmt);
42 }
43 return aos::vision::ProcessJpeg(data, view->img().data());
44}
45
46class DebugFramework : public DebugFrameworkInterface {
47 public:
Parker Schuhcd258b82017-04-09 16:28:29 -070048 explicit DebugFramework(FilterHarness *filter, CameraParams camera_params)
49 : camera_params_(camera_params), filter_(filter) {
Parker Schuh90641112017-02-25 12:18:36 -080050 view_.key_press_event = [this](uint32_t keyval) {
51 for (const auto &event : key_press_events()) {
52 event(keyval);
53 }
54 };
55 filter->InstallViewer(&view_);
Parker Schuhcd258b82017-04-09 16:28:29 -070056 auto key_press = filter->RegisterKeyPress();
57 if (key_press) {
58 InstallKeyPress(key_press);
59 }
60 if (GetScreenHeight() < 1024) {
Parker Schuh02f13f62019-02-16 16:42:41 -080061 view_.SetScale(1.0);
Parker Schuhcd258b82017-04-09 16:28:29 -070062 }
Alex Perry5b1e8e32019-04-07 13:25:31 -070063
64 // Pass along the set exposure so that users can acceess it.
65 filter->InstallSetExposure([this](uint32_t abs_exp) {
66 this->SetExposure(abs_exp);
67 });
Parker Schuh90641112017-02-25 12:18:36 -080068 }
69
70 // This the first stage in the pipeline that takes
Parker Schuhcd258b82017-04-09 16:28:29 -070071 bool NewJpeg(DataRef data) override {
Parker Schuh90641112017-02-25 12:18:36 -080072 DecodeJpeg(data, &view_);
73
74 auto fmt = view_.img().fmt();
Parker Schuhcd258b82017-04-09 16:28:29 -070075 return HandleBlobs(FindBlobs(filter_->Threshold(view_.img())), fmt);
Parker Schuh90641112017-02-25 12:18:36 -080076 }
77
Parker Schuh02f13f62019-02-16 16:42:41 -080078 bool NewImage(ImageFormat fmt,
79 const std::function<bool(ImagePtr data)> &process) override {
80 auto value = view_.img();
81 if (!value.fmt().Equals(fmt)) {
82 view_.SetFormatAndClear(fmt);
83 }
84 process(view_.img());
85
86 return HandleBlobs(FindBlobs(filter_->Threshold(view_.img())), fmt);
87 }
88
Parker Schuhcd258b82017-04-09 16:28:29 -070089 bool NewBlobList(BlobList blob_list, ImageFormat fmt) override {
Parker Schuh90641112017-02-25 12:18:36 -080090 view_.SetFormatAndClear(fmt);
91
Parker Schuhcd258b82017-04-09 16:28:29 -070092 return HandleBlobs(std::move(blob_list), fmt);
Parker Schuh90641112017-02-25 12:18:36 -080093 }
94
Parker Schuhcd258b82017-04-09 16:28:29 -070095 bool JustCheckForTarget(BlobList blob_list, ImageFormat fmt) override {
96 return filter_->JustCheckForTarget(std::move(blob_list), fmt);
97 }
98
99 bool HandleBlobs(BlobList blob_list, ImageFormat fmt) {
100 bool result = filter_->HandleBlobs(std::move(blob_list), fmt);
Parker Schuh90641112017-02-25 12:18:36 -0800101 view_.Redraw();
Parker Schuhcd258b82017-04-09 16:28:29 -0700102 return result;
Parker Schuh90641112017-02-25 12:18:36 -0800103 }
104
105 aos::events::EpollLoop *Loop() override { return &loop_; }
106
Parker Schuhcd258b82017-04-09 16:28:29 -0700107 const CameraParams &camera_params() override { return camera_params_; }
108
109 BlobStreamViewer *viewer() override { return &view_; }
110
Parker Schuh90641112017-02-25 12:18:36 -0800111 private:
Parker Schuhcd258b82017-04-09 16:28:29 -0700112 CameraParams camera_params_;
Parker Schuh90641112017-02-25 12:18:36 -0800113 FilterHarness *filter_;
114 BlobStreamViewer view_;
115
116 aos::events::EpollLoop loop_;
117};
118
119std::unique_ptr<ImageSource> MakeImageSource(
120 const std::string &image_source_string,
121 DebugFrameworkInterface *interface) {
122 (void)interface;
123 // Each of the image_source strings is of the form format_type:format_spec
124 auto it = image_source_string.find(':');
125 if (it == std::string::npos) {
126 fprintf(stderr, "invalid ImageSource: %s.\n", image_source_string.c_str());
127 exit(-1);
128 }
129 auto image_source_type = image_source_string.substr(0, it);
130 // Get std::function<std::unique_ptr<ImageSource>()> from the registration
131 // factory.
132 const auto &factory = ImageSourceGlobalFactory::Get(image_source_type);
133 if (!factory) {
134 fprintf(stderr, "invalid ImageSource: %s.\n", image_source_string.c_str());
135 exit(-1);
136 }
137 auto result = factory();
138 // Construct the image source.
139 result->Init(image_source_string.substr(it + 1), interface);
140 return result;
141}
142
143const char *kHelpMessage = R"(
144
145image_source is parsed out and selects where to get the images
146from. Each source type has a different configuration format string listed
147below. The colon separates the source specifier and the source config
148parameter. A single command line argument help will print this message.
149)";
150
Parker Schuhcd258b82017-04-09 16:28:29 -0700151void DebugFrameworkMain(int argc, char **argv, FilterHarness *filter,
152 CameraParams camera_params) {
Parker Schuh90641112017-02-25 12:18:36 -0800153 ::aos::logging::Init();
Tyler Chatow4b471e12020-01-05 20:19:36 -0800154 ::aos::logging::SetImplementation(
Parker Schuh90641112017-02-25 12:18:36 -0800155 new ::aos::logging::StreamLogImplementation(stdout));
156
157 gtk_init(&argc, &argv);
158
159 // Use fprintf because it is only supposed to be used interactively.
160 // This uses a registration system to pick out the individual file type
161 // registered by REGISTER_IMAGE_SOURCE.
162 // see jpeg_list-source.cc for ane sample of this.
163 if (argc < 2 || argv[1] == std::string("help")) {
164 fprintf(stderr, "Usage %s image_source:format_spec\n", argv[0]);
165 fprintf(stderr, "%s", kHelpMessage);
166 // Iterate through all registered entities in ImageSourceGlobalFactory
167 // and print out their individual help messages.
168 for (const auto &type : ImageSourceGlobalFactory::GetAll()) {
169 fprintf(stderr, " %s:\n", type.first.c_str());
170 fprintf(stderr, "%s", type.second()->GetHelpMessage());
171 }
172 exit(-1);
173 }
174
Parker Schuhcd258b82017-04-09 16:28:29 -0700175 DebugFramework replay(filter, camera_params);
Parker Schuh90641112017-02-25 12:18:36 -0800176
177 std::unique_ptr<ImageSource> image_source = MakeImageSource(argv[1], &replay);
178
179 replay.Loop()->RunWithGtkMain();
180}
181
182} // namespace vision
183} // namespace aos