implement the 'freeze' function for incoming frames;

fix a bug which caused a crash when a videodevice was
specified after startgui=1 in the config file. This also
involves a slightly different method to determine if the
gui is active or not.



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@126572 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.1
Luigi Rizzo 17 years ago
parent f55143f0a6
commit ff8ad6b497

@ -1387,6 +1387,11 @@ static struct chan_oss_pvt *store_config(struct ast_config *cfg, char *ctg)
system(cmd); system(cmd);
ast_free(cmd); ast_free(cmd);
} }
/* if the config file requested to start the GUI, do it */
if (get_gui_startup(o->env))
console_video_start(o->env, NULL);
if (o == &oss_default) /* we are done with the default */ if (o == &oss_default) /* we are done with the default */
return NULL; return NULL;

@ -50,7 +50,9 @@ handled differently according to their location:
keystrokes are used as keypad functions, or as text input keystrokes are used as keypad functions, or as text input
if we are in text-input mode. if we are in text-input mode.
- drag on some keypad areas (sliders etc.) are mapped to the - drag on some keypad areas (sliders etc.) are mapped to the
corresponding functions; corresponding functions (mute/unmute audio and video,
enable/disable Picture-in-Picture, freeze the incoming video,
dial numbers, pick up or hang up a call, ...)
Configuration options control the appeareance of the gui: Configuration options control the appeareance of the gui:
@ -58,9 +60,8 @@ Configuration options control the appeareance of the gui:
keypad_font = /tmp/font.png ; the font to use for output keypad_font = /tmp/font.png ; the font to use for output
For future implementation, intresting features can be the following: For future implementation, intresting features can be the following:
- freeze of the video coming from our remote party
- save of the whole SDL window as a picture - save of the whole SDL window as a picture
- oudio output device switching - audio output device switching
The audio switching feature should allow changing the device The audio switching feature should allow changing the device
or switching to a recorded message for audio sent to remote party. or switching to a recorded message for audio sent to remote party.
@ -343,10 +344,10 @@ enum skin_area {
associated with the audio device markers, clicking on these markers associated with the audio device markers, clicking on these markers
will change the source device for audio output */ will change the source device for audio output */
#endif
/* Keys related to video sources */
KEY_FREEZE = 220, /* freeze the incoming video */ KEY_FREEZE = 220, /* freeze the incoming video */
KEY_CAPTURE = 221, /* capture the whole SDL window as a picture */ KEY_CAPTURE = 221, /* capture the whole SDL window as a picture */
#endif
/* video source switching key(s) */
KEY_PIP = 230, KEY_PIP = 230,
/*indexes between 231 and 239 have been reserved for the "keys" /*indexes between 231 and 239 have been reserved for the "keys"
associated with the device thumbnails, clicking on these pictures associated with the device thumbnails, clicking on these pictures
@ -389,12 +390,19 @@ static char *keypad_toggle(struct video_desc *env, int index)
case KEY_SENDVIDEO: /* send or do not send video */ case KEY_SENDVIDEO: /* send or do not send video */
env->out.sendvideo = !env->out.sendvideo; env->out.sendvideo = !env->out.sendvideo;
break; break;
case KEY_PIP: /* enable or disable Picture in Picture */ case KEY_PIP: /* enable or disable Picture in Picture */
env->out.picture_in_picture = !env->out.picture_in_picture; env->out.picture_in_picture = !env->out.picture_in_picture;
break; break;
case KEY_MUTE: /* send or do not send audio */ case KEY_MUTE: /* send or do not send audio */
ast_cli_command(env->gui->outfd, "console mute toggle"); ast_cli_command(env->gui->outfd, "console mute toggle");
break; break;
case KEY_FREEZE: /* freeze/unfreeze the incoming frames */
env->frame_freeze = !env->frame_freeze;
break;
#ifdef notyet #ifdef notyet
case KEY_AUTOANSWER: { case KEY_AUTOANSWER: {
struct chan_oss_pvt *o = find_desc(oss_active); struct chan_oss_pvt *o = find_desc(oss_active);
@ -737,6 +745,7 @@ static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button
case KEY_AUTOANSWER: case KEY_AUTOANSWER:
case KEY_SENDVIDEO: /* send or not send the video */ case KEY_SENDVIDEO: /* send or not send the video */
case KEY_PIP: /* activate/deactivate picture in picture mode */ case KEY_PIP: /* activate/deactivate picture in picture mode */
case KEY_FREEZE: /* freeze/unfreeze the incoming video */
keypad_toggle(env, index); keypad_toggle(env, index);
break; break;
@ -746,8 +755,6 @@ static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button
break; break;
#ifdef notyet /* XXX for future implementations */ #ifdef notyet /* XXX for future implementations */
case KEY_FREEZE:
break
case KEY_CAPTURE: case KEY_CAPTURE:
break; break;
#endif #endif
@ -1407,6 +1414,9 @@ static void sdl_setup(struct video_desc *env)
if (set_win(gui->screen, &gui->win[WIN_REMOTE], dpy_fmt, if (set_win(gui->screen, &gui->win[WIN_REMOTE], dpy_fmt,
env->rem_dpy.w, env->rem_dpy.h, x0-kp_w/2-BORDER-env->rem_dpy.w, y0)) env->rem_dpy.w, env->rem_dpy.h, x0-kp_w/2-BORDER-env->rem_dpy.w, y0))
goto no_sdl; goto no_sdl;
/* unfreeze incoming frames if set (to avoid showing nothing) */
env->frame_freeze = 0;
if (set_win(gui->screen, &gui->win[WIN_LOCAL], dpy_fmt, if (set_win(gui->screen, &gui->win[WIN_LOCAL], dpy_fmt,
env->loc_dpy.w, env->loc_dpy.h, env->loc_dpy.w, env->loc_dpy.h,
x0+kp_w/2+BORDER, y0)) x0+kp_w/2+BORDER, y0))
@ -1496,6 +1506,7 @@ static int kp_match_area(const struct keypad_entry *e, int x, int y)
struct _s_k { const char *s; int k; }; struct _s_k { const char *s; int k; };
static struct _s_k gui_key_map[] = { static struct _s_k gui_key_map[] = {
{"FREEZE", KEY_FREEZE},
{"PIP", KEY_PIP}, {"PIP", KEY_PIP},
{"PICK_UP", KEY_PICK_UP }, {"PICK_UP", KEY_PICK_UP },
{"PICKUP", KEY_PICK_UP }, {"PICKUP", KEY_PICK_UP },
@ -1537,6 +1548,8 @@ static int gui_map_token(const char *s)
* token circle xc yc diameter * token circle xc yc diameter
* token circle xc yc x1 y1 h # ellipse, main diameter and height * token circle xc yc x1 y1 h # ellipse, main diameter and height
* token rect x0 y0 x1 y1 h # rectangle with main side and eight * token rect x0 y0 x1 y1 h # rectangle with main side and eight
* token x0 y0 w h # horizontal rectangle (short format)
* # this is used e.g. for message boards
* token is the token to be returned, either a character or a symbol * token is the token to be returned, either a character or a symbol
* as KEY_* above * as KEY_* above
* Return 1 on success, 0 on error. * Return 1 on success, 0 on error.
@ -1578,10 +1591,10 @@ static int keypad_cfg_read(struct gui_info *gui, const char *val)
else if (e.c == KEY_EDIT) else if (e.c == KEY_EDIT)
r = gui->kp_edit; r = gui->kp_edit;
if (r) { if (r) {
r->x = atoi(s2); r->x = atoi(s2); /* this becomes x0 */
r->y = e.x0; r->y = e.x0; /* this becomes y0 */
r->w = e.y0; r->w = e.y0; /* this becomes w */
r->h = e.x1; r->h = e.x1; /* this becomes h */
break; break;
} }
if (strcasecmp(s2, "circle")) /* invalid */ if (strcasecmp(s2, "circle")) /* invalid */

@ -137,6 +137,11 @@ void console_video_uninit(struct video_desc *env)
{ {
} }
int get_gui_startup(struct video_desc* env)
{
return 0; /* no gui here */
}
int console_video_formats = 0; int console_video_formats = 0;
#else /* defined(HAVE_FFMPEG) && defined(HAVE_SDL) */ #else /* defined(HAVE_FFMPEG) && defined(HAVE_SDL) */
@ -248,11 +253,11 @@ struct video_desc {
struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */ struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */ struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */
/*display for sources in additional windows, /* geometry of the thumbnails for all video sources. */
ideally infinite additional sources could be present
pratically we assume a maximum of 9 sources to show*/
struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */ struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */
int frame_freeze; /* flag to freeze the incoming frame */
/* local information for grabbers, codecs, gui */ /* local information for grabbers, codecs, gui */
struct gui_info *gui; struct gui_info *gui;
struct video_dec_desc *in; /* remote video descriptor */ struct video_dec_desc *in; /* remote video descriptor */
@ -274,6 +279,14 @@ void fbuf_free(struct fbuf_t *b)
b->pix_fmt = x.pix_fmt; b->pix_fmt = x.pix_fmt;
} }
/* return the status of env->stayopen to chan_oss, as the latter
* does not have access to fields of struct video_desc
*/
int get_gui_startup(struct video_desc* env)
{
return env->stayopen;
}
#if 0 #if 0
/* helper function to print the amount of memory used by the process. /* helper function to print the amount of memory used by the process.
* Useful to track memory leaks, unfortunately this code is OS-specific * Useful to track memory leaks, unfortunately this code is OS-specific
@ -432,6 +445,7 @@ static int video_out_uninit(struct video_desc *env)
v->devices[i].status_index = 0; v->devices[i].status_index = 0;
} }
v->picture_in_picture = 0; v->picture_in_picture = 0;
env->frame_freeze = 0;
return -1; return -1;
} }
@ -545,7 +559,7 @@ static int video_out_init(struct video_desc *env)
void console_video_uninit(struct video_desc *env) void console_video_uninit(struct video_desc *env)
{ {
int i, t = 100; /* initial wait is shorter, than make it longer */ int i, t = 100; /* initial wait is shorter, than make it longer */
if (env->stayopen == 0) { /* in a call */ if (env->stayopen == 0) { /* gui opened by a call, do the shutdown */
env->shutdown = 1; env->shutdown = 1;
for (i=0; env->shutdown && i < 10; i++) { for (i=0; env->shutdown && i < 10; i++) {
if (env->owner) if (env->owner)
@ -555,6 +569,7 @@ void console_video_uninit(struct video_desc *env)
if (env->owner) if (env->owner)
ast_channel_lock(env->owner); ast_channel_lock(env->owner);
} }
env->vthread = NULL;
} }
env->owner = NULL; /* this is unconditional */ env->owner = NULL; /* this is unconditional */
} }
@ -920,7 +935,8 @@ static void *video_thread(void *arg)
while (v->dec_in_dpy) { while (v->dec_in_dpy) {
struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */ struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */
if (v->d_callbacks->dec_run(v, tmp)) /* decode the frame, but show it only if not frozen */
if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze)
show_frame(env, WIN_REMOTE); show_frame(env, WIN_REMOTE);
tmp->used = 0; /* mark buffer as free */ tmp->used = 0; /* mark buffer as free */
tmp->ebit = 0; tmp->ebit = 0;
@ -1045,7 +1061,7 @@ void console_video_start(struct video_desc *env, struct ast_channel *owner)
if (env == NULL) /* video not initialized */ if (env == NULL) /* video not initialized */
return; return;
env->owner = owner; /* work even if no owner is specified */ env->owner = owner; /* work even if no owner is specified */
if (env->stayopen) if (env->vthread)
return; /* already initialized, nothing to do */ return; /* already initialized, nothing to do */
init_env(env); init_env(env);
env->out.enc = map_config_video_format(env->codec_name); env->out.enc = map_config_video_format(env->codec_name);
@ -1073,8 +1089,6 @@ void console_video_start(struct video_desc *env, struct ast_channel *owner)
ast_pthread_create_background(&env->vthread, NULL, video_thread, env); ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
/* detach the thread to make sure memory is freed on termination */ /* detach the thread to make sure memory is freed on termination */
pthread_detach(env->vthread); pthread_detach(env->vthread);
if (env->owner == NULL)
env->stayopen = 1; /* manually opened so don't close on hangup */
} }
/* /*
@ -1204,6 +1218,7 @@ int console_video_cli(struct video_desc *env, const char *var, int fd)
} else if (!strcasecmp(var, "fps")) { } else if (!strcasecmp(var, "fps")) {
ast_cli(fd, "fps is [%d]\n", env->out.fps); ast_cli(fd, "fps is [%d]\n", env->out.fps);
} else if (!strcasecmp(var, "startgui")) { } else if (!strcasecmp(var, "startgui")) {
env->stayopen = 1;
console_video_start(env, NULL); console_video_start(env, NULL);
} else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) { } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
env->stayopen = 0; env->stayopen = 0;
@ -1236,7 +1251,7 @@ int console_video_config(struct video_desc **penv,
return 1; /* error */ return 1; /* error */
} }
/* set default values */ /* set default values - 0's are already there */
env->out.device_primary = 0; env->out.device_primary = 0;
env->out.device_secondary = 0; env->out.device_secondary = 0;
env->out.fps = 5; env->out.fps = 5;
@ -1244,7 +1259,6 @@ int console_video_config(struct video_desc **penv,
env->out.sendvideo = 1; env->out.sendvideo = 1;
env->out.qmin = 3; env->out.qmin = 3;
env->out.device_num = 0; env->out.device_num = 0;
env->out.picture_in_picture = 0; /* PiP mode intially disabled */
} }
CV_START(var, val); CV_START(var, val);
CV_F("videodevice", device_table_fill(env->out.devices, &env->out.device_num, val)); CV_F("videodevice", device_table_fill(env->out.devices, &env->out.device_num, val));
@ -1255,7 +1269,7 @@ int console_video_config(struct video_desc **penv,
CV_F("remote_size", video_geom(&env->rem_dpy, val)); CV_F("remote_size", video_geom(&env->rem_dpy, val));
CV_STR("keypad", env->keypad_file); CV_STR("keypad", env->keypad_file);
CV_F("region", keypad_cfg_read(env->gui, val)); CV_F("region", keypad_cfg_read(env->gui, val));
CV_F("startgui", console_video_start(env, NULL)); // support enabling gui at startup CV_UINT("startgui", env->stayopen); /* enable gui at startup */
CV_STR("keypad_font", env->keypad_font); CV_STR("keypad_font", env->keypad_font);
CV_STR("sdl_videodriver", env->sdl_videodriver); CV_STR("sdl_videodriver", env->sdl_videodriver);
CV_UINT("fps", env->out.fps); CV_UINT("fps", env->out.fps);

@ -97,6 +97,7 @@ int console_video_cli(struct video_desc *env, const char *var, int fd);
int console_video_config(struct video_desc **penv, const char *var, const char *val); int console_video_config(struct video_desc **penv, const char *var, const char *val);
void console_video_uninit(struct video_desc *env); void console_video_uninit(struct video_desc *env);
void console_video_start(struct video_desc *env, struct ast_channel *owner); void console_video_start(struct video_desc *env, struct ast_channel *owner);
int get_gui_startup(struct video_desc* env);
/* console_board.c */ /* console_board.c */

Loading…
Cancel
Save