void software_sensor::on_video_frame(rs2_software_video_frame software_frame)
    {
        frame_additional_data data;
        data.timestamp = software_frame.timestamp;
        data.timestamp_domain = software_frame.domain;
        data.frame_number = software_frame.frame_number;

        rs2_extension extension = software_frame.profile->profile->get_stream_type() == RS2_STREAM_DEPTH ?
            RS2_EXTENSION_DEPTH_FRAME : RS2_EXTENSION_VIDEO_FRAME;

        auto frame = _source.alloc_frame(extension, 0, data, false);
        if (!frame)
        {
            return;
        }
        auto vid_profile = dynamic_cast<video_stream_profile_interface*>(software_frame.profile->profile);
        auto vid_frame = dynamic_cast<video_frame*>(frame);
        vid_frame->assign(vid_profile->get_width(), vid_profile->get_height(), software_frame.stride, software_frame.bpp * 8);

        frame->set_stream(std::dynamic_pointer_cast<stream_profile_interface>(software_frame.profile->profile->shared_from_this()));
        frame->attach_continuation(frame_continuation{ [=]() {
            software_frame.deleter(software_frame.pixels);
        }, software_frame.pixels });
        _source.invoke_callback(frame);
    }
    void software_sensor::on_video_frame(rs2_software_video_frame software_frame)
    {
        if (!_is_streaming) return;
        
        frame_additional_data data;
        data.timestamp = software_frame.timestamp;
        data.timestamp_domain = software_frame.domain;
        data.frame_number = software_frame.frame_number;

        data.metadata_size = 0;
        for (auto i : _metadata_map)
        {
            auto size_of_enum = sizeof(rs2_frame_metadata_value);
            auto size_of_data = sizeof(rs2_metadata_type);
            if (data.metadata_size + size_of_enum + size_of_data > 255)
            {
                continue; //stop adding metadata to frame
            }
            memcpy(data.metadata_blob.data() + data.metadata_size, &i.first, size_of_enum);
            data.metadata_size += static_cast<uint32_t>(size_of_enum);
            memcpy(data.metadata_blob.data() + data.metadata_size, &i.second, size_of_data);
            data.metadata_size += static_cast<uint32_t>(size_of_data);
        }

        rs2_extension extension = software_frame.profile->profile->get_stream_type() == RS2_STREAM_DEPTH ?
            RS2_EXTENSION_DEPTH_FRAME : RS2_EXTENSION_VIDEO_FRAME;

        auto frame = _source.alloc_frame(extension, 0, data, false);
        if (!frame)
        {
            LOG_WARNING("Dropped video frame. alloc_frame(...) returned nullptr");
            return;
        }
        auto vid_profile = dynamic_cast<video_stream_profile_interface*>(software_frame.profile->profile);
        auto vid_frame = dynamic_cast<video_frame*>(frame);
        vid_frame->assign(vid_profile->get_width(), vid_profile->get_height(), software_frame.stride, software_frame.bpp * 8);

        frame->set_stream(std::dynamic_pointer_cast<stream_profile_interface>(software_frame.profile->profile->shared_from_this()));
        frame->attach_continuation(frame_continuation{ [=]() {
            software_frame.deleter(software_frame.pixels);
        }, software_frame.pixels });

        auto sd = dynamic_cast<software_device*>(_owner);
        sd->register_extrinsic(*vid_profile, _unique_id);
        _source.invoke_callback(frame);
    }