2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 基于ffmpeg的音频转换器-rtp承载的amr转换为pcm音频流

基于ffmpeg的音频转换器-rtp承载的amr转换为pcm音频流

时间:2022-03-12 09:46:53

相关推荐

基于ffmpeg的音频转换器-rtp承载的amr转换为pcm音频流

根据近期项目中应用需要,需要将rtp协议承载的amr(8kHZ)媒体流,转换成pcm格式音频流并以udp协议发送出去。ffmpeg强大的媒体处理功能,再次得到了淋漓尽致的体现,不多说了,直接上代码,记录一下

#include <stdio.h> #include <stdlib.h>#include <WinSock2.h>#include <windows.h>#include <sys/stat.h>#include <process.h> #include <time.h> //_declspec(dllimport) int add(int, int);//_declspec(dllimport) int sub(int, int);#pragma comment(lib,"ws2_32.lib")#define AMR_MAGIC_NUMBER"#!AMR\n" #define MAX_PATH 256#defineAMR_FRAME_LENGTH32#define PCM_BUF_LEN1024#define CACHE_PCM_LEN10240typedef struct RTP_FIXED_HEADER{ /* byte 0 */ unsigned char csrc_len:4; /* expect 0 */ unsigned char extension:1;/* expect 1 */ unsigned char padding:1; /* expect 0 */ unsigned char version:2; /* expect 2 */ /* byte 1 */ unsigned char payload:7; unsigned char marker:1; /* expect 1 */ /* bytes 2, 3 */ unsigned short seq_no; /* bytes 4-7 */ unsigned long timestamp;/* bytes 8-11 */ unsigned long ssrc; /* stream number is used here. */ } RTP_FIXED_HEADER; int local_rtp_port;int local_udp_port;int local_pcm_port;int remote_port;int pcm_sample_rate;int end_task_flag;char remote_ip[MAX_PATH]={0};char local_ip[MAX_PATH]={0};int audio_header_flag;int udpsocket_setup_server(int serv_port){const int on = 1; /* for setsockopt() */const int newon = 512000;int optlen = 4;int optlen2 = 4;int sock = -1;char set = 1; WSADATA wsd; //初始化信息struct sockaddr_insaddr;if (WSAStartup(MAKEWORD(2,2),&wsd) != 0) {/*进行WinSocket的初始化, windows 初始化socket网络库,申请2,2的版本,windows socket编程必须先初始化。*/ printf( "WSAStartup Error = %d" , WSAGetLastError() ); return 0; }saddr.sin_family = AF_INET;saddr.sin_port = htons(serv_port);saddr.sin_addr.s_addr = inet_addr(local_ip); //setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(int));if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0){printf("socket (AF_INET, SOCK_DGRAM, 0)) failed!\n");return (-1);}if (getsockopt (sock, SOL_SOCKET, SO_RCVBUF,(char*) &on, (int *)&optlen) < 0){closesocket(sock);return (-1);}if (setsockopt (sock, SOL_SOCKET, SO_RCVBUF,(char*) &newon, optlen2) < 0){closesocket(sock);return (-1);}if (getsockopt (sock, SOL_SOCKET, SO_RCVBUF,(char*) &on, (int *)&optlen) < 0){closesocket(sock);return (-1);}if (bind (sock, (struct sockaddr *)&saddr, sizeof (saddr)) < 0){printf("bind (sock, (struct sockaddr *)&saddr, sizeof (saddr)) failed!\n");closesocket(sock);return (-1);}return sock;}int udpsocket_read(int sockfd, char *strip, int *serv_port, char *pbuf, int *len){long intmsgsize;struct sockaddr_insaddr;int saddrlen = sizeof (struct sockaddr_in);msgsize = recvfrom(sockfd, (char *)pbuf, *len, 0, (struct sockaddr *)&saddr,(int *)&saddrlen);if (0 >= msgsize){//printf("msgsize %d \n",msgsize);return -1;}/** If the input param is a pointer then thevalue can not be straight away assigned, it needs to be copied -- Rajen **/strcpy(strip,inet_ntoa(saddr.sin_addr));/** strip=inet_ntoa(saddr.sin_addr); **/*serv_port=ntohs(saddr.sin_port);*len = msgsize;/* return actually recv len */return 1;}int udpsocket_write(int sockfd, char *strip, int serv_port, char *pbuf, int len){struct sockaddr_insaddr;unsigned long serv_ipaddr;memset(&saddr, 0, sizeof(struct sockaddr_in));if ((serv_ipaddr = inet_addr(strip)) == -1){printf("Invalid IP address: %s\n",strip);return -1;}saddr.sin_family = AF_INET;saddr.sin_port = htons(serv_port);saddr.sin_addr.s_addr = inet_addr(strip);if (sendto(sockfd, pbuf, len, 0, (struct sockaddr *)&saddr,sizeof( struct sockaddr_in)) < 0){return -1;}return 1;}void udpsocket_close_server(int sock){closesocket(sock);return ;}int write_wav_file(char *file_name, char *p_data, int len){FILE* fpwav = NULL;static charpcm_header[] = { 'R','I','F','F', /* 0x52,0x49,0x46,0x46 RIFF */0x24,0x00,0x00,0x00, /* 0xff,0xff,0xff,0xff,RIFF_SIZE or 0*/'W','A','V','E', /* WAVE */'f','m','t',' ', /* fmt */0x10,0x00,0x00,0x00, /* FORMAT_SIZE */0x01,0x00, /* FORMATTAG */0x01,0x00, /* CHANNELS */0x44,0xac,0x00,0x00, /* SamplesPerSec */ /* 44100 */0x88,0x58,0x01,0x00, /* AvgBytesPerSec */ /* 88200 */ 0x02,0x00, /* BlockAlign */ /*2 */0x10,0x00, /* BitsPerSample */ /* 16 */'d','a','t','a', /*LIST or data*/0x00,0x00,0x00,0x00};//printf("in function WirteWavFile len:%d\n", len);fpwav = fopen(file_name, "rb+");if (fpwav == NULL){fpwav = fopen(file_name, "ab+");if (fpwav == NULL){return 0;}fwrite(pcm_header,1,sizeof(pcm_header),fpwav);} else{fclose(fpwav);fpwav = fopen(file_name, "ab+");}fwrite(p_data, 1, len, fpwav);fclose(fpwav);return 1; }int write_amr_file(char *file_name, unsigned char *p_data, int len){//static S8bit fname[256] = "test.amr";int bytes = 0;FILE*fpamr = NULL;fpamr = fopen(file_name, "rb");if (fpamr == NULL){fpamr = fopen(file_name, "wb+");if (fpamr == NULL){return 0;}/* write magic number to indicate single channel AMR file storage format */bytes = fwrite(AMR_MAGIC_NUMBER, sizeof( unsigned char), strlen(AMR_MAGIC_NUMBER), fpamr);//printf("fpamr is NULL!\n");//return 0;} else{fclose(fpamr);fpamr = fopen(file_name, "ab+");}#if 0if (NULL == fopen(file_name, "r")){fpamr = fopen(file_name, "wb");if (fpamr == NULL){return 0;}/* write magic number to indicate single channel AMR file storage format */bytes = fwrite(AMR_MAGIC_NUMBER, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr);}else{fpamr = fopen(file_name, "ab");}#endifif (p_data == NULL){return 0;}bytes += len;fwrite(p_data, sizeof( unsigned char), len, fpamr);fclose(fpamr);return bytes;}int make_final_pcm_stream(){int serSocket;char recvData[CACHE_PCM_LEN]={0};char cacheData[CACHE_PCM_LEN]={0};char finalData[PCM_BUF_LEN]={0};charsrc_ip[20] = {0};intsrc_port = 0;int rcv_data_len = 0;intcache_buf_len = 0;int result = 0;struct timeval select_time;struct fd_setsock_set;serSocket = udpsocket_setup_server(local_pcm_port);if(serSocket < 0){printf("make_final_pcm_stream serSocket setup fail\n");return -1;}while (1&&!end_task_flag){select_time.tv_sec = 0;select_time.tv_usec = 10000;FD_ZERO(&sock_set); FD_SET(serSocket, &sock_set);if((result = select(serSocket+1, &sock_set, (fd_set*)NULL, (fd_set*)NULL, &select_time)) > 0)//if( udpsocket_read(serSocket,src_ip,&src_port,recvData,&rcv_data_len)>0){rcv_data_len = CACHE_PCM_LEN;memset(recvData, 0, rcv_data_len);if(udpsocket_read(serSocket,src_ip,&src_port,recvData,&rcv_data_len)<0){continue;}if(rcv_data_len==78){continue;}memcpy(&cacheData[cache_buf_len],recvData,rcv_data_len);cache_buf_len+=rcv_data_len;//write_wav_file("test0.wav",recvData,rcv_data_len);//printf("rcv_data_len=%d\n",rcv_data_len);if(cache_buf_len>CACHE_PCM_LEN){cache_buf_len = 0;}if(cache_buf_len>PCM_BUF_LEN){memcpy(finalData,cacheData,PCM_BUF_LEN);cache_buf_len -= PCM_BUF_LEN;memcpy(cacheData,&cacheData[PCM_BUF_LEN],cache_buf_len);result = udpsocket_write(serSocket,remote_ip, remote_port, finalData, PCM_BUF_LEN);if(result<0){printf("make_final_pcm_stream send 1024 byte pcm fail!\n");continue;}//write_wav_file("test.wav",finalData,PCM_BUF_LEN);}}}return 1;}int amr_rtp_parser(){int serSocket;int cnt=0;intret=0;int parse_rtp=1; char recvData[100]={0};char parseData[100]={0};charsrc_ip[20] = {0};intsrc_port = 0;intrcv_buf_len = 0;int rtp_header_size = sizeof(RTP_FIXED_HEADER);intmsg_len;struct timeval select_time;struct fd_setsock_set;printf("Listening on port %d\n",local_rtp_port);serSocket = udpsocket_setup_server( local_rtp_port);if(serSocket < 0){printf("serSocket setup fail\n");}while (1&&!end_task_flag){select_time.tv_sec = 0;select_time.tv_usec = 5000;FD_ZERO(&sock_set); FD_SET(serSocket, &sock_set);if((ret = select(0, &sock_set, (fd_set*)NULL, (fd_set*)NULL, &select_time)) > 0){msg_len = 100;memset(recvData, 0, msg_len); //memset((void*)p_client_mes_req_st,0,sizeof(mes_req_st));ret = udpsocket_read(serSocket,src_ip,&src_port,recvData,&msg_len);if(ret<0){continue;}if(audio_header_flag==0){//ret = udpsocket_write(serSocket, remote_ip, remote_port, "#!AMR\n", 6);ret = udpsocket_write(serSocket, local_ip, local_udp_port, "#!AMR\n", 6);audio_header_flag=1;}//printf("recvData[rtp_header_size]=%x\n",recvData[rtp_header_size]);if(recvData[rtp_header_size]==0xf0){if(0x3c==recvData[rtp_header_size+1]){/*frame_cnt=1*///printf("frame_cnt=1;");memcpy(parseData,&recvData[rtp_header_size+1],AMR_FRAME_LENGTH); ret = udpsocket_write(serSocket,local_ip, local_udp_port, parseData, AMR_FRAME_LENGTH);//ret = udpsocket_write(serSocket,remote_ip, remote_port, parseData, AMR_FRAME_LENGTH);if(ret<0){printf("udpsocket_write fail!\n");}}else if(0xbc == recvData[rtp_header_size+1] && 0x3c == recvData[rtp_header_size+2]){/*frame_cnt=2*/memcpy(parseData,&(recvData[rtp_header_size+2]),AMR_FRAME_LENGTH);//ret = udpsocket_write(serSocket,local_ip, local_udp_port, parseData, AMR_FRAME_LENGTH);parseData[AMR_FRAME_LENGTH] = 0x3c;memcpy(&parseData[AMR_FRAME_LENGTH+1],&(recvData[rtp_header_size+2+AMR_FRAME_LENGTH]),AMR_FRAME_LENGTH-1);//parseData[0]=0x3c;//memcpy(&parseData[1],&(recvData[rtp_header_size+2+AMR_FRAME_LENGTH]),AMR_FRAME_LENGTH-1);ret = udpsocket_write(serSocket,local_ip, local_udp_port, parseData, AMR_FRAME_LENGTH*2);if(ret<0){printf("udpsocket_write fail!\n");}//write_amr_file("1.amr",parseData,AMR_FRAME_LENGTH*2);}}}}return 1;}int GetIniFullPath(char * temppath){char sPath[MAX_PATH];//临时路径char path[MAX_PATH]; //可执行文件的全路径,包括可执行文件名char exepath[MAX_PATH]; //配置文件的路径,包括配置文件文件名char inipath[MAX_PATH]; //配置文件的路径,包括配置文件文件名int iPosition;int i = 0;__try{memset(sPath, 0, sizeof(sPath));memset(path, 0, sizeof(path));memset(exepath, 0, sizeof(exepath));memset(inipath, 0, sizeof(inipath));GetModuleFileName(NULL, path, MAX_PATH);sprintf_s(sPath, sizeof(sPath), "%s", path);memcpy(sPath,path, MAX_PATH );for (i = sizeof(sPath); i > 0; i--){if (sPath[i - 1] == '\\'){iPosition = i;break;}}memcpy(exepath, sPath, iPosition);sprintf_s(inipath, sizeof(inipath), "%sconifg.ini", exepath);}__except(EXCEPTION_EXECUTE_HANDLER){return 0;}memcpy(temppath, inipath, sizeof(inipath));printf("inipath=%s\n",&inipath);return 1;}void GetIni(){char inifilepath[MAX_PATH];char buffini[80];memset(inifilepath,0, sizeof(inifilepath));GetIniFullPath(inifilepath);__try{local_rtp_port = GetPrivateProfileInt("音频转换器信息","LOCAL_RTP_PORT",20001,inifilepath);local_udp_port = GetPrivateProfileInt("音频转换器信息","LOCAL_UDP_PORT",20002,inifilepath);remote_port= GetPrivateProfileInt("音频转换器信息","REMOTE_PORT",20003,inifilepath); pcm_sample_rate = GetPrivateProfileInt("音频转换器信息","PCM_SAMPLE_RATE",44100,inifilepath);local_pcm_port = local_udp_port + 100;if (GetPrivateProfileString("音频转换器信息","REMOTE_IP","\0",(char*)remote_ip,MAX_PATH,(const char *)inifilepath) == 0){printf("GetIni, Error");}if (GetPrivateProfileString("音频转换器信息","LOCAL_IP","\0",(char*)local_ip,MAX_PATH,(const char *)inifilepath) == 0){printf("GetIni, Error");}}__except(EXCEPTION_EXECUTE_HANDLER ){printf("GetIni, Error:%d",GetLastError());}}void * ffmpeg_convert_audio(void * arg){char systemStateName[256] = {0};sprintf_s(systemStateName, sizeof(systemStateName), "ffmpeg -re -i udp://%s:%d -f s16le -acodec pcm_s16le -ar %d -ac 1 udp://%s:%d", local_ip,local_udp_port,pcm_sample_rate,local_ip,local_pcm_port);//sprintf_s(systemStateName, sizeof(systemStateName), "ffmpeg -re -i udp://%s:%d -acodec aac -f flv rtmp://%s:1935/live/0", //local_ip,local_udp_port,local_ip);printf("systemStateName=%s\n",systemStateName);system(systemStateName);}void *end_task(void *param){getchar();end_task_flag= 1;printf("the test will go to end\n");exit(1);}int main(){char * pstr = "start thread";GetIni();printf("local_ip=%s,local_port=%d\n,remote_port=%d\n,pcm_sample_rate=%d\n,remote_ip=%s\n",local_ip,local_rtp_port,remote_port,pcm_sample_rate,remote_ip);//先打开ffmpeg_beginthread(ffmpeg_convert_audio,0,pstr); _beginthread(end_task,0,pstr);//由于项目特殊需求,在每个pcm音频包发出去大小为1024字节。_beginthread(make_final_pcm_stream,0,pstr);//去除rtp头,amr音频解析为纯udp流_beginthread(amr_rtp_parser,0,pstr);getchar();return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。