mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
virtualize the interface for video grabbers, which should
make it easier to add support for more grabbers (V4L2, firewire, and so on). git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@95288 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -503,17 +503,6 @@ static void handle_keyboard_input(struct video_desc *env, SDLKey key)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the grab point is inside the X screen.
|
||||
*
|
||||
* x represent the new grab value
|
||||
* limit represent the upper value to use
|
||||
*/
|
||||
static int boundary_checks(int x, int limit)
|
||||
{
|
||||
return (x <= 0) ? 0 : (x > limit ? limit : x);
|
||||
}
|
||||
|
||||
/* implement superlinear acceleration on the movement */
|
||||
static int move_accel(int delta)
|
||||
{
|
||||
@@ -521,6 +510,7 @@ static int move_accel(int delta)
|
||||
return (delta > 0) ? delta + d1 : delta - d1;
|
||||
}
|
||||
|
||||
static void grabber_move(struct video_out_desc *, int dx, int dy);
|
||||
/*
|
||||
* Move the source of the captured video.
|
||||
*
|
||||
@@ -529,21 +519,17 @@ static int move_accel(int delta)
|
||||
*/
|
||||
static void move_capture_source(struct video_desc *env, int x_final_drag, int y_final_drag)
|
||||
{
|
||||
int new_x, new_y; /* new coordinates for grabbing local video */
|
||||
int x = env->out.loc_src.x; /* old value */
|
||||
int y = env->out.loc_src.y; /* old value */
|
||||
int dx, dy;
|
||||
|
||||
/* move the origin */
|
||||
#define POLARITY -1 /* +1 or -1 depending on the desired direction */
|
||||
new_x = x + POLARITY*move_accel(x_final_drag - env->gui->x_drag) * 3;
|
||||
new_y = y + POLARITY*move_accel(y_final_drag - env->gui->y_drag) * 3;
|
||||
dx = POLARITY*move_accel(x_final_drag - env->gui->x_drag) * 3;
|
||||
dy = POLARITY*move_accel(y_final_drag - env->gui->y_drag) * 3;
|
||||
#undef POLARITY
|
||||
env->gui->x_drag = x_final_drag; /* update origin */
|
||||
env->gui->y_drag = y_final_drag;
|
||||
|
||||
/* check boundary and let the source to grab from the new points */
|
||||
env->out.loc_src.x = boundary_checks(new_x, env->out.screen_width - env->out.loc_src.w);
|
||||
env->out.loc_src.y = boundary_checks(new_y, env->out.screen_height - env->out.loc_src.h);
|
||||
grabber_move(&env->out, dx, dy);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -131,6 +131,7 @@ int console_video_formats =
|
||||
static void my_scale(struct fbuf_t *in, AVPicture *p_in,
|
||||
struct fbuf_t *out, AVPicture *p_out);
|
||||
|
||||
struct grab_desc; /* grabber description */
|
||||
struct video_codec_desc; /* forward declaration */
|
||||
/*
|
||||
* Descriptor of the local source, made of the following pieces:
|
||||
@@ -140,7 +141,7 @@ struct video_codec_desc; /* forward declaration */
|
||||
* + the encoding and RTP info, including timestamps to generate
|
||||
* frames at the correct rate;
|
||||
* + source-specific info, i.e. fd for /dev/video, dpy-image for x11, etc,
|
||||
* filled in by video_open
|
||||
* filled in by grabber_open
|
||||
* NOTE: loc_src.data == NULL means the rest of the struct is invalid, and
|
||||
* the video source is not available.
|
||||
*/
|
||||
@@ -158,7 +159,7 @@ struct video_out_desc {
|
||||
|
||||
int sendvideo;
|
||||
|
||||
struct fbuf_t loc_src; /* local source buffer, allocated in video_open() */
|
||||
struct fbuf_t loc_src_geometry; /* local source geometry only (from config file) */
|
||||
struct fbuf_t enc_out; /* encoder output buffer, allocated in video_out_init() */
|
||||
|
||||
struct video_codec_desc *enc; /* encoder */
|
||||
@@ -169,14 +170,8 @@ struct video_out_desc {
|
||||
int mtu;
|
||||
struct timeval last_frame; /* when we read the last frame ? */
|
||||
|
||||
/* device specific info */
|
||||
int fd; /* file descriptor, for webcam */
|
||||
#ifdef HAVE_X11
|
||||
Display *dpy; /* x11 grabber info */
|
||||
XImage *image;
|
||||
int screen_width; /* width of X screen */
|
||||
int screen_height; /* height of X screen */
|
||||
#endif
|
||||
struct grab_desc *grabber;
|
||||
void *grabber_data;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -231,28 +226,37 @@ static void fbuf_free(struct fbuf_t *b)
|
||||
|
||||
/*------ end codec specific code -----*/
|
||||
|
||||
/* descriptor for a grabber */
|
||||
struct grab_desc {
|
||||
const char *name;
|
||||
void *(*open)(const char *name, struct fbuf_t *geom, int fps);
|
||||
struct fbuf_t *(*read)(void *d);
|
||||
void (*move)(void *d, int dx, int dy);
|
||||
void *(*close)(void *d);
|
||||
};
|
||||
|
||||
/* Video4Linux stuff is only used in video_open() */
|
||||
#ifdef HAVE_VIDEODEV_H
|
||||
#include <linux/videodev.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Open the local video source and allocate a buffer
|
||||
* for storing the image. Return 0 on success, -1 on error
|
||||
*/
|
||||
static int video_open(struct video_out_desc *v)
|
||||
#ifdef HAVE_X11
|
||||
struct grab_x11_desc {
|
||||
Display *dpy; /* x11 grabber info */
|
||||
XImage *image;
|
||||
int screen_width; /* width of X screen */
|
||||
int screen_height; /* height of X screen */
|
||||
struct fbuf_t b;
|
||||
};
|
||||
|
||||
static void *grab_x11_open(const char *name, struct fbuf_t *geom, int fps)
|
||||
{
|
||||
struct fbuf_t *b = &v->loc_src;
|
||||
if (b->data) /* buffer allocated means device already open */
|
||||
return v->fd;
|
||||
v->fd = -1;
|
||||
/*
|
||||
* if the device is "X11", then open the x11 grabber
|
||||
*/
|
||||
if (!strcasecmp(v->videodevice, "X11")) {
|
||||
XImage *im;
|
||||
int screen_num;
|
||||
struct grab_x11_desc *v;
|
||||
struct fbuf_t *b;
|
||||
|
||||
if (strcasecmp(name, "X11"))
|
||||
return NULL; /* not us */
|
||||
v = ast_calloc(1, sizeof(*v));
|
||||
if (v == NULL)
|
||||
return NULL; /* no memory */
|
||||
|
||||
/* init the connection with the X server */
|
||||
v->dpy = XOpenDisplay(NULL);
|
||||
@@ -261,6 +265,8 @@ static int video_open(struct video_out_desc *v)
|
||||
goto error;
|
||||
}
|
||||
|
||||
v->b = *geom; /* copy geometry */
|
||||
b = &v->b; /* shorthand */
|
||||
/* find width and height of the screen */
|
||||
screen_num = DefaultScreen(v->dpy);
|
||||
v->screen_width = DisplayWidth(v->dpy, screen_num);
|
||||
@@ -290,24 +296,106 @@ static int video_open(struct video_out_desc *v)
|
||||
|
||||
/* set the pointer but not the size as this is not malloc'ed */
|
||||
b->data = (uint8_t *)im->data;
|
||||
v->fd = -2;
|
||||
}
|
||||
return v;
|
||||
|
||||
error:
|
||||
/* XXX maybe XDestroy (v->image) ? */
|
||||
if (v->dpy)
|
||||
XCloseDisplay(v->dpy);
|
||||
v->dpy = NULL;
|
||||
ast_free(v);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fbuf_t *grab_x11_read(void *desc)
|
||||
{
|
||||
/* read frame from X11 */
|
||||
struct grab_x11_desc *v = desc;
|
||||
struct fbuf_t *b = &v->b;
|
||||
|
||||
XGetSubImage(v->dpy,
|
||||
RootWindow(v->dpy, DefaultScreen(v->dpy)),
|
||||
b->x, b->y, b->w, b->h, AllPlanes, ZPixmap, v->image, 0, 0);
|
||||
|
||||
b->data = (uint8_t *)v->image->data;
|
||||
return b;
|
||||
}
|
||||
|
||||
static int boundary_checks(int x, int limit)
|
||||
{
|
||||
return (x <= 0) ? 0 : (x > limit ? limit : x);
|
||||
}
|
||||
|
||||
/* move the origin for the grabbed area */
|
||||
static void grab_x11_move(void *desc, int dx, int dy)
|
||||
{
|
||||
struct grab_x11_desc *v = desc;
|
||||
|
||||
v->b.x = boundary_checks(v->b.x + dx, v->screen_width - v->b.w);
|
||||
v->b.y = boundary_checks(v->b.y + dy, v->screen_height - v->b.h);
|
||||
}
|
||||
|
||||
static void *grab_x11_close(void *desc)
|
||||
{
|
||||
struct grab_x11_desc *v = desc;
|
||||
|
||||
XCloseDisplay(v->dpy);
|
||||
v->dpy = NULL;
|
||||
v->image = NULL;
|
||||
ast_free(v);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct grab_desc grab_x11_desc = {
|
||||
.name = "X11",
|
||||
.open = grab_x11_open,
|
||||
.read = grab_x11_read,
|
||||
.move = grab_x11_move,
|
||||
.close = grab_x11_close,
|
||||
};
|
||||
|
||||
#endif /* HAVE_X11 */
|
||||
|
||||
/* Video4Linux stuff is only used in grabber_open() */
|
||||
#ifdef HAVE_VIDEODEV_H
|
||||
else {
|
||||
/* V4L specific */
|
||||
#include <linux/videodev.h>
|
||||
|
||||
struct grab_v4l1_desc {
|
||||
int fd;
|
||||
int fps;
|
||||
struct fbuf_t b;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Open the local video source and allocate a buffer
|
||||
* for storing the image. Return 0 on success, -1 on error
|
||||
*/
|
||||
static void *grab_v4l1_open(const char *dev, struct fbuf_t *geom, int fps)
|
||||
{
|
||||
struct video_window vw = { 0 }; /* camera attributes */
|
||||
struct video_picture vp;
|
||||
int i;
|
||||
const char *dev = v->videodevice;
|
||||
int fd, i;
|
||||
struct grab_v4l1_desc *v;
|
||||
struct fbuf_t *b;
|
||||
|
||||
v->fd = open(dev, O_RDONLY | O_NONBLOCK);
|
||||
if (v->fd < 0) {
|
||||
ast_log(LOG_WARNING, "error opening camera %s\n", v->videodevice);
|
||||
return v->fd;
|
||||
fd = open(dev, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING, "error opening camera %s\n", dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i = fcntl(v->fd, F_GETFL);
|
||||
if (-1 == fcntl(v->fd, F_SETFL, i | O_NONBLOCK)) {
|
||||
v = ast_calloc(1, sizeof(*v));
|
||||
if (v == NULL) {
|
||||
ast_log(LOG_WARNING, "no memory for camera %s\n", dev);
|
||||
close(fd);
|
||||
return NULL; /* no memory */
|
||||
}
|
||||
v->fd = fd;
|
||||
v->b = *geom;
|
||||
b = &v->b; /* shorthand */
|
||||
|
||||
i = fcntl(fd, F_GETFL);
|
||||
if (-1 == fcntl(fd, F_SETFL, i | O_NONBLOCK)) {
|
||||
/* non fatal, just emit a warning */
|
||||
ast_log(LOG_WARNING, "error F_SETFL for %s [%s]\n",
|
||||
dev, strerror(errno));
|
||||
@@ -316,15 +404,15 @@ static int video_open(struct video_out_desc *v)
|
||||
* In principle we could retry with a different format if the
|
||||
* one we are asking for is not supported.
|
||||
*/
|
||||
vw.width = v->loc_src.w;
|
||||
vw.height = v->loc_src.h;
|
||||
vw.flags = v->fps << 16;
|
||||
if (ioctl(v->fd, VIDIOCSWIN, &vw) == -1) {
|
||||
vw.width = b->w;
|
||||
vw.height = b->h;
|
||||
vw.flags = fps << 16;
|
||||
if (ioctl(fd, VIDIOCSWIN, &vw) == -1) {
|
||||
ast_log(LOG_WARNING, "error setting format for %s [%s]\n",
|
||||
dev, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
if (ioctl(v->fd, VIDIOCGPICT, &vp) == -1) {
|
||||
if (ioctl(fd, VIDIOCGPICT, &vp) == -1) {
|
||||
ast_log(LOG_WARNING, "error reading picture info\n");
|
||||
goto error;
|
||||
}
|
||||
@@ -351,44 +439,95 @@ static int video_open(struct video_out_desc *v)
|
||||
b->size = (b->w * b->h * 3)/2; /* yuv411 */
|
||||
ast_log(LOG_WARNING, "videodev %s opened, size %dx%d %d\n",
|
||||
dev, b->w, b->h, b->size);
|
||||
v->loc_src.data = ast_calloc(1, b->size);
|
||||
b->data = ast_calloc(1, b->size);
|
||||
if (!b->data) {
|
||||
ast_log(LOG_WARNING, "error allocating buffer %d bytes\n",
|
||||
b->size);
|
||||
goto error;
|
||||
}
|
||||
ast_log(LOG_WARNING, "success opening camera\n");
|
||||
}
|
||||
#endif /* HAVE_VIDEODEV_H */
|
||||
|
||||
if (v->image == NULL && v->fd < 0)
|
||||
goto error;
|
||||
b->used = 0;
|
||||
return 0;
|
||||
return v;
|
||||
|
||||
error:
|
||||
ast_log(LOG_WARNING, "fd %d dpy %p img %p data %p\n",
|
||||
v->fd, v->dpy, v->image, v->loc_src.data);
|
||||
/* XXX maybe XDestroy (v->image) ? */
|
||||
if (v->dpy)
|
||||
XCloseDisplay(v->dpy);
|
||||
v->dpy = NULL;
|
||||
if (v->fd >= 0)
|
||||
close(v->fd);
|
||||
close(v->fd);
|
||||
fbuf_free(b);
|
||||
ast_free(v);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fbuf_t *grab_v4l1_read(void *desc)
|
||||
{
|
||||
struct grab_v4l1_desc *v = desc;
|
||||
struct fbuf_t *b = &v->b;
|
||||
for (;;) {
|
||||
int r, l = b->size - b->used;
|
||||
r = read(v->fd, b->data + b->used, l);
|
||||
// ast_log(LOG_WARNING, "read %d of %d bytes from webcam\n", r, l);
|
||||
if (r < 0) /* read error */
|
||||
break;
|
||||
if (r == 0) /* no data */
|
||||
break;
|
||||
b->used += r;
|
||||
if (r == l) {
|
||||
b->used = 0; /* prepare for next frame */
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *grab_v4l1_close(void *desc)
|
||||
{
|
||||
struct grab_v4l1_desc *v = desc;
|
||||
|
||||
close(v->fd);
|
||||
v->fd = -1;
|
||||
fbuf_free(&v->loc_src);
|
||||
return -1;
|
||||
fbuf_free(&v->b);
|
||||
ast_free(v);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct grab_desc grab_v4l1_desc = {
|
||||
.name = "v4l1",
|
||||
.open = grab_v4l1_open,
|
||||
.read = grab_v4l1_read,
|
||||
.close = grab_v4l1_close,
|
||||
};
|
||||
#endif /* HAVE_VIDEODEV_H */
|
||||
|
||||
static struct grab_desc *my_grabbers[] = {
|
||||
&grab_x11_desc,
|
||||
&grab_v4l1_desc,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* try to open a video source, return 0 on success, 1 on error
|
||||
*/
|
||||
static int grabber_open(struct video_out_desc *v)
|
||||
{
|
||||
struct grab_desc *g;
|
||||
void *g_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; (g = my_grabbers[i]); i++) {
|
||||
g_data = g->open(v->videodevice, &v->loc_src_geometry, v->fps);
|
||||
if (g_data) {
|
||||
v->grabber = g;
|
||||
v->grabber_data = g_data;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1; /* no source found */
|
||||
}
|
||||
|
||||
/*! \brief complete a buffer from the local video source.
|
||||
* Called by get_video_frames(), in turn called by the video thread.
|
||||
*/
|
||||
static int video_read(struct video_out_desc *v)
|
||||
static struct fbuf_t *grabber_read(struct video_out_desc *v)
|
||||
{
|
||||
struct timeval now = ast_tvnow();
|
||||
struct fbuf_t *b = &v->loc_src;
|
||||
|
||||
if (b->data == NULL) /* not initialized */
|
||||
if (v->grabber == NULL) /* not initialized */
|
||||
return 0;
|
||||
|
||||
/* check if it is time to read */
|
||||
@@ -397,36 +536,13 @@ static int video_read(struct video_out_desc *v)
|
||||
if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
|
||||
return 0; /* too early */
|
||||
v->last_frame = now; /* XXX actually, should correct for drift */
|
||||
return v->grabber->read(v->grabber_data);
|
||||
}
|
||||
|
||||
#ifdef HAVE_X11
|
||||
if (v->image) {
|
||||
/* read frame from X11 */
|
||||
AVPicture p;
|
||||
XGetSubImage(v->dpy,
|
||||
RootWindow(v->dpy, DefaultScreen(v->dpy)),
|
||||
b->x, b->y, b->w, b->h, AllPlanes, ZPixmap, v->image, 0, 0);
|
||||
|
||||
b->data = (uint8_t *)v->image->data;
|
||||
fill_pict(b, &p);
|
||||
return p.linesize[0] * b->h;
|
||||
}
|
||||
#endif
|
||||
if (v->fd < 0) /* no other source */
|
||||
return 0;
|
||||
for (;;) {
|
||||
int r, l = v->loc_src.size - v->loc_src.used;
|
||||
r = read(v->fd, v->loc_src.data + v->loc_src.used, l);
|
||||
// ast_log(LOG_WARNING, "read %d of %d bytes from webcam\n", r, l);
|
||||
if (r < 0) /* read error */
|
||||
return 0;
|
||||
if (r == 0) /* no data */
|
||||
return 0;
|
||||
v->loc_src.used += r;
|
||||
if (r == l) {
|
||||
v->loc_src.used = 0; /* prepare for next frame */
|
||||
return v->loc_src.size;
|
||||
}
|
||||
}
|
||||
static void grabber_move(struct video_out_desc *v, int dx, int dy)
|
||||
{
|
||||
if (v->grabber && v->grabber->move)
|
||||
v->grabber->move(v->grabber_data, dx, dy);
|
||||
}
|
||||
|
||||
/* Helper function to process incoming video.
|
||||
@@ -476,19 +592,15 @@ static int video_out_uninit(struct video_desc *env)
|
||||
av_free(v->enc_in_frame);
|
||||
v->enc_in_frame = NULL;
|
||||
}
|
||||
v->codec = NULL; /* only a reference */
|
||||
|
||||
fbuf_free(&v->loc_src);
|
||||
v->codec = NULL; /* nothing to free, this is only a reference */
|
||||
/* release the buffers */
|
||||
fbuf_free(&env->enc_in);
|
||||
fbuf_free(&v->enc_out);
|
||||
if (v->image) { /* X11 grabber */
|
||||
XCloseDisplay(v->dpy);
|
||||
v->dpy = NULL;
|
||||
v->image = NULL;
|
||||
}
|
||||
if (v->fd >= 0) {
|
||||
close(v->fd);
|
||||
v->fd = -1;
|
||||
/* close the grabber */
|
||||
sleep(1);
|
||||
if (v->grabber) {
|
||||
v->grabber_data = v->grabber->close(v->grabber_data);
|
||||
v->grabber = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -512,10 +624,6 @@ static int video_out_init(struct video_desc *env)
|
||||
v->enc_in_frame = NULL;
|
||||
v->enc_out.data = NULL;
|
||||
|
||||
if (v->loc_src.data == NULL) {
|
||||
ast_log(LOG_WARNING, "No local source active\n");
|
||||
return -1; /* error, but nothing to undo yet */
|
||||
}
|
||||
codec = map_video_format(v->enc->format, CM_WR);
|
||||
v->codec = avcodec_find_encoder(codec);
|
||||
if (!v->codec) {
|
||||
@@ -786,7 +894,7 @@ int console_write_video(struct ast_channel *chan, struct ast_frame *f)
|
||||
}
|
||||
|
||||
|
||||
/*! \brief read a frame from webcam or X11 through video_read(),
|
||||
/*! \brief read a frame from webcam or X11 through grabber_read(),
|
||||
* display it, then encode and split it.
|
||||
* Return a list of ast_frame representing the video fragments.
|
||||
* The head pointer is returned by the function, the tail pointer
|
||||
@@ -796,14 +904,9 @@ static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_fra
|
||||
{
|
||||
struct video_out_desc *v = &env->out;
|
||||
struct ast_frame *dummy;
|
||||
struct fbuf_t *loc_src = grabber_read(v);
|
||||
|
||||
if (!v->loc_src.data) {
|
||||
static volatile int a = 0;
|
||||
if (a++ < 2)
|
||||
ast_log(LOG_WARNING, "fail, no loc_src buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!video_read(v))
|
||||
if (!loc_src)
|
||||
return NULL; /* can happen, e.g. we are reading too early */
|
||||
|
||||
if (tail == NULL)
|
||||
@@ -812,7 +915,7 @@ static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_fra
|
||||
/* Scale the video for the encoder, then use it for local rendering
|
||||
* so we will see the same as the remote party.
|
||||
*/
|
||||
my_scale(&v->loc_src, NULL, &env->enc_in, NULL);
|
||||
my_scale(loc_src, NULL, &env->enc_in, NULL);
|
||||
show_frame(env, WIN_LOCAL);
|
||||
if (!v->sendvideo)
|
||||
return NULL;
|
||||
@@ -855,19 +958,23 @@ static void *video_thread(void *arg)
|
||||
setenv("DISPLAY", save_display, 1);
|
||||
|
||||
/* initialize grab coordinates */
|
||||
env->out.loc_src.x = 0;
|
||||
env->out.loc_src.y = 0;
|
||||
env->out.loc_src_geometry.x = 0;
|
||||
env->out.loc_src_geometry.y = 0;
|
||||
|
||||
ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
|
||||
|
||||
if (video_open(&env->out)) {
|
||||
if (grabber_open(&env->out)) {
|
||||
ast_log(LOG_WARNING, "cannot open local video source\n");
|
||||
} else {
|
||||
/* try to register the fd. Unfortunately, if the webcam
|
||||
* driver does not support select/poll we are out of luck.
|
||||
#if 0
|
||||
/* In principle, try to register the fd.
|
||||
* In practice, many webcam drivers do not support select/poll,
|
||||
* so don't bother and instead read periodically from the
|
||||
* video thread.
|
||||
*/
|
||||
if (env->out.fd >= 0)
|
||||
ast_channel_set_fd(env->owner, 1, env->out.fd);
|
||||
#endif
|
||||
video_out_init(env);
|
||||
}
|
||||
|
||||
@@ -925,11 +1032,11 @@ static void *video_thread(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (env->shutdown)
|
||||
break;
|
||||
f = get_video_frames(env, &p); /* read and display */
|
||||
if (!f)
|
||||
continue;
|
||||
if (env->shutdown)
|
||||
break;
|
||||
chan = env->owner;
|
||||
ast_channel_lock(chan);
|
||||
|
||||
@@ -980,7 +1087,7 @@ static void copy_geometry(struct fbuf_t *src, struct fbuf_t *dst)
|
||||
*/
|
||||
static void init_env(struct video_desc *env)
|
||||
{
|
||||
struct fbuf_t *c = &(env->out.loc_src); /* local source */
|
||||
struct fbuf_t *c = &(env->out.loc_src_geometry); /* local source */
|
||||
struct fbuf_t *ei = &(env->enc_in); /* encoder input */
|
||||
struct fbuf_t *ld = &(env->loc_dpy); /* local display */
|
||||
struct fbuf_t *rd = &(env->rem_dpy); /* remote display */
|
||||
@@ -1110,7 +1217,7 @@ int console_video_cli(struct video_desc *env, const char *var, int fd)
|
||||
}
|
||||
ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
|
||||
env->enc_in.w, env->enc_in.h,
|
||||
env->out.loc_src.w, env->out.loc_src.h,
|
||||
env->out.loc_src_geometry.w, env->out.loc_src_geometry.h,
|
||||
env->loc_dpy.w, env->loc_dpy.h,
|
||||
env->rem_dpy.w, env->rem_dpy.h,
|
||||
in_w, in_h);
|
||||
@@ -1156,7 +1263,7 @@ int console_video_config(struct video_desc **penv,
|
||||
CV_STR("videodevice", env->out.videodevice);
|
||||
CV_BOOL("sendvideo", env->out.sendvideo);
|
||||
CV_F("video_size", video_geom(&env->enc_in, val));
|
||||
CV_F("camera_size", video_geom(&env->out.loc_src, val));
|
||||
CV_F("camera_size", video_geom(&env->out.loc_src_geometry, val));
|
||||
CV_F("local_size", video_geom(&env->loc_dpy, val));
|
||||
CV_F("remote_size", video_geom(&env->rem_dpy, val));
|
||||
CV_STR("keypad", env->keypad_file);
|
||||
|
Reference in New Issue
Block a user