disparity_transform::disparity_transform(bool transform_to_disparity):
        generic_processing_block(transform_to_disparity ? "Depth to Disparity" : "Disparity to Depth"),
        _transform_to_disparity(transform_to_disparity),
        _update_target(false),
        _stereoscopic_depth(false),
        _focal_lenght_mm(0.f),
        _stereo_baseline_meter(0.f),
        _depth_units(0.f),
        _d2d_convert_factor(0.f),
        _width(0), _height(0), _bpp(0)
    {
        auto transform_opt = std::make_shared<ptr_option<bool>>(
            false,true,true,true,
            &_transform_to_disparity,
            "Stereoscopic Transformation Mode");
        transform_opt->set_description(false, "Disparity to Depth");
        transform_opt->set_description(true, "Depth to Disparity");
        transform_opt->on_set([this, transform_opt](float val)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (!transform_opt->is_valid(val))
                throw invalid_value_exception(to_string() << "Unsupported transformation mode" << (int)val << " is out of range.");

            on_set_mode(static_cast<bool>(!!int(val)));
        });

        unregister_option(RS2_OPTION_FRAMES_QUEUE_SIZE);

        on_set_mode(_transform_to_disparity);
    }
    disparity_transform::disparity_transform(bool transform_to_disparity):
        _transform_to_disparity(transform_to_disparity),
        _update_target(false),
        _stereoscopic_depth(false),
        _focal_lenght_mm(0.f),
        _stereo_baseline(0.f),
        _depth_units(0.f),
        _d2d_convert_factor(0.f),
        _width(0), _height(0), _bpp(0)
    {
        auto transform_opt = std::make_shared<ptr_option<bool>>(
            false,true,true,true,
            &_transform_to_disparity,
            "Stereoscopic Transformation Mode");
        transform_opt->set_description(false, "Disparity to Depth");
        transform_opt->set_description(true, "Depth to Disparity");
        transform_opt->on_set([this, transform_opt](float val)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (!transform_opt->is_valid(val))
                throw invalid_value_exception(to_string() << "Unsupported transformation mode" << (int)val << " is out of range.");

            on_set_mode(static_cast<bool>(!!int(val)));
        });

        unregister_option(RS2_OPTION_FRAMES_QUEUE_SIZE);

        auto on_frame = [this](rs2::frame f, const rs2::frame_source& source)
        {
            std::lock_guard<std::mutex> lock(_mutex);

            rs2::frame out = f;
            rs2::frame tgt, depth_data;

            bool composite = f.is<rs2::frameset>();

            tgt = depth_data = (composite) ? f.as<rs2::frameset>().first_or_default(RS2_STREAM_DEPTH) : f;

            // Verify that the input depth format is aligned with the block's configuration
            if (depth_data &&  (f.is<rs2::disparity_frame>() != _transform_to_disparity))
            {
                update_transformation_profile(depth_data);

                if (_stereoscopic_depth && (tgt = prepare_target_frame(depth_data, source)))
                {
                    auto src = depth_data.as<rs2::video_frame>();

                    if (_transform_to_disparity)
                        convert<uint16_t, float>(src.get_data(), const_cast<void*>(tgt.get_data()));
                    else
                        convert<float, uint16_t>(src.get_data(), const_cast<void*>(tgt.get_data()));
                }
            }

            out = composite ? source.allocate_composite_frame({ tgt }) : tgt;

            source.frame_ready(out);
        };

        auto callback = new rs2::frame_processor_callback<decltype(on_frame)>(on_frame);
        processing_block::set_processing_callback(std::shared_ptr<rs2_frame_processor_callback>(callback));

        on_set_mode(_transform_to_disparity);
    }