mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-21 21:28:08 +00:00
- workaround v4l2/uvc problems
- preview mirroring git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@164 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
8c25164727
commit
a579563efa
6 changed files with 116 additions and 65 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.3 on Tue Oct 14 00:04:09 2008 -->
|
||||
<!--Generated with glade3 3.4.5 on Sat Nov 8 15:49:12 2008 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkDialog" id="sip_account">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
|
|
@ -36,33 +36,16 @@
|
|||
<property name="n_rows">4</property>
|
||||
<property name="n_columns">2</property>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="regperiod">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="adjustment">3600 0 100000 1 10 10</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label41">
|
||||
<widget class="GtkLabel" id="label38">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">Registration duration (sec):</property>
|
||||
<property name="label" translatable="yes">Your SIP identity:</property>
|
||||
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="route">
|
||||
<widget class="GtkEntry" id="identity">
|
||||
<property name="width_request">275</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
|
|
@ -70,20 +53,18 @@
|
|||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label40">
|
||||
<widget class="GtkLabel" id="label39">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">Route (optional):</property>
|
||||
<property name="label" translatable="yes">SIP Proxy address:</property>
|
||||
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
|
@ -101,19 +82,19 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label39">
|
||||
<widget class="GtkLabel" id="label40">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">SIP Proxy address:</property>
|
||||
<property name="label" translatable="yes">Route (optional):</property>
|
||||
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="identity">
|
||||
<widget class="GtkEntry" id="route">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
|
|
@ -121,15 +102,35 @@
|
|||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label38">
|
||||
<widget class="GtkLabel" id="label41">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">Your SIP identity:</property>
|
||||
<property name="label" translatable="yes">Registration duration (sec):</property>
|
||||
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="regperiod">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="adjustment">3600 0 100000 1 10 10</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
|
|
|||
|
|
@ -89,10 +89,11 @@ MSDisplay *ms_display_new(MSDisplayDesc *desc);
|
|||
void ms_display_set_window_id(MSDisplay *d, long window_id);
|
||||
void ms_display_destroy(MSDisplay *d);
|
||||
|
||||
#define MS_VIDEO_OUT_SET_DISPLAY MS_FILTER_METHOD(MS_VIDEO_OUT_ID,0,MSDisplay*)
|
||||
#define MS_VIDEO_OUT_HANDLE_RESIZING MS_FILTER_METHOD_NO_ARG(MS_VIDEO_OUT_ID,1)
|
||||
#define MS_VIDEO_OUT_SET_CORNER MS_FILTER_METHOD(MS_VIDEO_OUT_ID,2,int*)
|
||||
#define MS_VIDEO_OUT_AUTO_FIT MS_FILTER_METHOD(MS_VIDEO_OUT_ID,3,int)
|
||||
#define MS_VIDEO_OUT_SET_DISPLAY MS_FILTER_METHOD(MS_VIDEO_OUT_ID,0,MSDisplay*)
|
||||
#define MS_VIDEO_OUT_HANDLE_RESIZING MS_FILTER_METHOD_NO_ARG(MS_VIDEO_OUT_ID,1)
|
||||
#define MS_VIDEO_OUT_SET_CORNER MS_FILTER_METHOD(MS_VIDEO_OUT_ID,2,int)
|
||||
#define MS_VIDEO_OUT_AUTO_FIT MS_FILTER_METHOD(MS_VIDEO_OUT_ID,3,int)
|
||||
#define MS_VIDEO_OUT_ENABLE_MIRRORING MS_FILTER_METHOD(MS_VIDEO_OUT_ID,4,int)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ typedef struct _EncData{
|
|||
int mode;
|
||||
uint64_t framenum;
|
||||
Rfc3984Context packer;
|
||||
int keyframe_int;
|
||||
bool_t generate_keyframe;
|
||||
}EncData;
|
||||
|
||||
|
|
@ -54,6 +55,7 @@ static void enc_init(MSFilter *f){
|
|||
d->bitrate=384000;
|
||||
d->vsize=MS_VIDEO_SIZE_CIF;
|
||||
d->fps=30;
|
||||
d->keyframe_int=10; /*10 seconds */
|
||||
d->mode=0;
|
||||
d->framenum=0;
|
||||
d->generate_keyframe=FALSE;
|
||||
|
|
@ -87,6 +89,11 @@ static void enc_preprocess(MSFilter *f){
|
|||
params.rc.i_vbv_max_bitrate=(int) (((float)d->bitrate)*0.9/1000.0);
|
||||
params.rc.i_vbv_buffer_size=params.rc.i_vbv_max_bitrate;
|
||||
params.rc.f_vbv_buffer_init=0.5;
|
||||
/*enable this by config ?*/
|
||||
/*
|
||||
params.i_keyint_max = (int)d->fps*d->keyframe_int;
|
||||
params.i_keyint_min = (int)d->fps;
|
||||
*/
|
||||
params.b_repeat_headers=1;
|
||||
params.b_cabac=0;//disable cabac to be baseline
|
||||
params.i_bframe=0;/*no B frames*/
|
||||
|
|
|
|||
|
|
@ -81,13 +81,22 @@ static bool_t v4lv2_try_format(V4l2State *s, int fmtid){
|
|||
|
||||
memset(&fmt,0,sizeof(fmt));
|
||||
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (ioctl (s->fd, VIDIOC_G_FMT, &fmt)<0){
|
||||
ms_error("VIDIOC_G_FMT failed: %s",strerror(errno));
|
||||
}
|
||||
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.fmt.pix.width = s->vsize.width;
|
||||
fmt.fmt.pix.height = s->vsize.height;
|
||||
fmt.fmt.pix.pixelformat = fmtid;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
|
||||
if (ioctl (s->fd, VIDIOC_S_FMT, &fmt)<0){
|
||||
if (ioctl (s->fd, VIDIOC_TRY_FMT, &fmt)<0){
|
||||
ms_message("VIDIOC_TRY_FMT: %s",strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
if (ioctl (s->fd, VIDIOC_S_FMT, &fmt)<0){
|
||||
ms_message("VIDIOC_S_FMT: %s",strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -114,6 +123,7 @@ static int get_picture_buffer_size(MSPixFmt pix_fmt, int w, int h){
|
|||
static int v4l2_configure(V4l2State *s){
|
||||
struct v4l2_capability cap;
|
||||
struct v4l2_format fmt;
|
||||
MSVideoSize vsize;
|
||||
|
||||
if (ioctl (s->fd, VIDIOC_QUERYCAP, &cap)<0) {
|
||||
ms_message("Not a v4lv2 driver.");
|
||||
|
|
@ -131,29 +141,41 @@ static int v4l2_configure(V4l2State *s){
|
|||
}
|
||||
|
||||
ms_message("Driver is %s",cap.driver);
|
||||
|
||||
if (v4lv2_try_format(s,V4L2_PIX_FMT_YUV420)){
|
||||
s->pix_fmt=MS_YUV420P;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_YUV420;
|
||||
ms_message("v4lv2: YUV420P choosen");
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_NV12)){
|
||||
s->pix_fmt=MS_YUV420P;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_NV12;
|
||||
ms_message("v4lv2: V4L2_PIX_FMT_NV12 choosen");
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_MJPEG)){
|
||||
s->pix_fmt=MS_MJPEG;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_MJPEG;
|
||||
ms_message("v4lv2: MJPEG choosen");
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_YUYV)){
|
||||
s->pix_fmt=MS_YUYV;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_YUYV;
|
||||
ms_message("v4lv2: V4L2_PIX_FMT_YUYV choosen");
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_RGB24)){
|
||||
s->pix_fmt=MS_RGB24;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_RGB24;
|
||||
ms_message("v4lv2: RGB24 choosen");
|
||||
}else{
|
||||
ms_error("Could not find supported pixel format.");
|
||||
vsize=s->vsize;
|
||||
do{
|
||||
if (v4lv2_try_format(s,V4L2_PIX_FMT_YUV420)){
|
||||
s->pix_fmt=MS_YUV420P;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_YUV420;
|
||||
ms_message("v4lv2: YUV420P choosen");
|
||||
break;
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_MJPEG)){
|
||||
s->pix_fmt=MS_MJPEG;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_MJPEG;
|
||||
ms_message("v4lv2: MJPEG choosen");
|
||||
break;
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_YUYV)){
|
||||
s->pix_fmt=MS_YUYV;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_YUYV;
|
||||
ms_message("v4lv2: V4L2_PIX_FMT_YUYV choosen");
|
||||
break;
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_NV12)){
|
||||
s->pix_fmt=MS_YUV420P;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_NV12;
|
||||
ms_message("v4lv2: V4L2_PIX_FMT_NV12 choosen");
|
||||
break;
|
||||
}else if (v4lv2_try_format(s,V4L2_PIX_FMT_RGB24)){
|
||||
s->pix_fmt=MS_RGB24;
|
||||
s->int_pix_fmt=V4L2_PIX_FMT_RGB24;
|
||||
ms_message("v4lv2: RGB24 choosen");
|
||||
break;
|
||||
}else{
|
||||
ms_error("Could not find supported pixel format for %ix%i", s->vsize.width, s->vsize.height);
|
||||
}
|
||||
s->vsize=ms_video_size_get_just_lower_than(s->vsize);
|
||||
}while(s->vsize.width!=0);
|
||||
if (s->vsize.width==0){
|
||||
ms_message("Could not find any combination of resolution/pixel-format that works !");
|
||||
s->vsize=vsize;
|
||||
return -1;
|
||||
}
|
||||
memset(&fmt,0,sizeof(fmt));
|
||||
|
|
@ -339,9 +361,8 @@ static void v4l2_uninit(MSFilter *f){
|
|||
ms_free(s);
|
||||
}
|
||||
|
||||
static void v4l2_process(MSFilter *f){
|
||||
static void v4l2_preprocess(MSFilter *f){
|
||||
V4l2State *s=(V4l2State*)f->data;
|
||||
uint32_t elapsed;
|
||||
if (s->fd==-1){
|
||||
if (v4l2_open(s)==0 && v4l2_configure(s)==0 && v4l2_do_mmap(s)==0){
|
||||
ms_message("V4L2 video capture started.");
|
||||
|
|
@ -350,6 +371,12 @@ static void v4l2_process(MSFilter *f){
|
|||
}
|
||||
s->start_time=f->ticker->time;
|
||||
}
|
||||
}
|
||||
|
||||
static void v4l2_process(MSFilter *f){
|
||||
V4l2State *s=(V4l2State*)f->data;
|
||||
uint32_t elapsed;
|
||||
|
||||
if (s->fd!=-1){
|
||||
/*see it is necessary to output a frame:*/
|
||||
elapsed=f->ticker->time-s->start_time;
|
||||
|
|
@ -429,6 +456,7 @@ MSFilterDesc ms_v4l2_desc={
|
|||
.ninputs=0,
|
||||
.noutputs=1,
|
||||
.init=v4l2_init,
|
||||
.preprocess=v4l2_preprocess,
|
||||
.process=v4l2_process,
|
||||
.postprocess=v4l2_postprocess,
|
||||
.uninit=v4l2_uninit,
|
||||
|
|
|
|||
|
|
@ -526,6 +526,7 @@ typedef struct VideoOut
|
|||
bool_t own_display;
|
||||
bool_t ready;
|
||||
bool_t autofit;
|
||||
bool_t mirror;
|
||||
} VideoOut;
|
||||
|
||||
|
||||
|
|
@ -593,6 +594,7 @@ static void video_out_init(MSFilter *f){
|
|||
obj->own_display=FALSE;
|
||||
obj->ready=FALSE;
|
||||
obj->autofit=FALSE;
|
||||
obj->mirror=FALSE;
|
||||
set_vsize(obj,&def_size);
|
||||
f->data=obj;
|
||||
}
|
||||
|
|
@ -736,6 +738,7 @@ static void video_out_process(MSFilter *f){
|
|||
src.h, obj->fbuf.planes, obj->fbuf.strides)<0){
|
||||
ms_error("Error in sws_scale().");
|
||||
}
|
||||
if (obj->mirror && !mblk_get_precious_flag(inm)) yuv_buf_mirror(&obj->fbuf);
|
||||
ms_display_unlock(obj->display);
|
||||
}
|
||||
ms_queue_flush(f->inputs[0]);
|
||||
|
|
@ -800,12 +803,19 @@ static int video_out_set_corner(MSFilter *f,void *arg){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int video_out_enable_mirroring(MSFilter *f,void *arg){
|
||||
VideoOut *s=(VideoOut*)f->data;
|
||||
s->mirror=*(int*)arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MSFilterMethod methods[]={
|
||||
{ MS_FILTER_SET_VIDEO_SIZE , video_out_set_vsize },
|
||||
{ MS_VIDEO_OUT_SET_DISPLAY , video_out_set_display},
|
||||
{ MS_VIDEO_OUT_SET_CORNER , video_out_set_corner},
|
||||
{ MS_VIDEO_OUT_AUTO_FIT , video_out_auto_fit},
|
||||
{ MS_VIDEO_OUT_HANDLE_RESIZING , video_out_handle_resizing},
|
||||
{ MS_VIDEO_OUT_ENABLE_MIRRORING , video_out_enable_mirroring},
|
||||
{ 0 ,NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -353,6 +353,8 @@ VideoStream * video_preview_start(MSWebCam *device, MSVideoSize disp_size){
|
|||
VideoStream *stream = (VideoStream *)ms_new0 (VideoStream, 1);
|
||||
MSVideoSize vsize=disp_size;
|
||||
MSPixFmt format;
|
||||
float fps=29.97;
|
||||
int mirroring=1;
|
||||
|
||||
/* creates the filters */
|
||||
stream->source = ms_web_cam_create_reader(device);
|
||||
|
|
@ -361,6 +363,7 @@ VideoStream * video_preview_start(MSWebCam *device, MSVideoSize disp_size){
|
|||
|
||||
/* configure the filters */
|
||||
ms_filter_call_method(stream->source,MS_FILTER_SET_VIDEO_SIZE,&vsize);
|
||||
ms_filter_call_method(stream->source,MS_FILTER_SET_FPS,&fps);
|
||||
ms_filter_call_method(stream->source,MS_FILTER_GET_PIX_FMT,&format);
|
||||
ms_filter_call_method(stream->source,MS_FILTER_GET_VIDEO_SIZE,&vsize);
|
||||
if (format==MS_MJPEG){
|
||||
|
|
@ -374,6 +377,7 @@ VideoStream * video_preview_start(MSWebCam *device, MSVideoSize disp_size){
|
|||
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,&disp_size);
|
||||
ms_filter_call_method(stream->output,MS_VIDEO_OUT_ENABLE_MIRRORING,&mirroring);
|
||||
/* and then connect all */
|
||||
|
||||
ms_filter_link(stream->source,0, stream->pixconv,0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue