⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jvoipsounddevdrvthread.cpp

📁 使用VOIP进行网络传输声音的类库
💻 CPP
字号:
/*    This file is a part of JVOIPLIB, a library designed to facilitate    the use of Voice over IP (VoIP).    Copyright (C) 2000-2004  Jori Liesenborgs (jori@lumumba.luc.ac.be)    This library (JVOIPLIB) is based upon work done for my thesis at    the School for Knowledge Technology (Belgium/The Netherlands)    The full GNU Library General Public License can be found in the    file LICENSE.LGPL which is included in the source code archive.    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307    USA*/#include "jvoipconfig.h"#include "jvoipsounddevdrvthread.h"#include "jvoipsounddeviceblock.h"#include "jvoiperrors.h"#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/soundcard.h>#include <iostream>#include "debugnew.h"#define JVOIPSOUNDDEVDRVTHREAD_FRAGMENTTIME					10 // ten milliseconds// Make sure these are multiples of 4 !!!#define JVOIPSOUNDDEVDRVTHREAD_FRAGMENTMIN					128#define JVOIPSOUNDDEVDRVTHREAD_FRAGMENTMAX					4096JVOIPSoundDevDrvThread::JVOIPSoundDevDrvThread(int filedesc,int currentsamplingrate) throw (JVOIPException){	filedescriptor = filedesc;	stopthread = false;	firstbuffer = NULL;	lastbuffer = NULL;	if (sigwait.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITSIGWAIT);	if (flagmutex.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITMUTEX);	if (stopmutex.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITMUTEX);	if (buffermutex.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITMUTEX);	if (loopmutex.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITMUTEX);	if (resetmutex.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITMUTEX);	resetting = false;		CalculateFragmentLength(currentsamplingrate);}JVOIPSoundDevDrvThread::~JVOIPSoundDevDrvThread(){	StopThread();}int JVOIPSoundDevDrvThread::AddBuffer(JVOIPSoundDeviceBlock *blk){	buffermutex.Lock();	if (firstbuffer == NULL)		firstbuffer = blk;	else		lastbuffer->next = blk;	lastbuffer = blk;	blk->done = false;	blk->flagmutex = &flagmutex;	blk->next = NULL;	sigwait.Signal();	buffermutex.Unlock();	return 0;}void JVOIPSoundDevDrvThread::StopThread(){	time_t tm;	if (!IsRunning())		return;		Reset();	stopmutex.Lock();	stopthread = true;	stopmutex.Unlock();	sigwait.Signal(); // to make sure that the thread loops	tm = time(NULL);	while (IsRunning() && (time(NULL)-tm) < 5) // wait max 5 seconds		;	if (IsRunning())	{		Kill();		std::cerr << "JVOIPSoundDevDrvThread::StopThread -- Warning: killing thread" << std::endl;	}	ClearBuffers();}void JVOIPSoundDevDrvThread::Reset(){	stopmutex.Lock(); // to make sure the thread waits for a loop	resetmutex.Lock();	resetting = true;	resetmutex.Unlock();		sigwait.Signal(); // to avoid being trapped	loopmutex.Lock(); // wait till we're at the end of the loop	loopmutex.Unlock(); // the stopmutex will still pause the thread	// Clear all buffers	ClearBuffers();		sigwait.ClearSignalBuffers();			resetmutex.Lock();	resetting = false;	resetmutex.Unlock();		stopmutex.Unlock();}void JVOIPSoundDevDrvThread::ClearBuffers(){	JVOIPSoundDeviceBlock *tmp;			buffermutex.Lock(); 		tmp = firstbuffer;	while (tmp)	{		flagmutex.Lock();		tmp->done = true;		flagmutex.Unlock();		tmp = tmp->next;	}	firstbuffer = NULL;	lastbuffer = NULL;	buffermutex.Unlock();}void JVOIPSoundDevDrvThread::CalculateFragmentLength(int rate){	double samples;		int diff;		samples = (double)rate;	samples /= 1000.0;	samples *= (double)JVOIPSOUNDDEVDRVTHREAD_FRAGMENTTIME;	fragmentlength = (int)(samples*4.0); // *2 for sixteen bit; again *2 for stereo	if (fragmentlength < JVOIPSOUNDDEVDRVTHREAD_FRAGMENTMIN)		fragmentlength = JVOIPSOUNDDEVDRVTHREAD_FRAGMENTMIN;	else if (fragmentlength > JVOIPSOUNDDEVDRVTHREAD_FRAGMENTMAX)		fragmentlength = JVOIPSOUNDDEVDRVTHREAD_FRAGMENTMAX;	// Make sure the framgmentlength is a multiple of four, since we're working with	// sixteen bit samples and with stereo sound! 	if ((diff = fragmentlength%4) != 0)		fragmentlength -= diff;}JVOIPSoundDevDrvInputThread::JVOIPSoundDevDrvInputThread(int filedesc,int currentsamplingrate) throw (JVOIPException) : JVOIPSoundDevDrvThread(filedesc,currentsamplingrate){	if (callbackmutex.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITMUTEX);	inputcallback = NULL;	inputcallbackparam = NULL;}void JVOIPSoundDevDrvInputThread::SetInputCallback(void (*f)(void *param),void *param){	callbackmutex.Lock();	inputcallback = f;	inputcallbackparam = param;	callbackmutex.Unlock();}void *JVOIPSoundDevDrvInputThread::Thread(){	JThread::ThreadStarted();		bool stop;	int blklen;	JVOIPSoundDeviceBlock *blk;	int bytestoread,bytesleft;	unsigned char *buf;	bool done;		stopmutex.Lock();	stop = stopthread;	stopmutex.Unlock();	while (!stop)	{		loopmutex.Lock();		sigwait.WaitForSignal(); // wait until a buffer is available		buffermutex.Lock();		blk = firstbuffer;		if (firstbuffer)		{			firstbuffer = firstbuffer->next;			if (!firstbuffer)				lastbuffer = NULL;		}		buffermutex.Unlock();				if (blk)		{			if ((blklen = blk->datalen) > 0 && blk->data != NULL)			{				bytesleft = blklen;				buf = blk->data;				while (bytesleft > 0)				{					resetmutex.Lock();					done = resetting;					resetmutex.Unlock();					if (done)						break;										bytestoread = (bytesleft > fragmentlength)?fragmentlength:bytesleft;					read(filedescriptor,buf,bytestoread);					buf += bytestoread;					bytesleft -= bytestoread;				}			}			flagmutex.Lock();			blk->done = true;			flagmutex.Unlock();			callbackmutex.Lock();			if (inputcallback)				inputcallback(inputcallbackparam);			callbackmutex.Unlock();		}		loopmutex.Unlock();				stopmutex.Lock();		stop = stopthread;		stopmutex.Unlock();	}	return NULL;}void *JVOIPSoundDevDrvOutputThread::Thread(){	JThread::ThreadStarted();		bool stop;	int blklen;	JVOIPSoundDeviceBlock *blk;	int bytestowrite,bytesleft;	unsigned char *buf;	bool done;		stopmutex.Lock();	stop = stopthread;	stopmutex.Unlock();	while (!stop)	{		loopmutex.Lock();				sigwait.WaitForSignal(); // wait until a buffer is available		buffermutex.Lock();		blk = firstbuffer;		if (firstbuffer)		{			firstbuffer = firstbuffer->next;			if (!firstbuffer)				lastbuffer = NULL;		}		buffermutex.Unlock();		if (blk)		{			if ((blklen = blk->datalen) > 0 && blk->data != NULL)			{				bytesleft = blklen;				buf = blk->data;				while (bytesleft > 0)				{					resetmutex.Lock();					done = resetting;					resetmutex.Unlock();					if (done)						break;										bytestowrite = (bytesleft > fragmentlength)?fragmentlength:bytesleft;					write(filedescriptor,buf,bytestowrite);					buf += bytestowrite;					bytesleft -= bytestowrite;				}			}			flagmutex.Lock();			blk->done = true;			flagmutex.Unlock();		}		loopmutex.Unlock();			stopmutex.Lock();		stop = stopthread;		stopmutex.Unlock();	}	return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -