[asterisk-commits] rizzo: branch rizzo/video_v2 r89187 - /team/rizzo/video_v2/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Nov 12 12:52:34 CST 2007
Author: rizzo
Date: Mon Nov 12 12:52:33 2007
New Revision: 89187
URL: http://svn.digium.com/view/asterisk?view=rev&rev=89187
Log:
use multiple buffers to store incoming video frames
so we can do the decoding in the video thread and solve
a lot of problems, including not blocking the incoming thread
for a long time, and not having to synchronize on X11 updates.
Modified:
team/rizzo/video_v2/channels/console_video.c
Modified: team/rizzo/video_v2/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/console_video.c?view=diff&rev=89187&r1=89186&r2=89187
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Mon Nov 12 12:52:33 2007
@@ -225,6 +225,11 @@
* and store the result in a suitable frame buffer for later display.
* NOTE: dec_ctx == NULL means the rest is invalid (e.g. because no
* codec, no memory, etc.) and we must drop all incoming frames.
+ *
+ * Incoming payload is stored in one of the dec_in[] buffers, which are
+ * emptied by the video thread. dec_in_cur is the buffer in use by the
+ * incoming frame, dec_in_dpy is the one being displayed.
+ * We synchronize on dec_in_lock;
*/
struct video_in_desc {
struct video_codec_desc *dec; /* decoder */
@@ -234,7 +239,11 @@
AVCodecParserContext *parser;
uint16_t next_seq; /* must be 16 bit */
int discard; /* flag for discard status */
- struct fbuf_t dec_in; /* incoming bitstream, allocated/extended in fbuf_append() */
+#define N_DEC_IN 3 /* number of incoming buffers */
+ struct fbuf_t *dec_in_cur; /* buffer being filled in */
+ struct fbuf_t *dec_in_dpy; /* buffer to display */
+ ast_mutex_t dec_in_lock;
+ struct fbuf_t dec_in[N_DEC_IN]; /* incoming bitstream, allocated/extended in fbuf_append() */
struct fbuf_t dec_out; /* decoded frame, no buffer (data is in AVFrame) */
struct fbuf_t rem_dpy; /* display remote image, no buffer (managed by SDL in bmp[0]) */
};
@@ -300,7 +309,6 @@
struct video_out_desc out; /* local video descriptor */
int sdl_ok;
- ast_mutex_t sdl_lock;
SDL_Surface *screen;
struct display_window win[WIN_MAX];
};
@@ -1623,6 +1631,8 @@
/*! \brief uninitialize the descriptor for remote video stream */
static int video_in_uninit(struct video_in_desc *v)
{
+ int i;
+
if (v->parser) {
av_parser_close(v->parser);
v->parser = NULL;
@@ -1639,7 +1649,8 @@
v->codec = NULL; /* only a reference */
v->dec = NULL; /* forget the decoder */
v->discard = 1; /* start in discard mode */
- fbuf_free(&v->dec_in);
+ for (i = 0; i < N_DEC_IN; i++)
+ fbuf_free(&v->dec_in[i]);
fbuf_free(&v->dec_out);
fbuf_free(&v->rem_dpy);
return -1; /* error, in case someone cares */
@@ -1828,7 +1839,7 @@
env->screen = NULL; /* XXX check reference */
bzero(env->win, sizeof(env->win));
if (env->sdl_ok)
- ast_mutex_destroy(&(env->sdl_lock));
+ ast_mutex_destroy(&(env->in.dec_in_lock));
}
/*! \brief uninitialize the entire environment. */
@@ -1985,13 +1996,11 @@
p_out.linesize[2] = bmp->pitches[2];
my_scale(b_in, p_in, b_out, &p_out);
- SDL_UnlockYUVOverlay(bmp);
/* lock to protect access to Xlib by different threads. */
- ast_mutex_lock(&env->sdl_lock);
SDL_UpdateRects(env->screen, 1, &env->win[WIN_KEYPAD].rect);// XXX inefficient
SDL_DisplayYUVOverlay(bmp, &env->win[out].rect);
- ast_mutex_unlock(&env->sdl_lock);
+ SDL_UnlockYUVOverlay(bmp);
}
static struct video_desc *get_video_desc(struct ast_channel *c);
@@ -2029,6 +2038,8 @@
return 0; /* error */
}
+ if (v->dec_in_cur == NULL) /* no buffer for incoming frames, drop */
+ return 0;
#if defined(DROP_PACKETS) && DROP_PACKETS > 0
/* Simulate lost packets */
if ((random() % 10000) <= 100*DROP_PACKETS) {
@@ -2045,8 +2056,8 @@
* normally used for audio so there is no interference.
*/
if (f->subclass & 0x01) {
- v->dec_in.used = 0;
- v->dec_in.ebit = 0;
+ v->dec_in_cur->used = 0;
+ v->dec_in_cur->ebit = 0;
v->next_seq = f->seqno + 1; /* wrap at 16 bit */
v->discard = 0;
ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
@@ -2071,13 +2082,23 @@
ast_log(LOG_WARNING, "empty video frame, discard\n");
return 0;
}
- if (v->dec->dec_decap(&v->dec_in, f->data, f->datalen)) {
+ if (v->dec->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
ast_log(LOG_WARNING, "error in dec_decap, enter discard\n");
v->discard = 1;
}
if (f->subclass & 0x01) { // RTP Marker
- if (v->dec->dec_run(v, &v->dec_in))
- show_frame(env, WIN_REMOTE);
+ /* prepare to decode: advance the buffer so the video thread knows. */
+ struct fbuf_t *tmp = v->dec_in_cur; /* store current pointer */
+ ast_mutex_lock(&v->dec_in_lock);
+ fprintf(stderr, "using buffer %d\n", v->dec_in_cur - v->dec_in);
+ if (++v->dec_in_cur == &v->dec_in[N_DEC_IN]) /* advance to next, circular */
+ v->dec_in_cur = &v->dec_in[0];
+ if (v->dec_in_dpy == NULL) { /* were not displaying anything, so set it */
+ v->dec_in_dpy = tmp;
+ } else if (v->dec_in_dpy == v->dec_in_cur) { /* current slot is busy */
+ v->dec_in_cur = NULL;
+ }
+ ast_mutex_unlock(&v->dec_in_lock);
}
return 0;
}
@@ -2123,6 +2144,18 @@
return v->enc->enc_encap(v, tail);
}
+static void eventhandler(struct video_desc *env)
+{
+ SDL_Event event;
+ return;
+
+ if (!SDL_PollEvent(&event)) {
+ fprintf(stderr, "-- no event\n");
+ } else {
+ fprintf(stderr, "-- event %d at %d %d\n",
+ event.type, event.button.x, event.button.y);
+ }
+}
/*
* Helper thread to periodically poll the video source and enqueue the
* generated frames to the channel's queue.
@@ -2148,7 +2181,8 @@
/* XXX 20 times/sec */
struct timeval t = { 0, 50000 };
struct ast_frame *p, *f;
-
+ struct video_in_desc *v = &env->in;
+
struct ast_channel *chan = env->owner;
int fd = chan->alertpipe[1];
@@ -2170,8 +2204,32 @@
}
/* sleep for a while */
ast_select(0, NULL, NULL, NULL, &t);
-
- f = get_video_frames(env, &p);
+
+ /*
+ * While there is something to display, call the decoder and free
+ * the buffer, possibly enabling the receiver to store new data.
+ */
+ while (v->dec_in_dpy) {
+ struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */
+
+ if (v->dec->dec_run(v, tmp))
+ show_frame(env, WIN_REMOTE);
+ tmp->used = 0; /* mark buffer as free */
+ tmp->ebit = 0;
+ ast_mutex_lock(&v->dec_in_lock);
+ if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */
+ v->dec_in_dpy = &v->dec_in[0];
+
+ if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */
+ v->dec_in_cur = tmp; /* using the slot just freed */
+ else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
+ v->dec_in_dpy = NULL; /* nothing more to display */
+ ast_mutex_unlock(&v->dec_in_lock);
+ }
+
+ eventhandler(env);
+
+ f = get_video_frames(env, &p); /* read and display */
if (!f)
continue;
chan = env->owner;
@@ -2366,7 +2424,9 @@
goto no_sdl;
#endif
- ast_mutex_init(&env->sdl_lock);
+ ast_mutex_init(&env->in.dec_in_lock);
+ env->in.dec_in_cur = &env->in.dec_in[0];
+ env->in.dec_in_dpy = NULL; /* nothing to display */
env->sdl_ok = 1;
no_sdl:
More information about the asterisk-commits
mailing list