/*
 * Postprocess result data structures.
 *
 * Copyright (C) 2021 Kneron, Inc. All rights reserved.
 *
 */
#ifndef MODEL_RES_H
#define MODEL_RES_H

#define BOXES_MAX_NUM 80
#define YOLO_KEYPOINT_MAX       127
#define YOLO_GOOD_BOX_MAX_SCPU 500
#define CLASSIFIER_MAX_NUM 1000
#define FR_FEATURE_MAP_SIZE 256
#define KEYPOINT_POINTS 11
#define LANDMARK_POINTS 5
#define LAND_MARK_MOUTH_POINTS 4	// new
#define LAND_MARK_EYE_POINTS   7    // new
#define MAX_LANDMARK_POINTS 5
#define MAX_ONET_POINTS 100
#define MAX_YOLO_FACE_LANDMARK_CNT 4 * 2 // (x and y) * max point count
#define OCR_MAX_NUM 20
#define SEG_WIDTH 80
#define SEG_HEIGHT 60

// used with post_age_gender
struct age_gender_result_s {
    uint32_t age;       // detected age
    uint32_t ismale;    // 0 for female, 1 for male
};

// bounding box coordinates, score, and class
struct bounding_box_s {
    float x1;           // top-left x corner
    float y1;           // top-left y corner
    float x2;           // bottom-right x corner
    float y2;           // bottom-right y corner
    float score;        // probability score
    int32_t class_num;  // class number (of many) with highest probability
};

// bounding box and landmark data
struct bounding_box_landmark_s {
    float x1;                               // top-left x corner
    float y1;                               // top-left y corner
    float x2;                               // bottom-right x corner
    float y2;                               // bottom-right y corner
    float score;                            // probability score
    int32_t class_num;                      // class number (of many) with highest probability
    float lm[MAX_YOLO_FACE_LANDMARK_CNT];   // landmark data
};

// bounding box and landmark plus data
struct bounding_box_landmark_plus_s {
    float x1;                               // top-left x corner
    float y1;                               // top-left y corner
    float x2;                               // bottom-right x corner
    float y2;                               // bottom-right y corner
    float score;                            // probability score
    int32_t class_num;                      // class number (of many) with highest probability
    float score_next;                       // second best probability score
    int32_t class_num_next;                 // class number with second highest probability
    float lm[MAX_YOLO_FACE_LANDMARK_CNT];   // landmark data
};


// used with post_classifier
struct classifier_result_s {
    float score[CLASSIFIER_MAX_NUM];    // score for each class index
};

// used with post_face_pose
struct face_occlude_result_s {
    float yaw;
    float pitch;
    float roll;
    float occ;
    float seg_res[5];
};

// used with post_face_recognition
struct fr_result_s {
    float feature_map[FR_FEATURE_MAP_SIZE];
};

// used with post_face_recognition (floating & fixed point face embedding)
struct fr_flfix_result_s {
    float feature_map[FR_FEATURE_MAP_SIZE];
    int8_t raw_feature_map[FR_FEATURE_MAP_SIZE];
};

// used with post_face_landmark_onet
struct landmark_result_s {
    struct {
        uint32_t x;
        uint32_t y;
    } marks[MAX_ONET_POINTS];
    float score;
    float blur;
};

// used with post_face_landmark_onet_5p
struct landmark_result_5p_s {
    struct {
        uint32_t x;
        uint32_t y;
    } marks[LANDMARK_POINTS];
    float score;
    float blur;
    int32_t class_num;
};

// used with post_onet_plus
struct onet_plus_result_s {
    struct {
        float x;
        float y;
    } marks[MAX_LANDMARK_POINTS];
    float scores[MAX_LANDMARK_POINTS];
};

typedef struct classifier_pupil_result_s {   // new
    float fScore;    // fScore for each class index
    int idx_class;
}classifier_pupil_result_t;

struct landmark_68pt_result_s {	// new
    struct {	
        uint32_t x;	
        uint32_t y;	
    } marks[MAX_ONET_POINTS];	
    float score;	
    float blur;	
};	

struct eye_landmarks_s{	// new
    struct {	
        uint32_t x;	
        uint32_t y;	
    } marks[LAND_MARK_EYE_POINTS];	
};

enum mouth {	// new
    MOUTH_T = 0,	
    MOUTH_B,	
    MOUTH_L,	
    MOUTH_R,	
};	

struct yawning_result_s {	// new
    struct {	
        float x;	
        float y;	
        } marks[LAND_MARK_MOUTH_POINTS]; // mouth 0:top  1:bottom  2: left 3:right	
    uint32_t isYawning;	
    float yawning_rate;	
};

// used with post_ocr
typedef struct ocr_s {
    /*copy from lpr_result_s to store each bounding box of ocr value*/
    uint32_t chars_count;
    struct bounding_box_s char_boxes[OCR_MAX_NUM];
    /*-------------------------------------------------------------*/
    uint8_t valid;                      // 0 for invalid, 1 for valid
    uint8_t value[OCR_MAX_NUM];      // integers representing characters in order, mapping
                                        //     defined in licenseplate_ocr.c
    uint8_t hyphen;                     // position after which the hyphen should occur
} ocr_t;

struct general_semantic_segmentation_with_score_result_s {
    uint32_t width;                                                             /**< class map width */
    uint32_t height;                                                            /**< class map height */
    uint64_t total_class_num;                                                   /**< total class number */
    uint64_t class_map_address;                                                 /**< address of class number data in class_score_map */
    uint64_t score_map_address;                                                 /**< address of score data in class_score_map */
    uint32_t class_score_map[];                                                 /**< class number and score data per image pixel (the score map data follows the class map data) */
};

// used with post_rsn
struct upperbody_keypoint_result_s {
    struct {
        float x;        // x coordinate
        float y;        // y coordinate
    } marks[KEYPOINT_POINTS];
};

// used with fd, yolo postprocesses
struct yolo_result_s {
    uint32_t class_count;                           // total class count
    uint32_t box_count;                             // total box count
    struct bounding_box_s boxes[YOLO_GOOD_BOX_MAX_SCPU];     // found bounding boxes
};

struct keypoint_s {
    float x;
    float y;
    float score;
};

struct bounding_box_keypoint_s {
    struct bounding_box_s bbox;
    uint32_t keypoint_count;
    struct keypoint_s kpts[YOLO_KEYPOINT_MAX];  // keypoint data
};

struct yolo_and_keypoint_result_s {
    uint32_t class_count;                                         // total class count
    uint32_t box_count;                                           // total box count
    struct bounding_box_keypoint_s boxes_kpts[BOXES_MAX_NUM];     // found bounding boxes
};

// used with yolo_face
struct yolo_and_landmark_result_s {
    uint32_t class_count;                                   // total class count
    uint32_t box_count;                                     // total box count
    struct bounding_box_landmark_s boxes[BOXES_MAX_NUM];    // found bounding boxes
};

// used with yolo_X
struct yolox_and_landmark_result_s {
    uint32_t class_count;                                           // total class count
    uint32_t box_count;                                             // total box count
    struct bounding_box_landmark_plus_s boxes[BOXES_MAX_NUM];       // found bounding boxes
};

/***********************************
struct raw_onode_t only support one channel quantization only here.
if the model has quantization parameters per channel,
then host side need to parse the fw model to get all parameters,
because too many parameters convey impact performance.
************************************/
typedef struct {
    uint32_t idx;  //sequence number of out sub-nodes
    uint32_t fmt;
    uint32_t batch;
    uint32_t ch_length;
    uint32_t row_length;
    uint32_t col_length;
    uint32_t buf_addr;
    uint32_t buf_len;
    uint32_t scale;
    uint32_t radix;
    uint32_t start_offset;
    uint32_t buf_aligned_len;
    uint32_t quant_vect_len;

} raw_onode_t;

typedef struct {
    uint32_t total_raw_len;
    int32_t   total_nodes;
    raw_onode_t onode_a[40];
    uint8_t data[];
} raw_cnn_res_t;

#endif
