array[index] &= ~PACKET

本文详细解释了JAVA表达式 `array[index]&=~PACKET;` 的含义,并深入探讨了 `switch(move&3)` 中位运算的用法。通过实例分析,帮助读者理解位操作符在JAVA中的应用,以及如何在switch语句中使用位运算进行复杂判断。
请大家解释一个JAVA表达式:array[index] &= ~PACKET; 2009-4-16 11:05 提问者: nbkhic | 浏览次数:882次
请大家解释一个JAVA表达式:array[index] &= ~PACKET;

在Sun给的源代码里面看见的,一时没反应过来是什么意思,不知道哪位能帮忙解答一下。问题补充:

另外再请问一段代码
private int indexOffset(int move) {
switch (move & 3) {
case LEFT:
return -1;

case RIGHT:
return +1;

case UP:
return -width;

case DOWN:
return +width;
}

return 0;
}
其中的switch (move & 3)括号里的内容我弄不明白,貌似括号里只能是变量,但是move & 3似乎是表达式吧。
还请高人给以解惑啊,不胜感激
我来帮他解答 输入内容已经达到长度限制还能输入 9999 字插入图片删除图片插入地图删除地图插入视频视频地图不登录也可以回答
参考资料:提交回答取消
2009-4-16 11:13 满意回答 (1)java里面a = a + b;可以写成
a += b;这个应该知道吧。

(2)& 和 ~都是位操作符比如:
int a =1;
int b= 2;
a &= ~b; // 等效于 a = a & (~b);
System.out.println(a);

这个位运算你可以这样看。。。a = 1 = 001(8进制)
b = 2 = 010(8进制)
~b = ~(010) = 101
然后是a 和 b 与运算。结果是 a & ~b = 001 & 101 = 001 = 1
所以 a &= ~b = 1;
#include "hal_bsp.h" #include "hal_uart.h" #include "hal_gpio.h" #include "hal_wdt.h" #include "queue.h" #include "log.h" #include "subg_port.h" #include "subg_link.h" #include "device.h" #include "tty.h" #include <stdio.h> #define read_low_power_pin hal_gpio_readpin(LP_TEST) #define PACKET_HEAD (0XFE) #define START_INDEX 0 #define LENGTH_INDEX 1 #define CMD_INDEX 2 #define STATUS_INDEX 3 #define DATA_INDEX 4 enum TEST_CMD { CMD_CONNECT =0X01 ,//data:? CMD_CONNECT_RSP , //data:? CMD_GET_HW_ID , //data:? CMD_GET_HW_ID_RSP , //data:status + HW ID CMD_SET_DEV_ID ,//data:DEVICE ID??????,???40 CMD_SET_DEV_ID_RSP , //data:status:1 byte,0 == success CMD_GET_DEV_ID , //data:? CMD_GET_DEV_ID_RSP , //data:status + DEVICE ID CMD_SET_MAC , //data:MAC??,??6 CMD_SET_MAC_RSP , //data:status:1 byte,0 == success CMD_GET_MAC , //data:? CMD_GET_MAC_RSP , //data:status + MAC CMD_SET_KEY , //data:KEY,??16 CMD_SET_KEY_RSP , //data:status:1 byte,0 == success CMD_GET_KEY , //data:? CMD_GET_KEY_RSP , //data:status + KEY CMD_SET_ENC_KEY , //data:????KEY,??16 CMD_SET_ENC_KEY_RSP , //data:status:1 byte,0 == success CMD_GET_ENC_KEY , //data:? CMD_GET_ENC_KEY_RSP , //data:status + ENC KEY CMD_ENTER_LOW_POWER_MODE , //data:? CMD_ENTER_LOW_POWER_MODE_RSP , //data:? CMD_SUB1G_RX_MODE, CMD_SUB1G_RX_MODE_RSP, CMD_SUB1G_TX_MODE, CMD_SUB1G_TX_MODE_RSP, CMD_RELAY_CONTROL, CMD_RELAY_CONTROL_RSP, CMD_SET_MODEL_CONF, CMD_SET_MODEL_CONF_RSP, CMD_GET_MODEL_CONF, CMD_GET_MODEL_CONF_RSP, CMD_END, }; struct tty_pro { struct v_timer timer; }; static struct tty_pro tty_pro; struct queue *tty_rx_queue; u32 rev_cmd_time_out; u8 tty_low_power=0; struct pt debug_pt; void hal_tty_init(); void hal_tty_stop(); void hal_tty_send(u8 *buffer,u8 length); static int cal_packet_crc(u8 * buffer,u8 length) { u8 pkt_crc[2]; sub1g_ll_calc_crc(pkt_crc, buffer , length); if(sub1g_memcmp(pkt_crc, &buffer[length], 2)){ return 1; }else{ return 0; } } u8 tty_low_power_status() { return tty_low_power; } static void tty_cmd_append_crc(u8 *buffer,u8 length) { sub1g_ll_calc_crc(&buffer[length],buffer,length); } static void tty_send_packet(u8 *buffer,u8 length) { hal_tty_send(buffer,length); } static void deal_tty_cmd(u8 cmd,u8 *cmd_buffer,u8 cmd_length) { u8 data_length; u8 rsp_packet[MAX_CMD_LENGTH]; u8 rsp; u8 status; u8 low_power,cnt; rsp=1; rsp_packet[START_INDEX]=PACKET_HEAD; rsp_packet[CMD_INDEX]=cmd+1; data_length=1; status=0; low_power=0; switch(cmd){ case CMD_CONNECT: if(rev_cmd_time_out<1000){ rev_cmd_time_out=ONE_MINUTE*5; } break; case CMD_GET_HW_ID: sub1g_memcpy(&rsp_packet[DATA_INDEX],g_hw_id,PARAM_HW_ID_LEN); data_length+=(PARAM_HW_ID_LEN+1); break; case CMD_SET_DEV_ID: status=log_save(DEVICE_ID_ENTRY_NAME,cmd_buffer,PARAM_DEVICE_ID_LEN); data_length++; break; case CMD_GET_DEV_ID: status=log_read(DEVICE_ID_ENTRY_NAME,&rsp_packet[DATA_INDEX]); data_length+=(PARAM_DEVICE_ID_LEN+1); break; case CMD_SET_MAC: status=log_save(DEVICE_MAC_ENTRY_NAME,cmd_buffer,SHIP_SUB1G_ADDR_LEN); data_length++; break; case CMD_GET_MAC: status=log_read(DEVICE_MAC_ENTRY_NAME,&rsp_packet[DATA_INDEX]); if(status){ status=0; for(cnt=0;cnt<SHIP_SUB1G_ADDR_LEN;cnt++){ rsp_packet[DATA_INDEX+cnt]=0; } } data_length+=(SHIP_SUB1G_ADDR_LEN+1); break; case CMD_SET_KEY: status=log_save(MASTER_KEY_ENTRY_NAME,cmd_buffer,PARAM_ENCRYPT_MASTER_KEY_LEN); data_length++; break; case CMD_GET_KEY: status=log_read(MASTER_KEY_ENTRY_NAME,&rsp_packet[DATA_INDEX]); data_length+=(PARAM_ENCRYPT_MASTER_KEY_LEN+1); break; case CMD_SET_ENC_KEY: status=log_save(MASTER_ENC_KEY_ENTRY_NAME,cmd_buffer,PARAM_ENCRYPT_MASTER_KEY_LEN); data_length++; break; case CMD_GET_ENC_KEY: status=log_read(MASTER_ENC_KEY_ENTRY_NAME,&rsp_packet[DATA_INDEX]); data_length+=(PARAM_ENCRYPT_MASTER_KEY_LEN+1); break; case CMD_ENTER_LOW_POWER_MODE: low_power=1; break; case CMD_SUB1G_RX_MODE: low_power=2; break; case CMD_SUB1G_TX_MODE: low_power=3; break; #ifdef SUPPORT_MODEL_CONFIG case CMD_SET_MODEL_CONF: device_set_model_conf(cmd_buffer,cmd_length); status=device_get_model_conf(); data_length++; break; case CMD_GET_MODEL_CONF: status=device_get_model_conf(); data_length++; break; #endif default: rsp=0; break; } if(rsp){ rsp_packet[LENGTH_INDEX]=data_length+2; if(data_length>1){ rsp_packet[STATUS_INDEX]=status; } tty_cmd_append_crc(&rsp_packet[LENGTH_INDEX],data_length+1); tty_send_packet(rsp_packet,rsp_packet[LENGTH_INDEX]+2); } if(low_power==1){ hal_tty_stop(); subg_sleep(); tty_low_power=1; while(1){ hal_sys_sleep(1); } }else if(low_power==2){ subg_rx(); }else if(low_power==3){ } } /*! ******************************************************** * @name deal_tty_packet * @desc deal the input cmd * *********************************************************/ static void deal_tty_packet(u8 packet_data) { static u8 cmd_status=0; static u8 cmd_length; static u8 cmd_buffer[MAX_CMD_LENGTH]; static u8 cmd_index; switch(cmd_status){ case 0: if(packet_data==PACKET_HEAD){ cmd_status=1; } break; case 1: cmd_length=packet_data; if(cmd_length<3||cmd_length>MAX_CMD_LENGTH){ cmd_status=0; }else{ cmd_status=2; cmd_index=1; cmd_buffer[0]=cmd_length; } break; case 2: if(cmd_index<=cmd_length){ cmd_buffer[cmd_index]=packet_data; cmd_index++; if(cmd_index==cmd_length+1){ if(cal_packet_crc(cmd_buffer,cmd_length-1)==0){ deal_tty_cmd(cmd_buffer[1],&cmd_buffer[2],cmd_length-3); } cmd_status=0; } } break; default: break; } } /*! ******************************************************** * @name tty_thread * @desc tty_thread * *********************************************************/ #define INVALID_U32 (123456789) #define MAX_CMD_LENGTH 64 #define CMD_END_CHAR ('\r') #define BACK_CHAR (0X08) #define DELETE_CHAR (0X7F) #define MAX_SUPPORT_CMD_HISTORY (10) #define PRODUCT_CODE "DEMO" #define $PS1 "root:"PRODUCT_CODE" " #define HAL_OK (0) #define HAL_POINTER_ERROR (2) #define HAL_LENGTH_ERROR (3) #define HAL_PARA_ERROR (4) #define HAL_MIS_ERROR (5) #define HAL_TIME_OUT_ERROR (6) #define HAL_LIMIT_ERROR (7) #define HAL_NO_MEM_ERROR (8) #define HAL_NO_CMD_ERROR (9) #define HAL_PACKET_ERROR (10) #define HAL_SY_EVENT_STOP (11) #define HAL_NO_SUPPORT_ERROR (12) #define HAL_DEV_ERROR (13) #define HAL_STATUS_REPEAT (14) #define HAL_NOT_FIND_ERROR (15) #define HAL_IPC_ADD_UNREACH (16) #define HAL_NO_EXIST (-158) #ifdef DEBUG_NO_PASSWD int debug_auth; #else int debug_auth; #endif LIST_HEAD(cmd_list); static int cmd_number; //struct wake_lock_t debug_wake_lock; //struct queue* tty_rx_queue; static const u8* tty_password="admin"; static u8 g_cmd_buffer[MAX_CMD_LENGTH+1]; static const u8 history_direct[4][3]={ {0X1B,0x5B,0x41},//up {0X1B,0x5B,0x42},//down {0X1B,0x5B,0x44},//left {0X1B,0x5B,0x43}//right }; struct cmd_info cmd_queue[MAX_SUPPORT_CMD_HISTORY]; int cmd_queue_index,cmd_queue_number,cmd_history_index; int g_cmd_cursor_index,cmd_move,g_cmd_index,g_fresh_cmd_line; static int deal_root(const u8 * name,u8 *cmd,int length); int debug_log_level; static void debug_task(); void assert_failed(u8* file, u32 line) { printf("Wrong parameters value: file %s on line %d\r\n", file, line); while(1); } static void debug_rx_data(u8 data,int id) { write_queue(tty_rx_queue,&data); //schedule_work(&debug_work); } static void my_cp_str(u8 *dest,const u8 *source,u8 length) { int cnt; for(cnt=0;cnt<length;cnt++){ dest[cnt]=source[cnt]; } } static int my_com_str(const u8 *source,const u8 *dest,u8 length) { int result; int cnt; result=0; for(cnt=0;cnt<length;cnt++){ if(*source!=*dest){ result=1; break; } source++; dest++; } return result; } static int my_com_str1(const u8 *source,const u8 *dest) { int result; int cnt; result=0; while(1){ if(*source==0||*dest==0){ break; } if(*source!=*dest){ result=1; break; } source++; dest++; } return result; } static int my_com_str2(const u8 *source,const u8 *dest,u8 *length) { int result; int cnt; result=0; cnt=0; while(1){ if(*source==0||*dest==0){ if(*dest){ result=1; }else{ *length=cnt; } break; } if(*source!=*dest){ result=1; *length=cnt; break; } source++; dest++; cnt++; } return result; } int my_convert_str_to_u32(u8 *str,u8 length) { u8 cnt; u32 number; number=0; for(cnt=0;cnt<length;cnt++){ if('0'<=str[cnt]&&'9'>=str[cnt]){ number=number*10+(str[cnt]-'0'); }else{ return -1; } } return number; } int my_convert_str_to_u321(u8 *str,int* start_index,u8 max_index,u8 guard) { int cnt; int number; number=0; cnt=*start_index; while(str[cnt]!=guard&&cnt<max_index){ if('0'<=str[cnt]&&'9'>=str[cnt]){ number=number*10+(str[cnt]-'0'); }else{ number=INVALID_U32; break; } cnt++; } *start_index=cnt+1; return number; } static int deal_cmd(u8* cmd,int length) { int result=HAL_NO_EXIST; struct debug_cmd_info *tmp; u8 cmd_index; list_for_each_entry(tmp, &cmd_list,head) { if(my_com_str2(cmd,tmp->cmd,&cmd_index)==0){ result=tmp->parse(tmp->cmd,&cmd[cmd_index],length-cmd_index); break; } } return result; } static void printf_cmd_list() { struct debug_cmd_info *tmp; int cnt; printf("Support %d cmd\r\n",cmd_number); printf("Use help=[cmd index] to show cmd help,if it have\r\n"); cnt=0; list_for_each_entry(tmp, &cmd_list,head) { printf("Cmd[%d]:%s",cnt,tmp->cmd); if(tmp->help){ printf(" (have help)\r\n"); }else{ printf("\r\n"); } cnt++; } } static void cmd_help(u8 *data,u8 len) { int cnt,cmd_index; struct debug_cmd_info *tmp; if(len==0){ printf_cmd_list(); }else{ if(len<2||data[0]!='='){ goto fromat_error ; } cmd_index=my_convert_str_to_u32(&data[1],len-1); if(cmd_index==-1){ goto fromat_error ; } if(cmd_index>=cmd_number){ printf("Wrong index\r\n"); return; } cnt=0; list_for_each_entry(tmp, &cmd_list,head) { if(cnt==cmd_index){ if(tmp->help){ printf("Cmd:%s,%s\r\n",tmp->cmd,tmp->help); }else{ printf("Cmd:%s,no help\r\n",tmp->cmd); } return; } cnt++; } fromat_error: printf("help format error\r\n"); } } /*! ******************************************************** * @name parse_tty_cmd * @desc deal the input cmd * *********************************************************/ static int parse_tty_cmd(u8* cmd,u8 length) { int result=1; u8 temp; if(length>1){ if(my_com_str2(cmd,"help",&temp)==0){ cmd_help(&cmd[temp],length-temp); result=0; }else{ if(1){ result=deal_cmd(cmd,length); if(result==HAL_NO_EXIST){ printf("Don't support this cmd,enter help to show support cmd\r\n"); } }else{ if(my_com_str1(cmd,"root=")==0){ deal_cmd(cmd,length); } } } } return result; } void enqueue_cmd(u8 *cmd,u8 length) { my_cp_str(&cmd_queue[cmd_queue_index].cmd,cmd,length); cmd_queue[cmd_queue_index].cmd_index=length; cmd_queue[cmd_queue_index].valid=1; cmd_queue_index =(cmd_queue_index+1)%MAX_SUPPORT_CMD_HISTORY; if(cmd_queue_number<MAX_SUPPORT_CMD_HISTORY){ cmd_queue_number++; } } void move_cmd_history_index(u8 up) { int next_index; if(cmd_queue_number){ if(up){ cmd_history_index=(cmd_history_index+1)%cmd_queue_number; }else{ if(cmd_history_index>0){ cmd_history_index=cmd_history_index-1; }else{ cmd_history_index=cmd_queue_number-1; } } } } int retrieve_historycmd(u8 *cmd,u8 *length) { int result; result=0; if(cmd_queue_number){ if(cmd_queue[cmd_history_index].valid){ *length=cmd_queue[cmd_history_index].cmd_index; my_cp_str(cmd,&cmd_queue[cmd_history_index].cmd,*length); result=1; } } return result; } void printf_current_cmd(u8 *cmd,u8 length) { int cnt; for(cnt=0;cnt<length;cnt++){ putchar(cmd[cnt]); } } void printf_bank(u8 length) { int cnt; for(cnt=0;cnt<length;cnt++){ putchar(0X20); } } void printf_delete(u8 length) { int cnt; for(cnt=0;cnt<length;cnt++){ putchar(DELETE_CHAR); } } void printf_back(u8 length) { int cnt; for(cnt=0;cnt<length;cnt++){ putchar(0X08); } } void printf_char(u8 *cmd,u8 length) { int cnt; for(cnt=0;cnt<length;cnt++){ putchar(cmd[cnt]); } } int deal_cmd_history(u8 input) { static u8 history_char_cnt; static u8 history_char[3]; u8 temp_cnt,need_last_index,need_cur_index; int history_index; u32 time; if(input==0X1B){ history_char[0]=input; history_char_cnt=1; }else if(input==0x5B){ if(history_char_cnt==1){ history_char[history_char_cnt]=input; history_char_cnt++; }else{ history_char_cnt=0; } }else if(input==0x41||input==0x42||input==0x43||input==0x44){ if(history_char_cnt==2){ history_char[history_char_cnt]=input; history_char_cnt++; }else{ history_char_cnt=0; } }else{ history_char_cnt=0; } if(history_char_cnt==3){ time= hal_get_ms_tick(); if(time%2){ need_last_index=2; }else{ need_last_index=3; } if(time%10>=5){ need_cur_index=2; }else{ need_cur_index=3; } for(history_index=-1;history_index<3;history_index++){ if(my_com_str(history_char,history_direct[history_index+1],3)==0){ break; } } if(history_index!=3){ history_index++; printf_char(history_char,3); switch(history_index){ case 0: move_cmd_history_index(0); if(retrieve_historycmd(g_cmd_buffer,&temp_cnt)){ putchar('\n'); printf_delete(g_cmd_index+temp_cnt); g_cmd_index=temp_cnt; g_cmd_cursor_index=g_cmd_index; g_fresh_cmd_line=1; } break; case 1: move_cmd_history_index(1); if(retrieve_historycmd(g_cmd_buffer,&temp_cnt)){ printf_delete(g_cmd_index+temp_cnt); g_cmd_index=temp_cnt; g_cmd_cursor_index=g_cmd_index; g_fresh_cmd_line=1; } break; case 2: if(g_cmd_cursor_index>0){ g_cmd_cursor_index--; } break; case 3: if(g_cmd_cursor_index<g_cmd_index){ g_cmd_cursor_index++; } break; } } } return history_char_cnt; } void move_cmd_buffer_right(u8 *cmd_buffer,u8 h_index,u8 cmd_tail_index) { int i; for(i=cmd_tail_index-1;i>=h_index;i--){ cmd_buffer[i+1]=cmd_buffer[i]; } } void move_cmd_buffer_left(u8 *cmd_buffer,u8 h_index,u8 cmd_tail_index) { int i; for(i=h_index;i>1&&i<cmd_tail_index;i++){ cmd_buffer[i-1]=cmd_buffer[i]; } } void printf_cmd(u8 *cmd_buffer,u8 length,u8 cursor_index) { printf_char(cmd_buffer,length); printf_back(length-cursor_index); } void fresh_cmd_line() { printf_cmd(g_cmd_buffer,g_cmd_index,g_cmd_cursor_index); } int debug_regist_cmd(struct debug_cmd_info* info,int len) { int cnt; for(cnt=0;cnt<len;cnt++){ list_add(&info[cnt].head,&cmd_list); cmd_number++; } return cmd_number; } static int deal_logl(const u8 * name,u8 *cmd,int length) { int new_logl; new_logl=my_convert_str_to_u32(cmd,length); if(new_logl>=0&&new_logl<=5){ debug_log_level=new_logl; printf("new logl=%d\r\n",debug_log_level); }else{ printf("logl value invalid value:%d,valid value:0-5\r\n",new_logl); } return 0; } static int deal_root(const u8 * name,u8 *cmd,int length) { if(my_com_str(cmd,tty_password,length)==0){ printf("auth ok\r\n"); debug_auth=1; } else{ printf("wrong passwd\r\n"); } return 0; } static int deal_clear(const u8 * name,u8 *cmd,int length) { printf("\033[H""\033[J"); return HAL_OK; } static int deal_test(const u8 * name,u8 *cmd,int length) { printf("test success!\r\n"); return 0; } struct debug_cmd_info tty_cmd[]= { { .cmd="test=", .help=NULL, .parse=deal_test, }, }; static PT_THREAD (debug_thread(struct pt *pt)) { u8 input; int result; PT_BEGIN(pt); while(read_queue(tty_rx_queue,&input)==QUEUE_TRUE){ result=deal_cmd_history(input); if(g_fresh_cmd_line){ g_fresh_cmd_line=0; fresh_cmd_line(); } if(result==0){ if(input!=CMD_END_CHAR){ if(g_cmd_index<MAX_CMD_LENGTH){ if(g_cmd_cursor_index!=g_cmd_index){ if(input==BACK_CHAR){ move_cmd_buffer_left(g_cmd_buffer,g_cmd_cursor_index,g_cmd_index); if(g_cmd_cursor_index>0){ g_cmd_cursor_index--; g_cmd_index--; } printf_bank(g_cmd_index-g_cmd_cursor_index); printf_delete(1); putchar('\r'); fresh_cmd_line(); }else{ move_cmd_buffer_right(g_cmd_buffer,g_cmd_cursor_index,g_cmd_index); g_cmd_buffer[g_cmd_cursor_index]=input; g_cmd_cursor_index++; g_cmd_index++; putchar('\r'); fresh_cmd_line(); } }else{ if(input==BACK_CHAR){ printf_delete(1); if(g_cmd_index>0){ g_cmd_index--; g_cmd_cursor_index=g_cmd_index; } }else{ putchar(input); g_cmd_buffer[g_cmd_index]=input; g_cmd_index++; g_cmd_cursor_index=g_cmd_index; } } }else{ g_cmd_index=0; g_cmd_cursor_index=g_cmd_index; printf("Cmd too long\r\n"); } }else{ //wake_lock_timeout(&debug_wake_lock,ONE_SECOND*10); printf("\r\n"); g_cmd_buffer[g_cmd_index]=0; cmd_move=0; if(parse_tty_cmd(g_cmd_buffer,g_cmd_index)==0){ enqueue_cmd(g_cmd_buffer,g_cmd_index); cmd_history_index=cmd_queue_index; } g_cmd_index=0; g_cmd_cursor_index=g_cmd_index; printf($PS1); } } } PT_END(pt); } static PT_THREAD (tty_thread(struct pt *pt)) { static u8 input; static struct v_timer count_timer; hal_tty_init(); rev_cmd_time_out=500; v_timer_update(&count_timer,NULL); while(v_timer_wait_ms(&count_timer,rev_cmd_time_out,0)==0){ if(read_queue(tty_rx_queue,&input)==QUEUE_TRUE){ deal_tty_packet(input); } hal_wdt_feed(); } hal_tty_stop(); } /*! ******************************************************** * @name led_init * @desc Init the led module; * *********************************************************/ void tty_init() { hal_tty_init(); tty_rx_queue=new_queue(sizeof(u8),MAX_CMD_LENGTH*2); debug_regist_cmd(tty_cmd,ARRAY_SIZE(tty_cmd)); if(tty_rx_queue==NULL){ log_d("tty creat queue fail\r\n"); }else{ log_d("tty creat queue success!!!!\r\n"); } } /*! ******************************************************** * @name led_task * @desc led task * *********************************************************/ void tty_task() { hal_wdt_feed(); PT_SCHEDULE(debug_thread(&debug_pt)); }帮我解析下这个函数,并且取名为tty.c
09-27
// 修改后的getFileContent方法 async function getFileContent(contentResolver, uri) { try { // 使用同步方法获取文件路径 const filePath = await new Promise((resolve, reject) => { plus.io.resolveLocalFileSystemURL(uri, entry => { resolve(entry.toLocalURL()); }, reject); }); // 通过文件路径获取File对象 const file = await new Promise((resolve, reject) => { plus.io.getFileInfo({ filePath: filePath, success: res => resolve(res), fail: reject }); }); // 读取文件为ArrayBuffer const arrayBuffer = await new Promise((resolve, reject) => { const reader = new plus.io.FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsArrayBuffer(file.file); }); // 转换为Uint8Array const uint8Array = new Uint8Array(arrayBuffer); console.log(`文件读取完成,共 ${uint8Array.length} 字节`); // 生成YMODEM协议数据包 const ymodemPackets = generateYmodemPackets(uint8Array, 'firmware.bin'); return ymodemPackets; } catch (e) { console.error("读取文件内容时发生错误:", e); return null; } } // YMODEM协议数据包生成器 function generateYmodemPackets(fileData, fileName) { const packets = []; // 0号包:文件信息包 const headerPacket = createHeaderPacket(fileName, fileData.length); packets.push(headerPacket); // 数据包(每128字节一个包) let packetNumber = 1; for (let i = 0; i < fileData.length; i += 128) { const chunk = fileData.subarray(i, i + 128); const dataPacket = createDataPacket(chunk, packetNumber++); packets.push(dataPacket); } // EOT结束包 packets.push(new Uint8Array([0x04])); // EOT return packets; } // 创建头部信息包(0号包) function createHeaderPacket(fileName, fileSize) { const packet = new Uint8Array(133); let position = 0; // SOH(0x01) packet[position++] = 0x01; // 包序号0和补码 packet[position++] = 0x00; // 包序号 packet[position++] = 0xFF; // 补码 // 文件名(以null结尾) const nameBuffer = new TextEncoder().encode(fileName + '\0'); packet.set(nameBuffer, position); position += nameBuffer.length; // 文件大小(ASCII字符串) const sizeStr = fileSize.toString() + '\0'; const sizeBuffer = new TextEncoder().encode(sizeStr); packet.set(sizeBuffer, position); position += sizeBuffer.length; // 填充剩余空间为0x00 while (position < 128) { packet[position++] = 0x00; } // 计算CRC(前128字节) const crc = calculateCRC16(packet.subarray(0, 128)); packet[128] = (crc >> 8) & 0xFF; // CRC高位 packet[129] = crc & 0xFF; // CRC低位 return packet; } // 创建数据包(从1号包开始) function createDataPacket(dataChunk, packetNumber) { const packet = new Uint8Array(133); let position = 0; // STX(0x02) packet[position++] = 0x02; // 包序号和补码 const seq = packetNumber % 256; packet[position++] = seq; packet[position++] = 0xFF - seq; // 填充数据 packet.set(dataChunk, position); position += dataChunk.length; // 填充剩余数据(用0x1A填充) while (position < 128) { packet[position++] = 0x1A; // EOF字符 } // 计算CRC(前128字节) const crc = calculateCRC16(packet.subarray(0, 128)); packet[128] = (crc >> 8) & 0xFF; // CRC高位 packet[129] = crc & 0xFF; // CRC低位 return packet; } // CRC-16计算(符合YMODEM规范) function calculateCRC16(data) { let crc = 0x0000; const poly = 0x1021; for (const byte of data) { crc ^= byte << 8; for (let i = 0; i < 8; i++) { crc = crc & 0x8000 ? (crc << 1) ^ poly : crc << 1; crc &= 0xFFFF; } } return crc; } 计算错误,显示文件读取完成,共 0 字节 at pages/index/index.vue:127 16:01:21.158 文件内容: undefined
05-14
/* * Function:spi_stop_module * Param<uint8_t spi_config_index>: * Return<bool>: * REQ IDs: * Description: * Note: */ static bool spi_module_uninit(uint8_t spi_config_index) { bool ret_val = true; uint8_t sin_pcr = 0; uint8_t sout_pcr = 0; uint8_t sck_pcr = 0; volatile struct DSPI_tag* p_dspi_module = NULL; if(spi_config_index >= SPI_MODULES_COUNT) { return false; } else { sin_pcr = spi_config_array[spi_config_index].spi_sin_pcr; sout_pcr = spi_config_array[spi_config_index].spi_sout_pcr; sck_pcr = spi_config_array[spi_config_index].spi_sck_pcr; switch(spi_config_array[spi_config_index].spi_module) { case SPI_MODULE_NUM_0: p_dspi_module = &DSPI_0; break; case SPI_MODULE_NUM_1: p_dspi_module = &DSPI_1; break; case SPI_MODULE_NUM_2: p_dspi_module = &DSPI_2; break; case SPI_MODULE_NUM_3: p_dspi_module = &DSPI_3; break; case SPI_MODULE_NUM_4: p_dspi_module = &DSPI_4; break; case SPI_MODULE_NUM_5: p_dspi_module = &DSPI_5; break; default: ret_val=false; break; } SIU.PCR[sin_pcr].R = 0x0; SIU.PCR[sout_pcr].R = 0x0; SIU.PCR[sck_pcr].R = 0x0; p_dspi_module->MCR.B.MDIS = DSPI_MODULE_CLK_DISABLE; } return ret_val; } bool spi_uninit(void) { bool ret_val = true; uint8_t spi_module_index = 0; for(;spi_module_index < SPI_MODULES_COUNT;spi_module_index++) { if(ret_val) { ret_val = spi_module_uninit(spi_module_index); } else { spi_module_uninit(spi_module_index); } } return ret_val; } /* * Function:spi_communication * Param<uint8_t spi_config_index,uint8_t tx_data,uint8_t* rx_data>: * Return<bool>: * REQ IDs: * Description: * Note: */ bool spi_communication(uint8_t spi_config_index,uint8_t tx_data,uint8_t* rx_data) { bool ret_val= true; uint16_t dspi_tx_timeout = 0; uint16_t dspi_rx_timeout = 0; volatile struct DSPI_tag* p_dspi_module = NULL; switch(spi_config_array[spi_config_index].spi_module) { case SPI_MODULE_NUM_0: p_dspi_module = &DSPI_0; break; case SPI_MODULE_NUM_1: p_dspi_module = &DSPI_1; break; case SPI_MODULE_NUM_2: p_dspi_module = &DSPI_2; break; case SPI_MODULE_NUM_3: p_dspi_module = &DSPI_3; break; case SPI_MODULE_NUM_4: p_dspi_module = &DSPI_4; break; case SPI_MODULE_NUM_5: p_dspi_module = &DSPI_5; break; default: ret_val = false; break; } (void)p_dspi_module->POPR.R; p_dspi_module->SR.R = 0x90020000; (void)p_dspi_module->POPR.R; p_dspi_module->PUSHR.B.TXDATA = tx_data; /* Write data transferred by DSPI */ while(DSPI_TRANSFER_NOT_COMPLETE == p_dspi_module->SR.B.TCF) { if(dspi_tx_timeout++ > US(500)) { ret_val = false; break; } } p_dspi_module->SR.B.TCF = DSPI_TRANSFER_COMPLETE; /* Clear TCF by writing 1 */ while (DSPI_RX_FIFO_IS_EMPTY == p_dspi_module->SR.B.RFDF) { if(dspi_rx_timeout++ > US(500)) { ret_val = false; break; } } if(rx_data == NULL) { (void)p_dspi_module->POPR.B.RXDATA; } else { *rx_data = (uint8_t)p_dspi_module->POPR.B.RXDATA; /* Read data received by DSPI */ } p_dspi_module->SR.B.RFDF = DSPI_RX_FIFO_IS_NOT_EMPTY; /* Clear RDRF by writing 1 */ return ret_val; } /* * Function:spi_communication_dw * Param<uint8_t spi_config_index,uint16_t tx_data,uint16_t* rx_data>: * Return<bool>: * REQ IDs: * Description: * Note: */ bool spi_communication_dw(uint8_t spi_config_index,uint16_t tx_data,uint16_t* rx_data) { bool ret_val = true; uint16_t dspi_tx_timeout = 0; uint16_t dspi_rx_timeout = 0; uint8_t temp_frame_num_bits = 0; volatile struct DSPI_tag* p_dspi_module = NULL; switch(spi_config_array[spi_config_index].spi_module) { case SPI_MODULE_NUM_0: p_dspi_module = &DSPI_0; break; case SPI_MODULE_NUM_1: p_dspi_module = &DSPI_1; break; case SPI_MODULE_NUM_2: p_dspi_module = &DSPI_2; break; case SPI_MODULE_NUM_3: p_dspi_module = &DSPI_3; break; case SPI_MODULE_NUM_4: p_dspi_module = &DSPI_4; break; case SPI_MODULE_NUM_5: p_dspi_module = &DSPI_5; break; default: ret_val = false; break; } temp_frame_num_bits = spi_config_array[spi_config_index].data_length - 1; if(temp_frame_num_bits >= DSPI_FRAME_SZIE_NUM_MAX) { ret_val = false; } else { p_dspi_module->CTAR[0].B.FMSZ =(dspi_one_frame_num_bits_t)temp_frame_num_bits; } (void)p_dspi_module->POPR.R; p_dspi_module->SR.R = 0x90020000; (void)p_dspi_module->POPR.R; p_dspi_module->PUSHR.B.TXDATA = tx_data; /* Write data transferred by DSPI */ while(DSPI_TRANSFER_NOT_COMPLETE == p_dspi_module->SR.B.TCF) { if(dspi_tx_timeout++ > US(500)) { ret_val = false; break; } } p_dspi_module->SR.B.TCF = DSPI_TRANSFER_COMPLETE; /* Clear TCF by writing 1 */ while (DSPI_RX_FIFO_IS_EMPTY == p_dspi_module->SR.B.RFDF) { if(dspi_rx_timeout++ > US(500)) { ret_val = false; break; } } if(rx_data == NULL) { (void)p_dspi_module->POPR.B.RXDATA; } else { *rx_data = (uint16_t)p_dspi_module->POPR.B.RXDATA;/* Read data received by DSPI */ } p_dspi_module->SR.B.RFDF = DSPI_RX_FIFO_IS_NOT_EMPTY;/* Clear RDRF by writing 1 */ return ret_val; } // CRC-8计算 (多项式: X^8 + X^2 + X + 1, 初始值0x41) uint8_t Calculate_CRC8(const uint8_t *data, uint8_t len) { uint8_t crc = 0x41; uint8_t i; uint8_t j; for (i = 0; i < len; i++) { crc ^= data[i]; for (j = 0; j < 8; j++) { if (crc & 0x80) { crc = (crc << 1) ^ 0x07; } else { crc <<= 1; } } } return crc; } // CRC-10计算 (多项式: X^10 + X^7 + X^3 + X^2 + X + 1, 初始值0x10) uint16_t Calculate_CRC10(const uint8_t *data, uint8_t len) { uint16_t crc = 0x10; uint8_t i; uint8_t j; for ( i = 0; i < len; i++) { crc ^= (data[i] << 2); // 数据左移2位对齐CRC10 for ( j = 0; j < 8; j++) { if (crc & 0x200) { // 检测第10位 crc = (crc << 1) ^ 0x26D; // 多项式掩码 } else { crc <<= 1; } } } return crc & 0x3FF; // 保留10位 } static uint8_t rolling_count = 0; // 全局计数器 // 更新Rolling Count(6位) uint8_t Update_RollingCount() { rolling_count = (rolling_count + 1) & 0x3F; // 取低6位 return rolling_count; } bool Send_SystemCommand(uint8_t cmd) { uint8_t packet[2]; bool ret; packet[0] = cmd; packet[1] = Calculate_CRC8(packet, 1); // 计算命令CRC ret = spi_communication(SPI_CONFIG_INDEX, packet[0], NULL) && spi_communication(SPI_CONFIG_INDEX, packet[1], NULL); if (cmd != 0xFA && cmd != 0xFC) { // 读命令不更新Rolling Count Update_RollingCount(); } return ret; } bool Write_GMD1006(uint8_t cmd, const uint8_t *data) { uint8_t packet[11]; // 8+8+48+6+10 = 80位 → 10字节 uint16_t crc10; uint8_t i; bool ret; // 构造命令部分tamenchaowo packet[0] = cmd; packet[1] = Calculate_CRC8(packet, 1); // 填充数据 if(data != NULL) { memcpy(&packet[2], data, 6); } // 48位数据 // 添加Rolling Count和CRC10 packet[8] = Update_RollingCount() << 2; // 低6位左移对齐 crc10 = Calculate_CRC10(packet, 9); // 计算前9字节CRC10 packet[9] = (crc10 >> 2) & 0xFF; // CRC10分高低字节 packet[10] = crc10 & 0x03; // 发送完整数据包 ESP32_CS_ENABLE(); ret = true; for(i = 0; i < 11; i++) { if(!spi_communication(SPI_CONFIG_INDEX, packet[i], NULL)) { ret = false; break; } } ESP32_CS_DISABLE(); return ret; } bool Write_GMD1032(uint8_t cmd, const uint8_t *data) { uint8_t packet[11]; uint16_t crc10; uint8_t i; bool ret; // 构造命令部分tamenchaowo packet[0] = cmd; packet[1] = Calculate_CRC8(packet, 1); // 填充数据 if(data != NULL) { memcpy(&packet[2], data, 6); }// 48位数据 // 添加Rolling Count和CRC10 packet[8] = Update_RollingCount() << 2; // 低6位左移对齐 crc10 = Calculate_CRC10(packet, 9); // 计算前9字节CRC10 packet[9] = (crc10 >> 2) & 0xFF; // CRC10分高低字节 packet[10] = crc10 & 0x03; ret = true; for(i = 0; i < 11; i++) { if(!spi_communication(SPI_CONFIG_INDEX, packet[i], NULL)) { ret = false; break; } } return ret; } bool Read_GMD1006(uint8_t cmd, uint8_t *data, uint8_t *rcnt) { uint8_t tx_packet[2], rx_packet[8]; uint16_t crc10; uint8_t i; if(data == NULL || rcnt == NULL) { return false; } // 发送命令 tx_packet[0] = cmd; tx_packet[1] = Calculate_CRC8(tx_packet, 1); if(!spi_communication(SPI_CONFIG_INDEX, tx_packet[0], NULL) || !spi_communication(SPI_CONFIG_INDEX, tx_packet[1], NULL)) { return false; } // 接收数据 for ( i = 0; i < 8; i++) { if(!spi_communication(SPI_CONFIG_INDEX, 0xFF, &rx_packet[i])) { return false; } } // 校验CRC10 crc10 = Calculate_CRC10(rx_packet, 7); // 前7字节(48+6位) if (((crc10 >> 8) != rx_packet[6]) || ((crc10 & 0xFF) != rx_packet[7])) { return false; } // 提取数据 memcpy(data, rx_packet, 6); // 48位数据 *rcnt = rx_packet[6] >> 2; // 提取Rolling Count return true; } bool Read_GMD1032(uint8_t cmd, uint8_t *data, uint8_t *rcnt) { uint8_t tx_packet[2], rx_packet[8]; uint16_t crc10; uint8_t i; if(data == NULL || rcnt == NULL) { return false; } tx_packet[0] = cmd; tx_packet[1] = Calculate_CRC8(tx_packet, 1); if(!spi_communication(SPI_CONFIG_INDEX, tx_packet[0], NULL) || !spi_communication(SPI_CONFIG_INDEX, tx_packet[1], NULL)) { return false; } for ( i = 0; i < 8; i++) { if(!spi_communication(SPI_CONFIG_INDEX, 0xFF, &rx_packet[i])) { return false; } } crc10 = Calculate_CRC10(rx_packet, 7); if (((crc10 >> 8) != rx_packet[6]) || ((crc10 & 0xFF) != rx_packet[7])) { return false; } memcpy(data, rx_packet, 6); *rcnt = rx_packet[6] >> 2; return true; } bool Read_DaisyChain(uint8_t cmd, uint8_t *data_1006, uint8_t *rcnt_1006, uint8_t *data_1034, uint8_t *rcnt_1034) { uint8_t status, crc_status; uint8_t i; uint8_t tx_packet[2]; uint8_t rx_1006[8]; uint8_t rx_1034[8]; // 发送读命令 //tx_packet[2] = {cmd, Calculate_CRC8_SingleByte(cmd)}; tx_packet[0] = cmd; tx_packet[1] = Calculate_CRC8(&cmd, 1); spi_communication(SPI_CONFIG_INDEX, tx_packet[0], NULL); spi_communication(SPI_CONFIG_INDEX, tx_packet[1], NULL); // 接收GMD1006状态 spi_communication(SPI_CONFIG_INDEX, 0xFF, &status); spi_communication(SPI_CONFIG_INDEX, 0xFF, &crc_status); // 校验状态CRC if (crc_status != Calculate_CRC8(&status, 1)) { return false; } // 接收GMD1006数据 for ( i = 0; i < 8; i++) { spi_communication(SPI_CONFIG_INDEX, 0xFF, &rx_1006[i]); } // 接收GMD1034数据(菊花链末端) for ( i = 0; i < 8; i++) { spi_communication(SPI_CONFIG_INDEX, 0xFF, &rx_1034[i]); } // 提取数据(省略CRC校验步骤) memcpy(data_1006, rx_1006, 6); *rcnt_1006 = rx_1006[6] >> 2; memcpy(data_1034, rx_1034, 6); *rcnt_1034 = rx_1034[6] >> 2; return true; } bool get_bi() { uint8_t cfg0_data[6] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }; uint8_t data_1006[6], data_1032[6], rcnt_1006, rcnt_1032; // 清除状态寄存器 Send_SystemCommand(0x01); // 写CFG0寄存器 Write_GMD1032(0x2A, cfg0_data); Write_GMD1032(0x40, cfg0_data); // 读菊花链数据 //if (Read_DaisyChain(0x8F, data_1006, rcnt_1006, data_1034, rcnt_1034)) //{ //} Read_GMD1032(0xC0, data_1032, &rcnt_1032); }
11-22
分析如下RTSP函数的流程,并指明哪里实际发送了数据包 int TPSendRtpQueueCb(trans_session_desc_t *desc, trans_stream_t *stream) { RTPDATAFRAME *p_frame = NULL; TPRTSPSERVERSESSION *pSession = NULL; TPRTPPACKAGE *ptr_rtp_package = NULL; int iSessionID = 0; int sendmute = 0; unsigned char mutebuf[RTP_MAX_PACKET_SIZE] = {0}; unsigned char RTPextern[RTP_MAX_EXTEN_LEN + 1] = {0}; unsigned char pucPrefix[RTP_PREFIX_SIZE] = {0}; int externtionlen = 0; unsigned long cur_time = 0; struct iovec iov[RTP_MAX_SEND_NUM * 3]; int ret = 0; RETRY_INFO *p_retry_info = NULL; RETRY_INFO tmp_retry_info = {0}; unsigned long long ullCurrentTime = 0; RETURN_VALUE_IF(!desc || !desc->send_data || !desc->priv || !stream->package, 0); p_frame = (RTPDATAFRAME *)desc->send_data; pSession = (TPRTSPSERVERSESSION *)desc->priv; ptr_rtp_package = (TPRTPPACKAGE )stream->package; / 可能底层给的数据是错的,这里就可能出现打包异常,增加一个防护机制 */ RETURN_VALUE_IF(!p_frame->rtp_head_pos || !p_frame->rtp_payload_pos, 0); if(pSession->pRTPServer->bIsRunning != 1) { return 0; } if (pSession->iAudioVideo == RTSP_AUDIO) { pSession->getIFrame = 1; } if (pSession->iAudioVideo == RTSP_META_DATA) { pSession->getIFrame = 1; } if ( ptr_rtp_package->av_codec >= TP_ENCODE_TYPE_AUDIO_MIN && ptr_rtp_package->av_codec <= TP_ENCODE_TYPE_AUDIO_MAX) { iSessionID = RTP_SESSION_AUDIO; } #ifdef RTSP_USE_SMART_DATA else if (TP_ENCODE_TYPE_VIDEO_SMART == ptr_rtp_package->av_codec) { iSessionID = RTP_SESSION_SMART_DATA; } #endif else if (TP_ENCODE_TYPE_VIDEO_META == ptr_rtp_package->av_codec) { iSessionID = RTP_SESSION_META_DATA; } else if (TP_ENCODE_TYPE_VIDEO_SMART != ptr_rtp_package->av_codec) { iSessionID = RTP_SESSION_VIDEO; } //回放数据流中同时有音频与视频数据,onvif回放会出现只拉取音频/视频的操作,此处判断过虑不需要的数据,防止空指针引用 if (pSession->pRTPServer == NULL || pSession->pRTPServer->pSessions[iSessionID] == NULL) { return 0; } if (pSession->iSessionState == TPHTTP_SESSION_STATE_PLAYING && pSession->iCurStreamID == TPRTP_STREAM_ID_ONVIF_REPLAY && ptr_rtp_package->DataFrame.iExtension && pSession->end_time > 0 && pSession->end_time <= (ptr_rtp_package->DataFrame.RTPHeaderExtension.piAddr[0] - SECS_FROM_1900_TO_1970)) { pSession->iSessionState = TPHTTP_SESSION_STATE_PAUSE; pSession->start_time = -1; trans_pause(&pSession->vedio_desc); } p_retry_info = (iSessionID == RTP_SESSION_AUDIO) ? &pSession->audio_retry_info : &pSession->video_retry_info; if (iSessionID != RTP_SESSION_AUDIO && iSessionID != RTP_SESSION_VIDEO) { p_retry_info = &tmp_retry_info; } //没收到I帧数据的话其他的数据丢掉 if ((!pSession->getIFrame && (!ptr_rtp_package->is_iframe || !ptr_rtp_package->is_first_rtp || p_retry_info->retry_flag)) && pSession->iStreamType != TPRTP_STREAM_TYPE_VIDEO_JPEG) { p_retry_info->send_pos = 0; p_retry_info->retry_flag = 0; return 0; } if (!pSession->getIFrame && pSession->ulFirstVideoRTPTS == 0) { pSession->ulFirstVideoRTPTS = (unsigned long)ptr_rtp_package->curPTS; } else if (pSession->getIFrame && pSession->ulFirstAudioRTPTS == 0 && iSessionID == RTP_SESSION_AUDIO) { pSession->ulFirstAudioRTPTS = (unsigned long)ptr_rtp_package->curPTS; } #ifdef RTSP_USE_SMART_DATA else if (pSession->getIFrame && pSession->ulFirstSmartRTPTS == 0 && iSessionID == RTP_SESSION_SMART_DATA) { pSession->ulFirstSmartRTPTS = (unsigned long)ptr_rtp_package->curPTS; } #endif else if (pSession->getIFrame && pSession->ulFirstSmartRTPTS == 0 && iSessionID == RTP_SESSION_META_DATA) { pSession->ulFirstSmartRTPTS = (unsigned long)ptr_rtp_package->curPTS; } pSession->getIFrame = 1; rtsp_send_notify(pSession); #ifdef TAPO_USE_RTSP_MULTITRANS //流控 if (pSession->start_time != -1 && pSession->windowsize != 0 && pSession->stream_seq - pSession->recv_size > pSession->windowsize) { set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); p_retry_info->send_pos = 0; return RTSP_SEND_RETRY; } #endif /* 如果音频或视频流没有传输完,则不能交叉传输,需要将剩余数据发完,其他流走重传流程 */ if ((pSession->video_retry_info.send_pos != 0 && iSessionID != RTP_SESSION_VIDEO) || (pSession->audio_retry_info.send_pos != 0 && iSessionID != RTP_SESSION_AUDIO)) { set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); p_retry_info->sn = p_frame->iSN; // RTSP_ERROR(“cannot send all data send retry, client ip:%s, dump socket:%d”, pSession->pcClientIP, pSession->iSock); // tcp_dump_info(pSession->iSock); return RTSP_SEND_RETRY; } #ifdef TAPO_USE_RTSP_MULTITRANS //半双工时有语音数据时不发送音频数据 if (RTSPGetMute() == 1 && iSessionID == RTP_SESSION_AUDIO) { sendmute = 1; } #endif if (ptr_rtp_package->av_codec != TP_ENCODE_TYPE_UNDET && iSessionID == RTP_SESSION_VIDEO) { char codestr[TEMP_FORMAT_LEN]; if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_VIDEO_H264) snprintf(codestr, TEMP_FORMAT_LEN, “H264”); else if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_VIDEO_H265) snprintf(codestr, TEMP_FORMAT_LEN, “H265”); else if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_SNAPSHOT_JPEG) { snprintf(codestr, TEMP_FORMAT_LEN, “JPEG”); } else { return 0; } if (strcmp(pSession->SDPServer.SDPInfo.MediaInfo.pcVideoFormat, codestr) != 0) { snprintf(pSession->SDPServer.SDPInfo.MediaInfo.pcVideoFormat, 16, codestr); #ifdef TAPO_USE_RTSP_MULTITRANS RTSPSessionNotificationResChange(pSession, “HD”); #endif } } #ifdef TAPO_USE_RTSP_MULTITRANS /* 仅当multitrans时 */ if (MULTITRANS_NONE != pSession->multitrans_business_type && iSessionID == RTP_SESSION_AUDIO) { char codestr[TEMP_FORMAT_LEN]; if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_AUDIO_G711A) snprintf(codestr, TEMP_FORMAT_LEN, “PCMA”); else if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_AUDIO_G711U) snprintf(codestr, TEMP_FORMAT_LEN, “PCMU”); else return 0; if (strcmp(pSession->SDPServer.SDPInfo.MediaInfo.pcAudioFormat, codestr) != 0) { snprintf(pSession->SDPServer.SDPInfo.MediaInfo.pcAudioFormat, 16, codestr); RTSPSessionNotificationResChange(pSession, “HD”); } } #endif if(RTP4SIsMulticast(pSession->pRTPServer) && p_frame->multicast_send == 1) { return 0; } else if(RTP4SIsMulticast(pSession->pRTPServer)) { p_frame->multicast_send = 1; } if ((iSessionID == RTP_SESSION_AUDIO || iSessionID == RTP_SESSION_VIDEO)) { if (p_retry_info->send_pos > 0) { if (iSessionID == RTP_SESSION_AUDIO) { pSession->usCurAudioRTPSN = p_retry_info->sn; p_frame->iSN = pSession->usCurAudioRTPSN++; } else { pSession->usCurVideoRTPSN = p_retry_info->sn; p_frame->iSN = pSession->usCurVideoRTPSN++; } RtspPutUshortToBufBE((unsigned char *)p_frame->rtp_head_pos + 2, p_frame->iSN); } else { if (iSessionID == RTP_SESSION_AUDIO) { p_frame->iSN = pSession->usCurAudioRTPSN++; } else { p_frame->iSN = pSession->usCurVideoRTPSN++; } RtspPutUshortToBufBE((unsigned char *)p_frame->rtp_head_pos + 2, p_frame->iSN); } } RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 8, pSession->pRTPServer->pSessions[iSessionID]->iClientSSRC); RtspGetUintFromBufBE((unsigned char *)p_frame->rtp_head_pos + 4, (unsigned int *)&cur_time); RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4, cur_time - ((iSessionID == RTP_SESSION_VIDEO) ? pSession->ulFirstVideoRTPTS : pSession->ulFirstAudioRTPTS)); #ifdef RTSP_USE_SMART_DATA if (RTP_SESSION_SMART_DATA == iSessionID) { RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4, cur_time - pSession->ulFirstSmartRTPTS ); } #endif if (RTP_SESSION_META_DATA == iSessionID) { RtspPutUintToBufBE((unsigned char )p_frame->rtp_head_pos + 4, cur_time - pSession->ulFirstSmartRTPTS ); } #ifdef TAPO_USE_RTSP_MULTITRANS if (ptr_rtp_package->is_first_rtp && pSession->multitrans_business_type != MULTITRANS_NONE) { / I帧 */ if(ptr_rtp_package->is_iframe == 1) { *(p_frame->rtp_head_pos) |= RTP_HEADER_EXTENTION_BIT; /* 只解码I帧 / if (ptr_rtp_package->is_decode_only == 1) { externtionlen = RtspAddExtention(RTPextern, ptr_rtp_package->utc_time, RTP_EXTEN_DECODE_ONLY_BIT); } / 普通I帧 / else { externtionlen = RtspAddExtention(RTPextern, ptr_rtp_package->utc_time, RTP_EXTEN_I_FRAME_BIT); } } / 虚拟I帧 */ else if (ptr_rtp_package->is_virtual_iframe == 1) { *(p_frame->rtp_head_pos) |= RTP_HEADER_EXTENTION_BIT; externtionlen = RtspAddExtention(RTPextern, ptr_rtp_package->utc_time, RTP_EXTEN_VIRTUAL_FRAME_BIT); } } #endif /* TP NVR虚拟I帧的RTP包要包含扩展字段 */ if (pSession->bIsVirtualIFrameEnabled && ptr_rtp_package->is_virtual_iframe == 1 #ifdef TAPO_USE_RTSP_MULTITRANS && pSession->multitrans_business_type == MULTITRANS_NONE #endif ) { *(p_frame->rtp_head_pos) |= RTP_HEADER_EXTENTION_BIT; externtionlen = RtspAddAvbrExtention(RTPextern); } int need_encrypt = pSession->bIsRTPSessionCrypto[iSessionID] && (iSessionID!=RTP_SESSION_VIDEO || (ptr_rtp_package->is_iframe && pSession->rtp_send_data_index < SRTP_ENCRYPT_RTP_NUM)); // 标识加密的情况 if (pSession->bIsRTPSessionCrypto[iSessionID] == 1 && iSessionID != RTP_SESSION_SMART_DATA) { if ( (ptr_rtp_package->is_iframe && pSession->rtp_send_data_index < SRTP_ENCRYPT_RTP_NUM) || iSessionID == RTP_SESSION_AUDIO) { (p_frame->rtp_head_pos) |= RTP_HEADER_EXTENTION_BIT; externtionlen = RtspAddSrtpExtention(RTPextern); } } if (iSessionID == RTP_SESSION_SMART_DATA) { //common_version为0,表示这是不支持SRTP 2.0的NVR客户端,需要按照SRTP 1.0的方式对智能数据帧进行全部加密 //判断RTP包索引,如果相等则表示当前RTP需要加密 if(pSession->common_version == 0 || (g_smart_data_is_first_rtp_set == 1 && g_smart_data_rtp_index[smart_data_rtp_index] == pSession->rtp_send_data_index)) { (p_frame->rtp_head_pos) |= RTP_HEADER_EXTENTION_BIT; externtionlen = RtspAddSrtpExtention(RTPextern); smart_data_rtp_index = (smart_data_rtp_index + 1) % 10; need_encrypt = 1; } else { need_encrypt = 0; } } if(pSession->bRTPOverTCP) { int rtp_length = p_frame->rtp_head_len + p_frame->rtp_payload_len + externtionlen; if (need_encrypt) { rtp_length += SRTP_TAG_SIZE; } int send_count = 0; int expectlen = 0; int rtp_cur_index = pSession->rtp_send_data_index; int i = 0; pucPrefix[0] = ‘$’; pucPrefix[1] = pSession->piTCPDataID[iSessionID]; pucPrefix[2] = rtp_length >> 8; pucPrefix[3] = rtp_length & 0xff; iov[send_count].iov_base = pucPrefix; iov[send_count++].iov_len = 4; int fu_header_len = p_frame->rtp_head_len - RTP_HEADER_SIZE; if (externtionlen > 0) { iov[send_count].iov_base = p_frame->rtp_head_pos; iov[send_count++].iov_len = RTP_HEADER_SIZE; iov[send_count].iov_base = RTPextern; iov[send_count++].iov_len = externtionlen; if(fu_header_len > 0) { // 如果没有加密则把fu放在header中 if (!need_encrypt) { iov[send_count].iov_base = p_frame->rtp_head_pos + RTP_HEADER_SIZE; iov[send_count++].iov_len = fu_header_len; } } } else { iov[send_count].iov_base = p_frame->rtp_head_pos; iov[send_count++].iov_len = need_encrypt ? RTP_HEADER_SIZE : p_frame->rtp_head_len; } iov[send_count].iov_base = sendmute ? mutebuf : p_frame->rtp_payload_pos; iov[send_count++].iov_len = p_frame->rtp_payload_len; pSession->rtp_send_data[rtp_cur_index].rtp_head_size = 0; for (i = 0; i < send_count - 1; i ++) { memcpy(pSession->rtp_send_data[rtp_cur_index].rtp_header_data + pSession->rtp_send_data[rtp_cur_index].rtp_head_size, iov[i].iov_base, iov[i].iov_len); pSession->rtp_send_data[rtp_cur_index].rtp_head_size += iov[i].iov_len; } if (need_encrypt) { // 重传不需要再次分配内存加密 if (!p_retry_info->send_pos) { // 如果有fu,则需要填充到payload前面,这里把fu和payload拼起来放在加密后的地址,原地加密 unsigned char cur_encrypted_pos = pSession->encrypted_pos+rtp_cur_indexRTP_MAX_PACKET_SIZE; if (fu_header_len > 0) { memcpy(cur_encrypted_pos, p_frame->rtp_head_pos+RTP_HEADER_SIZE, fu_header_len); memcpy(cur_encrypted_pos + fu_header_len, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); if (0 != SRTPEncrypt(&pSession->cryptoCtx, cur_encrypted_pos, cur_encrypted_pos, p_frame->rtp_payload_len + fu_header_len, p_frame->iSN)) { RTSP_ERROR(“SRTP encrypt failed, go to next frame”); return 0; } } else { if (0 != SRTPEncrypt(&pSession->cryptoCtx, cur_encrypted_pos, p_frame->rtp_payload_pos, p_frame->rtp_payload_len, p_frame->iSN)) { RTSP_ERROR(“SRTP encrypt failed, go to next frame”); return 0; } } pSession->rtp_send_data[rtp_cur_index].rtp_encrypted_payload_pos = cur_encrypted_pos; pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos = iov[i].iov_base; pSession->rtp_send_data[rtp_cur_index].rtp_playload_size = iov[i].iov_len; pSession->rtp_send_data[rtp_cur_index].rtp_encryped_payload_size = iov[i].iov_len + fu_header_len; //生成auth tag unsigned int total_len = pSession->rtp_send_data[rtp_cur_index].rtp_head_size + pSession->rtp_send_data[rtp_cur_index].rtp_encryped_payload_size; memset(pSession->auth_mem, 0, (RTP_MAX_PACKET_SIZE2)); memcpy(pSession->auth_mem, pSession->rtp_send_data[rtp_cur_index].rtp_header_data, pSession->rtp_send_data[rtp_cur_index].rtp_head_size); memcpy(pSession->auth_mem + pSession->rtp_send_data[rtp_cur_index].rtp_head_size, pSession->rtp_send_data[rtp_cur_index].rtp_encrypted_payload_pos, pSession->rtp_send_data[rtp_cur_index].rtp_encryped_payload_size); if (0 != SRTPAuthenticate(&pSession->cryptoCtx, p_frame->rtp_auth_tag, pSession->auth_mem, total_len, p_frame->iSN)) { RTSP_ERROR(“SRTP authenticate failed, go to next frame”); return 0; } memcpy(pSession->rtp_send_data[rtp_cur_index].rtp_auth_tag, p_frame->rtp_auth_tag, SRTP_TAG_SIZE); pSession->rtp_send_data[rtp_cur_index].rtp_tag_size = SRTP_TAG_SIZE; } } else { pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos = iov[i].iov_base; pSession->rtp_send_data[rtp_cur_index].rtp_playload_size = iov[i].iov_len; } pSession->rtp_send_data_index++; /还原设置的拓展标记,避免对其他会话的影响/ if((p_frame->rtp_head_pos) & RTP_HEADER_EXTENTION_BIT) { *(p_frame->rtp_head_pos) &= ~RTP_HEADER_EXTENTION_BIT; } RtspPutUintToBufBE((unsigned char )p_frame->rtp_head_pos + 4, cur_time); if (pSession->rtp_send_data_index >= RTP_MAX_SEND_NUM || desc->frame_end #ifdef SUPPORT_WEBSOCK_EX_HEADER || pSession->wsp_status != NOT_WSP_PROTO #endif ) { / 如果是重传,则他有一个起始pos,不是packet index,而是一个发送的数据量 */ int send_pos = p_retry_info->send_pos; int iov_index = 0; int left_size = 0; int send_len = 0; int rtp_index = 0; expectlen = 0; if (send_pos > 0) { while (send_pos >= send_len) { if (rtp_index >= RTP_MAX_SEND_NUM) { RTSP_ERROR(“invalid rtp_index, array out of bounds”); return TP_TCP_EC_FAILURE; } if (pSession->rtp_send_data[rtp_index].rtp_tag_size == SRTP_TAG_SIZE) // encrypted packet { send_len += (pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size + pSession->rtp_send_data[rtp_index].rtp_tag_size); rtp_index++; } else { send_len += (pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_playload_size); rtp_index++; } } rtp_index–; left_size = send_len - send_pos; int encrypted = pSession->rtp_send_data[rtp_index].rtp_tag_size == SRTP_TAG_SIZE; // 根据tag size判断rtp是否加密 if (encrypted == 1) { if (left_size > pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size + pSession->rtp_send_data[rtp_index].rtp_tag_size) { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_header_data + (pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size + pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_tag_size - left_size); iov[iov_index++].iov_len = left_size - pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size - pSession->rtp_send_data[rtp_index].rtp_tag_size; expectlen += (left_size - pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size - pSession->rtp_send_data[rtp_index].rtp_tag_size); iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_encrypted_payload_pos; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size; expectlen += pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size; iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_auth_tag; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_tag_size; expectlen += pSession->rtp_send_data[rtp_index].rtp_tag_size; } else if (left_size > pSession->rtp_send_data[rtp_index].rtp_tag_size) { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_encrypted_payload_pos + (pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size + pSession->rtp_send_data[rtp_index].rtp_tag_size - left_size); iov[iov_index++].iov_len = left_size - pSession->rtp_send_data[rtp_index].rtp_tag_size; expectlen += (left_size - pSession->rtp_send_data[rtp_index].rtp_tag_size); iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_auth_tag; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_tag_size; expectlen += pSession->rtp_send_data[rtp_index].rtp_tag_size; } else { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_auth_tag + pSession->rtp_send_data[rtp_index].rtp_tag_size - left_size; iov[iov_index++].iov_len = left_size; expectlen += left_size; } rtp_index++; } else { if (left_size > pSession->rtp_send_data[rtp_index].rtp_playload_size) { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_header_data + (pSession->rtp_send_data[rtp_index].rtp_playload_size + pSession->rtp_send_data[rtp_index].rtp_head_size - left_size); iov[iov_index++].iov_len = left_size - pSession->rtp_send_data[rtp_index].rtp_playload_size; expectlen += left_size - pSession->rtp_send_data[rtp_index].rtp_playload_size; left_size = pSession->rtp_send_data[rtp_index].rtp_playload_size; } iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_playload_pos + pSession->rtp_send_data[rtp_index].rtp_playload_size - left_size; iov[iov_index++].iov_len = left_size; expectlen += left_size; rtp_index++; } } for (; rtp_index < pSession->rtp_send_data_index; rtp_index++) { int encrypted = pSession->rtp_send_data[rtp_index].rtp_tag_size == SRTP_TAG_SIZE; if (encrypted == 1) { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_header_data; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_head_size; iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_encrypted_payload_pos; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size; iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_auth_tag; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_tag_size; expectlen += (pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_encryped_payload_size + pSession->rtp_send_data[rtp_index].rtp_tag_size); } else { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_header_data; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_head_size; iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_playload_pos; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_playload_size; expectlen += (pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_playload_size); } } if(iSessionID == RTP_SESSION_SMART_DATA) { RTSP_DEBUG(“start send smart data”); } ret = RTSPSessionSendV(pSession, iov, iov_index); if (ret == TP_TCP_EC_FAILURE && iSessionID != RTP_SESSION_SMART_DATA) { pSession->pRTPServer->iRTPStatus = RTP_STATUS_SEND_FAILURE; set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); p_retry_info->send_pos = 0; p_retry_info->sn = p_frame->iSN; pSession->rtp_send_data_index–; return TP_TCP_EC_FAILURE; } else if(ret != expectlen && iSessionID != RTP_SESSION_SMART_DATA) // 接收方缓冲区满了,发不出去了 { set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); // 会把sn记录成暂时不用的payloadCTX中的sn,下面手动更新成p_frame中的sn p_retry_info->send_pos += ret > 0 ? ret : 0; p_retry_info->sn = p_frame->iSN; pSession->rtp_send_data_index–; ullCurrentTime = tpgetboottime(); pSession->send_retry_times++; g_tel_rtsp_retry_cnt++; if (pSession->ullTimeForSendRetry == 0 || pSession->ullTimeForSendRetry + SEND_RETRY_PRINT_TIMEOUT < ullCurrentTime) { RTSP_ERROR(“cannot send all data send retry, client ip:%s, dump socket:%d, send_retry_times:%d, already send:%d, expect send:%d”, pSession->pcClientIP, pSession->iSock, pSession->send_retry_times, ret, expectlen); tcp_dump_info(pSession->iSock); pSession->ullTimeForSendRetry = ullCurrentTime; pSession->send_retry_times = 0; #ifdef TELEMETRY_SUPPORT TELEMETRY_RTSP telemetry_rtsp; memset(&telemetry_rtsp, 0, sizeof(telemetry_rtsp)); ds_read(TELEMETRY_RTSP_PATH, &telemetry_rtsp, sizeof(TELEMETRY_RTSP)); telemetry_rtsp.rtsp_retry_count = g_tel_rtsp_retry_cnt; ds_write(TELEMETRY_RTSP_PATH, &telemetry_rtsp, sizeof(TELEMETRY_RTSP)); #endif } return RTSP_SEND_RETRY; } if(iSessionID == RTP_SESSION_SMART_DATA) { if(ret < 0) { RTSP_DEBUG(“send smart data return error %d”,ret); } else if(ret != expectlen) { RTSP_DEBUG(“send part of smart data”); } else { RTSP_DEBUG(“send smart data successfully”); } } if (desc->frame_end) { #ifdef TAPO_USE_RTSP_MULTITRANS if (pSession->start_time != -1 && pSession->stream_seq % 25 == 0) //回放需要有流控 { RTSPSendMultitransSeq(pSession); } pSession->stream_seq ++; #endif } if(iSessionID == RTP_SESSION_SMART_DATA) { if(desc->frame_end) { g_smart_data_is_first_rtp_set = 1; } else { g_smart_data_is_first_rtp_set = 0; } } desc->frame_end = 0; memset(pSession->rtp_send_data, 0, sizeof(RTPSENDDATA) * RTP_MAX_SEND_NUM); pSession->rtp_send_data_index = 0; smart_data_rtp_index = 0; p_retry_info->send_pos = 0; if (pSession->send_retry_times > 0) { ullCurrentTime = tpgetboottime(); if (pSession->ullTimeForSendRetry + SEND_RETRY_PRINT_TIMEOUT < ullCurrentTime) { RTSP_ERROR(“send retry %d times, client ip:%s,”, pSession->send_retry_times, pSession->pcClientIP); pSession->ullTimeForSendRetry = 0; pSession->send_retry_times = 0; } } } } else { MBUFFERByteArray mBuffer; unsigned char TXBufferMemSpace[TPRTSPSERVER_BUFFER_SIZE] = {0}; MBUFFERByteArrayInit(TXBufferMemSpace, 0, 0, TPRTSPSERVER_BUFFER_SIZE - 4, &mBuffer); MBUFFERByteArrayReset(&mBuffer); int fu_header_len = p_frame->rtp_head_len - RTP_HEADER_SIZE; if (pSession->bIsCrypto) { MBUFFERByteArrayPutMultiUCharBE((unsigned char )p_frame->rtp_head_pos, RTP_HEADER_SIZE, &mBuffer); if(externtionlen > 0) { MBUFFERByteArrayPutMultiUCharBE(RTPextern, externtionlen, &mBuffer); } if (fu_header_len > 0) { memcpy(pSession->encrypted_pos, p_frame->rtp_head_pos + RTP_HEADER_SIZE, fu_header_len); memcpy(pSession->encrypted_pos + fu_header_len, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); } else { memcpy(pSession->encrypted_pos, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); } if (0 != SRTPEncrypt(&pSession->cryptoCtx, pSession->encrypted_pos, pSession->encrypted_pos, p_frame->rtp_payload_len + fu_header_len, p_frame->iSN)) { RTSP_ERROR(“SRTP encrypt failed, go to next frame”); return 0; } // fu 已经考虑在内 unsigned int total_len = p_frame->rtp_head_len + externtionlen + p_frame->rtp_payload_len; memset(pSession->auth_mem, 0, (RTP_MAX_PACKET_SIZE2)); memcpy(pSession->auth_mem, p_frame->rtp_head_pos, p_frame->rtp_head_len); if(externtionlen > 0) { memcpy(pSession->auth_mem + p_frame->rtp_head_len, RTPextern, externtionlen); } // put encrypted payload and auth tag in buffer memcpy(pSession->auth_mem + p_frame->rtp_head_len + externtionlen, pSession->encrypted_pos, p_frame->rtp_payload_len); if (0 != SRTPAuthenticate(&pSession->cryptoCtx, p_frame->rtp_auth_tag, pSession->auth_mem, total_len, p_frame->iSN)) { RTSP_ERROR(“SRTP authenticate failed, go to next frame”); return 0; } MBUFFERByteArrayPutMultiUCharBE(sendmute ? mutebuf : pSession->encrypted_pos, p_frame->rtp_payload_len + fu_header_len, &mBuffer); MBUFFERByteArrayPutMultiUCharBE(p_frame->rtp_auth_tag, SRTP_TAG_SIZE, &mBuffer); } else { if(externtionlen > 0) { MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos, RTP_HEADER_SIZE, &mBuffer); MBUFFERByteArrayPutMultiUCharBE(RTPextern, externtionlen, &mBuffer); if (fu_header_len > 0) { MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos + RTP_HEADER_SIZE, fu_header_len, &mBuffer); } } else { MBUFFERByteArrayPutMultiUCharBE((unsigned char )p_frame->rtp_head_pos, p_frame->rtp_head_len, &mBuffer); } MBUFFERByteArrayPutMultiUCharBE(sendmute ? mutebuf : p_frame->rtp_payload_pos, p_frame->rtp_payload_len, &mBuffer); } MBUFFERByteConvert2ReadBuff(&mBuffer); TPUdpSendByBuffer(pSession->pRTPServer->pSessions[iSessionID]->DataServer, &mBuffer); /还原设置的拓展标记,避免对其他会话的影响/ if((p_frame->rtp_head_pos) & RTP_HEADER_EXTENTION_BIT) { *(p_frame->rtp_head_pos) &= ~RTP_HEADER_EXTENTION_BIT; } RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4, cur_time); } reset_retry_info(p_retry_info, ptr_rtp_package); p_retry_info->sn = p_frame->iSN; return 0; }
09-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值