📄 dspoutrtp.cpp
字号:
#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <unistd.h>#include <stdio.h>#include <g711.h>#include <qsettings.h>#include <qtimer.h>#include "../dissipate2/sipuri.h"#include "../dissipate2/sipclient.h"#include "audiobuffer.h"#include "rtpdataheader.h"#include "dspoutrtp.h"#include "kphone.h"short ILBCencode_20( iLBC_Enc_Inst_t *iLBCenc_inst,short *encoded_data, short *data);short ILBCdecode_20( iLBC_Dec_Inst_t *iLBCdec_inst,short *decoded_data, short *encoded_data, short mode);short ILBCencode_30( iLBC_Enc_Inst_t *iLBCenc_inst,short *encoded_data, short *data);short ILBCdecode_30( iLBC_Dec_Inst_t *iLBCdec_inst,short *decoded_data, short *encoded_data, short mode);DspOutRtp::DspOutRtp( const codecType newCodec, int newCodecNum, const QString &hostName, UDPMessageSocket *s ) : portnum(0) , curseq(0) , qlen(0) , numunsend(0) , fixedrtplen(160) , deb_frag(0L) , deb_rtp(0L) , ssrc(10) , ref_sec(0) , ref_usec(0) , dsize(4096) , useStun(false) , destroySocket(false){ #ifdef SRTP QSettings settings; if(settings.readEntry("/kphone/SRTP/Enable", "") == "Yes"){ wrapper = SRTPWrapper::getInstance(); } else{ wrapper = 0; } #endif codec = newCodec; codecNum = newCodecNum; if (s) { socket = s; } else { socket = new UDPMessageSocket(); destroySocket = true; if (socket == 0) { printf( QObject::tr("DspOutRtp:: Can't create socket") + "\n" ); abort(); } } if( hostName != QString::null && !socket->setHostname( hostName.latin1() ) ) { printf( QObject::tr("DspOutRtp::Hostname lookup failed") + "\n" ); } if( !( gsmInstEnc = gsm_create() ) ) { printf( "DspOutRtp::GSM_CREATE -error !\n" ); } if( !( gsmInstDec = gsm_create() ) ) { printf( "DspOutRtp::GSM_CREATE -error !\n" ); } packetbuf = new unsigned char[ sizeof( rtp_hdr_t ) + dsize ]; bufunsend = new unsigned char[ dsize ]; outbuf = new unsigned char[ dsize ]; tmpbuf = new unsigned char[ dsize ]; quebuf = new unsigned char[ dsize ]; initEncode(&ilbcEncInst_20, 20 ); initDecode(&ilbcDecInst_20, 20, 1); initEncode(&ilbcEncInst_30, 30 ); initDecode(&ilbcDecInst_30, 30, 1); audio_buf.resize( dsize * sizeof( short ) ); setDeviceName("rtp");}DspOutRtp::~DspOutRtp( void ){ if( gsmInstEnc ) gsm_destroy( gsmInstEnc ); if( gsmInstDec ) gsm_destroy( gsmInstDec ); delete[] static_cast<unsigned char *>( packetbuf ); delete[] static_cast<unsigned char *>( bufunsend ); delete[] static_cast<unsigned char *>( outbuf ); delete[] static_cast<unsigned char *>( tmpbuf ); delete[] static_cast<unsigned char *>( quebuf ); if (destroySocket) delete socket; #ifdef SRTP if(!wrapper == 0){ wrapper->dispose(); } #endif}bool DspOutRtp::openDevice( DeviceMode mode ){ int min, max; QSettings settings; min = settings.readNumEntry("/kphone/Media/MinPort", constMinPort); max = settings.readNumEntry("/kphone/Media/MaxPort", constMaxPort); devmode = mode; if( devmode == ReadOnly ) { socket->listenOnEvenPort(min, max); portnum = socket->getPortNumber(); /* Use STUN to rewrite port number only if the user * didn't set a static port range which is being forwarded * on the NAT */ if ((min == 0) && (max == 0)) { if ( sendStunRequest( socket ) ) { portnum = receiveStunResponse( socket ); if( portnum > 0 ) { socket->forcePortNumber( portnum ); } } }//------------------------------// Linux kernels 2.4.x// Do not allow any double binds even when same user and REUSEADDR./* UDPMessageSocket *socketVideo = new UDPMessageSocket() ; socketVideo->forcePortNumber( videoPortnum ); socketVideo->listenOnEvenPortForVideo(); videoPortnum = socketVideo->getPortNumber(); socketVideo->forcePortNumber( videoPortnum ); if( sendStunRequest( *socketVideo ) ) { videoPortnum = receiveStunResponse( *socketVideo ); } delete socketVideo;*/ videoPortnum = portnum + 20;//------------------------------ } else { if( socket->connect( portnum ) ) { if ( socket->SetTOS() ) return false ; } else return false; } devstate = DeviceOpened; return true;}#define PCMUCODEC 0#define GSMCODEC 3#define PCMACODEC 8typedef struct cb {unsigned char (*func)( int frombuf );} cb_t;bool DspOutRtp::writeBuffer( void ){ short *s; short *frombuf; unsigned char *databuf; rtp_hdr_t *h = (rtp_hdr_t *) packetbuf; size_t fromsize; unsigned char *wlbuf; size_t bytesnew; size_t bytesgot; int tmpsize; unsigned int i; bytesnew = audio_buf.getSize() / sizeof( short ); fromsize = audio_buf.getSize() / sizeof( short ); inbuf = (unsigned char*)audio_buf.getData(); frombuf = (short *)inbuf; if( codec == codecGSM ) { short *frombuf_test; frombuf_test = frombuf; s = (short *)inbuf; for( i=0; i<fromsize; ++i) { s[i] = (short)(*frombuf_test); ++frombuf_test; } tmpsize = writeGSMBuffer( gsmInstEnc, inbuf, outbuf, tmpbuf, quebuf, &qlen, fromsize ); h->version = 2; h->p = 0; h->x = 0; h->cc = 0; h->m = 0; h->pt = GSMCODEC; while( tmpsize > 0 ) { h->seq = htons( ++curseq ); h->ts = htonl( ts ); ts += GSM_DEC_SAMPLES; h->ssrc = ssrc; databuf = packetbuf + sizeof( rtp_hdr_t ); for( int i = 0; i < tmpsize; ++i ) { databuf[ i ] = outbuf[ i ]; } #ifdef SRTP int* length = new int(sizeof( rtp_hdr_t ) + tmpsize); if(!wrapper == 0){ wrapper->protect(packetbuf, length); } if( socket->send( (char *) packetbuf, *length) < 0 ) { #else if( socket->send( (char *) packetbuf, sizeof( rtp_hdr_t ) + tmpsize ) < 0 ) { #endif printf("DspOutRtp::writeBuffer: %s\n", strerror(errno)); return false; } tmpsize = writeGSMBuffer( gsmInstEnc, inbuf, outbuf, tmpbuf, quebuf, &qlen, 0 ); } } else if( codec == codecILBC_20 || codec == codecILBC_30 ) { short *frombuf_test; frombuf_test = frombuf; s = (short *)inbuf; for( i=0; i<fromsize; ++i) { s[i] = (short)(*frombuf_test); ++frombuf_test; } if( codec == codecILBC_20 ) { tmpsize = writeILBCBuffer_20( &ilbcEncInst_20, inbuf, outbuf, tmpbuf, quebuf, &qlen, fromsize ); } else { tmpsize = writeILBCBuffer_30( &ilbcEncInst_30, inbuf, outbuf, tmpbuf, quebuf, &qlen, fromsize ); } h->version = 2; h->p = 0; h->x = 0; h->cc = 0; h->m = 0; h->pt = codecNum; while( tmpsize > 0 ) { h->seq = htons( ++curseq ); h->ts = htonl( ts ); if( codec == codecILBC_20 ) { ts += BLOCKL_20MS; } else { ts += BLOCKL_30MS; } h->ssrc = ssrc; databuf = packetbuf + sizeof( rtp_hdr_t ); for( int i = 0; i < tmpsize; ++i ) { databuf[ i ] = outbuf[ i ]; } #ifdef SRTP int* length = new int(sizeof( rtp_hdr_t ) + tmpsize); if(!wrapper == 0){ wrapper->protect(packetbuf, length); } if( socket->send( (char *) packetbuf, *length) < 0 ) { #else if( socket->send( (char *) packetbuf, sizeof( rtp_hdr_t ) + tmpsize ) < 0 ) { #endif printf("DspOutRtp::writeBuffer: %s\n", strerror(errno)); return false; } if( codec == codecILBC_20 ) { tmpsize = writeILBCBuffer_20( &ilbcEncInst_20, inbuf, outbuf, tmpbuf, quebuf, &qlen, 0 ); } else { tmpsize = writeILBCBuffer_30( &ilbcEncInst_30, inbuf, outbuf, tmpbuf, quebuf, &qlen, 0 ); } } } else if( codec == codecPCMA || codec == codecPCMU ) { cb_t callb; wlbuf = bufunsend; h->version = 2; h->p = 0; h->x = 0; h->cc = 0; h->m = 0; switch ( codec ) { case codecPCMU: h->pt = PCMUCODEC; callb.func = &linear2ulaw; break; case codecPCMA: h->pt = PCMACODEC; callb.func = &linear2pcma; default: break; } while(bytesnew+numunsend >= fixedrtplen){ ++deb_rtp; h->seq = htons( ++curseq ); h->ts = htonl( ts ); ts += fixedrtplen; h->ssrc = ssrc; databuf = packetbuf + sizeof( rtp_hdr_t ); bytesgot = 0; while( numunsend > 0 ) { *databuf = *wlbuf; ++databuf; ++wlbuf; --numunsend; ++bytesgot; } wlbuf = bufunsend; while( bytesgot < fixedrtplen ) { *databuf = callb.func( *frombuf ); ++databuf; ++frombuf; --bytesnew; ++bytesgot; } #ifdef SRTP int* length = new int(sizeof( rtp_hdr_t ) + fixedrtplen); if(!wrapper == 0){ wrapper->protect(packetbuf, length); } if( socket->send( (char *) packetbuf, *length ) < 0 ) { #else if( socket->send( (char *) packetbuf, sizeof( rtp_hdr_t ) + fixedrtplen ) < 0 ) { #endif printf("DspOutRtp::writeBuffer: %s\n", strerror(errno)); return false; } } if( bytesnew > 0 ) { wlbuf = bufunsend + numunsend; numunsend += bytesnew; while( bytesnew > 0 ){ *wlbuf = callb.func( *frombuf ); ++wlbuf; ++frombuf; --bytesnew; } } ++deb_frag; } else { printf("DspOutRtp::writeBuffer: unknown Codec %i\n",codec); return false; } return true;}bool DspOutRtp::setPortNum( int newport ){ portnum = newport; return true;}unsigned int DspOutRtp::readableBytes( void ){ struct timeval timeout; fd_set read_fds; int highest_fd; timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO( &read_fds ); FD_SET( socket->getFileDescriptor(), &read_fds ); highest_fd = socket->getFileDescriptor() + 1;retry: if ( select( highest_fd, &read_fds, NULL, NULL, &timeout ) == -1 ) { if ( errno == EINTR ) goto retry; perror( "DspOutRtp::doSelect(): select() punted" ); exit( 1 ); } if ( FD_ISSET( socket->getFileDescriptor(), &read_fds ) ) { return 1; } return 0;}bool DspOutRtp::readBuffer( int bytes ){ unsigned char *inbuf; short *outbuf; int recvsize; int i; int size; recvsize = socket->receive( (char *) packetbuf, sizeof( rtp_hdr_t ) + dsize ); rtp_hdr_t *h = (rtp_hdr_t *) packetbuf; #ifdef SRTP if(!wrapper == 0){ int* length = new int(recvsize); wrapper->unprotect(packetbuf, length); recvsize = *length; } #endif if( h->pt == PCMUCODEC ) { audio_buf.resize( ( recvsize - (int) sizeof( rtp_hdr_t ) ) * sizeof( short ) ); outbuf = (short *) audio_buf.getData(); inbuf = &packetbuf[ sizeof( rtp_hdr_t ) ]; for( i = 0; i < recvsize - (int) sizeof( rtp_hdr_t ); ++i ) { *outbuf = (short) ulaw2linear( inbuf[ i ] ); ++outbuf; } } else if( h->pt == GSMCODEC ) { audio_buf.resize( GSM_DEC_SAMPLES * sizeof( short ) ); outbuf = (short *) audio_buf.getData(); inbuf = &packetbuf[ sizeof( rtp_hdr_t ) ]; readGSMBuffer( gsmInstDec, inbuf, tmpbuf, false ); short *s = (short *)tmpbuf; for( i = 0; i < GSM_DEC_SAMPLES; ++i) { *outbuf = (short)(s[i]); ++outbuf; } } else if( h->pt == PCMACODEC ) { audio_buf.resize( ( recvsize - (int) sizeof( rtp_hdr_t ) ) * sizeof( short ) ); outbuf = (short *) audio_buf.getData(); inbuf = &packetbuf[ sizeof( rtp_hdr_t ) ]; for( i = 0; i < recvsize - (int) sizeof( rtp_hdr_t ); ++i ) { *outbuf = (short) pcma2linear( inbuf[ i ] ); ++outbuf; } } else if( codec == codecILBC_20 && (int)h->pt == codecNum ) { audio_buf.resize( BLOCKL_20MS * sizeof( short ) ); outbuf = (short *) audio_buf.getData(); inbuf = &packetbuf[ sizeof( rtp_hdr_t ) ]; size = readILBCBuffer_20( &ilbcDecInst_20, inbuf, tmpbuf, 1, false ); short *s = (short *)tmpbuf; for( i = 0; i < size; ++i) { *outbuf = (short)(s[i]); ++outbuf; } } else if( codec == codecILBC_30 && (int)h->pt == codecNum ) { audio_buf.resize( BLOCKL_30MS * sizeof( short ) ); outbuf = (short *) audio_buf.getData(); inbuf = &packetbuf[ sizeof( rtp_hdr_t ) ]; size = readILBCBuffer_30( &ilbcDecInst_30, inbuf, tmpbuf, 1, false ); short *s = (short *)tmpbuf; for( i = 0; i < size; i++) { *outbuf++ = (short)(s[i]); } } return true;}bool DspOutRtp::sendStunRequest( UDPMessageSocket *socketStun ){ SipUri stun; if( useStun ) { stun = SipUri( stunSrv ); if( !socketStun->setHostname( stun.getHostname() ) ) { return false; } socketStun->connect( stun.getPortNumber() ); printf( "DspOutRtp: STUN request\n" ); StunRequestSimple req;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -