hdr-merge.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2020 Intel Corporation. All Rights Reserved.
3 
4 #include "hdr-merge.h"
5 
6 namespace librealsense
7 {
9  : generic_processing_block("HDR Merge"),
10  _previous_depth_frame_counter(0),
11  _frames_without_requested_metadata_counter(0)
12  {}
13 
14  // processing only framesets
16  {
17  if (!frame)
18  return false;
19 
20  auto set = frame.as<rs2::frameset>();
21  if (!set)
22  return false;
23 
24  auto depth_frame = set.get_depth_frame();
25  if (!depth_frame)
26  return false;
27 
29 
32  {
33  // warning message will be sent to user if more than NUMBER_OF_FRAMES_WITHOUT_METADATA_FOR_WARNING
34  // frames are received without the needed metadata params
36  {
38  LOG_WARNING("HDR Merge filter cannot process frames because relevant metadata params are missing");
39  }
40 
41  return false;
42  }
43 
45  if (depth_seq_size != 2)
46  return false;
47 
48  return true;
49  }
50 
52  {
53  auto depth_frame_counter = depth_frame.get_frame_number();
54 
55  if (depth_frame_counter < _previous_depth_frame_counter)
57 
58  _previous_depth_frame_counter = depth_frame_counter;
59  }
60 
61 
63  {
64  // steps:
65  // 1. get depth frame from incoming frameset
66  // 2. add the frameset to vector of framesets
67  // 3. check if size of this vector is at least 2 (if not - return latest merge frame)
68  // 4. pop out both framesets from the vector
69  // 5. apply merge algo
70  // 6. save merge frame as latest merge frame
71  // 7. return the merge frame
72 
73  // 1. get depth frame from incoming frameset
74  auto fs = f.as<rs2::frameset>();
75  auto depth_frame = fs.get_depth_frame();
76 
77  // 2. add the frameset to vector of framesets
78  auto depth_seq_id = depth_frame.get_frame_metadata(RS2_FRAME_METADATA_SEQUENCE_ID);
79 
80  // condition added to ensure that frames are saved in the right order
81  // to prevent for example the saving of frame with sequence id 1 before
82  // saving frame of sequence id 0
83  // so that the merging with be deterministic - always done with frame n and n+1
84  // with frame n as basis
85  if (_framesets.size() == depth_seq_id)
86  {
87  _framesets[(int)depth_seq_id] = fs;
88  }
89 
90  // discard merged frame if not relevant
92 
93  // 3. check if size of this vector is at least 2 (if not - return latest merge frame)
94  if (_framesets.size() >= 2)
95  {
96  // 4. pop out both framesets from the vector
97  rs2::frameset fs_0 = _framesets[0];
98  rs2::frameset fs_1 = _framesets[1];
99  _framesets.clear();
100 
101  bool use_ir = false;
102  if (check_frames_mergeability(fs_0, fs_1, use_ir))
103  {
104  // 5. apply merge algo
105  rs2::frame new_frame = merging_algorithm(source, fs_0, fs_1, use_ir);
106  if (new_frame)
107  {
108  // 6. save merge frame as latest merge frame
109  _depth_merged_frame = new_frame;
110  }
111  }
112  }
113 
114  // 7. return the merge frame
116  return _depth_merged_frame;
117 
118  return f;
119  }
120 
122  {
124  {
125  // criteria for discarding saved merged_depth_frame:
126  // 1 - frame counter for merged depth is greater than the input frame
127  // 2 - resolution change
129  auto input_frame_counter = f.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER);
130 
131  auto merged_d_profile = _depth_merged_frame.get_profile().as<rs2::video_stream_profile>();
132  auto new_d_profile = f.get_profile().as<rs2::video_stream_profile>();
133 
134  bool restart_pipe_detected = (depth_merged_frame_counter > input_frame_counter);
135  bool resolution_change_detected = (merged_d_profile.width() != new_d_profile.width()) ||
136  (merged_d_profile.height() != new_d_profile.height());
137 
138  if (restart_pipe_detected || resolution_change_detected)
139  {
140  _depth_merged_frame = nullptr;
141  }
142  }
143  }
144 
146  bool& use_ir) const
147  {
148  auto first_depth = first_fs.get_depth_frame();
149  auto second_depth = second_fs.get_depth_frame();
150  auto first_ir = first_fs.get_infrared_frame();
151  auto second_ir = second_fs.get_infrared_frame();
152 
153  auto first_fs_frame_counter = first_depth.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER);
154  auto second_fs_frame_counter = second_depth.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER);
155 
156  // The aim of this checking is that the output merged frame will have frame counter n and
157  // frame counter n and will be created by frames n and n+1
158  if (first_fs_frame_counter + 1 != second_fs_frame_counter)
159  return false;
160  // Depth dimensions must align
161  if ((first_depth.get_height() != second_depth.get_height()) ||
162  (first_depth.get_width() != second_depth.get_width()))
163  return false;
164 
165  use_ir = should_ir_be_used_for_merging(first_depth, first_ir, second_depth, second_ir);
166 
167  return true;
168  }
169 
170  rs2::frame hdr_merge::merging_algorithm(const rs2::frame_source& source, const rs2::frameset first_fs, const rs2::frameset second_fs, const bool use_ir) const
171  {
172  auto first = first_fs;
173  auto second = second_fs;
174 
175  auto first_depth = first.get_depth_frame();
176  auto second_depth = second.get_depth_frame();
177  auto first_ir = first.get_infrared_frame();
178  auto second_ir = second.get_infrared_frame();
179 
180  // new frame allocation
181  auto vf = first_depth.as<rs2::depth_frame>();
182  auto width = vf.get_width();
183  auto height = vf.get_height();
184  auto new_f = source.allocate_video_frame(first_depth.get_profile(), first_depth,
185  vf.get_bytes_per_pixel(), width, height, vf.get_stride_in_bytes(), RS2_EXTENSION_DEPTH_FRAME);
186 
187  if (new_f)
188  {
189  auto ptr = dynamic_cast<librealsense::depth_frame*>((librealsense::frame_interface*)new_f.get());
190  auto orig = dynamic_cast<librealsense::depth_frame*>((librealsense::frame_interface*)first_depth.get());
191 
192  auto d0 = (uint16_t*)first_depth.get_data();
193  auto d1 = (uint16_t*)second_depth.get_data();
194 
195  auto new_data = (uint16_t*)ptr->get_frame_data();
196 
197  ptr->set_sensor(orig->get_sensor());
198 
199  memset(new_data, 0, width * height * sizeof(uint16_t));
200 
201  int width_height_product = width * height;
202 
203  if (use_ir)
204  {
205  if (first_ir.get_profile().format() == RS2_FORMAT_Y8)
206  {
207  merge_frames_using_ir<uint8_t>(new_data, d0, d1, first_ir, second_ir, width_height_product);
208  }
209  else if (first_ir.get_profile().format() == RS2_FORMAT_Y16)
210  {
211  merge_frames_using_ir<uint16_t>(new_data, d0, d1, first_ir, second_ir, width_height_product);
212  }
213  else
214  {
215  merge_frames_using_only_depth(new_data, d0, d1, width_height_product);
216  }
217  }
218  else
219  {
220  merge_frames_using_only_depth(new_data, d0, d1, width_height_product);
221  }
222 
223  return new_f;
224  }
225  return first_fs;
226  }
227 
228  void hdr_merge::merge_frames_using_only_depth(uint16_t* new_data, uint16_t* d0, uint16_t* d1, int width_height_prod) const
229  {
230  for (int i = 0; i < width_height_prod; i++)
231  {
232  if (d0[i])
233  new_data[i] = d0[i];
234  else if (d1[i])
235  new_data[i] = d1[i];
236  else
237  new_data[i] = 0;
238  }
239  }
240 
242  const rs2::depth_frame& second_depth, const rs2::video_frame& second_ir) const
243  {
244  // checking ir frames are not null
245  bool use_ir = (first_ir && second_ir);
246 
247  if (use_ir)
248  {
249  // IR and Depth dimensions must be aligned
250  if ((first_depth.get_height() != first_ir.get_height()) ||
251  (first_depth.get_width() != first_ir.get_width()) ||
252  (second_ir.get_height() != first_ir.get_height()) ||
253  (second_ir.get_width() != first_ir.get_width()))
254  use_ir = false;
255  }
256 
257  // checking frame counter of first depth and ir are the same
258  if (use_ir)
259  {
260  int depth_frame_counter = static_cast<int>(first_depth.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER));
261  int ir_frame_counter = static_cast<int>(first_ir.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER));
262  use_ir = (depth_frame_counter == ir_frame_counter);
263 
264  // checking frame counter of second depth and ir are the same
265  if (use_ir)
266  {
267  depth_frame_counter = static_cast<int>(second_depth.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER));
268  ir_frame_counter = static_cast<int>(second_ir.get_frame_metadata(RS2_FRAME_METADATA_FRAME_COUNTER));
269  use_ir = (depth_frame_counter == ir_frame_counter);
270 
271  // checking sequence id of first depth and ir are the same
272  if (use_ir)
273  {
274  auto depth_seq_id = first_depth.get_frame_metadata(RS2_FRAME_METADATA_SEQUENCE_ID);
275  auto ir_seq_id = first_ir.get_frame_metadata(RS2_FRAME_METADATA_SEQUENCE_ID);
276  use_ir = (depth_seq_id == ir_seq_id);
277 
278  // checking sequence id of second depth and ir are the same
279  if (use_ir)
280  {
281  depth_seq_id = second_depth.get_frame_metadata(RS2_FRAME_METADATA_SEQUENCE_ID);
282  ir_seq_id = second_ir.get_frame_metadata(RS2_FRAME_METADATA_SEQUENCE_ID);
283  use_ir = (depth_seq_id == ir_seq_id);
284 
285  // checking both ir have the same format
286  if (use_ir)
287  {
288  use_ir = (first_ir.get_profile().format() == second_ir.get_profile().format());
289  }
290  }
291  }
292  }
293  }
294 
295  return use_ir;
296  }
297 }
bool supports_frame_metadata(const rs2_frame_metadata_value &frame_metadata) const override
Definition: archive.cpp:250
orig
Definition: rmse.py:46
unsigned long long _previous_depth_frame_counter
Definition: hdr-merge.h:47
rs2_metadata_type get_frame_metadata(rs2_frame_metadata_value frame_metadata) const
Definition: rs_frame.hpp:497
#define LOG_WARNING(...)
Definition: src/types.h:241
stream_profile get_profile() const
Definition: rs_frame.hpp:557
const int NUMBER_OF_FRAMES_WITHOUT_METADATA_FOR_WARNING
Definition: hdr-merge.h:30
unsigned short uint16_t
Definition: stdint.h:79
depth_frame get_depth_frame() const
Definition: rs_frame.hpp:1006
frame allocate_video_frame(const stream_profile &profile, const frame &original, int new_bpp=0, int new_width=0, int new_height=0, int new_stride=0, rs2_extension frame_type=RS2_EXTENSION_VIDEO_FRAME) const
rs2::frame merging_algorithm(const rs2::frame_source &source, const rs2::frameset first_fs, const rs2::frameset second_fs, const bool use_ir) const
Definition: hdr-merge.cpp:170
GLdouble f
bool should_ir_be_used_for_merging(const rs2::depth_frame &first_depth, const rs2::video_frame &first_ir, const rs2::depth_frame &second_depth, const rs2::video_frame &second_ir) const
Definition: hdr-merge.cpp:241
rs2::frame _depth_merged_frame
Definition: hdr-merge.h:50
GLint GLsizei GLsizei height
std::map< int, rs2::frameset > _framesets
Definition: hdr-merge.h:49
GLint first
bool check_frames_mergeability(const rs2::frameset first_fs, const rs2::frameset second_fs, bool &use_ir) const
Definition: hdr-merge.cpp:145
int _frames_without_requested_metadata_counter
Definition: hdr-merge.h:48
rs2_format format() const
Definition: rs_frame.hpp:44
rs2::frame process_frame(const rs2::frame_source &source, const rs2::frame &f) override
Definition: hdr-merge.cpp:62
int get_height() const
Definition: rs_frame.hpp:671
void reset_warning_counter_on_pipe_restart(const rs2::depth_frame &depth_frame)
Definition: hdr-merge.cpp:51
GLsizei GLsizei GLchar * source
video_frame get_infrared_frame(const size_t index=0) const
Definition: rs_frame.hpp:1032
int i
void merge_frames_using_only_depth(uint16_t *new_data, uint16_t *d0, uint16_t *d1, int width_height_prod) const
Definition: hdr-merge.cpp:228
const byte * get_frame_data() const override
Definition: archive.cpp:276
unsigned long long get_frame_number() const
Definition: rs_frame.hpp:521
void discard_depth_merged_frame_if_needed(const rs2::frame &f)
Definition: hdr-merge.cpp:121
bool should_process(const rs2::frame &frame) override
Definition: hdr-merge.cpp:15
int get_width() const
Definition: rs_frame.hpp:659
rs2_metadata_type get_frame_metadata(const rs2_frame_metadata_value &frame_metadata) const override
Definition: archive.cpp:216
GLint GLsizei width
T as() const
Definition: rs_frame.hpp:580


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:16