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> &param);
132    int32_t dec_task_count (const SmartPtr<SoftStitcher::StitcherParam> &param);
133
134    XCamReturn start_dewarp_works (const SmartPtr<SoftStitcher::StitcherParam> &param);
135    XCamReturn start_task_count (const SmartPtr<SoftStitcher::StitcherParam> &param);
136    XCamReturn start_overlap_tasks (
137        const SmartPtr<SoftStitcher::StitcherParam> &param,
138        const uint32_t idx, const SmartPtr<VideoBuffer> &buf);
139    XCamReturn start_copy_tasks (
140        const SmartPtr<SoftStitcher::StitcherParam> &param,
141        const uint32_t idx, const SmartPtr<VideoBuffer> &buf);
142
143    XCamReturn start_single_blender (const uint32_t idx, const SmartPtr<BlenderParam> &param);
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> &param)
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> &param)
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> &param)
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> &param)
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> &param,
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> &param,
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> &param)
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> &param)
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