一种C语言实现面向对象特性的继承,多态

基类:

//.h

typedef int (*TELE_SEND_CB)(char *pdata, int len);


//函数表结构
typedef struct tele_pro_base_vtbl
{
    int (*trans_data)(int chun,enum rtsp_frame_type type, char *pdata, unsigned int len,unsigned int ts);
    int (*send_cmd)(int cmd,char *para,unsigned int len);
    int (*parse_cmd)(char *data_in, int size_in, void *data_out);
}tele_pro_base_vtbl_t;

 
//基类
typedef struct tele_pro_base
{
    /*virtual table*/
    tele_pro_base_vtbl_t *vptr;
    TELE_SEND_CB   send_cb;    
}tele_pro_base_t;



int akp_tele_pro_low_send(tele_pro_base_t *this,char *pdata,unsigned int len);
tele_pro_base_t * akp_tele_pro_base_ctor(TELE_SEND_CB send_cb);

int akp_tele_pro_send_cmd(tele_pro_base_t *this,int cmd,char *pdata,unsigned int len);

int akp_tele_pro_trans_data(tele_pro_base_t *this,int chun,enum rtsp_frame_type type, char *pdata, unsigned int len,unsigned int ts);

int akp_tele_pro_parse_cmd(tele_pro_base_t *this, char *data_in, int size_in, void *data_out);

// .c

/******************************************************
*                    Constant         
******************************************************/


/******************************************************
*                    Macro         
******************************************************/



/******************************************************
*                    Type Definitions         
******************************************************/


/******************************************************
*                    Global Variables         
******************************************************/
static tele_pro_base_t *ptele_pro_base = NULL;

/******************************************************
*               Function interface
******************************************************/
static int __send(char *pdata,unsigned int len)
{
    int ret = 0;;
    if(NULL != ptele_pro_base->send_cb) {
        ret = ptele_pro_base->send_cb(pdata,len);
    }
    return ret;
}

static int anyka_trans_data(int chun,enum rtsp_frame_type type, \
        char *pdata, unsigned int len,unsigned int ts)
{
    int ret = -1;
    
    ret = ak_rtsp_send_stream(chun,type,pdata,len,ts);

    return ret;
}


static int anyka_send_cmd(int cmd,char *pdata,unsigned int len)
{
    int ret = 0;

    unsigned int len_out = 0;
    char *pout = malloc(len+TEL_CTRLPRO_FRAME_SIZE_MIN);
    
    akp_tel_ctrlpro_pack(cmd, pdata, len, pout, &len_out);
    if(len_out > len+TEL_CTRLPRO_FRAME_SIZE_MIN) {
        ak_print_error("akp_tel_ctrlpro_pack error\n");
        ret = -1;
    }
    ret = __send(pout, len_out);
    free(pout);
    return ret;
}


/**
 * akp_tel_ctrlpro_parse-report net state to observer
 * @data_in[IN]: recv data.
 * @size_in[IN]: recv data lenght.
 * @data_out[IN]: out frame data.
 * eg: akp_tel_ctrlpro_parse(recv_buf, len,parse_buf);
 *     tel_video_set_t video_para = (tel_video_set_t)parse_buf;
 * return: > 0 command, -1 error, -2 continue recv
 * notes: if have data,pl ensure length > TEL_CTRLPRO_FRAME_SIZE_MAX
 */
static int anyka_parse_cmd(char *data_in, int size_in, void *data_out)
{
    return akp_tel_ctrlpro_parse(data_in, size_in,data_out);
}

/* 可多态的函数表 */
static tele_pro_base_vtbl_t base_table =
{
    anyka_trans_data,
    anyka_send_cmd,
    anyka_parse_cmd
};


//基类的构造函数
tele_pro_base_t * akp_tele_pro_base_ctor(TELE_SEND_CB send_cb)
{
    tele_pro_base_t *temp = (tele_pro_base_t *)malloc(sizeof(tele_pro_base_t));
    temp->vptr = &base_table;
    temp->send_cb = send_cb;
    ptele_pro_base = temp;
    return temp;
}


//基类方法
int akp_tele_pro_low_send(tele_pro_base_t *this,char *pdata,unsigned int len)
{
    int ret = 0;;
    
    if(NULL != this->send_cb) {
        ret = this->send_cb(pdata,len);
    }
    return ret;
}

int akp_tele_pro_send_cmd(tele_pro_base_t *this,int cmd,char *pdata,unsigned int len)
{
    int ret = 0;
    if(NULL != this->vptr->send_cmd) {
        ret = this->vptr->send_cmd(cmd,pdata,len);
    } else {
        ak_print_warning_ex("tele pro send cmd fun is null\n");
        ret = -1;
    }
    return ret;
}

int akp_tele_pro_trans_data(tele_pro_base_t *this,int chun,enum rtsp_frame_type type, char *pdata, unsigned int len,unsigned int ts)
{
    int ret = 0;
    if(NULL != this->vptr->trans_data) {
        ret = this->vptr->trans_data(chun,type,pdata,len ,ts);
    } else {
        ak_print_warning_ex("tele pro trans data fun is null\n");
        ret = -1;
    }
    return ret;
}

int akp_tele_pro_parse_cmd(tele_pro_base_t *this, char *data_in, int size_in, void *data_out)
{
    int ret = 0;   
    if(NULL != this->vptr->parse_cmd) {
        ret = this->vptr->parse_cmd(data_in,size_in,data_out);
    } else {
        ak_print_warning_ex("tele pro parse cmd fun is null\n");
        ret = -1;
    }

    return ret;
}

派生类:

// .h

#define JUAN_TXBUF_SIZE            1024
#define JUAN_PARSE_BUF_SIZE        2048

typedef struct tele_pro_juan {
    tele_pro_base_t base;
    
    unsigned int    ssrc;
    unsigned short  seqNumber;
    int             fw_type;
    unsigned int    fw_size;
    unsigned int    fw_seq; 
        
    int     buf_len;
    char    parse_buf[JUAN_PARSE_BUF_SIZE];

    int     tx_buf_length;
    char    tx_buf[JUAN_TXBUF_SIZE];
    ak_mutex_t mutex_tx; 
}tele_pro_juan_t;



int akp_telepro_juan_post_describe(int chun);

tele_pro_juan_t* akp_tele_pro_juan_data_chun_ctor(TELE_SEND_CB send_cb);

// .c

//------------------基类函数的多态实现---------------------
static int juan_trans_data(int chun,enum rtsp_frame_type type, char *pdata, unsigned int len,unsigned int ts_ms)
{
    int ret = -1;

    static unsigned long bit_len = 0;
    static unsigned long t1 = 0;
    unsigned long t2;

    ak_thread_mutex_lock(&ptele_pro->mutex_tx);
    // calculate bsp
    if(0 == bit_len) {
        t1 = ak_get_tick_count_ms();
    }
    bit_len += len;
    t2 = ak_get_tick_count_ms();
    if(t2-t1 >= 1000) {
        ak_print_notice("[juan rtsp]: bps=%d\n",bit_len*8);
        bit_len = 0;
    }

    unsigned int ts = ts_ms*1000;
    if(RTSP_AFRAME == type) {
        ret = __juan_data_chun_send_data(HICHIP_FRAME_TYPE_UNUSE,HICHIP_MD_TYPE_G711,pdata,len,ts);
    } else if(RTSP_IFRAME == type){
        ret = __juan_data_chun_send_data(HICHIP_FRAME_TYPE_BASE_IDRSLICE,HICHIP_MD_TYPE_H264,pdata,len,ts);
    } else if(RTSP_PFRAME == type) {
         ret = __juan_data_chun_send_data(HICHIP_FRAME_TYPE_UNUSE,HICHIP_MD_TYPE_H264,pdata,len,ts);
    } else {
        ak_print_error("[tele]: donot support this frame type=%d\n",type);
    }        
      ak_thread_mutex_unlock(&ptele_pro->mutex_tx);
    
    return ret;
}

static int juan_data_chun_send_cmd(int cmd,char *para,unsigned int len)
{
    int ret = 0;

    ak_thread_mutex_lock(&ptele_pro->mutex_tx);
    switch(cmd) {
    case TELE_MSG_SEND_LOGIN:
        ak_print_normal("[anyka]: UL_WAKEUP_IND_MSG\n");
        __juan_data_chun_post_describe(0);
        __juan_data_chun_login();
        break;

    case TELE_MSG_SEND_DEVINFO: {
        ring_dev_info_t *dev_info = (ring_dev_info_t *)para;
        unsigned int event = 0;
        unsigned int io = 0;
        if(WAKEUP_EVENT_PIR == dev_info->wake_event) {
           event |= NK_HICHIP_EVENT_IO;
           io    |= NK_HICHIP_IO_PIR;
        }
        if(dev_info->md) {
            event |= NK_HICHIP_EVENT_MD;
        }
        ak_print_normal_ex("stream chun: event=%d io=%d\n",event,io);
        __juan_data_chun_send_cmd(event,io);
        }break;


    default:
        //ak_print_warning_ex("[tele]: donot support this cmd=%d\n",cmd);
        break;
    }  
     ak_thread_mutex_unlock(&ptele_pro->mutex_tx);
    
    return ret;
}

/**
 * akp_tel_ctrlpro_parse-report net state to observer
 * @data_in[IN]: recv data.
 * @size_in[IN]: recv data lenght.
 * @data_out[IN]: out frame data.
 * eg: akp_tel_ctrlpro_parse(recv_buf, len,parse_buf);
 *     tel_video_set_t video_para = (tel_video_set_t)parse_buf;
 * return: > 0 command, -1 error, -2 continue recv
 * notes: if have data,pl ensure length > TEL_CTRLPRO_FRAME_SIZE_MAX
 */
static int juan_data_chun_parse_cmd(char* data_in, int size_in, void *data_out)
{
    char *recv_buf = ptele_pro->parse_buf;
    int cmd_len;
    int ret = -2;
    int i;
    
    for(i = 0; i< size_in; i++) {
        juan_debug_log("%c",data_in[i]);
    }
    juan_debug_log("\n");

#if 1
    /* join data */
    memcpy(recv_buf+ptele_pro->buf_len,data_in, size_in);
    ptele_pro->buf_len += size_in;

    
    cmd_len = find_string(recv_buf,ptele_pro->buf_len,"\r\n");
    juan_debug_log("cmd_len=%d\n",cmd_len);
    if(cmd_len > 0)
    {
        ret = __juan_data_chun_do_cmd(recv_buf,cmd_len+2,data_out);
        //ak_print_normal("cmd ret = %d DL_START_VIDEO_MSG=%d\n",ret,DL_START_VIDEO_MSG);
        
        memcpy(recv_buf, recv_buf+cmd_len, ptele_pro->buf_len-cmd_len);
        ptele_pro->buf_len -= cmd_len;
        memset(recv_buf + ptele_pro->buf_len, 0, cmd_len);
    }

    if(ptele_pro->buf_len > JUAN_PARSE_BUF_SIZE-64) {
        ak_print_warning_ex(" ptele_pro->parse_buf have too many data\n");
    }
    return ret;
#else
    if(strstr(data_in,"HTTP/1.1 100") != NULL)
    {      
        ret = DL_START_VIDEO_MSG; 
    }  
    return ret;
#endif

}

/*函数表 */
static tele_pro_base_vtbl_t vir_table =
{
    juan_trans_data,
    juan_data_chun_send_cmd,
    juan_data_chun_parse_cmd
};

//派生类的构造函数
tele_pro_juan_t* akp_tele_pro_juan_data_chun_ctor(TELE_SEND_CB send_cb)
{
    tele_pro_juan_t *temp= (tele_pro_juan_t*)malloc(sizeof(tele_pro_juan_t));
    temp->base.vptr = &vir_table;
    temp->base.send_cb = send_cb;
    ptele_pro = temp;

    memset(ptele_pro->parse_buf,0,sizeof(ptele_pro->parse_buf));
    ptele_pro->buf_len = 0;

    ak_thread_mutex_init(&ptele_pro->mutex_tx,NULL);
    return temp;
}

猜你喜欢

转载自www.cnblogs.com/mic-chen/p/9382790.html