diff --git a/linphone/coreapi/liblinphone.dev b/linphone/coreapi/liblinphone.dev index 73409274a..0f98e9a4d 100755 --- a/linphone/coreapi/liblinphone.dev +++ b/linphone/coreapi/liblinphone.dev @@ -222,7 +222,7 @@ Libs=../oRTP/build/win32native;../mediastreamer2/build/win32native;../../linphon PrivateResource= ResourceIncludes= MakeIncludes= -Compiler=-Wall -Werror_@@_-D_WIN32_WINNT=0x501_@@_-D_WORKAROUND_MINGW32_BUGS_@@_-DINET6_@@_-DORTP_INET6_@@_-DORTP_STATIC_@@_-DVIDEO_ENABLED_@@_-ggdb_@@_-DOSIP_MT_@@_ +Compiler=-Wall -Werror_@@_-D_WIN32_WINNT=0x501_@@_-DINET6_@@_-DORTP_INET6_@@_-DORTP_STATIC_@@_-DVIDEO_ENABLED_@@_-ggdb_@@_-DOSIP_MT_@@_ CppCompiler= Linker= PreprocDefines= diff --git a/linphone/gtk-glade/linphone.iss b/linphone/gtk-glade/linphone.iss index 7413f8a37..8af8bba96 100755 --- a/linphone/gtk-glade/linphone.iss +++ b/linphone/gtk-glade/linphone.iss @@ -37,6 +37,7 @@ Source: "..\..\linphone-deps\bin\libogg.dll"; DestDir: "{app}"; Flags: ignorever ;;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\swscale.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 diff --git a/linphone/gtk-glade/propertybox.c b/linphone/gtk-glade/propertybox.c index 7cf5ae3c8..3776aada1 100644 --- a/linphone/gtk-glade/propertybox.c +++ b/linphone/gtk-glade/propertybox.c @@ -173,7 +173,7 @@ void linphone_gtk_cam_changed(GtkWidget *w){ void linphone_gtk_video_size_changed(GtkWidget *w){ int sel=gtk_combo_box_get_active(GTK_COMBO_BOX(w)); const MSVideoSizeDef *defs=linphone_core_get_supported_video_sizes(linphone_gtk_get_core()); - if (defs<0) return; + if (sel<0) return; linphone_core_set_preferred_video_size(linphone_gtk_get_core(), defs[sel].vsize); } diff --git a/linphone/mediastreamer2/build/win32native/mediastream.dev b/linphone/mediastreamer2/build/win32native/mediastream.dev index 30a4e63ed..5a08399a1 100755 --- a/linphone/mediastreamer2/build/win32native/mediastream.dev +++ b/linphone/mediastreamer2/build/win32native/mediastream.dev @@ -51,7 +51,7 @@ Libs=../../../oRTP/build/win32native;../../../../linphone-deps/lib PrivateResource= ResourceIncludes= MakeIncludes= -Compiler=-DINET6 _@@_-DORTP_INET6 _@@_-DORTP_STATIC_@@_-D_WORKAROUND_MINGW32_BUGS_@@_-D_WIN32_WINNT=0x0501 _@@_-DDISABLE_RESAMPLE_@@_-DVIDEO_ENABLED_@@_-Wall -Werror_@@_-g_@@_ +Compiler=-DINET6 _@@_-DORTP_INET6 _@@_-DORTP_STATIC_@@_-D_WIN32_WINNT=0x0501 _@@_-DDISABLE_RESAMPLE_@@_-DVIDEO_ENABLED_@@_-Wall -Werror_@@_-g_@@_ CppCompiler= Linker=libmediastreamer2.a_@@_-lortp_@@_-lgsm_@@_-lspeex_@@_-lws2_32_@@_-liphlpapi_@@_-lwinmm_@@_-lavcodec_@@_-lavutil_@@_-ltheora_@@_-logg_@@_-lvfw32_@@__@@_ PreprocDefines= diff --git a/linphone/mediastreamer2/build/win32native/mediastreamer2.dev b/linphone/mediastreamer2/build/win32native/mediastreamer2.dev index ef196210f..ea12760bf 100755 --- a/linphone/mediastreamer2/build/win32native/mediastreamer2.dev +++ b/linphone/mediastreamer2/build/win32native/mediastreamer2.dev @@ -512,9 +512,9 @@ 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_@@_-D_TRUE_TIME_@@_ +Compiler=-ggdb_@@_-DINET6 _@@_-DORTP_INET6 _@@_-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_@@__@@_ +Linker=-lortp_@@_-lswscale_@@_-lavcodec_@@_-lavutil_@@_-ltheora_@@_-lspeex_@@_-lspeexdsp_@@_-lgsm_@@_-lws2_32_@@_-lwinmm_@@_-lvfw32_@@_-logg_@@__@@_ PreprocDefines= CompilerSettings=0000000000010000000000 Icon= @@ -609,5 +609,5 @@ Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 -BuildCmd= $(CC) -c winvideo2.c -o "Default Profile/winvideo2.o" $(CFLAGS) +BuildCmd=$(CC) -c winvideo2.c -o "Default Profile/winvideo2.o" $(CFLAGS) diff --git a/linphone/mediastreamer2/include/mediastreamer2/msvideo.h b/linphone/mediastreamer2/include/mediastreamer2/msvideo.h index bed814e84..a6750c79f 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/msvideo.h +++ b/linphone/mediastreamer2/include/mediastreamer2/msvideo.h @@ -54,8 +54,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MS_VIDEO_SIZE_MAX_W MS_VIDEO_SIZE_1024_W #define MS_VIDEO_SIZE_MAX_H MS_VIDEO_SIZE_1024_H +/* those structs are part of the ABI: don't change their size otherwise binary plugins will be broken*/ + typedef struct MSVideoSize{ - int16_t width,height; + int width,height; } MSVideoSize; typedef struct MSRect{ @@ -78,21 +80,6 @@ typedef struct MSRect{ #define MS_VIDEO_SIZE_800X600 (MSVideoSize){MS_VIDEO_SIZE_800X600_W, MS_VIDEO_SIZE_800X600_H} -static inline bool_t ms_video_size_greater_than(MSVideoSize vs1, MSVideoSize vs2){ - return (vs1.width>=vs2.width) && (vs1.height>=vs2.height); -} - -static inline MSVideoSize ms_video_size_max(MSVideoSize vs1, MSVideoSize vs2){ - return ms_video_size_greater_than(vs1,vs2) ? vs1 : vs2; -} - -static inline MSVideoSize ms_video_size_min(MSVideoSize vs1, MSVideoSize vs2){ - return ms_video_size_greater_than(vs1,vs2) ? vs2 : vs1; -} - -static inline bool_t ms_video_size_equal(MSVideoSize vs1, MSVideoSize vs2){ - return vs1.width==vs2.width && vs1.height==vs2.height; -} typedef enum{ MS_YUV420P, @@ -130,6 +117,25 @@ void yuv_buf_mirror(YuvBuf *buf); void rgb24_revert(uint8_t *buf, int w, int h, int linesize); void rgb24_copy_revert(uint8_t *dstbuf, int dstlsz, const uint8_t *srcbuf, int srclsz, MSVideoSize roi); + +static inline bool_t ms_video_size_greater_than(MSVideoSize vs1, MSVideoSize vs2){ + return (vs1.width>=vs2.width) && (vs1.height>=vs2.height); +} + +static inline MSVideoSize ms_video_size_max(MSVideoSize vs1, MSVideoSize vs2){ + return ms_video_size_greater_than(vs1,vs2) ? vs1 : vs2; +} + +static inline MSVideoSize ms_video_size_min(MSVideoSize vs1, MSVideoSize vs2){ + return ms_video_size_greater_than(vs1,vs2) ? vs2 : vs1; +} + +static inline bool_t ms_video_size_equal(MSVideoSize vs1, MSVideoSize vs2){ + return vs1.width==vs2.width && vs1.height==vs2.height; +} + +MSVideoSize ms_video_size_get_just_lower_than(MSVideoSize vs); + #ifdef __cplusplus } #endif diff --git a/linphone/mediastreamer2/plugins/msx264/src/msx264.c b/linphone/mediastreamer2/plugins/msx264/src/msx264.c index 119b1f2a8..327960fa3 100644 --- a/linphone/mediastreamer2/plugins/msx264/src/msx264.c +++ b/linphone/mediastreamer2/plugins/msx264/src/msx264.c @@ -224,6 +224,12 @@ static int enc_get_vsize(MSFilter *f, void *arg){ return 0; } +static int enc_set_vsize(MSFilter *f, void *arg){ + EncData *d=(EncData*)f->data; + d->vsize=*(MSVideoSize*)arg; + return 0; +} + static int enc_add_fmtp(MSFilter *f, void *arg){ EncData *d=(EncData*)f->data; const char *fmtp=(const char *)arg; @@ -247,6 +253,7 @@ static MSFilterMethod enc_methods[]={ { MS_FILTER_SET_BITRATE , enc_set_br }, { MS_FILTER_GET_FPS , enc_get_fps }, { MS_FILTER_GET_VIDEO_SIZE, enc_get_vsize }, + { MS_FILTER_SET_VIDEO_SIZE, enc_set_vsize }, { MS_FILTER_ADD_FMTP , enc_add_fmtp }, { MS_FILTER_REQ_VFU , enc_req_vfu }, { 0 , NULL } diff --git a/linphone/mediastreamer2/src/msvideo.c b/linphone/mediastreamer2/src/msvideo.c index b13eaee50..624680fa1 100644 --- a/linphone/mediastreamer2/src/msvideo.c +++ b/linphone/mediastreamer2/src/msvideo.c @@ -189,3 +189,26 @@ void rgb24_copy_revert(uint8_t *dstbuf, int dstlsz, psrc+=srclsz; } } + +static MSVideoSize _ordered_vsizes[]={ + MS_VIDEO_SIZE_QCIF, + MS_VIDEO_SIZE_QVGA, + MS_VIDEO_SIZE_CIF, + MS_VIDEO_SIZE_VGA, + MS_VIDEO_SIZE_4CIF, + MS_VIDEO_SIZE_720P, + {0,0} +}; + +MSVideoSize ms_video_size_get_just_lower_than(MSVideoSize vs){ + MSVideoSize *p; + MSVideoSize ret; + ret.width=0; + ret.height=0; + for(p=_ordered_vsizes;p->width!=0;++p){ + if (ms_video_size_greater_than(vs,*p) && !ms_video_size_equal(vs,*p)){ + ret=*p; + }else return ret; + } + return ret; +}; diff --git a/linphone/mediastreamer2/src/videostream.c b/linphone/mediastreamer2/src/videostream.c index cf229f130..611cb1b08 100644 --- a/linphone/mediastreamer2/src/videostream.c +++ b/linphone/mediastreamer2/src/videostream.c @@ -349,8 +349,9 @@ void video_stream_set_rtcp_information(VideoStream *st, const char *cname, const -VideoStream * video_preview_start(MSWebCam *device, MSVideoSize vsize){ +VideoStream * video_preview_start(MSWebCam *device, MSVideoSize disp_size){ VideoStream *stream = (VideoStream *)ms_new0 (VideoStream, 1); + MSVideoSize vsize=disp_size; MSPixFmt format; /* creates the filters */ @@ -372,7 +373,7 @@ VideoStream * video_preview_start(MSWebCam *device, MSVideoSize vsize){ format=MS_YUV420P; ms_filter_call_method(stream->output,MS_FILTER_SET_PIX_FMT,&format); - ms_filter_call_method(stream->output,MS_FILTER_SET_VIDEO_SIZE,&vsize); + ms_filter_call_method(stream->output,MS_FILTER_SET_VIDEO_SIZE,&disp_size); /* and then connect all */ ms_filter_link(stream->source,0, stream->pixconv,0); diff --git a/linphone/mediastreamer2/src/winvideo.c b/linphone/mediastreamer2/src/winvideo.c index 2d0b0cb5b..1fde96c30 100644 --- a/linphone/mediastreamer2/src/winvideo.c +++ b/linphone/mediastreamer2/src/winvideo.c @@ -27,8 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "nowebcam.h" #include "mediastreamer2/mswebcam.h" -#ifndef _MSC_VER -#include "vfw-missing.h" +#ifndef AVSTREAMMASTER_NONE +#define AVSTREAMMASTER_NONE 1 #endif #define AMD_HACK2 diff --git a/linphone/mediastreamer2/src/winvideo2.c b/linphone/mediastreamer2/src/winvideo2.c index 8bcf299d5..16b00ecbb 100755 --- a/linphone/mediastreamer2/src/winvideo2.c +++ b/linphone/mediastreamer2/src/winvideo2.c @@ -26,8 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/mswebcam.h" -#ifndef _MSC_VER -#include "vfw-missing.h" +#ifndef AVSTREAMMASTER_NONE +#define AVSTREAMMASTER_NONE 1 #endif typedef void (*queue_msg_t)(void *, mblk_t *); @@ -42,6 +42,7 @@ typedef struct VfwEngine{ queue_msg_t cb; void *cb_data; bool_t started; + bool_t configured; bool_t thread_running; }VfwEngine; @@ -50,31 +51,38 @@ typedef struct VfwEngine{ static VfwEngine *engines[VFW_ENGINE_MAX_INSTANCES]={0}; static bool_t try_format(VfwEngine *s, BITMAPINFO *videoformat, MSPixFmt pixfmt){ + MSVideoSize tried_size=s->vsize; bool_t ret; - capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); - videoformat->bmiHeader.biSizeImage = 0; - videoformat->bmiHeader.biWidth = s->vsize.width; - videoformat->bmiHeader.biHeight = s->vsize.height; - switch(pixfmt){ - case MS_YUV420P: - videoformat->bmiHeader.biBitCount = 12; - videoformat->bmiHeader.biCompression=MAKEFOURCC('I','4','2','0'); - break; - case MS_YUY2: - videoformat->bmiHeader.biBitCount = 16; - videoformat->bmiHeader.biCompression=MAKEFOURCC('Y','U','Y','2'); - break; - case MS_RGB24: - videoformat->bmiHeader.biBitCount = 24; - videoformat->bmiHeader.biCompression=BI_RGB; - break; - default: - return FALSE; - } - ret=capSetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + do{ + capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + videoformat->bmiHeader.biSizeImage = 0; + videoformat->bmiHeader.biWidth = tried_size.width; + videoformat->bmiHeader.biHeight = tried_size.height; + switch(pixfmt){ + case MS_YUV420P: + videoformat->bmiHeader.biBitCount = 12; + videoformat->bmiHeader.biCompression=MAKEFOURCC('I','4','2','0'); + break; + case MS_YUY2: + videoformat->bmiHeader.biBitCount = 16; + videoformat->bmiHeader.biCompression=MAKEFOURCC('Y','U','Y','2'); + break; + case MS_RGB24: + videoformat->bmiHeader.biBitCount = 24; + videoformat->bmiHeader.biCompression=BI_RGB; + break; + default: + return FALSE; + } + ms_message("Trying video size %ix%i",tried_size.width,tried_size.height); + ret=capSetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + tried_size=ms_video_size_get_just_lower_than(tried_size); + }while(ret==FALSE && tried_size.width!=0); if (ret) { /*recheck video format */ capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); + s->vsize.width=videoformat->bmiHeader.biWidth; + s->vsize.height=videoformat->bmiHeader.biHeight; } return ret; } @@ -87,7 +95,8 @@ static int _vfw_engine_select_format(VfwEngine *obj){ capGetVideoFormat(obj->capvideo, &videoformat, sizeof(BITMAPINFO)); memcpy(compname,&videoformat.bmiHeader.biCompression,4); compname[4]='\0'; - ms_message("vfw: camera's current format is %s", compname); + ms_message("vfw: camera's current format is '%s' at %ix%i", compname, + videoformat.bmiHeader.biWidth,videoformat.bmiHeader.biHeight); driver_last=ms_fourcc_to_pix_fmt(videoformat.bmiHeader.biCompression); if (driver_last!=MS_PIX_FMT_UNKNOWN && try_format(obj,&videoformat,driver_last)){ ms_message("Using driver last setting"); @@ -144,26 +153,38 @@ vfw_engine_thread(void *arg) while(s->thread_running) { BOOL fGotMessage; - if((fGotMessage = PeekMessage(&msg, (HWND) s->capvideo, 0, 0, PM_REMOVE)) != 0) + while((fGotMessage = PeekMessage(&msg, (HWND) s->capvideo, 0, 0, PM_REMOVE)) != 0) { TranslateMessage(&msg); DispatchMessage(&msg); } - else - Sleep(10); + Sleep(10); } ms_thread_exit(NULL); return NULL; } -static void vfw_engine_destroy(VfwEngine *obj){ +static void _vfw_engine_unconfigure(VfwEngine *obj){ if (!capCaptureStop(obj->capvideo)){ ms_error("vfw: fail to stop capture !"); } obj->thread_running=FALSE; ms_thread_join(obj->thread,NULL); + obj->configured=FALSE; +} + +static void _vfw_engine_disconnect(VfwEngine *obj){ capDriverDisconnect(obj->capvideo); DestroyWindow(obj->capvideo); + obj->capvideo=NULL; +} + +static void vfw_engine_destroy(VfwEngine *obj){ + if (obj->configured){ + _vfw_engine_unconfigure(obj); + } + _vfw_engine_disconnect(obj); + ms_free(obj); } static int _vfw_engine_setup(VfwEngine *obj){ @@ -188,50 +209,60 @@ static int _vfw_engine_setup(VfwEngine *obj){ return 0; } +static int _vfw_engine_connect(VfwEngine *obj){ + MSVideoSize sz; + sz.width=MS_VIDEO_SIZE_CIF_W; + sz.height=MS_VIDEO_SIZE_CIF_H; + HWND hwnd=capCreateCaptureWindow("Capture Window",WS_CHILD /* WS_OVERLAPPED */ + ,0,0,sz.width,sz.height,HWND_MESSAGE, 0) ; + + if (hwnd==NULL) return -1; + if(!capDriverConnect(hwnd,obj->devidx)){ + ms_warning("vfw: could not connect to capture driver, no webcam connected."); + DestroyWindow(hwnd); + return -1; + } + obj->capvideo=hwnd; + obj->vsize=sz; + return 0; +} + static VfwEngine * vfw_engine_new(int i){ char dev[512]; char ver[512]; VfwEngine *obj=(VfwEngine*)ms_new0(VfwEngine,1); if (capGetDriverDescription(i, dev, sizeof (dev), ver, sizeof (ver))){ - MSVideoSize sz; - sz.width=MS_VIDEO_SIZE_CIF_W; - sz.height=MS_VIDEO_SIZE_CIF_H; - HWND hwnd=capCreateCaptureWindow("Capture Window",WS_CHILD /* WS_OVERLAPPED */ - ,0,0,sz.width,sz.height,HWND_MESSAGE, 0) ; - - if (hwnd==NULL) return NULL; - if(!capDriverConnect(hwnd,i)){ - ms_warning("vfw: could not connect to capture driver, no webcam connected."); - DestroyWindow(hwnd); + obj->devidx=i; + if (_vfw_engine_connect(obj)==-1){ + ms_free(obj); return NULL; } strcpy(obj->dev,dev); - obj->devidx=i; - obj->capvideo=hwnd; - obj->vsize=sz; - - if (_vfw_engine_setup(obj)==-1){ - vfw_engine_destroy(obj); - return NULL; - } - - if (_vfw_engine_select_format(obj)==-1){ - vfw_engine_destroy(obj); - return NULL; - } - capSetCallbackOnVideoStream(obj->capvideo, vfw_engine_stream_callback); - if (!capCaptureSequenceNoFile(obj->capvideo)){ - ms_error("vfw: fail to start capture !"); - } - ms_thread_create(&obj->thread,NULL,vfw_engine_thread,obj); engines[i]=obj; return obj; } return NULL; } +static void _vfw_engine_configure(VfwEngine *obj){ + if (_vfw_engine_setup(obj)==-1){ + return; + } + if (_vfw_engine_select_format(obj)==-1){ + return ; + } + capSetCallbackOnVideoStream(obj->capvideo, vfw_engine_stream_callback); + if (!capCaptureSequenceNoFile(obj->capvideo)){ + ms_error("vfw: fail to start capture !"); + } + ms_thread_create(&obj->thread,NULL,vfw_engine_thread,obj); + obj->configured=TRUE; +} + static MSPixFmt vfw_engine_get_pix_fmt(VfwEngine *obj){ + if (!obj->configured) + _vfw_engine_configure(obj); return obj->pix_fmt; } @@ -239,12 +270,25 @@ static MSVideoSize vfw_engine_get_video_size(VfwEngine *obj){ return obj->vsize; } +static void vfw_engine_set_video_size(VfwEngine *obj, MSVideoSize vsize){ + if (!obj->configured) + obj->vsize=vsize; + else if (ms_video_size_greater_than(vsize,obj->vsize) && !ms_video_size_equal(vsize,obj->vsize) ){ + _vfw_engine_unconfigure(obj); + _vfw_engine_disconnect(obj); + _vfw_engine_connect(obj); + obj->vsize=vsize; + _vfw_engine_configure(obj); + } +} + static void vfw_engine_set_callback(VfwEngine* obj, queue_msg_t cb, void *cb_data){ obj->cb=cb; obj->cb_data=cb_data; } static void vfw_engine_start_capture(VfwEngine *obj){ + if (!obj->configured) _vfw_engine_configure(obj); obj->started=TRUE; } @@ -326,7 +370,6 @@ static void vfw_process(MSFilter * obj){ s->frame_count=0; } - cur_frame=((obj->ticker->time-s->start_time)*s->fps/1000.0); if (cur_frame>s->frame_count){ mblk_t *om=NULL; @@ -366,6 +409,7 @@ static int vfw_get_pix_fmt(MSFilter *f,void *arg){ static int vfw_set_vsize(MSFilter *f, void *arg){ VfwState *s=(VfwState*)f->data; s->vsize=*((MSVideoSize*)arg); + vfw_engine_set_video_size(s->eng,s->vsize); return 0; }