📄 network_ctrl_recv_thread.cpp
字号:
///////////////////////////////////////////////////////// FileName: network_ctrl_recv_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 <qthread.h>#include <poll.h>#include <qevent.h>#include <linux/if.h>#include "network_ctrl_recv_thread.h"#include "network_audio_recv_thread.h"#include "network_video_recv_thread.h"#include "video_cap.h"#include "capture_event.h"#include "video_send.h"#include "network_audio_send.h"#include "network_video_send.h"#include "network_ctrl.h"#include "video.h"#include "network.h"#include "common.h"#include "audio.h"#include "avi.h"#include "signal_def.h"#include "capture_event.h"using namespace std;///////////////////////////////////////////////////////// Public Functions///////////////////////////////////////////////////////// 构造函数// 传入参数为// nc_in 上层network_ctrl对象指针// stackSize QThread所用的参数network_ctrl_recv_thread::network_ctrl_recv_thread ( avi * avi_ptr_in, network_ctrl * nc_in, unsigned int stackSize ) :QThread( stackSize ) // {{{{ verbose_output( 2, "create network_ctrl_recv_thread." ); nc = nc_in; fd_ctrl = 0; recv_buff = new BUFF [ PACKET_LENGTH ]; send_buff = new BUFF [ PACKET_LENGTH ]; addr_accept = new sockaddr_in; acclen = new socklen_t; packet_num = 0; expect_num = 0; nart = NULL; nvrt = NULL; avi_ptr = avi_ptr_in;} // }}}// 析构函数network_ctrl_recv_thread::~network_ctrl_recv_thread ( void ) // {{{{ if ( 0 != fd_ctrl ) { close( fd_ctrl ); } if ( NULL != nart ) { if ( nart->running() ) { nart->terminate(); cerr << "Warning! Terminate network audio recv thread." << endl; } delete nart; } if ( NULL != nvrt ) { if ( nvrt->running() ) { nvrt->terminate(); cerr << "Warning! Terminate network video recv thread." << endl; } delete nvrt; } delete [] recv_buff; delete [] send_buff; delete addr_accept; delete acclen;} // }}}// 运行部分,线程代码在这里void network_ctrl_recv_thread::run ( void ) // {{{{ verbose_output( 1, "network ctrl recv thread running..." ); int init_ok; if ( avi_ptr->use_multicast ) { init_ok = connect_init_mc(); } else { init_ok = connect_init(); } if ( init_ok == SUCCEED ) { if ( avi_ptr->va_mode != AUDIO_ONLY ) { verbose_output( 1, "create new network_video_recv_thread." ); nvrt = new network_video_recv_thread( avi_ptr, nc ); nvrt->start(); } if ( avi_ptr->va_mode != VIDEO_ONLY ) { verbose_output( 1, "create new network_audio_recv_thread." ); nart = new network_audio_recv_thread( avi_ptr, nc ); nart->start(); } if ( avi_ptr->use_multicast ) { connect_handle_mc(); } else { connect_handle(); } } verbose_output( 1, "end of network_audio_recv_thread" ); return;} // }}}///////////////////////////////////////////////////////// Private Functions///////////////////////////////////////////////////////// 连接初始化,创建套接字int network_ctrl_recv_thread::connect_init ( void ) // {{{{ verbose_output( 3, "network_ctrl_recv_thread init." ); //expect_num = WELCOME_NUM; *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); // 网络连接的参数设置 addr_accept->sin_family = AF_INET; addr_accept->sin_port = htons( DEFAULT_CTRL_PORT ); inet_pton( AF_INET, static_cast< const char* > ( avi_ptr->ip ), &addr_accept->sin_addr ); verbose_output( 3, "creating ctrl connect socket..." ); fd_ctrl = socket( AF_INET, SOCK_DGRAM, 0 ); pollfd connect_to = { fd_ctrl, POLLIN, 0, }; bool read_ok = false; option_t * opt_buf = NULL; BUFF * temp; int connect_times = 0; 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 ) { QCustomEvent * event = new QCustomEvent( SIG_DISCONNECT_OK ); QApplication::postEvent( avi_ptr, event ); return FAILED; } verbose_output( 3, "send ctrl Hello message ..." ); send_data( fd_ctrl, addr_accept, send_buff, NULL, 0, expect_num, SYN ); int result = poll( &connect_to, 1, DEFAULT_TIMEOUT ); if ( result == 0 ) { // 超时返回 connect_times++; if ( connect_times >= DEFAULT_CONNECT_TIMES ) { cerr << "Warning! Can't connect to peer host." << endl; QCustomEvent * event = new QCustomEvent( SIG_CONNECT_TIMEOUT ); QApplication::postEvent( avi_ptr, event ); return FAILED; } continue; } else { if ( result > 0 ) { // 网络可读 recv_line( fd_ctrl, addr_accept, recv_buff, temp, packet_head ); opt_buf = (option_t *) temp; if ( !TEST_CTRL_SYN_BIT( packet_head->opt_bits ) ) { cerr << "Warning! not the Welcome reply." << endl; } else { read_ok = true; } } else { // 套接口错误 perror( "Error in connecting" ); ::exit( 1 ); } } } while ( !read_ok ); expect_num++; QCustomEvent * event = new QCustomEvent( SIG_CONNECT_OK ); QApplication::postEvent( avi_ptr, (QEvent*) event ); // 获得参数设置 avi_ptr->va_mode = opt_buf->va_mode; avi_ptr->video_opt.factor = opt_buf->factor; if ( opt_buf->use_g723 == 0 ) { avi_ptr->use_g723 = false; } else { if ( opt_buf->use_g723 == 1 ) { avi_ptr->use_g723 = true; } } verbose_output( 4, "get peer configuration" ); verbose_output( 4, "va_mode\t", avi_ptr->va_mode ); verbose_output( 4, "factor\t", avi_ptr->video_opt.factor ); verbose_output( 4, "use_g723\t", opt_buf->use_g723 ); return SUCCEED;} // }}}// 处理连接后的数据发送工作void network_ctrl_recv_thread::connect_handle ( void ) // {{{{ bool should_exit = false; int count = 0; while( 1 ) { (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { send_data( fd_ctrl, addr_accept, send_buff, NULL, 0, packet_num, GOODBYE ); QCustomEvent * event = new QCustomEvent( SIG_DISCONNECT_OK ); QApplication::postEvent( avi_ptr, event ); nart->wait(); cout << " wait nart ok " << endl; nvrt->wait(); cout << " wait nvrt ok " << endl; return; } msleep( HEARTBEAT_INTERVAL / 4 ); count = ( count + 1 ) % 4; if ( count == 3 ) { cout << "send heartbeat" << endl; send_data( fd_ctrl, addr_accept, send_buff, NULL, 0, packet_num, HEARTBEAT ); } } return;} // }}}// 组播初始化,创建套接字int network_ctrl_recv_thread::connect_init_mc ( void ) // {{{{ verbose_output( 3, "network ctrl recv thread Multicast init." ); ///////////////////////////////////////// // 创建控制端口 ///////////////////////////////////////// *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); // 创建控制端监听socket verbose_output( 3, "creating multicast listen socket..." ); fd_ctrl = socket( AF_INET, SOCK_DGRAM, 0 ); // 绑定指定端口 addr_accept->sin_family = AF_INET; inet_pton( AF_INET, static_cast< const char* >( avi_ptr->mc_addr ), &addr_accept->sin_addr ); addr_accept->sin_port = htons( DEFAULT_MC_CTRL_PORT ); // 绑定端口 if ( bind( fd_ctrl, (sockaddr*) addr_accept, *acclen ) == -1 ) { cerr << "Can't bind to the listen port [" << DEFAULT_MC_CTRL_PORT << "]" << endl; ::exit( 1 ); } // 初始化组播 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_ctrl, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) ); return SUCCEED;} // }}}// 处理组播连接后的数据接收工作void network_ctrl_recv_thread::connect_handle_mc ( void ) // {{{{ nart->wait(); cout << " wait nart ok " << endl; nvrt->wait(); cout << " wait nvrt ok " << endl; QCustomEvent * event = new QCustomEvent( SIG_DISCONNECT_OK ); QApplication::postEvent( avi_ptr, event ); return;} // }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -