From ef247886e58d5f9fd18dc3355aeafe76e5a68833 Mon Sep 17 00:00:00 2001 From: smorlat Date: Sat, 4 Oct 2008 20:59:24 +0000 Subject: [PATCH] - bug fixes - new winsnd3.c (clear audio) git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@66 3f6dc0c8-ddfe-455d-9043-3cd528dc4637 --- linphone/coreapi/misc.c | 27 +- linphone/gtk-glade/linphone.iss | 6 +- linphone/gtk-glade/main.c | 3 + .../build/win32native/mediastreamer2.dev | 4 +- linphone/mediastreamer2/src/msvideo.c | 4 +- linphone/mediastreamer2/src/winsnd2.c | 7 + linphone/mediastreamer2/src/winsnd3.c | 711 ++++++++++++++++++ linphone/mediastreamer2/src/winvideo.c | 18 +- linphone/oRTP/build/win32native/ortp-dll.dev | 4 +- linphone/win32/liblinphone.dev | 3 +- 10 files changed, 763 insertions(+), 24 deletions(-) create mode 100755 linphone/mediastreamer2/src/winsnd3.c diff --git a/linphone/coreapi/misc.c b/linphone/coreapi/misc.c index 08d035e11..d9663b1a9 100644 --- a/linphone/coreapi/misc.c +++ b/linphone/coreapi/misc.c @@ -464,7 +464,7 @@ static ortp_socket_t create_socket(int local_port){ laddr.sin_addr.s_addr=INADDR_ANY; laddr.sin_port=htons(local_port); if (bind(sock,(struct sockaddr*)&laddr,sizeof(laddr))<0){ - ms_error("Bind to 0.0.0.0:%i failed: %s",local_port,strerror(errno)); + ms_error("Bind socket to 0.0.0.0:%i failed: %s",local_port,getSocketError()); close_socket(sock); return -1; } @@ -636,7 +636,7 @@ static int extract_sip_port(const char *config){ int linphone_core_wake_up_possible_already_running_instance(const char *config_file){ int port=extract_sip_port(config_file); const char *wakeup="WAKEUP sip:127.0.0.1 SIP/2.0\r\n" - "Via: SIP/2.0/UDP 127.0.0.1:57655;rport;branch=z9hG4bK%u\r\n" + "Via: SIP/2.0/UDP 127.0.0.1:%i;rport;branch=z9hG4bK%u\r\n" "From: ;tag=%u\r\n" "To: \r\n" "CSeq: 1 WAKEUP\r\n" @@ -650,18 +650,23 @@ int linphone_core_wake_up_possible_already_running_instance(const char *config_f char tmp[100]; snprintf(tmp,sizeof(tmp),"127.0.0.1:%i",port); if (parse_stun_server_addr(tmp,&ss,&sslen)==0){ - int sock=create_socket(57655); + int locport=57123; + ortp_socket_t sock=create_socket(locport); + if (sock<0) sock=create_socket(++locport); if (sock>=0){ char req[512]; - snprintf(req,sizeof(req),wakeup,random(),random(),random()); - if (sendto(sock,req,strlen(req),0,(struct sockaddr*)&ss,sslen)>0){ + snprintf(req,sizeof(req),wakeup,locport,random(),random(),random()); + if (connect(sock,(struct sockaddr*)&ss,sslen)<0){ + fprintf(stderr,"connect failed: %s\n",getSocketError()); + }else if (send(sock,req,strlen(req),0)>0){ /*wait a bit for a response*/ int i; for(i=0;i<10;++i){ - if (recv(sock,tmp,sizeof(tmp),0)>0){ - ms_message("Another linphone has been woken-up !"); - close(sock); + if (recv(sock,req,sizeof(req),0)>0){ + close_socket(sock); return 0; + }else if (getSocketErrorCode()!=EWOULDBLOCK){ + break; } #ifdef WIN32 Sleep(10); @@ -669,9 +674,9 @@ int linphone_core_wake_up_possible_already_running_instance(const char *config_f usleep(10000); #endif } - } - }else ms_error("Fail to create socket on port 57655"); - close(sock); + }else ms_message("sendto() of WAKEUP request failed, nobody to wakeup."); + } + close_socket(sock); } } return -1; diff --git a/linphone/gtk-glade/linphone.iss b/linphone/gtk-glade/linphone.iss index 9d68bba3a..16b49beae 100755 --- a/linphone/gtk-glade/linphone.iss +++ b/linphone/gtk-glade/linphone.iss @@ -34,11 +34,11 @@ Source: "..\..\linphone-deps\bin\osipparser2.dll"; DestDir: "{app}"; Flags: igno Source: "..\..\linphone-deps\bin\osip2.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\..\linphone-deps\bin\exosip2.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\..\linphone-deps\bin\libogg.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\speex.dll"; DestDir: "{app}"; Flags: ignoreversion +;;Source: "..\..\linphone-deps\bin\speex.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\..\linphone-deps\bin\avcodec.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\..\linphone-deps\bin\avutil.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\libspeex-1.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\libspeexdsp-1.dll"; DestDir: "{app}"; Flags: ignoreversion +;;Source: "..\..\linphone-deps\bin\libspeex-1.dll"; DestDir: "{app}"; Flags: ignoreversion +;;Source: "..\..\linphone-deps\bin\libspeexdsp-1.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\mediastreamer2\build\win32native\mediastreamer2.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\oRTP\build\win32native\ortp.dll"; DestDir: "{app}"; Flags: ignoreversion ;;Sound files: diff --git a/linphone/gtk-glade/main.c b/linphone/gtk-glade/main.c index f12460ba6..838acff1a 100644 --- a/linphone/gtk-glade/main.c +++ b/linphone/gtk-glade/main.c @@ -716,6 +716,9 @@ int main(int argc, char *argv[]){ add_pixmap_directory("pixmaps"); add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone"); +#ifdef WIN32 + add_pixmap_directory("linphone"); +#endif the_ui=linphone_gtk_create_window("main"); diff --git a/linphone/mediastreamer2/build/win32native/mediastreamer2.dev b/linphone/mediastreamer2/build/win32native/mediastreamer2.dev index 3ddde2f96..a7d09a9eb 100755 --- a/linphone/mediastreamer2/build/win32native/mediastreamer2.dev +++ b/linphone/mediastreamer2/build/win32native/mediastreamer2.dev @@ -444,7 +444,7 @@ OverrideBuildCmd=0 BuildCmd= [Unit42] -FileName=..\..\src\winsnd2.c +FileName=..\..\src\winsnd3.c CompileCpp=0 Folder=mediastreamer2 Compile=1 @@ -512,7 +512,7 @@ Libs=../../../../linphone-deps/lib;../../../oRTP/build/win32native PrivateResource= ResourceIncludes= MakeIncludes= -Compiler=-ggdb_@@_-DINET6 _@@_-DORTP_INET6 _@@_-D_WORKAROUND_MINGW32_BUGS_@@_-D_WIN32_WINNT=0x0501 _@@_-DNOSDL_@@_-DVIDEO_ENABLED_@@_-DNORESAMPLE_@@_-Wall _@@_-DHAVE_LIBAVCODEC_AVCODEC_H_@@_ +Compiler=-ggdb_@@_-DINET6 _@@_-DORTP_INET6 _@@_-D_WORKAROUND_MINGW32_BUGS_@@_-D_WIN32_WINNT=0x0501 _@@_-DNOSDL_@@_-DVIDEO_ENABLED_@@_-DNORESAMPLE_@@_-Wall _@@_-DHAVE_LIBAVCODEC_AVCODEC_H_@@_-D_TRUE_TIME_@@_ CppCompiler= Linker=-lortp_@@_-lavcodec_@@_-lavutil_@@_-ltheora_@@_-lspeex_@@_-lspeexdsp_@@_-lgsm_@@_-lws2_32_@@_-lwinmm_@@_-lvfw32_@@_-logg_@@__@@_ PreprocDefines= diff --git a/linphone/mediastreamer2/src/msvideo.c b/linphone/mediastreamer2/src/msvideo.c index e03fb8325..813a0d87e 100644 --- a/linphone/mediastreamer2/src/msvideo.c +++ b/linphone/mediastreamer2/src/msvideo.c @@ -156,12 +156,12 @@ MSPixFmt ms_fourcc_to_pix_fmt(uint32_t fourcc){ void rgb24_revert(uint8_t *buf, int w, int h, int linesize){ uint8_t *p,*pe; int i,j; - uint8_t *end=buf+(h*linesize*3); + uint8_t *end=buf+(h*linesize); uint8_t exch; p=buf; pe=end-1; for(i=0;iwfx.nAvgBytesPerSec=d->wfx.nSamplesPerSec*d->wfx.nBlockAlign; } + +#ifndef _TRUE_TIME static uint64_t winsnd_get_cur_time( void *data){ WinSnd *d=(WinSnd*)data; uint64_t curtime=((uint64_t)d->bytes_read*1000)/(uint64_t)d->wfx.nAvgBytesPerSec; /* ms_debug("winsnd_get_cur_time: bytes_read=%u return %lu\n",d->bytes_read,(unsigned long)curtime); */ return curtime; } +#endif static void winsnd_init(MSFilter *f){ @@ -408,14 +411,18 @@ static void winsnd_read_preprocess(MSFilter *f){ ms_error("waveInStart() error"); return ; } +#ifndef _TRUE_TIME ms_ticker_set_time_func(f->ticker,winsnd_get_cur_time,d); +#endif } static void winsnd_read_postprocess(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; MMRESULT mr; int i; +#ifndef _TRUE_TIME ms_ticker_set_time_func(f->ticker,NULL,NULL); +#endif d->running=FALSE; mr=waveInStop(d->indev); if (mr != MMSYSERR_NOERROR){ diff --git a/linphone/mediastreamer2/src/winsnd3.c b/linphone/mediastreamer2/src/winsnd3.c new file mode 100755 index 000000000..377d5cedb --- /dev/null +++ b/linphone/mediastreamer2/src/winsnd3.c @@ -0,0 +1,711 @@ +/* +mediastreamer2 library - modular sound and video processing and streaming +Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org) + +This program 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 +of the License, or (at your option) any later version. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "mediastreamer2/mssndcard.h" +#include "mediastreamer2/msfilter.h" +#include "mediastreamer2/msticker.h" + +#include +#ifdef _MSC_VER +#include +#endif +#include + +#if defined(_WIN32_WCE) +//#define DISABLE_SPEEX +//#define WCE_OPTICON_WORKAROUND 1000 +#endif + + +#define WINSND_NBUFS 10 +#define WINSND_OUT_DELAY 0.100 +#define WINSND_OUT_NBUFS 20 +#define WINSND_NSAMPLES 320 +#define WINSND_MINIMUMBUFFER 5 + +static MSFilter *ms_winsnd_read_new(MSSndCard *card); +static MSFilter *ms_winsnd_write_new(MSSndCard *card); + +typedef struct WinSndCard{ + int in_devid; + int out_devid; +}WinSndCard; + +static void winsndcard_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent){ + MMRESULT mr = MMSYSERR_NOERROR; + DWORD dwVolume = 0xFFFF; + dwVolume = ((0xFFFF) * percent) / 100; + + switch(e){ + case MS_SND_CARD_MASTER: + /*mr = waveOutSetVolume(d->waveoutdev, dwVolume); */ + if (mr != MMSYSERR_NOERROR) + { + ms_warning("Failed to set master volume. (waveOutSetVolume:0x%i)", mr); + return; + } + break; + case MS_SND_CARD_CAPTURE: + break; + case MS_SND_CARD_PLAYBACK: + break; + default: + ms_warning("winsnd_card_set_level: unsupported command."); + } +} + +static int winsndcard_get_level(MSSndCard *card, MSSndCardMixerElem e){ + switch(e){ + case MS_SND_CARD_MASTER: + /*mr=waveOutGetVolume(d->waveoutdev, &dwVolume);*/ + /* Transform to 0 to 100 scale*/ + /*dwVolume = (dwVolume *100) / (0xFFFF);*/ + return 60; + break; + case MS_SND_CARD_CAPTURE: + break; + case MS_SND_CARD_PLAYBACK: + break; + default: + ms_warning("winsnd_card_get_level: unsupported command."); + return -1; + } + return -1; +} + +static void winsndcard_set_source(MSSndCard *card, MSSndCardCapture source){ + + switch(source){ + case MS_SND_CARD_MIC: + break; + case MS_SND_CARD_LINE: + break; + } +} + +static void winsndcard_init(MSSndCard *card){ + WinSndCard *c=(WinSndCard *)ms_new(WinSndCard,1); + card->data=c; +} + +static void winsndcard_uninit(MSSndCard *card){ + ms_free(card->data); +} + +static void winsndcard_detect(MSSndCardManager *m); +static MSSndCard *winsndcard_dup(MSSndCard *obj); + +MSSndCardDesc winsnd_card_desc={ + "WINSND", + winsndcard_detect, + winsndcard_init, + winsndcard_set_level, + winsndcard_get_level, + winsndcard_set_source, + ms_winsnd_read_new, + ms_winsnd_write_new, + winsndcard_uninit, + winsndcard_dup +}; + +static MSSndCard *winsndcard_dup(MSSndCard *obj){ + MSSndCard *card=ms_snd_card_new(&winsnd_card_desc); + card->name=ms_strdup(obj->name); + card->data=ms_new(WinSndCard,1); + memcpy(card->data,obj->data,sizeof(WinSndCard)); + return card; +} + +static MSSndCard *winsndcard_new(const char *name, int in_dev, int out_dev, unsigned cap){ + MSSndCard *card=ms_snd_card_new(&winsnd_card_desc); + WinSndCard *d=(WinSndCard*)card->data; + card->name=ms_strdup(name); + d->in_devid=in_dev; + d->out_devid=out_dev; + card->capabilities=cap; + return card; +} + +static void add_or_update_card(MSSndCardManager *m, const char *name, int indev, int outdev, unsigned int capability){ + MSSndCard *card; + const MSList *elem=ms_snd_card_manager_get_list(m); + for(;elem!=NULL;elem=elem->next){ + card=(MSSndCard*)elem->data; + if (strcmp(card->name,name)==0){ + /*update already entered card */ + WinSndCard *d=(WinSndCard*)card->data; + card->capabilities|=capability; + if (indev!=-1) + d->in_devid=indev; + if (outdev!=-1) + d->out_devid=outdev; + + return; + } + } + /* add this new card:*/ + ms_snd_card_manager_add_card(m,winsndcard_new(name,indev,outdev,capability)); +} + +static void winsndcard_detect(MSSndCardManager *m){ + MMRESULT mr = NOERROR; + unsigned int nOutDevices = waveOutGetNumDevs (); + unsigned int nInDevices = waveInGetNumDevs (); + unsigned int item; + + if (nOutDevices>nInDevices) + nInDevices = nOutDevices; + + for (item = 0; item < nInDevices; item++){ + + WAVEINCAPS incaps; + WAVEOUTCAPS outcaps; + mr = waveInGetDevCaps (item, &incaps, sizeof (WAVEINCAPS)); + if (mr == MMSYSERR_NOERROR) + { +#if defined(_WIN32_WCE) + char card[256]; + snprintf(card, sizeof(card), "Input card %i", item); + add_or_update_card(m,card,item,-1,MS_SND_CARD_CAP_CAPTURE); + /* _tprintf(L"new card: %s", incaps.szPname); */ +#else + add_or_update_card(m,incaps.szPname,item,-1,MS_SND_CARD_CAP_CAPTURE); +#endif + } + mr = waveOutGetDevCaps (item, &outcaps, sizeof (WAVEOUTCAPS)); + if (mr == MMSYSERR_NOERROR) + { +#if defined(_WIN32_WCE) + char card[256]; + snprintf(card, sizeof(card), "Output card %i", item); + add_or_update_card(m,card,-1,item,MS_SND_CARD_CAP_PLAYBACK); + /* _tprintf(L"new card: %s", outcaps.szPname); */ +#else + add_or_update_card(m,outcaps.szPname,-1,item,MS_SND_CARD_CAP_PLAYBACK); +#endif + } + } +} + + +typedef struct WinSnd{ + int dev_id; + HWAVEIN indev; + HWAVEOUT outdev; + WAVEFORMATEX wfx; + WAVEHDR hdrs_read[WINSND_NBUFS]; + WAVEHDR hdrs_write[WINSND_OUT_NBUFS]; + queue_t rq; + ms_mutex_t mutex; + unsigned int bytes_read; + unsigned int nbufs_playing; + bool_t running; + int outcurbuf; + int nsamples; + queue_t wq; + int32_t stat_input; + int32_t stat_output; + int32_t stat_notplayed; + + int32_t stat_minimumbuffer; + int ready; + int workaround; /* workaround for opticon audio device */ + bool_t overrun; +}WinSnd; + +static void winsnd_apply_settings(WinSnd *d){ + d->wfx.nBlockAlign=d->wfx.nChannels*d->wfx.wBitsPerSample/8; + d->wfx.nAvgBytesPerSec=d->wfx.nSamplesPerSec*d->wfx.nBlockAlign; +} + + +#ifndef _TRUE_TIME +static uint64_t winsnd_get_cur_time( void *data){ + WinSnd *d=(WinSnd*)data; + uint64_t curtime=((uint64_t)d->bytes_read*1000)/(uint64_t)d->wfx.nAvgBytesPerSec; + /* ms_debug("winsnd_get_cur_time: bytes_read=%u return %lu\n",d->bytes_read,(unsigned long)curtime); */ + return curtime; +} +#endif + + +static void winsnd_init(MSFilter *f){ + WinSnd *d=(WinSnd *)ms_new0(WinSnd,1); + d->wfx.wFormatTag = WAVE_FORMAT_PCM; + d->wfx.cbSize = 0; + d->wfx.nAvgBytesPerSec = 16000; + d->wfx.nBlockAlign = 2; + d->wfx.nChannels = 1; + d->wfx.nSamplesPerSec = 8000; + d->wfx.wBitsPerSample = 16; + qinit(&d->rq); + qinit(&d->wq); + d->ready=0; + d->workaround=0; + ms_mutex_init(&d->mutex,NULL); + f->data=d; + + d->stat_input=0; + d->stat_output=0; + d->stat_notplayed=0; + d->stat_minimumbuffer=WINSND_MINIMUMBUFFER; +} + +static void winsnd_uninit(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + flushq(&d->rq,0); + flushq(&d->wq,0); + d->ready=0; + d->workaround=0; + ms_mutex_destroy(&d->mutex); + ms_free(f->data); +} + +static void add_input_buffer(WinSnd *d, WAVEHDR *hdr, int buflen){ + mblk_t *m=allocb(buflen,0); + MMRESULT mr; + memset(hdr,0,sizeof(*hdr)); + if (buflen==0) ms_error("add_input_buffer: buflen=0 !"); + hdr->lpData=(LPSTR)m->b_wptr; + hdr->dwBufferLength=buflen; + hdr->dwFlags = 0; + hdr->dwUser = (DWORD)m; + mr = waveInPrepareHeader (d->indev,hdr,sizeof(*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInPrepareHeader() error"); + return ; + } + mr=waveInAddBuffer(d->indev,hdr,sizeof(*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInAddBuffer() error"); + return ; + } +} + +static void CALLBACK +read_callback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, + DWORD dwParam2) +{ + WAVEHDR *wHdr=(WAVEHDR *) dwParam1; + MSFilter *f=(MSFilter *)dwInstance; + WinSnd *d=(WinSnd*)f->data; + mblk_t *m; + int bsize; + switch (uMsg){ + case WIM_OPEN: + ms_debug("read_callback : WIM_OPEN"); + break; + case WIM_CLOSE: + ms_debug("read_callback : WIM_CLOSE"); + break; + case WIM_DATA: + bsize=wHdr->dwBytesRecorded; + + /* ms_warning("read_callback : WIM_DATA (%p,%i)",wHdr,bsize); */ + m=(mblk_t*)wHdr->dwUser; + m->b_wptr+=bsize; + wHdr->dwUser=0; + ms_mutex_lock(&d->mutex); + putq(&d->rq,m); + ms_mutex_unlock(&d->mutex); + d->bytes_read+=wHdr->dwBufferLength; + d->stat_input++; + d->stat_input++; +#ifdef WIN32_TIMERS + if (f->ticker->TimeEvent!=NULL) + SetEvent(f->ticker->TimeEvent); +#endif + break; + } +} + + +static void winsnd_read_preprocess(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + MMRESULT mr; + int i; + int bsize; + DWORD dwFlag; + + d->stat_input=0; + d->stat_output=0; + d->stat_notplayed=0; + d->stat_minimumbuffer=WINSND_MINIMUMBUFFER; + + winsnd_apply_settings(d); + /* Init Microphone device */ + dwFlag = CALLBACK_FUNCTION; + if (d->dev_id != WAVE_MAPPER) + dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION; + mr = waveInOpen (&d->indev, d->dev_id, &d->wfx, + (DWORD) read_callback, (DWORD)f, dwFlag); + if (mr != MMSYSERR_NOERROR) + { + ms_error("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr); + mr = waveInOpen (&d->indev, WAVE_MAPPER, &d->wfx, + (DWORD) read_callback, (DWORD)d, CALLBACK_FUNCTION); + if (mr != MMSYSERR_NOERROR) + { + d->indev=NULL; + ms_error("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr); + return ; + } + } + bsize=WINSND_NSAMPLES*d->wfx.nAvgBytesPerSec/8000; + ms_debug("Using input buffers of %i bytes",bsize); + for(i=0;ihdrs_read[i]; + add_input_buffer(d,hdr,bsize); + } + d->running=TRUE; + mr=waveInStart(d->indev); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInStart() error"); + return ; + } +#ifndef _TRUE_TIME + ms_ticker_set_time_func(f->ticker,winsnd_get_cur_time,d); +#endif +} + +static void winsnd_read_postprocess(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + MMRESULT mr; + int i; +#ifndef _TRUE_TIME + ms_ticker_set_time_func(f->ticker,NULL,NULL); +#endif + d->running=FALSE; + mr=waveInStop(d->indev); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInStop() error"); + return ; + } + mr=waveInReset(d->indev); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInReset() error"); + return ; + } + for(i=0;ihdrs_read[i]; + if (hdr->dwFlags & WHDR_PREPARED) + { + mr = waveInUnprepareHeader(d->indev,hdr,sizeof (*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInUnPrepareHeader() error"); + } + } + } + mr = waveInClose(d->indev); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveInClose() error"); + return ; + } + + ms_message("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->nbufs_playing, d->stat_input - d->stat_output, d->stat_notplayed); + flushq(&d->rq,0); +} + +static void winsnd_read_process(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + mblk_t *m; + int i; + ms_mutex_lock(&d->mutex); + while((m=getq(&d->rq))!=NULL){ + ms_queue_put(f->outputs[0],m); + } + ms_mutex_unlock(&d->mutex); + for(i=0;ihdrs_read[i]; + if (hdr->dwUser==0) { + MMRESULT mr; + mr=waveInUnprepareHeader(d->indev,hdr,sizeof(*hdr)); + if (mr!=MMSYSERR_NOERROR) + ms_warning("winsnd_read_process: Fail to unprepare header!"); + add_input_buffer(d,hdr,hdr->dwBufferLength); + } + } +} + +static void CALLBACK +write_callback(HWAVEOUT outdev, UINT uMsg, DWORD dwInstance, + DWORD dwParam1, DWORD dwParam2) +{ + WAVEHDR *hdr=(WAVEHDR *) dwParam1; + WinSnd *d=(WinSnd*)dwInstance; + + switch (uMsg){ + case WOM_OPEN: + break; + case WOM_CLOSE: + case WOM_DONE: + if (hdr){ + d->nbufs_playing--; + } + if (d->stat_output==0) + { + d->stat_input=1; /* reset */ + d->stat_notplayed=0; + } + d->stat_output++; + break; + } +} + +static void winsnd_write_preprocess(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + MMRESULT mr; + DWORD dwFlag; + int i; + + d->stat_input=0; + d->stat_output=0; + d->stat_notplayed=0; + d->stat_minimumbuffer=WINSND_MINIMUMBUFFER; + + winsnd_apply_settings(d); + /* Init Microphone device */ + dwFlag = CALLBACK_FUNCTION; + if (d->dev_id != WAVE_MAPPER) + dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION; + mr = waveOutOpen (&d->outdev, d->dev_id, &d->wfx, + (DWORD) write_callback, (DWORD)d, dwFlag); + if (mr != MMSYSERR_NOERROR) + { + ms_error("Failed to open windows sound device %i. (waveOutOpen:0x%i)",d->dev_id, mr); + mr = waveOutOpen (&d->outdev, WAVE_MAPPER, &d->wfx, + (DWORD) write_callback, (DWORD)d, CALLBACK_FUNCTION); + if (mr != MMSYSERR_NOERROR) + { + ms_error("Failed to open windows sound device %i. (waveOutOpen:0x%i)",d->dev_id, mr); + d->outdev=NULL; + return ; + } + } + for(i=0;ihdrs_write[i]; + hdr->dwFlags=0; + hdr->dwUser=0; + } + d->outcurbuf=0; + d->overrun=FALSE; + d->nsamples=0; +} + +static void winsnd_write_postprocess(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + MMRESULT mr; + int i; + if (d->outdev==NULL) return; + mr=waveOutReset(d->outdev); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveOutReset() error"); + return ; + } + for(i=0;ihdrs_write[i]; + mblk_t *old; + if (hdr->dwFlags & WHDR_DONE){ + mr=waveOutUnprepareHeader(d->outdev,hdr,sizeof(*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveOutUnprepareHeader error"); + } + old=(mblk_t*)hdr->dwUser; + if (old) freemsg(old); + hdr->dwUser=0; + } + } + mr=waveOutClose(d->outdev); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveOutClose() error"); + return ; + } + d->ready=0; + d->workaround=0; +} + +static void playout_buf(WinSnd *d, WAVEHDR *hdr, mblk_t *m){ + MMRESULT mr; + hdr->dwUser=(DWORD)m; + hdr->lpData=(LPSTR)m->b_rptr; + hdr->dwBufferLength=msgdsize(m); + hdr->dwFlags = 0; + mr = waveOutPrepareHeader(d->outdev,hdr,sizeof(*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveOutPrepareHeader() error"); + d->stat_notplayed++; + } + mr=waveOutWrite(d->outdev,hdr,sizeof(*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveOutWrite() error"); + d->stat_notplayed++; + }else { + d->nbufs_playing++; + } +} + +static void winsnd_write_process(MSFilter *f){ + WinSnd *d=(WinSnd*)f->data; + mblk_t *m; + MMRESULT mr; + mblk_t *old; + if (d->outdev==NULL) { + ms_queue_flush(f->inputs[0]); + return; + } + if (d->overrun){ + ms_warning("nbufs_playing=%i",d->nbufs_playing); + if (d->nbufs_playing>0){ + ms_queue_flush(f->inputs[0]); + return; + } + else d->overrun=FALSE; + } + while(1){ + int outcurbuf=d->outcurbuf % WINSND_OUT_NBUFS; + WAVEHDR *hdr=&d->hdrs_write[outcurbuf]; + old=(mblk_t*)hdr->dwUser; + if (d->nsamples==0){ + int tmpsize=WINSND_OUT_DELAY*d->wfx.nAvgBytesPerSec; + mblk_t *tmp=allocb(tmpsize,0); + memset(tmp->b_wptr,0,tmpsize); + tmp->b_wptr+=tmpsize; + playout_buf(d,hdr,tmp); + d->outcurbuf++; + d->nsamples+=WINSND_OUT_DELAY*d->wfx.nSamplesPerSec; + continue; + } + m=ms_queue_get(f->inputs[0]); + if (!m) break; + d->nsamples+=msgdsize(m)/d->wfx.nBlockAlign; + /*if the output buffer has finished to play, unprepare it*/ + if (hdr->dwFlags & WHDR_DONE){ + mr=waveOutUnprepareHeader(d->outdev,hdr,sizeof(*hdr)); + if (mr != MMSYSERR_NOERROR){ + ms_error("waveOutUnprepareHeader error"); + } + freemsg(old); + old=NULL; + hdr->dwFlags=0; + hdr->dwUser=0; + } + if (old==NULL){ + /* a free wavheader */ + playout_buf(d,hdr,m); + }else{ + /* no more free wavheader, overrun !*/ + ms_warning("WINSND overrun, restarting"); + d->overrun=TRUE; + d->nsamples=0; + waveOutReset(d->outdev); + } + d->outcurbuf++; + } +} + +static int set_rate(MSFilter *f, void *arg){ + WinSnd *d=(WinSnd*)f->data; + d->wfx.nSamplesPerSec=*((int*)arg); + return 0; +} + +static int set_nchannels(MSFilter *f, void *arg){ + WinSnd *d=(WinSnd*)f->data; + d->wfx.nChannels=*((int*)arg); + return 0; +} + +static int winsnd_get_stat_input(MSFilter *f, void *arg){ + WinSnd *d=(WinSnd*)f->data; + return d->stat_input; +} + +static int winsnd_get_stat_ouptut(MSFilter *f, void *arg){ + WinSnd *d=(WinSnd*)f->data; + + return d->stat_output; +} + +static int winsnd_get_stat_discarded(MSFilter *f, void *arg){ + WinSnd *d=(WinSnd*)f->data; + + return d->stat_notplayed; +} + +static MSFilterMethod winsnd_methods[]={ + { MS_FILTER_SET_SAMPLE_RATE , set_rate }, + { MS_FILTER_SET_NCHANNELS , set_nchannels }, + { MS_FILTER_GET_STAT_INPUT, winsnd_get_stat_input }, + { MS_FILTER_GET_STAT_OUTPUT, winsnd_get_stat_ouptut }, + { MS_FILTER_GET_STAT_DISCARDED, winsnd_get_stat_discarded }, + { 0 , NULL } +}; + +MSFilterDesc winsnd_read_desc={ + MS_WINSND_READ_ID, + "MSWinSndRead", + "Sound capture filter for Windows Sound drivers", + MS_FILTER_OTHER, + NULL, + 0, + 1, + winsnd_init, + winsnd_read_preprocess, + winsnd_read_process, + winsnd_read_postprocess, + winsnd_uninit, + winsnd_methods +}; + + +MSFilterDesc winsnd_write_desc={ + MS_WINSND_WRITE_ID, + "MSWinSndWrite", + "Sound playback filter for Windows Sound drivers", + MS_FILTER_OTHER, + NULL, + 1, + 0, + winsnd_init, + winsnd_write_preprocess, + winsnd_write_process, + winsnd_write_postprocess, + winsnd_uninit, + winsnd_methods +}; + +MSFilter *ms_winsnd_read_new(MSSndCard *card){ + MSFilter *f=ms_filter_new_from_desc(&winsnd_read_desc); + WinSndCard *wc=(WinSndCard*)card->data; + WinSnd *d=(WinSnd*)f->data; + d->dev_id=wc->in_devid; + return f; +} + + +MSFilter *ms_winsnd_write_new(MSSndCard *card){ + MSFilter *f=ms_filter_new_from_desc(&winsnd_write_desc); + WinSndCard *wc=(WinSndCard*)card->data; + WinSnd *d=(WinSnd*)f->data; + d->dev_id=wc->out_devid; + return f; +} + +MS_FILTER_DESC_EXPORT(winsnd_read_desc) +MS_FILTER_DESC_EXPORT(winsnd_write_desc) diff --git a/linphone/mediastreamer2/src/winvideo.c b/linphone/mediastreamer2/src/winvideo.c index f08e8793c..7f06263f9 100644 --- a/linphone/mediastreamer2/src/winvideo.c +++ b/linphone/mediastreamer2/src/winvideo.c @@ -58,6 +58,7 @@ typedef struct V4wState{ bool_t startwith_yuv_bug; /* avoid bug with USB vimicro cards. */ bool_t started; bool_t autostarted; + bool_t invert_rgb; }V4wState; static void dummy(void*p){ @@ -86,6 +87,7 @@ LRESULT CALLBACK VideoStreamCallback(HWND hWnd, LPVIDEOHDR lpVHdr) } static bool_t try_format(V4wState *s, BITMAPINFO *videoformat, MSPixFmt pixfmt){ + bool_t ret; capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); videoformat->bmiHeader.biSizeImage = 0; videoformat->bmiHeader.biWidth = s->vsize.width; @@ -106,7 +108,12 @@ static bool_t try_format(V4wState *s, BITMAPINFO *videoformat, MSPixFmt pixfmt){ default: return FALSE; } - return capSetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + ret=capSetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + if (ret) { + /*recheck video format */ + capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + } + return ret; } static int v4w_open_videodevice(V4wState *s) @@ -185,7 +192,6 @@ static int v4w_open_videodevice(V4wState *s) ms_message("v4w: camera's current format is %s", compname); driver_last=ms_fourcc_to_pix_fmt(videoformat.bmiHeader.biCompression); - if (s->startwith_yuv_bug==TRUE && try_format(s,&videoformat,MS_RGB24)){ s->pix_fmt=MS_RGB24; ms_message("Using RGB24"); @@ -209,6 +215,9 @@ static int v4w_open_videodevice(V4wState *s) s->capvideo=NULL; return -1; } + if (s->pix_fmt==MS_RGB24){ + s->invert_rgb=(videoformat.bmiHeader.biHeight>0); + }else s->invert_rgb=FALSE; if (!capSetCallbackOnVideoStream(s->capvideo, VideoStreamCallback)) { ms_error("v4w: fail to set capture callback"); @@ -246,7 +255,7 @@ static void v4w_init(MSFilter *f){ s->fps=15; s->started=FALSE; s->autostarted=FALSE; - + s->invert_rgb=FALSE; #ifdef AMD_HACK2 /* avoid bug with USB vimicro cards: How can I detect that this problem exist? @@ -502,6 +511,9 @@ static void v4w_process(MSFilter * obj){ if (om!=NULL) freemsg(om); om=m; } + if (om!=NULL){ + if (s->invert_rgb) rgb24_revert(om->b_rptr,s->vsize.width,s->vsize.height,s->vsize.width*3); + } }else { mblk_t *nowebcam = v4w_make_nowebcam(s); if (nowebcam!=NULL){ diff --git a/linphone/oRTP/build/win32native/ortp-dll.dev b/linphone/oRTP/build/win32native/ortp-dll.dev index 336b4e44f..4be4861f7 100755 --- a/linphone/oRTP/build/win32native/ortp-dll.dev +++ b/linphone/oRTP/build/win32native/ortp-dll.dev @@ -381,7 +381,7 @@ ProductName= ProductVersion= AutoIncBuildNrOnRebuild=0 AutoIncBuildNrOnCompile=0 -UnitCount=40 +UnitCount=41 [Unit37] FileName=..\..\src\stun_udp.c @@ -469,5 +469,5 @@ Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 -BuildCmd= $(CC) -c b64.c -o "Default Profile/b64.o" $(CFLAGS) +BuildCmd=$(CC) -c b64.c -o "Default Profile/b64.o" $(CFLAGS) diff --git a/linphone/win32/liblinphone.dev b/linphone/win32/liblinphone.dev index 743c965fc..5242625b2 100755 --- a/linphone/win32/liblinphone.dev +++ b/linphone/win32/liblinphone.dev @@ -211,6 +211,7 @@ ProductName= ProductVersion= AutoIncBuildNrOnRebuild=0 AutoIncBuildNrOnCompile=0 +UnitCount=18 [Profile1] ProfileName=Default Profile @@ -225,7 +226,7 @@ Compiler=-Wall -Werror_@@_-D_WIN32_WINNT=0x501_@@_-D_WORKAROUND_MINGW32_BUGS_@@_ CppCompiler= Linker= PreprocDefines= -CompilerSettings=0000000000100000000000 +CompilerSettings=0000000000010000000000 Icon= ExeOutput=..\win32 ObjectOutput=Default Profile