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;
} // }}}