soft_stitcher.cpp revision 99ccf8e9caaffe4cedfce01df4c3ec0aece0d23a
1/* 2 * soft_stitcher.cpp - soft stitcher implementation 3 * 4 * Copyright (c) 2017 Intel Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Wind Yuan <feng.yuan@intel.com> 19 */ 20 21#include "soft_stitcher.h" 22#include "soft_blender.h" 23#include "soft_geo_mapper.h" 24#include "soft_video_buf_allocator.h" 25#include "interface/feature_match.h" 26#include "surview_fisheye_dewarp.h" 27#include <map> 28 29#define SOFT_STITCHER_ALIGNMENT_X 8 30#define SOFT_STITCHER_ALIGNMENT_Y 4 31 32#define MAP_FACTOR_X 16 33#define MAP_FACTOR_Y 16 34 35#define ENABLE_FEATURE_MATCH 0 36 37#define DUMP_STITCHER 1 38 39namespace XCam { 40 41#if DUMP_STITCHER 42static void 43stitcher_dump_buf (const SmartPtr<VideoBuffer> buf, uint32_t idx, const char *prefix) 44{ 45 XCAM_ASSERT (prefix); 46 char name[256]; 47 snprintf (name, 256, "%s-%d", prefix, idx); 48 dump_buf_perfix_path (buf, name); 49} 50#else 51static void stitcher_dump_buf (...) {} 52#endif 53 54 55namespace SoftSitcherPriv { 56 57DECLARE_HANDLER_CALLBACK (CbGeoMap, SoftStitcher, dewarp_done); 58DECLARE_HANDLER_CALLBACK (CbBlender, SoftStitcher, blender_done); 59 60struct BlenderParam 61 : SoftBlender::BlenderParam 62{ 63 SmartPtr<SoftStitcher::StitcherParam> stitch_param; 64 uint32_t idx; 65 66 BlenderParam ( 67 uint32_t i, 68 const SmartPtr<VideoBuffer> &in0, 69 const SmartPtr<VideoBuffer> &in1, 70 const SmartPtr<VideoBuffer> &out) 71 : SoftBlender::BlenderParam (in0, in1, out) 72 , idx (i) 73 {} 74}; 75 76typedef std::map<void*, SmartPtr<BlenderParam>> BlenderParams; 77typedef std::map<void*, int32_t> BlendCopyTaskNums; 78 79struct HandlerParam 80 : ImageHandler::Parameters 81{ 82 SmartPtr<SoftStitcher::StitcherParam> stitch_param; 83 uint32_t idx; 84 85 HandlerParam (uint32_t i) 86 : idx (i) 87 {} 88}; 89 90struct Factor { 91 float x, y; 92 93 Factor () : x (1.0f), y (1.0f) {} 94 void reset () { 95 x = 1.0f; 96 y = 1.0f; 97 } 98}; 99 100struct Overlap { 101 SmartPtr<FeatureMatch> matcher; 102 SmartPtr<SoftBlender> blender; 103 BlenderParams param_map; 104 105 SmartPtr<BlenderParam> find_blender_param_in_map ( 106 const SmartPtr<SoftStitcher::StitcherParam> &key, 107 const uint32_t idx); 108}; 109 110struct FisheyeDewarp { 111 SmartPtr<SoftGeoMapper> dewarp; 112 SmartPtr<BufferPool> buf_pool; 113 Factor left_factor, right_factor; 114 115 bool set_dewarp_factor (); 116 XCamReturn set_dewarp_geo_table ( 117 SmartPtr<SoftGeoMapper> mapper, 118 const CameraInfo &cam_info, const BowlDataConfig &bowl); 119}; 120 121class StitcherImpl { 122 friend class XCam::SoftStitcher; 123 124public: 125 StitcherImpl (SoftStitcher *handler) 126 : _stitcher (handler) 127 {} 128 129 XCamReturn init_config (uint32_t count); 130 131 bool remove_task_count (const SmartPtr<SoftStitcher::StitcherParam> ¶m); 132 int32_t dec_task_count (const SmartPtr<SoftStitcher::StitcherParam> ¶m); 133 134 XCamReturn start_dewarp_works (const SmartPtr<SoftStitcher::StitcherParam> ¶m); 135 XCamReturn start_task_count (const SmartPtr<SoftStitcher::StitcherParam> ¶m); 136 XCamReturn start_overlap_tasks ( 137 const SmartPtr<SoftStitcher::StitcherParam> ¶m, 138 const uint32_t idx, const SmartPtr<VideoBuffer> &buf); 139 XCamReturn start_copy_tasks ( 140 const SmartPtr<SoftStitcher::StitcherParam> ¶m, 141 const uint32_t idx, const SmartPtr<VideoBuffer> &buf); 142 143 XCamReturn start_single_blender (const uint32_t idx, const SmartPtr<BlenderParam> ¶m); 144 145 XCamReturn fisheye_dewarp_to_table (); 146 XCamReturn feature_match ( 147 const SmartPtr<VideoBuffer> &left_buf, 148 const SmartPtr<VideoBuffer> &right_buf, 149 const uint32_t idx); 150 151private: 152 XCamReturn init_fisheye (uint32_t idx); 153 154private: 155 FisheyeDewarp _fisheye [XCAM_STITCH_MAX_CAMERAS]; 156 Overlap _overlaps [XCAM_STITCH_MAX_CAMERAS]; 157 SmartPtr<BufferPool> _dewarp_pool; 158 159 Mutex _map_mutex; 160 BlendCopyTaskNums _task_counts; 161 162 SoftStitcher *_stitcher; 163}; 164 165bool 166FisheyeDewarp::set_dewarp_factor () 167{ 168 XCAM_FAIL_RETURN ( 169 ERROR, dewarp.ptr (), false, 170 "FisheyeDewarp dewarp handler empty"); 171 172 Factor cur_left_factor, cur_right_factor; 173 Factor unify_factor; 174 dewarp->get_factors (unify_factor.x, unify_factor.y); 175 cur_left_factor = cur_right_factor = unify_factor; 176 if (XCAM_DOUBLE_EQUAL_AROUND(cur_left_factor.x, 0.0f) || 177 XCAM_DOUBLE_EQUAL_AROUND(cur_right_factor.x, 0.0f)) { // not started. 178 return true; 179 } 180 181 cur_left_factor.x *= left_factor.x; 182 cur_left_factor.y *= left_factor.y; 183 cur_right_factor.x *= right_factor.x; 184 cur_right_factor.y *= right_factor.y; 185 unify_factor.x = (cur_left_factor.x + cur_right_factor.x) / 2.0f; 186 unify_factor.y = (cur_left_factor.y + cur_right_factor.y) / 2.0f; 187 dewarp->set_factors (unify_factor.x, unify_factor.y); 188 189 left_factor.reset (); 190 right_factor.reset (); 191 return true; 192} 193 194XCamReturn 195FisheyeDewarp::set_dewarp_geo_table (SmartPtr<SoftGeoMapper> mapper, const CameraInfo &cam_info, const BowlDataConfig &bowl) 196{ 197 PolyFisheyeDewarp fd; 198 fd.set_intrinsic_param (cam_info.calibration.intrinsic); 199 fd.set_extrinsic_param (cam_info.calibration.extrinsic); 200 201 uint32_t table_width, table_height; 202 table_width = cam_info.slice_view.width / MAP_FACTOR_X; 203 table_width = XCAM_ALIGN_UP (table_width, 4); 204 table_height = cam_info.slice_view.height / MAP_FACTOR_Y; 205 table_height = XCAM_ALIGN_UP (table_height, 2); 206 SurViewFisheyeDewarp::MapTable map_table(table_width * table_height * 2); 207 fd.fisheye_dewarp ( 208 map_table, table_width, table_height, 209 cam_info.slice_view.width, cam_info.slice_view.height, bowl); 210 211 std::vector<GeoData> geo_data (table_width * table_height); 212 213 for (uint32_t row = 0; row < table_height; row++) { 214 for(uint32_t col = 0; col < table_width; col++) { 215 GeoData &data = geo_data[row * table_width + col]; 216 data.x = map_table[row * table_width * 2 + col * 2]; 217 data.y = map_table[row * table_width * 2 + col * 2 + 1]; 218 data.z = 0.0f; 219 data.w = 0.0f; 220 } 221 } 222 223 XCAM_FAIL_RETURN ( 224 ERROR, mapper->set_lookup_table (geo_data.data (), table_width, table_height), 225 XCAM_RETURN_ERROR_UNKNOWN, "set fisheye dewarp lookup table failed"); 226 return XCAM_RETURN_NO_ERROR; 227} 228 229XCamReturn 230StitcherImpl::init_fisheye (uint32_t idx) 231{ 232 FisheyeDewarp &fisheye = _fisheye[idx]; 233 SmartPtr<ImageHandler::Callback> dewarp_cb = new CbGeoMap (_stitcher); 234 fisheye.dewarp = new SoftGeoMapper ("sitcher_remapper"); 235 XCAM_ASSERT (fisheye.dewarp.ptr ()); 236 fisheye.dewarp->set_callback (dewarp_cb); 237 238 CameraInfo cam_info; 239 _stitcher->get_camera_info (idx, cam_info); 240 241 VideoBufferInfo buf_info; 242 buf_info.init ( 243 V4L2_PIX_FMT_NV12, cam_info.slice_view.width, cam_info.slice_view.height, 244 XCAM_ALIGN_UP (cam_info.slice_view.width, SOFT_STITCHER_ALIGNMENT_X), 245 XCAM_ALIGN_UP (cam_info.slice_view.height, SOFT_STITCHER_ALIGNMENT_Y)); 246 247 fisheye.buf_pool = new SoftVideoBufAllocator (buf_info); 248 XCAM_ASSERT (fisheye.buf_pool.ptr ()); 249 XCAM_FAIL_RETURN ( 250 ERROR, fisheye.buf_pool->reserve (2), XCAM_RETURN_ERROR_MEM, 251 "stitcher:%s reserve dewarp buffer pool(w:%d,h:%d) failed", 252 XCAM_STR (_stitcher->get_name ()), buf_info.width, buf_info.height); 253 return XCAM_RETURN_NO_ERROR; 254} 255 256XCamReturn 257StitcherImpl::init_config (uint32_t count) 258{ 259 SmartPtr<ImageHandler::Callback> blender_cb = new CbBlender (_stitcher); 260 for (uint32_t i = 0; i < count; ++i) { 261 XCamReturn ret = init_fisheye (i); 262 XCAM_FAIL_RETURN ( 263 ERROR, xcam_ret_is_ok (ret), ret, 264 "stitcher:%s init fisheye failed, idx:%d.", XCAM_STR (_stitcher->get_name ()), i); 265 266#if ENABLE_FEATURE_MATCH 267 _overlaps[i].matcher = new CVCapiFeatureMatch; 268 //_overlaps[i].matcher->set_config (); 269 _overlaps[i].matcher->set_fm_index (i); 270#endif 271 272 _overlaps[i].blender = create_soft_blender ().dynamic_cast_ptr<SoftBlender>(); 273 XCAM_ASSERT (_overlaps[i].blender.ptr ()); 274 _overlaps[i].blender->set_callback (blender_cb); 275 _overlaps[i].param_map.clear (); 276 } 277 278 return XCAM_RETURN_NO_ERROR; 279} 280 281bool 282StitcherImpl::remove_task_count (const SmartPtr<SoftStitcher::StitcherParam> ¶m) 283{ 284 XCAM_ASSERT (param.ptr ()); 285 SmartLock locker (_map_mutex); 286 BlendCopyTaskNums::iterator i = _task_counts.find (param.ptr ()); 287 if (i == _task_counts.end ()) 288 return false; 289 290 _task_counts.erase (i); 291 return true; 292} 293 294int32_t 295StitcherImpl::dec_task_count (const SmartPtr<SoftStitcher::StitcherParam> ¶m) 296{ 297 XCAM_ASSERT (param.ptr ()); 298 SmartLock locker (_map_mutex); 299 BlendCopyTaskNums::iterator i = _task_counts.find (param.ptr ()); 300 if (i == _task_counts.end ()) 301 return -1; 302 303 int32_t &count = i->second; 304 --count; 305 if (count > 0) 306 return count; 307 308 XCAM_ASSERT (count == 0); 309 _task_counts.erase (i); 310 return 0; 311} 312 313XCamReturn 314StitcherImpl::fisheye_dewarp_to_table () 315{ 316 std::vector<GeoData> table; 317 uint32_t camera_num = _stitcher->get_camera_num (); 318 for (uint32_t i = 0; i < camera_num; ++i) { 319 CameraInfo cam_info; 320 _stitcher->get_camera_info (i, cam_info); 321 322 BowlDataConfig bowl = _stitcher->get_bowl_config (); 323 bowl.angle_start = cam_info.slice_view.hori_angle_start; 324 bowl.angle_end = format_angle ( 325 cam_info.slice_view.hori_angle_start + cam_info.slice_view.hori_angle_range); 326 327 uint32_t out_width, out_height; 328 _stitcher->get_output_size (out_width, out_height); 329 330 _fisheye[i].dewarp->set_output_size (cam_info.slice_view.width, cam_info.slice_view.height); 331 if (bowl.angle_end < bowl.angle_start) 332 bowl.angle_start -= 360.0f; 333 XCAM_LOG_INFO ( 334 "soft-stitcher:%s camera(idx:%d) info (angle start:%.2f, range:%.2f), bowl info (angle start%.2f, end:%.2f)", 335 XCAM_STR (_stitcher->get_name ()), i, 336 cam_info.slice_view.hori_angle_start, cam_info.slice_view.hori_angle_range, 337 bowl.angle_start, bowl.angle_end); 338 XCamReturn ret = _fisheye[i].set_dewarp_geo_table (_fisheye[i].dewarp, cam_info, bowl); 339 XCAM_FAIL_RETURN ( 340 ERROR, xcam_ret_is_ok (ret), ret, 341 "stitcher:%s set dewarp geo table failed, idx:%d.", XCAM_STR (_stitcher->get_name ()), i); 342 343 } 344 345 return XCAM_RETURN_NO_ERROR; 346} 347 348XCamReturn 349StitcherImpl::start_dewarp_works (const SmartPtr<SoftStitcher::StitcherParam> ¶m) 350{ 351 uint32_t camera_num = _stitcher->get_camera_num (); 352 for (uint32_t i = 0; i < camera_num; ++i) { 353 SmartPtr<VideoBuffer> out_buf = _fisheye[i].buf_pool->get_buffer (); 354 SmartPtr<HandlerParam> dewarp_params = new HandlerParam (i); 355 dewarp_params->in_buf = param->in_bufs[i]; 356 dewarp_params->out_buf = out_buf; 357 dewarp_params->stitch_param = param; 358 _fisheye[i].set_dewarp_factor (); 359 XCamReturn ret = _fisheye[i].dewarp->execute_buffer (dewarp_params, false); 360 XCAM_FAIL_RETURN ( 361 ERROR, xcam_ret_is_ok (ret), ret, 362 "soft-stitcher:%s fisheye dewarp buffer failed", XCAM_STR (_stitcher->get_name ())); 363 } 364 return XCAM_RETURN_NO_ERROR; 365} 366 367SmartPtr<BlenderParam> 368Overlap::find_blender_param_in_map ( 369 const SmartPtr<SoftStitcher::StitcherParam> &key, 370 const uint32_t idx) 371{ 372 SmartPtr<BlenderParam> param; 373 BlenderParams::iterator i = param_map.find (key.ptr ()); 374 if (i == param_map.end ()) { 375 param = new BlenderParam (idx, NULL, NULL, NULL); 376 XCAM_ASSERT (param.ptr ()); 377 param->stitch_param = key; 378 param_map.insert (std::make_pair ((void*)key.ptr (), param)); 379 } else { 380 param = (*i).second; 381 } 382 383 return param; 384} 385 386XCamReturn 387StitcherImpl::feature_match ( 388 const SmartPtr<VideoBuffer> &left_buf, 389 const SmartPtr<VideoBuffer> &right_buf, 390 const uint32_t idx) 391{ 392 const ImageOverlapInfo overlap_info = _stitcher->get_overlap (idx); 393 Rect left_ovlap = overlap_info.left; 394 Rect right_ovlap = overlap_info.right; 395 const VideoBufferInfo left_buf_info = left_buf->get_video_info (); 396 397 _overlaps[idx].matcher->reset_offsets (); 398 _overlaps[idx].matcher->optical_flow_feature_match ( 399 left_buf, right_buf, left_ovlap, right_ovlap, left_buf_info.width); 400 float left_offsetx = _overlaps[idx].matcher->get_current_left_offset_x (); 401 402 uint32_t left_idx = idx; 403 float center_x = (float) _stitcher->get_center (left_idx).slice_center_x; 404 float feature_center_x = (float)left_ovlap.pos_x + (left_ovlap.width / 2.0f); 405 float range = feature_center_x - center_x; 406 XCAM_ASSERT (range > 1.0f); 407 _fisheye[left_idx].right_factor.x = (range + left_offsetx / 2.0f) / range; 408 _fisheye[left_idx].right_factor.y = 1.0; 409 XCAM_ASSERT (_fisheye[left_idx].right_factor.x > 0.0f && _fisheye[left_idx].right_factor.x < 2.0f); 410 411 uint32_t right_idx = (idx + 1) % _stitcher->get_camera_num (); 412 center_x = (float) _stitcher->get_center (right_idx).slice_center_x; 413 feature_center_x = (float)right_ovlap.pos_x + (right_ovlap.width / 2.0f); 414 range = center_x - feature_center_x; 415 XCAM_ASSERT (range > 1.0f); 416 _fisheye[right_idx].left_factor.x = (range + left_offsetx / 2.0f) / range; 417 _fisheye[right_idx].left_factor.y = 1.0; 418 XCAM_ASSERT (_fisheye[right_idx].left_factor.x > 0.0f && _fisheye[right_idx].left_factor.x < 2.0f); 419 420 return XCAM_RETURN_NO_ERROR; 421} 422 423XCamReturn 424StitcherImpl::start_single_blender ( 425 const uint32_t idx, 426 const SmartPtr<BlenderParam> ¶m) 427{ 428 SmartPtr<SoftBlender> blender = _overlaps[idx].blender; 429 const ImageOverlapInfo &overlap_info = _stitcher->get_overlap (idx); 430 uint32_t out_width, out_height; 431 _stitcher->get_output_size (out_width, out_height); 432 433 blender->set_output_size (out_width, out_height); 434 blender->set_merge_window (overlap_info.out_area); 435 blender->set_input_valid_area (overlap_info.left, 0); 436 blender->set_input_valid_area (overlap_info.right, 1); 437 blender->set_input_merge_area (overlap_info.left, 0); 438 blender->set_input_merge_area (overlap_info.right, 1); 439 return blender->execute_buffer (param, false); 440} 441 442XCamReturn 443StitcherImpl::start_overlap_tasks ( 444 const SmartPtr<SoftStitcher::StitcherParam> ¶m, 445 const uint32_t idx, const SmartPtr<VideoBuffer> &buf) 446{ 447 SmartPtr<BlenderParam> cur_param, prev_param; 448 const uint32_t camera_num = _stitcher->get_camera_num (); 449 uint32_t pre_idx = (idx + camera_num - 1) % camera_num; 450 XCamReturn ret = XCAM_RETURN_NO_ERROR; 451 { 452 SmartPtr<BlenderParam> param_b; 453 454 SmartLock locker (_map_mutex); 455 param_b = _overlaps[idx].find_blender_param_in_map (param, idx); 456 param_b->in_buf = buf; 457 if (param_b->in_buf.ptr () && param_b->in1_buf.ptr ()) { 458 cur_param = param_b; 459 _overlaps[idx].param_map.erase (param.ptr ()); 460 } 461 462 param_b = _overlaps[pre_idx].find_blender_param_in_map (param, idx); 463 param_b->in1_buf = buf; 464 if (param_b->in_buf.ptr () && param_b->in1_buf.ptr ()) { 465 prev_param = param_b; 466 _overlaps[pre_idx].param_map.erase (param.ptr ()); 467 } 468 } 469 470 if (cur_param.ptr ()) { 471 cur_param->out_buf = param->out_buf; 472 ret = start_single_blender (idx, cur_param); 473 XCAM_FAIL_RETURN ( 474 ERROR, xcam_ret_is_ok (ret), ret, 475 "soft-stitcher:%s blend overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), idx); 476 } 477 478 if (prev_param.ptr ()) { 479 prev_param->out_buf = param->out_buf; 480 ret = start_single_blender (pre_idx, prev_param); 481 XCAM_FAIL_RETURN ( 482 ERROR, xcam_ret_is_ok (ret), ret, 483 "soft-stitcher:%s blend overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), pre_idx); 484 } 485 486#if ENABLE_FEATURE_MATCH 487 //start feature match 488 if (cur_param.ptr ()) { 489 ret = feature_match (cur_param->in_buf, cur_param->in1_buf, idx); 490 XCAM_FAIL_RETURN ( 491 ERROR, xcam_ret_is_ok (ret), ret, 492 "soft-stitcher:%s feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), idx); 493 } 494 495 if (prev_param.ptr ()) { 496 ret = feature_match (prev_param->in_buf, prev_param->in1_buf, pre_idx); 497 XCAM_FAIL_RETURN ( 498 ERROR, xcam_ret_is_ok (ret), ret, 499 "soft-stitcher:%s feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), pre_idx); 500 } 501#endif 502 return XCAM_RETURN_NO_ERROR; 503} 504 505XCamReturn 506StitcherImpl::start_copy_tasks ( 507 const SmartPtr<SoftStitcher::StitcherParam> ¶m, 508 const uint32_t idx, const SmartPtr<VideoBuffer> &buf) 509{ 510 //TODO add copy tasks 511 return XCAM_RETURN_NO_ERROR; 512} 513 514}; 515 516SoftStitcher::SoftStitcher (const char *name) 517 : SoftHandler (name) 518 , Stitcher (SOFT_STITCHER_ALIGNMENT_X, SOFT_STITCHER_ALIGNMENT_Y) 519{ 520 _impl = new SoftSitcherPriv::StitcherImpl (this); 521 XCAM_ASSERT (_impl.ptr ()); 522} 523 524SoftStitcher::~SoftStitcher () 525{ 526} 527 528XCamReturn 529SoftStitcher::stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf) 530{ 531 XCAM_FAIL_RETURN ( 532 ERROR, !in_bufs.empty (), XCAM_RETURN_ERROR_PARAM, 533 "soft-stitcher:%s stitch buffer failed, in_bufs is empty", XCAM_STR (get_name ())); 534 535 SmartPtr<StitcherParam> param = new StitcherParam; 536 param->out_buf = out_buf; 537 uint32_t count = 0; 538 for (VideoBufferList::const_iterator i = in_bufs.begin(); i != in_bufs.end (); ++i) { 539 SmartPtr<VideoBuffer> buf = *i; 540 XCAM_ASSERT (buf.ptr ()); 541 param->in_bufs[count++] = buf; 542 } 543 param->in_buf_num = count; 544 XCamReturn ret = execute_buffer (param, true); 545 if (!out_buf.ptr () && xcam_ret_is_ok (ret)) { 546 out_buf = param->out_buf; 547 } 548 return ret; 549} 550 551XCamReturn 552SoftStitcher::start_task_count (const SmartPtr<SoftStitcher::StitcherParam> ¶m) 553{ 554 XCAM_ASSERT (param.ptr ()); 555 XCAM_ASSERT (_impl.ptr ()); 556 557 SmartLock locker (_impl->_map_mutex); 558 559 XCAM_FAIL_RETURN ( 560 ERROR, check_work_continue (param, XCAM_RETURN_NO_ERROR), XCAM_RETURN_ERROR_PARAM, 561 "soft-stitcher:%s start task count failed in work check", XCAM_STR (get_name ())); 562 563 if (_impl->_task_counts.find (param.ptr ()) != _impl->_task_counts.end ()) { 564 XCAM_LOG_ERROR ("tasks already started, this should never happen."); 565 return XCAM_RETURN_ERROR_UNKNOWN; 566 } 567 568 int32_t count = get_camera_num (); 569 //count += get_copy_area ().size (); 570 571 XCAM_LOG_DEBUG ("stitcher :%s start task count :%d", XCAM_STR(get_name ()), count); 572 _impl->_task_counts.insert (std::make_pair((void*)param.ptr(), count)); 573 return XCAM_RETURN_NO_ERROR; 574} 575 576void 577SoftStitcher::dewarp_done ( 578 const SmartPtr<ImageHandler> &handler, 579 const SmartPtr<ImageHandler::Parameters> &base, 580 const XCamReturn error) 581{ 582 SmartPtr<SoftSitcherPriv::HandlerParam> dewarp_param = base.dynamic_cast_ptr<SoftSitcherPriv::HandlerParam> (); 583 XCAM_ASSERT (dewarp_param.ptr ()); 584 SmartPtr<SoftStitcher::StitcherParam> param = dewarp_param->stitch_param; 585 XCAM_ASSERT (param.ptr ()); 586 XCAM_UNUSED (handler); 587 588 if (!check_work_continue (param, error)) 589 return; 590 591 XCAM_LOG_INFO ("soft-stitcher:%s camera(idx:%d) dewarp done", XCAM_STR (get_name ()), dewarp_param->idx); 592 stitcher_dump_buf (dewarp_param->out_buf, dewarp_param->idx, "stitcher-dewarp"); 593 594 //start both blender and feature match 595 XCamReturn ret = _impl->start_overlap_tasks (param, dewarp_param->idx, dewarp_param->out_buf); 596 if (!xcam_ret_is_ok (ret)) { 597 work_broken (param, ret); 598 } 599 600 ret = _impl->start_copy_tasks (param, dewarp_param->idx, dewarp_param->out_buf); 601 if (!xcam_ret_is_ok (ret)) { 602 work_broken (param, ret); 603 } 604} 605 606void 607SoftStitcher::blender_done ( 608 const SmartPtr<ImageHandler> &handler, 609 const SmartPtr<ImageHandler::Parameters> &base, 610 const XCamReturn error) 611{ 612 SmartPtr<SoftSitcherPriv::BlenderParam> blender_param = base.dynamic_cast_ptr<SoftSitcherPriv::BlenderParam> (); 613 XCAM_ASSERT (blender_param.ptr ()); 614 SmartPtr<SoftStitcher::StitcherParam> param = blender_param->stitch_param; 615 XCAM_ASSERT (param.ptr ()); 616 XCAM_UNUSED (handler); 617 618 if (!check_work_continue (param, error)) { 619 _impl->remove_task_count (param); 620 return; 621 } 622 623 stitcher_dump_buf (blender_param->out_buf, blender_param->idx, "stitcher-blend"); 624 XCAM_LOG_INFO ("blender:(%s) overlap:%d done", XCAM_STR (handler->get_name ()), blender_param->idx); 625 626 if (_impl->dec_task_count (param) == 0) { 627 work_well_done (param, error); 628 } 629} 630 631XCamReturn 632SoftStitcher::configure_resource (const SmartPtr<Parameters> ¶m) 633{ 634 XCAM_UNUSED (param); 635 XCAM_ASSERT (_impl.ptr ()); 636 637 uint32_t camera_count = get_camera_num (); 638 XCamReturn ret = _impl->init_config (camera_count); 639 XCAM_FAIL_RETURN ( 640 ERROR, xcam_ret_is_ok (ret), ret, 641 "soft-stitcher:%s initialize private config failed", XCAM_STR (get_name ())); 642 643 ret = estimate_coarse_crops (); 644 XCAM_FAIL_RETURN ( 645 ERROR, xcam_ret_is_ok (ret), ret, 646 "soft-stitcher:%s estimate coarse crops failed", XCAM_STR (get_name ())); 647 648 ret = mark_centers (); 649 XCAM_FAIL_RETURN ( 650 ERROR, xcam_ret_is_ok (ret), ret, 651 "soft-stitcher:%s mark centers failed", XCAM_STR (get_name ())); 652 653 ret = estimate_overlap (); 654 XCAM_FAIL_RETURN ( 655 ERROR, xcam_ret_is_ok (ret), ret, 656 "soft-stitcher:%s estimake coarse overlap failed", XCAM_STR (get_name ())); 657 658 ret = _impl->fisheye_dewarp_to_table (); 659 XCAM_FAIL_RETURN ( 660 ERROR, xcam_ret_is_ok (ret), ret, 661 "soft-stitcher:%s fisheye_dewarp_to_table failed", XCAM_STR (get_name ())); 662 663 VideoBufferInfo out_info; 664 uint32_t out_width, out_height; 665 get_output_size (out_width, out_height); 666 XCAM_FAIL_RETURN ( 667 ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM, 668 "soft-stitcher:%s output size was not set", XCAM_STR(get_name ())); 669 670 out_info.init ( 671 V4L2_PIX_FMT_NV12, out_width, out_height, 672 XCAM_ALIGN_UP (out_width, SOFT_STITCHER_ALIGNMENT_X), 673 XCAM_ALIGN_UP (out_height, SOFT_STITCHER_ALIGNMENT_Y)); 674 set_out_video_info (out_info); 675 676 return ret; 677} 678 679XCamReturn 680SoftStitcher::start_work (const SmartPtr<Parameters> &base) 681{ 682 SmartPtr<StitcherParam> param = base.dynamic_cast_ptr<StitcherParam> (); 683 684 XCAM_FAIL_RETURN ( 685 ERROR, param.ptr () && param->in_buf_num > 0 && param->in_bufs[0].ptr (), XCAM_RETURN_ERROR_PARAM, 686 "soft_stitcher:%s start_work failed, params(in_buf_num) in_bufs are set", 687 XCAM_STR (get_name ())); 688 689 XCamReturn ret = start_task_count (param); 690 XCAM_FAIL_RETURN ( 691 ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_PARAM, 692 "soft_stitcher:%s start blender count failed", XCAM_STR (get_name ())); 693 694 ret = _impl->start_dewarp_works (param); 695 XCAM_FAIL_RETURN ( 696 ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_PARAM, 697 "soft_stitcher:%s start dewarp works failed", XCAM_STR (get_name ())); 698 699 for (uint32_t i = 0; i < param->in_buf_num; ++i) { 700 param->in_bufs[i].release (); 701 } 702 703 return ret; 704} 705 706SmartPtr<Stitcher> 707Stitcher::create_soft_stitcher () 708{ 709 return new SoftStitcher; 710} 711 712} 713 714