www.pudn.com > exosip.rar > sound-win32.cpp
/* * josua - Jack's open sip User Agent * * Copyright (C) 2002,2003 Aymeric Moizard* * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with dpkg; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "stdafx.h" #include "jcalls.h" #include "sdptools.h" #include #ifdef WIN32 #include #include #include #include WAVEFORMATEX wfx; #define MAX_IN_BUFFERS 32 #define USED_IN_BUFFERS 6 #define MAX_OUT_BUFFERS 32 #define USED_OUT_BUFFERS 32 unsigned int waveoutDeviceID = WAVE_MAPPER; WAVEHDR waveHdrOut[MAX_OUT_BUFFERS]; HWAVEOUT hWaveOut; char dataBufferOut[MAX_OUT_BUFFERS][3200]; unsigned int waveinDeviceID = WAVE_MAPPER; HWAVEIN hWaveIn; WAVEHDR waveHdrIn[MAX_IN_BUFFERS]; char dataBufferIn[MAX_IN_BUFFERS][3200]; call_t *current_call = NULL; extern "C" void va_g729a_init_encoder(); extern "C" void va_g729a_encoder(short *speech, unsigned char *bitstream); extern "C" void va_g729a_init_decoder(); extern "C" void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi); static void CALLBACK SpeakerCallback (HWAVEOUT _hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { WAVEHDR *wHdr; switch (uMsg) { case WOM_OPEN: fprintf (stderr, "SpeakerCallback : WOM_OPEN\n"); break; case WOM_CLOSE: fprintf (stderr, "SpeakerCallback : WOM_CLOSE\n"); break; case WOM_DONE: fprintf (stderr, "SpeakerCallback : WOM_DONE\n"); wHdr = (WAVEHDR *) dwParam1; break; default: break; } } static void CALLBACK WaveInCallback (HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { WAVEHDR *wHdr; MMRESULT mr = NOERROR; char szSendBuffer[1024]; int nLen = sizeof(szSendBuffer); switch (uMsg) { case WIM_OPEN: break; case WIM_CLOSE: break; case WIM_DATA: wHdr = (WAVEHDR *) dwParam1; if (current_call == NULL) return; mr = waveInAddBuffer (hWaveIn, &(waveHdrIn[wHdr->dwUser]), sizeof (waveHdrIn[wHdr->dwUser])); if (mr == MMSYSERR_NOERROR) { static int timestamp = 0; if (current_call) { EncodeAudioData(wHdr->lpData, wHdr->dwBytesRecorded, szSendBuffer,&nLen); rtp_session_send_with_ts (current_call->rtp_session, (BYTE*)szSendBuffer, nLen, timestamp); timestamp += nLen; } } break; default: break; } } bool EncodeAudioData(char *pin,int len,char* pout,int* lenr) { bool bRet = false; va_g729a_encoder((short*)pin,(BYTE*)pout); va_g729a_encoder((short*)(pin+320),(BYTE*)pout+20); va_g729a_encoder((short*)(pin+640),(BYTE*)pout+40); va_g729a_encoder((short*)(pin+800),(BYTE*)pout+50); *lenr = 60; bRet = true; RET: return bRet; } bool DecodeAudioData(char *pin,int len,char* pout,int* lenr) { bool bRet = false; va_g729a_decoder((BYTE*)pin,(short*)(pout),0); va_g729a_decoder((BYTE*)pin+20,(short*)(pout+320),0); va_g729a_decoder((BYTE*)pin+40,(short*)(pout+640),0); va_g729a_decoder((BYTE*)pin+50,(short*)(pout+800),0); *lenr=960; bRet=true; RET: return bRet; } int os_sound_init () { ortp_init (); ortp_scheduler_init (); va_g729a_init_encoder(); va_g729a_init_decoder(); return 0; } int open_sndcard (int format) { MMRESULT mr = NOERROR; WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = 8000; wfx.nAvgBytesPerSec = 1 * 8000 * 16 / 8; wfx.nBlockAlign = 16 * 1 / 8; wfx.wBitsPerSample = 16; wfx.cbSize = 0; mr = waveOutOpen (&hWaveOut, waveoutDeviceID, &wfx,(DWORD)0,0,CALLBACK_NULL); if (mr == NOERROR) { int i; for (i = 0; i < USED_OUT_BUFFERS; i++) { memset (&(waveHdrOut[i]), 0, sizeof (waveHdrOut[i])); waveHdrOut[i].lpData = dataBufferOut[i]; waveHdrOut[i].dwBufferLength = 960; /* frameSize */ waveHdrOut[i].dwFlags = 0; waveHdrOut[i].dwUser = i; mr = waveOutPrepareHeader (hWaveOut, &(waveHdrOut[i]),sizeof (waveHdrOut[i])); } } mr = waveInOpen (&hWaveIn, waveinDeviceID, &wfx, (DWORD) WaveInCallback, 0, CALLBACK_FUNCTION); if (mr == MMSYSERR_NOERROR) { int i; for (i = 0; i < MAX_IN_BUFFERS; i++) { waveHdrIn[i].lpData = dataBufferIn[i]; waveHdrIn[i].dwBufferLength = 960; /* frameSize */ waveHdrIn[i].dwFlags = 0; waveHdrIn[i].dwUser = i; mr = waveInPrepareHeader (hWaveIn, &(waveHdrIn[i]), sizeof (waveHdrIn[i])); if (mr == MMSYSERR_NOERROR) { mr = waveInAddBuffer (hWaveIn, &(waveHdrIn[i]), sizeof (waveHdrIn[i])); } } mr = waveInStart (hWaveIn); if (mr != MMSYSERR_NOERROR) { exit (-1); return -1; } } return 0; } void * os_sound_start_thread (void *_ca) { int pos_whdr = 0; call_t *ca = (call_t *) _ca; char data_in[3000]; char szBuffer[2048]; int nLen = 2048; int have_more; int timestamp = 0; int i; current_call = ca; while (ca->enable_audio != -1) { int length; static int sound_played = 0; static int cpt = 0; memset (data_in, 0, 3000); if (ca->payload == 3) length = 260; /* 280 ?? */ else length = 160; i = rtp_session_recv_with_ts (ca->rtp_session, (unsigned char*)data_in, length, timestamp, &have_more); if (i > 0) { MMRESULT mr = NOERROR; DecodeAudioData(data_in,i,szBuffer,&nLen); memset (waveHdrOut[pos_whdr].lpData, 0, length); memcpy (waveHdrOut[pos_whdr].lpData, szBuffer, nLen); waveHdrOut[pos_whdr].dwBufferLength = nLen; mr = waveOutWrite (hWaveOut, &waveHdrOut[pos_whdr], sizeof (waveHdrOut[pos_whdr])); pos_whdr++; if (pos_whdr == USED_OUT_BUFFERS) { pos_whdr = 0; /* loop over the prepared blocks */ } if (mr != MMSYSERR_NOERROR) switch (mr) { case MMSYSERR_INVALHANDLE: fprintf (stderr, "__call_free: waveOutWrite: 0x%i MMSYSERR_INVALHANDLE\n", mr); break; case MMSYSERR_NODRIVER: fprintf (stderr, "__call_free: waveOutWrite: 0x%i MMSYSERR_NODRIVER\n", mr); break; case MMSYSERR_NOMEM: fprintf (stderr, "__call_free: waveOutWrite: 0x%i MMSYSERR_NOMEM\n", mr); break; case WAVERR_UNPREPARED: fprintf (stderr, "__call_free: waveOutWrite: 0x%i WAVERR_UNPREPARED\n", mr); break; case WAVERR_STILLPLAYING: fprintf (stderr, "__call_free: waveOutWrite: 0x%i WAVERR_STILLPLAYING\n", mr); default: fprintf (stderr, "__call_free: waveOutWrite: 0x%i\n", mr); } else ++sound_played; fprintf (stderr, "sound played = %i\n", sound_played); fprintf (stderr, "cpt = %i\n", ++cpt); } timestamp += length; } current_call = NULL; return NULL; } int os_sound_start (call_t * ca, int port) { int format = WAVE_FORMAT_MULAW; char localip[128]; eXosip_guess_localip (AF_INET, localip, 128); if (open_sndcard (format) != 0) return -1; ca->rtp_session = rtp_session_new (RTP_SESSION_SENDRECV); rtp_session_set_scheduling_mode (ca->rtp_session, 1); /* yes */ rtp_session_set_blocking_mode (ca->rtp_session, 1); rtp_session_set_profile (ca->rtp_session, &av_profile); rtp_session_set_jitter_compensation (ca->rtp_session, 60); rtp_session_set_local_addr (ca->rtp_session, localip, port); rtp_session_set_remote_addr (ca->rtp_session, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port); rtp_session_set_payload_type (ca->rtp_session, ca->payload); rtp_session_signal_connect (ca->rtp_session, "telephone-event", (RtpCallback) rcv_telephone_event, /*ca*/0); ca->audio_thread = osip_thread_create (20000, os_sound_start_thread, ca); return 0; } void os_sound_close (call_t * ca) { osip_thread_join (ca->audio_thread); osip_free (ca->audio_thread); rtp_session_signal_disconnect_by_callback (ca->rtp_session, "telephone-event", (RtpCallback) rcv_telephone_event); rtp_session_destroy (ca->rtp_session); /* waveInReset (hWaveIn); waveInClose (hWaveIn); waveOutReset (hWaveOut); waveOutClose (hWaveOut);*/ } #endif