C++程序  |  208行  |  6.29 KB

/*
 * soft_geo_mapper.cpp - soft geometry mapper implementation
 *
 *  Copyright (c) 2017 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author: Wind Yuan <feng.yuan@intel.com>
 */

#include "soft_geo_mapper.h"
#include "soft_geo_tasks_priv.h"

#define XCAM_GEO_MAP_ALIGNMENT_X 8
#define XCAM_GEO_MAP_ALIGNMENT_Y 2

namespace XCam {

DECLARE_WORK_CALLBACK (CbGeoMapTask, SoftGeoMapper, remap_task_done);

SoftGeoMapper::SoftGeoMapper (const char *name)
    : SoftHandler (name)
{
}

SoftGeoMapper::~SoftGeoMapper ()
{
}

bool
SoftGeoMapper::set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height)
{
    XCAM_FAIL_RETURN(
        ERROR, width > 1 && height > 1 && data, false,
        "SoftGeoMapper(%s) set loop up table need w>1 and h>1, but width:%d, height:%d",
        XCAM_STR (get_name ()), width, height);

    _lookup_table = new Float2Image (width, height);

    XCAM_FAIL_RETURN(
        ERROR, _lookup_table.ptr () && _lookup_table->is_valid (), false,
        "SoftGeoMapper(%s) set loop up table failed in data allocation",
        XCAM_STR (get_name ()));

    for (uint32_t i = 0; i < height; ++i) {
        Float2 *ret = _lookup_table->get_buf_ptr (0, i);
        const PointFloat2 *line = &data[i * width];
        for (uint32_t j = 0; j < width; ++j) {
            ret[j].x = line [j].x;
            ret[j].y = line [j].y;
        }
    }
    return true;
}

XCamReturn
SoftGeoMapper::remap (
    const SmartPtr<VideoBuffer> &in,
    SmartPtr<VideoBuffer> &out_buf)
{
    SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in, out_buf);
    XCamReturn ret = execute_buffer (param, true);
    if (xcam_ret_is_ok (ret) && !out_buf.ptr ()) {
        out_buf = param->out_buf;
    }
    return ret;
}

XCamReturn
SoftGeoMapper::configure_resource (const SmartPtr<Parameters> &param)
{
    XCAM_FAIL_RETURN(
        ERROR, _lookup_table.ptr () && _lookup_table->is_valid (), XCAM_RETURN_ERROR_PARAM,
        "SoftGeoMapper(%s) configure failed, look_up_table was not set correctly",
        XCAM_STR (get_name ()));

    const VideoBufferInfo &in_info = param->in_buf->get_video_info ();
    XCAM_FAIL_RETURN (
        ERROR, in_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM,
        "SoftGeoMapper(:%s) only support format(NV12) but input format is %s",
        XCAM_STR(get_name ()), xcam_fourcc_to_string (in_info.format));

    Float2 factors;
    get_factors (factors.x, factors.y);
    if (XCAM_DOUBLE_EQUAL_AROUND (factors.x, 0.0f) ||
            XCAM_DOUBLE_EQUAL_AROUND (factors.y, 0.0f)) {
        auto_calculate_factors (_lookup_table->get_width (), _lookup_table->get_height ());
    }

    uint32_t width, height;
    get_output_size (width, height);
    VideoBufferInfo out_info;
    out_info.init (
        in_info.format, width, height,
        XCAM_ALIGN_UP (width, XCAM_GEO_MAP_ALIGNMENT_X),
        XCAM_ALIGN_UP (height, XCAM_GEO_MAP_ALIGNMENT_Y));
    set_out_video_info (out_info);

    XCAM_ASSERT (!_map_task.ptr ());
    _map_task = new XCamSoftTasks::GeoMapTask (new CbGeoMapTask(this));
    XCAM_ASSERT (_map_task.ptr ());

    return XCAM_RETURN_NO_ERROR;
}

XCamReturn
SoftGeoMapper::start_remap_task (const SmartPtr<ImageHandler::Parameters> &param)
{
    XCAM_ASSERT (_map_task.ptr ());
    XCAM_ASSERT (_lookup_table.ptr ());

    Float2 factors;
    get_factors (factors.x, factors.y);

    SmartPtr<VideoBuffer> in_buf = param->in_buf, out_buf = param->out_buf;
    SmartPtr<XCamSoftTasks::GeoMapTask::Args> args = new XCamSoftTasks::GeoMapTask::Args (param);
    args->in_luma = new UcharImage (in_buf, 0);
    args->in_uv = new Uchar2Image (in_buf, 1);
    args->out_luma = new UcharImage (out_buf, 0);
    args->out_uv = new Uchar2Image (out_buf, 1);
    args->lookup_table = _lookup_table;
    args->factors = factors;

    uint32_t thread_x = 2, thread_y = 2;
    WorkSize work_unit = _map_task->get_work_uint ();
    WorkSize global_size (
        xcam_ceil (args->out_luma->get_width (), work_unit.value[0]) / work_unit.value[0],
        xcam_ceil (args->out_luma->get_height (), work_unit.value[1]) / work_unit.value[1]);
    WorkSize local_size (
        xcam_ceil(global_size.value[0], thread_x) / thread_x ,
        xcam_ceil(global_size.value[1], thread_y) / thread_y);

    _map_task->set_local_size (local_size);
    _map_task->set_global_size (global_size);

    param->in_buf.release ();
    return _map_task->work (args);
}

XCamReturn
SoftGeoMapper::start_work (const SmartPtr<ImageHandler::Parameters> &param)
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    XCAM_ASSERT (param->out_buf.ptr ());

    ret = start_remap_task (param);
    XCAM_FAIL_RETURN (
        ERROR, xcam_ret_is_ok (ret), ret,
        "geo_mapper:%s start_work failed on idx0", XCAM_STR (get_name ()));

    param->in_buf.release ();

    return ret;
};

XCamReturn
SoftGeoMapper::terminate ()
{
    if (_map_task.ptr ()) {
        _map_task->stop ();
        _map_task.release ();
    }
    return SoftHandler::terminate ();
}

void
SoftGeoMapper::remap_task_done (
    const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
{
    XCAM_UNUSED (worker);
    XCAM_ASSERT (worker.ptr () == _map_task.ptr ());
    SmartPtr<XCamSoftTasks::GeoMapTask::Args> args = base.dynamic_cast_ptr<XCamSoftTasks::GeoMapTask::Args> ();
    XCAM_ASSERT (args.ptr ());
    const SmartPtr<ImageHandler::Parameters> param = args->get_param ();

    if (!check_work_continue (param, error))
        return;

    work_well_done (param, error);
}

SmartPtr<SoftHandler> create_soft_geo_mapper ()
{
    SmartPtr<SoftHandler> mapper = new SoftGeoMapper ();
    XCAM_ASSERT (mapper.ptr ());
    return mapper;
}

SmartPtr<GeoMapper>
GeoMapper::create_soft_geo_mapper ()
{
    SmartPtr<SoftHandler> handler = XCam::create_soft_geo_mapper ();
    return handler.dynamic_cast_ptr<GeoMapper> ();
}

}