📄 network_ctrl_send_thread.cpp
字号:
///////////////////////////////////////////////////////// FileName: network_ctrl_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 <qthread.h>#include <poll.h>#include <qevent.h>#include "network_ctrl_send_thread.h"#include "network_audio_send_thread.h"#include "network_video_send_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"using namespace std;///////////////////////////////////////////////////////// Public Functions///////////////////////////////////////////////////////// 构造函数// 传入参数为// nc_in 上层network_ctrl对象指针// stackSize QThread所用的参数network_ctrl_send_thread::network_ctrl_send_thread ( avi * avi_ptr_in, network_ctrl * nc_in, unsigned int stackSize ) :QThread( stackSize ) // {{{{ verbose_output( 2, "create network_ctrl_send_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; nast = NULL; nvst = NULL; avi_ptr = avi_ptr_in; client_num = 0;} // }}}// 析构函数network_ctrl_send_thread::~network_ctrl_send_thread ( void ) // {{{{ if ( 0 != fd_ctrl ) { close( fd_ctrl ); } if ( NULL != nast ) { if ( nast->running() ) { nast->terminate(); cerr << "Warning! Terminate network audio send thread." << endl; } delete nast; } if ( NULL != nvst ) { if ( nvst->running() ) { nvst->terminate(); cerr << "Warning! Terminate network video send thread." << endl; } delete nvst; } delete [] recv_buff; delete [] send_buff; delete addr_accept; delete acclen;} // }}}// 运行部分,线程代码在这里void network_ctrl_send_thread::run ( void ) // {{{{ verbose_output( 1, "network ctrl send thread running..." ); if ( avi_ptr->use_multicast ) { listen_init_mc(); } else { listen_init(); } if ( avi_ptr->va_mode != AUDIO_ONLY ) { // 使用视频 nvst = new network_video_send_thread( avi_ptr, nc ); nvst->start(); } if ( avi_ptr->va_mode != VIDEO_ONLY ) { // 使用音频 nast = new network_audio_send_thread( avi_ptr, nc ); nast->start(); } if ( avi_ptr->use_multicast ) { listen_handle_mc(); } else { listen_handle(); } return;} // }}}///////////////////////////////////////////////////////// Private Functions///////////////////////////////////////////////////////// 连接初始化,创建套接字void network_ctrl_send_thread::listen_init ( void ) // {{{{ verbose_output( 3, "net_mode LISTEN" ); ///////////////////////////////////////// // 创建控制端口 sockaddr_in addr_listen; socklen_t len = sizeof( addr_listen ); int port = DEFAULT_CTRL_PORT; // 创建一个等待server daemon的监听端口 // 创建控制端监听socket verbose_output( 3, "creating listen socket..." ); fd_ctrl = 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_ctrl, (sockaddr*) & addr_listen, len ) == -1 ) { cerr << "Can't bind to the listen port [" << port << "]" << endl; ::exit( 1 ); } verbose_output( 3, "waiting for connection...", avi_ptr->ip ); *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen );} // }}}// 处理连接后的数据发送工作void network_ctrl_send_thread::listen_handle ( void ) // {{{{ // 接收进来的连接 int recv_num; BUFF * buff; bool should_exit = false; int lost_heartbeat = 0; packet_head_t * packet_head = NULL; while ( 1 ) { (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { cout << "before nast" << endl; nast->wait(); cout << "after nvst" << endl; cout << "before nvst" << endl; nvst->wait(); cout << "after nvst" << endl; QCustomEvent * event = new QCustomEvent( SIG_STOP_OK ); QApplication::postEvent( avi_ptr, event ); return; } // 监听端口 pollfd connect_in = { fd_ctrl, POLLIN, 0 }; int result = poll( &connect_in, 1, DEFAULT_TIMEOUT ); if ( result < 0 ) { perror( "Error in video listening" ); } if ( result == 0 && client_num > 0 ) // {{{ { // 超时,无heartbeat lost_heartbeat++; if ( lost_heartbeat >= MAX_LOST_HEARTBEAT ) { // 客户端丢失 QCustomEvent * event = new QCustomEvent( SIG_LOST_CLIENT ); QApplication::postEvent( avi_ptr, event ); client_num--; nast->wait(); nvst->wait(); return; } } else { // 有数据可读? if ( ( connect_in.revents & POLLIN ) != 0 ) // {{{ { recv_line( fd_ctrl, addr_accept, recv_buff, buff, packet_head ); if ( TEST_CTRL_SYN_BIT( packet_head->opt_bits ) ) { packet_num = recv_num; QCustomEvent * event = new QCustomEvent( SIG_ACCEPT_CONNECT ); QApplication::postEvent( avi_ptr, event ); client_num++; // 写入参数 option_t opt_buf; opt_buf.factor = avi_ptr->video_opt.factor; opt_buf.va_mode = avi_ptr->va_mode; if ( avi_ptr->use_g723 ) { opt_buf.use_g723 = 1; } else { opt_buf.use_g723 = 0; } int length = sizeof( opt_buf ); send_data( fd_ctrl, addr_accept, send_buff, (BUFF *) &opt_buf, length, packet_num, SYN ); verbose_output( 4, "transfer 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", avi_ptr->use_g723 ); } else { if ( TEST_CTRL_HEARTBEAT_BIT( packet_head->opt_bits ) ) { lost_heartbeat = 0; } else { if ( TEST_CTRL_GOODBYE_BIT( packet_head->opt_bits ) ) { // 客户端正常退出 QCustomEvent * event = new QCustomEvent( SIG_ACCEPT_DISCONNECT ); QApplication::postEvent( avi_ptr, event ); nast->wait(); nvst->wait(); client_num--; return; } } } } // if ( ( connect_in.revents & POLLIN ) != 0 ) }}} } // if ( result == 0 ) // }}} } // while ( 1 ) return;} // }}}// 组播初始化,创建套接字void network_ctrl_send_thread::listen_init_mc ( void ) // {{{{ verbose_output( 3, "network ctrl 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_CTRL_PORT ); inet_pton( AF_INET, static_cast< const char* >( avi_ptr->mc_addr ), &addr_accept->sin_addr ); // 创建控制端发送socket fd_ctrl = 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_ctrl, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) ); verbose_output( 3, "ready to send data", avi_ptr->ip );} // }}}// 处理组播连接后的数据接收工作void network_ctrl_send_thread::listen_handle_mc ( void ) // {{{{ verbose_output( 3, "network ctrl send thread Multicast handle." ); nast->wait(); cout << "nast wait" << endl; nvst->wait(); cout << "nvst wait" << endl;} // }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -