gusucode.com > 嵌入式linux系统的网络编程源码程序 > 嵌入式linux系统的网络编程源码程序/视频会议源码/network_audio_send_thread.cpp
/////////////////////////////////////////////////////// // FileName: network_audio_send_thread.cpp // Author: b1gm0use // Project: myvideo #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <qapplication.h> #include <poll.h> #include "network_audio_send_thread.h" #include "capture_event.h" #include "network_audio_send.h" #include "network_ctrl.h" #include "network.h" #include "common.h" #include "audio.h" #include "avi.h" using namespace std; /////////////////////////////////////////////////////// // Public Functions /////////////////////////////////////////////////////// // 构造函数 // 传入参数为 // nc_in 上层network_ctrl对象指针 // stackSize QThread所用的参数 network_audio_send_thread::network_audio_send_thread ( avi * avi_ptr_in, network_ctrl * nc_in, unsigned int stackSize ) :QThread( stackSize ) // {{{ { verbose_output( 2, "create network_audio_send_thread." ); nc = nc_in; fd_audio = 0; audio_frame = 0; recv_buff = new BUFF [ PACKET_LENGTH ]; send_buff = new BUFF [ PACKET_LENGTH ]; merge_buff = NULL; max_size = 0; addr_accept = new sockaddr_in; acclen = new socklen_t; packet_num = 0; expect_num = 0; to_be_send = NULL; avi_ptr = avi_ptr_in; } // }}} // 析构函数 network_audio_send_thread::~network_audio_send_thread ( void ) // {{{ { if ( 0 != fd_audio ) { close( fd_audio ); } delete [] recv_buff; delete [] send_buff; delete [] merge_buff; delete addr_accept; delete acclen; delete [] to_be_send; } // }}} // 运行部分,线程代码在这里 void network_audio_send_thread::run ( void ) // {{{ { verbose_output( 1, "network audio send thread running..." ); max_size = MAX_AUDIO_BUFF_SIZE; to_be_send = new BUFF [ max_size + DATA_OFFSET ]; if ( avi_ptr->use_multicast ) { listen_init_mc(); listen_handle_mc(); } else { listen_init(); listen_handle(); } return; } // }}} /////////////////////////////////////////////////////// // Private Functions /////////////////////////////////////////////////////// // 连接初始化,创建套接字 void network_audio_send_thread::listen_init ( void ) // {{{ { verbose_output( 3, "network audio send thread init." ); ///////////////////////////////////////// // 创建音频端口 ///////////////////////////////////////// sockaddr_in addr_listen; socklen_t len = sizeof( addr_listen ); int port = DEFAULT_AUDIO_PORT; // 创建一个等待server daemon的监听端口 // 创建控制端监听socket verbose_output( 3, "creating audio listen socket..." ); fd_audio = socket( AF_INET, SOCK_DGRAM, 0 ); // 绑定指定端口 memset( &addr_listen, 0, sizeof( addr_listen ) ); addr_listen.sin_family = AF_INET; addr_listen.sin_addr.s_addr = htonl( INADDR_ANY ); addr_listen.sin_port = htons( port ); // 绑定端口 if ( bind( fd_audio, (sockaddr*) & addr_listen, len ) == -1 ) { cerr << "Can't bind to the listen port [" << port << "]" << endl; ::exit( 1 ); } verbose_output( 3, "waiting for audio connection...", avi_ptr->ip ); *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); return; } // }}} // 处理连接进入后的数据发送工作 void network_audio_send_thread::listen_handle ( void ) // {{{ { verbose_output( 3, "network audio send thread handle." ); BUFF * pos = NULL; audio_frame = 0; // 接收进来的连接 BUFF * buff = NULL; bool read_ok = false; bool should_exit = false; packet_head_t * packet_head = NULL; do { // 判断是否应该退出 (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { return; } pollfd connect_in = { fd_audio, POLLIN, DEFAULT_TIMEOUT }; int result = poll( &connect_in, 1, 0 ); if ( result < 0 ) { perror( "Error in audio listening" ); } if ( result == 0 ) { // 超时 continue; } if ( ( connect_in.revents & POLLIN ) != 0 ) { // 有数据可读? recv_line( fd_audio, addr_accept, recv_buff, buff, packet_head ); if ( !TEST_CTRL_SYN_BIT( packet_head->opt_bits ) ) { cerr << "not audio welcome number" << endl; continue; } read_ok = true; send_data( fd_audio, addr_accept, send_buff, NULL, 0, packet_num, SYN ); } } while( !read_ok ); int size = max_size; // 处理发送数据 while( 1 ) { // 判断是否应该退出 (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { return; } // 等待可发送数据 nc->ready_to_send_audio->wait(); (*(nc->audio_send_buff_sema))++; size = nc->audio_buff[audio_frame]->buff_size; memcpy( to_be_send + DATA_OFFSET, nc->audio_buff[audio_frame]->buff_ptr, size ); (*(nc->audio_send_buff_sema))--; audio_frame = (audio_frame + 1) % 3; pos = to_be_send; memcpy( pos, "ABGN", 4 ); memcpy( pos+4, (char*) &size, sizeof( int ) ); pollfd connect_in = { fd_audio, POLLIN | POLLOUT, 0 }; int result = poll( &connect_in, 1, 0 ); if ( result < 0 ) { perror( "Error in audio listening" ); } if ( ( connect_in.revents & POLLIN ) != 0 ) { // 有数据可读? recv_line( fd_audio, addr_accept, recv_buff, buff, packet_head ); if ( TEST_CTRL_SYN_BIT( packet_head->opt_bits ) ) { send_data( fd_audio, addr_accept, send_buff, NULL, 0, packet_num, SYN ); } else { cerr << "Warning! read in unknown audio packet" << endl; } } if ( ( connect_in.revents & POLLOUT ) != 0 ) { // 可以写入数据 *acclen = sizeof( *addr_accept ); send_data( fd_audio, addr_accept, send_buff, to_be_send, size+DATA_OFFSET, packet_num ); } pos = NULL; } } // }}} // 组播初始化,创建套接字 void network_audio_send_thread::listen_init_mc ( void ) // {{{ { verbose_output( 3, "network audio send thread Multicast init." ); ///////////////////////////////////////// // 创建音频端口 ///////////////////////////////////////// *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); // 网络连接的参数设置 addr_accept->sin_family = AF_INET; addr_accept->sin_port = htons( DEFAULT_MC_AUDIO_PORT ); inet_pton( AF_INET, static_cast< const char* >( avi_ptr->mc_addr ), &addr_accept->sin_addr ); // 创建控制端发送socket fd_audio = socket( AF_INET, SOCK_DGRAM, 0 ); // 初始化组播 ip_mreq mreq; memcpy( &mreq.imr_multiaddr, &(((sockaddr_in*) addr_accept)->sin_addr), sizeof( in_addr ) ); mreq.imr_interface.s_addr = htonl( INADDR_ANY ); // 加入组播 setsockopt( fd_audio, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) ); return; } // }}} // 处理组播连接后的数据接收工作 void network_audio_send_thread::listen_handle_mc ( void ) // {{{ { verbose_output( 3, "network audio send thread Multicast handle." ); BUFF * pos = NULL; audio_frame = 0; int size = max_size; bool should_exit = false; // 处理发送数据 while( 1 ) { // 判断是否应该退出 (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { return; } // 等待可发送数据 nc->ready_to_send_audio->wait(); // 取出等待发送的数据 (*(nc->audio_send_buff_sema))++; size = nc->audio_buff[audio_frame]->buff_size; memcpy( to_be_send + DATA_OFFSET, nc->audio_buff[audio_frame]->buff_ptr, size ); (*(nc->audio_send_buff_sema))--; audio_frame = (audio_frame + 1) % 3; // 处理头信息 pos = to_be_send; memcpy( pos, "ABGN", 4 ); memcpy( pos+4, (char*) &size, sizeof( int ) ); // 写入数据 *acclen = sizeof( *addr_accept ); send_data( fd_audio, addr_accept, send_buff, to_be_send, size+DATA_OFFSET, packet_num ); pos = NULL; } return; } // }}}