Program Listing for File xf_axi.hpp

Return to documentation for file (/tmp/ws/src/vitis_common/include/common/xf_axi.hpp)

/*
 * Copyright 2019 Xilinx, Inc.
 *
 * 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.
 */

//#include "opencv_core_types.h"

#include <opencv2/core/types_c.h>
#include <opencv2/core/core_c.h>
/* From/To AXI video stream */
#include "ap_axi_sdata.h"
#include "utils/x_hls_utils.h"

#include <assert.h>

namespace xf {
namespace cv {

template <int W, int NPC>
void xfAXISetBitFields(ap_uint<W>& pix, IplImage* img, int row, int col) {
// clang-format off
    #pragma HLS inline
    // clang-format on
    int start = 0;
    ap_uint<W> pack;
    CvScalar cv_pix;
    fp_struct<float> temp;

    //    int depth_8s=IPL_DEPTH_8S;
    //    int depth_16s=IPL_DEPTH_16S;
    //    int depth_16u=IPL_DEPTH_16U;
    //    int depth_32s=IPL_DEPTH_32S;
    //    int depth_32f=IPL_DEPTH_32F;
    //    int IPL_DEPTH_64F=IPL_DEPTH_64F;
    int pix_depth = (img->depth & 0xff);

    for (int n_pix = 0; n_pix < NPC; n_pix++) {
        cv_pix = cvGet2D(img, row, col + n_pix);

        for (int k = 0; k < img->nChannels; k++) {
            switch (img->depth) {
                case IPL_DEPTH_8S: {
                    pack(start + pix_depth - 1, start) = (char)cv_pix.val[k];
                } break;
                case IPL_DEPTH_16U: {
                    pack(start + pix_depth - 1, start) = (unsigned short)cv_pix.val[k];
                } break;
                case IPL_DEPTH_16S: {
                    pack(start + pix_depth - 1, start) = (short)cv_pix.val[k];
                } break;
                case IPL_DEPTH_32S: {
                    pack(start + pix_depth - 1, start) = (int)cv_pix.val[k];
                } break;
                case IPL_DEPTH_32F: {
                    fp_struct<float> temp((float)cv_pix.val[k]);
                    pack(start + pix_depth - 1, start) = temp.data();
                } break;
                case IPL_DEPTH_64F: {
                    pack(start + pix_depth - 1, start) = (double)cv_pix.val[k];
                } break;
                default: { // Includes IPL_DEPTH_8U
                    pack(start + pix_depth - 1, start) = (unsigned char)cv_pix.val[k];
                } break;
            }

            start = start + pix_depth;
        }
    }
    pix = pack;
}
template <int W, int NPC>
void xfAXISetBitFields(ap_axiu<W, 1, 1, 1>& axi, IplImage* img, int row, int col) {
// clang-format off
    #pragma HLS inline
    // clang-format on
    xfAXISetBitFields<W, NPC>(axi.data, img, row, col);
}
template <int W, int NPC>
void IplImage2AXIvideoxf(IplImage* img, hls::stream<ap_axiu<W, 1, 1, 1> >& AXI_video_strm) {
    int i, j, p = 0;

    CvScalar cv_pix;
    ap_axiu<W, 1, 1, 1> axi;
    int depth = (img->depth & 0xff);
    assert(img && img->imageData && (W >= depth * img->nChannels) &&
           "Image must be valid and have width less than the width of the stream.");

    int channels = img->nChannels;

    for (i = 0; i < img->height; i++) {
        for (j = 0; j < (img->width); j = j + NPC) {
            if ((i == 0) && (j == 0)) {
                axi.user = 1;
            } else {
                axi.user = 0;
            }
            if (j == (img->width - NPC)) {
                axi.last = 1;
            } else {
                axi.last = 0;
            }
            axi.data = -1;

            xfAXISetBitFields<W, NPC>(axi, img, i, j);
            axi.keep = -1;
            AXI_video_strm << axi;
        }
    }
}

template <int NPC, int W>
void cvMat2AXIvideoxf(::cv::Mat& cv_mat, hls::stream<ap_axiu<W, 1, 1, 1> >& AXI_video_strm) {
    IplImage img = cvIplImage(cv_mat);
    IplImage2AXIvideoxf<W, NPC>(&img, AXI_video_strm);
}
template <int NPC, int W>
void xfAXIGetBitFields(ap_uint<W> pix, IplImage* img, int row, int col) {
// clang-format off
    #pragma HLS inline
    // clang-format on
    CvScalar cv_pix;
    int depth = (img->depth & 0xff);
    int start = 0;
    //    const int depth_8u=IPL_DEPTH_8U;
    //    const int depth_8s=IPL_DEPTH_8S;
    //    const int depth_16s=IPL_DEPTH_16S;
    //    const int depth_16u=IPL_DEPTH_16U;
    //    const int depth_32s=IPL_DEPTH_32S;
    //    const int depth_32f=IPL_DEPTH_32F;
    //    const int depth_64f=IPL_DEPTH_64F;

    for (int n_pix = 0; n_pix < NPC; n_pix++) {
        for (int k = 0; k < img->nChannels; k++) {
            switch (img->depth) {
                case IPL_DEPTH_8U: {
                    unsigned char temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
                case IPL_DEPTH_8S: {
                    char temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
                case IPL_DEPTH_16U: {
                    unsigned short temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
                case IPL_DEPTH_16S: {
                    short temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
                case IPL_DEPTH_32S: {
                    int temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
                case IPL_DEPTH_32F: {
                    float temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
                case IPL_DEPTH_64F: {
                    double temp;
                    cv_pix.val[k] = temp;
                } break;
                default: {
                    unsigned char temp = pix.range(start + depth - 1, start);
                    cv_pix.val[k] = temp;
                } break;
            }

            start = start + depth;
        }
        cvSet2D(img, row, col + n_pix, cv_pix);
    }
}
template <int NPC, int W>
void xfAXIGetBitFields(ap_axiu<W, 1, 1, 1> axi, IplImage* img, int row, int col) {
// clang-format off
    #pragma HLS inline
    // clang-format on
    xfAXIGetBitFields<NPC, W>(axi.data, img, row, col);
}
template <int W, int NPC>
void AXIvideo2IplImagexf(hls::stream<ap_axiu<W, 1, 1, 1> >& AXI_video_strm, IplImage* img) {
    int i, j;
    ap_axiu<W, 1, 1, 1> axi;
    CvScalar cv_pix;
    int depth = (img->depth & 0xff);
    bool sof = 0;
    assert(img && img->imageData && (W >= depth * img->nChannels) &&
           "Image must be valid and have width less than the width of the stream.");

    for (i = 0; i < img->height; i++) {
        for (j = 0; j < (img->width); j += NPC) {
            AXI_video_strm >> axi;
            if ((i == 0) && (j == 0)) {
                if (axi.user.to_int() == 1) {
                    sof = 1;
                } else {
                    j--;
                }
            }
            if (sof) {
                xfAXIGetBitFields<NPC, W>(axi, img, i, j);
            }
        }
    }
}

template <int NPC, int W>
void AXIvideo2cvMatxf(hls::stream<ap_axiu<W, 1, 1, 1> >& AXI_video_strm, ::cv::Mat& cv_mat) {
    IplImage img = cvIplImage(cv_mat);
    AXIvideo2IplImagexf<W, NPC>(AXI_video_strm, &img);
}
} // namespace cv
} // namespace xf