[asterisk-commits] rizzo: branch rizzo/video_v2 r83636 - /team/rizzo/video_v2/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Sep 24 03:30:21 CDT 2007
Author: rizzo
Date: Mon Sep 24 03:30:20 2007
New Revision: 83636
URL: http://svn.digium.com/view/asterisk?view=rev&rev=83636
Log:
update latest code from Sergio Fadda, which brings the processing
of local video source in the video thread.
Still one problem to debug with ast_queue_frame.
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=83636&r1=83635&r2=83636
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Mon Sep 24 03:30:20 2007
@@ -127,7 +127,7 @@
AVCodecContext *context; /* encoding context */
AVCodec *codec;
AVFrame *frame;
- int lasttxframe; /* XXX - useless: RTP overwrite seqno */
+ int lasttxframe; /* XXX useless: RTP overwrite seqno */
struct fbuf_t encbuf; /* encoding buffer */
int mtu;
struct timeval last_frame; /* when we read the last frame ? */
@@ -153,9 +153,7 @@
AVCodecParserContext *parser;
int completed; /* probably unnecessary */
uint16_t next_seq; /* must be 16 bit */
- int discard;
- struct timeval ts;
- int received;
+ int discard; /* flag for discard status */
struct fbuf_t buf; /* decoded frame */
};
@@ -164,25 +162,23 @@
* received data descriptors, SDL info, etc.
*/
struct video_desc {
- int w;
+ int w; /* geometry */
int h;
- int fps;
+ int fps; /* framerate */
int bitrate;
char videodevice[64];
- ast_mutex_t lock;
-
- pthread_t vthread;
- int shutdown; /* set to ask the thread to shutdown */
+ pthread_t vthread; /* video thread */
+ int shutdown; /* set to ask the thread to shutdown */
struct ast_channel *owner; /* owner channel */
- struct video_in_desc in;
- struct video_out_desc out;
+ struct video_in_desc in; /* remote video descriptor */
+ struct video_out_desc out; /* local video descriptor */
SDL_Surface *screen;
int sdl_ok;
+ ast_mutex_t sdl_lock;
SDL_Overlay *bmp[2];
-
};
/*
@@ -244,7 +240,7 @@
ast_log(LOG_WARNING, "error creating Ximage\n");
goto error;
}
- ast_log(LOG_WARNING, "image: data %p %d bpp, mask 0x%lx 0x%lx 0x%lx\n",
+ ast_log(LOG_NOTICE, "image: data %p %d bpp, mask 0x%lx 0x%lx 0x%lx\n",
im->data,
im->bits_per_pixel,
im->red_mask, im->green_mask, im->blue_mask);
@@ -253,6 +249,7 @@
}
#if defined(HAVE_V4L) && HAVE_V4L > 0
else {
+ /* V4L specific */
struct video_window vw = { 0 }; /* camera attributes */
struct video_picture vp;
@@ -335,7 +332,7 @@
return 0; /* too early */
v->last_frame = now; /* XXX actually, should correct for drift */
- if (v->image) { // X11 grabber
+ if (v->image) {
/* read frame from X11 */
XGetSubImage(v->dpy,
RootWindow(v->dpy, DefaultScreen(v->dpy)),
@@ -368,9 +365,8 @@
int r, l = v->buf.size - v->buf.used;
r = read(v->fd, v->buf.data + v->buf.used, l);
// ast_log(LOG_WARNING, "read %d of %d bytes from webcam\n", r, l);
- if (r < 0) { /* read error */
+ if (r < 0) /* read error */
return 0;
- }
if (r == 0) /* no data */
return 0;
v->buf.used += r;
@@ -403,6 +399,7 @@
return CODEC_ID_NONE;
}
+/*! \brief uninitialize the descriptor for remote video stream */
static int video_in_uninit(struct video_in_desc *v)
{
if (v->context) {
@@ -432,7 +429,6 @@
v->completed = 0;
v->discard = 1;
- v->ts = ast_tvnow();
codec = map_video_format(format, CM_RD);
v->codec = avcodec_find_decoder(codec);
@@ -466,6 +462,7 @@
return 0; /* ok */
}
+/*! \brief uninitialize the descriptor for local video stream */
static int video_out_uninit(struct video_out_desc *v)
{
if (v->context) {
@@ -492,12 +489,10 @@
}
/*
- * Initialize the encoder for the local source.
- * - AVCodecContext
- * - AVCodec
- * - AVFrame
- * - encbuf
- * - mtu
+ * Initialize the encoder for the local source:
+ * - AVCodecContext, AVCodec, AVFrame are used by ffmpeg for encoding;
+ * - encbuf is used to store the encoded frame (to be sent)
+ * - mtu is used to determine the max size of video fragment
*/
static int video_out_init(struct video_out_desc *v, uint32_t format)
{
@@ -574,23 +569,34 @@
return 0;
}
-/*
- * Freeing all memory used and uninitialize
- * the ffmpeg and SDL environments.
- */
+/*! \brief uninitialize the entire environment. */
static void console_video_uninit(struct video_desc *env)
{
env->shutdown = 1;
+ /*
+ * XXX the locking here must be revised.
+ * When asterisk calls shutdown, the channel is locked; however
+ * the video thread might also need to acquire the lock on the channel
+ * to enqueue the frames. So, we unlock the channel here to give
+ * vthread a chance to exit the critical section and terminate.
+ */
+ ast_channel_unlock(env->owner);
+ /* wait for video thread to finish */
pthread_join(env->vthread, NULL);
- ast_log(LOG_WARNING, "thread terminated\n");
+ ast_channel_lock(env->owner);
+
+ /* uninitialize the local and remote video environments */
video_in_uninit(&env->in);
video_out_uninit(&env->out);
+
+ /* uninitialize the SDL environment */
if (env->sdl_ok) {
if (env->bmp[0])
SDL_FreeYUVOverlay(env->bmp[0]);
if (env->bmp[1])
SDL_FreeYUVOverlay(env->bmp[1]);
SDL_Quit();
+ ast_mutex_destroy(&(env->sdl_lock));
}
{ /* clear the struct but restore some fields */
struct video_desc x = *env; /* make a copy */
@@ -602,7 +608,6 @@
env->fps = x.fps;
env->bitrate = x.bitrate;
}
- ast_mutex_destroy(&env->lock);
}
#define MAKE_MASK(bits) ( (1<<(bits)) -1 )
@@ -676,9 +681,10 @@
}
/*
- * It decodes a valid H.263 frame.
- * The av_parser_parse should merge a randomly choped up stream into proper frames.
- * After that, if we have a valid frame, we decode it until the entire frame is processed.
+ * Decode a valid H.263 frame.
+ * av_parser_parse should merge a randomly chopped up stream into
+ * proper frames. After that, if we have a valid frame, we decode it
+ * until the entire frame is processed.
*/
static int decode_video(struct video_in_desc *v)
{
@@ -700,16 +706,15 @@
src += ret;
srclen -= ret;
}
- // ast_log(LOG_WARNING, "in %d ret %d/%d outlen %d complete %d\n", v->buf.used, srclen, ret, datalen, v->completed);
}
return 1;
}
/*
- * Display the decoded video frame using the SDL library.
+ * Display video frames (from local or remote stream) using the SDL library.
* - Set the video mode to use the resolution specified by the codec context
- * - Create a YUV Overlay to copy into it the decoded frame
- * - After the decoded frame is copied into the overlay, we display it
+ * - Create a YUV Overlay to copy the frame into it;
+ * - After the frame is copied into the overlay, display it
*
* The size is taken from the configuration.
*
@@ -791,7 +796,10 @@
rect.w = w;
rect.h = h;
+ /* lock to protect access to Xlib by different threads. */
+ ast_mutex_lock(&env->sdl_lock);
SDL_DisplayYUVOverlay(bmp, &rect);
+ ast_mutex_unlock(&env->sdl_lock);
SDL_UnlockYUVOverlay(bmp);
}
@@ -819,7 +827,6 @@
return 0; /* error */
}
- v->received++;
#if defined(DROP_PACKETS) && DROP_PACKETS > 0
/*
* Fragment of code to simulate lost/delayed packets
@@ -865,7 +872,6 @@
return 0;
}
len = f->datalen;
- // ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, f->datalen);
data = pre_process_data(f->data, &len);
if (len < 1 || len > 128*1024) {
ast_log(LOG_WARNING, "--- huge frame %d\n", len);
@@ -873,7 +879,8 @@
return 0;
}
- /* Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE,
+ /*
+ * Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE,
* and also wants 0 as a buffer terminator to prevent trouble.
*/
need = len + FF_INPUT_BUFFER_PADDING_SIZE;
@@ -934,7 +941,6 @@
}
}
if (l > out->mtu || l > len) { /* psc not found, split */
- // ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
l = MIN(len, out->mtu);
}
if (l < 1 || l > out->mtu) {
@@ -993,6 +999,10 @@
return first;
}
+/*! \brief read a frame from webcam or X11 through video_read(),
+ * display it, then encode and split it.
+ * Return a list of ast_frame representing the video fragments.
+ */
static struct ast_frame *get_video_frames(struct video_desc *env)
{
int buflen;
@@ -1029,19 +1039,37 @@
struct video_desc *env = arg;
for (;;i++) {
struct timeval t = { 1, 0 };
- struct ast_frame *f;
+ struct ast_frame *p, *f;
+ struct ast_channel *chan = env->owner;
+ int fd = chan->alertpipe[1];
if (env->shutdown) {
ast_log(LOG_WARNING, "video_thread shutting down%d\n", i);
break;
}
+ /* sleep for a while */
ast_select(0, NULL, NULL, NULL, &t);
- if (0) {
- f = get_video_frames(env);
- ast_channel_lock(env->owner);
- // enqueue on env->owner->readq
- }
- }
+ f = get_video_frames(env);
+ if (!f)
+ continue;
+ chan = env->owner;
+ ast_channel_lock(chan);
+ /*
+ * more or less same as ast_queue_frame, but extra
+ * write on the alertpipe to signal frames.
+ */
+ AST_LIST_INSERT_TAIL(&(chan->readq), f, frame_list);
+ if (fd > -1) {
+ int blah = 1, l = sizeof(blah);
+ for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
+ if (write(fd, &blah, l) != l)
+ ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
+ chan->name, f->frametype, f->subclass, strerror(errno));
+ }
+ }
+ ast_channel_unlock(chan);
+ }
+ /* thread terminating, here could call the uninit */
return NULL;
}
@@ -1067,7 +1095,6 @@
* Register all codecs supported by the ffmpeg library.
* Doing it once is enough.
*/
- ast_mutex_init(&env->lock);
avcodec_init();
avcodec_register_all();
@@ -1099,8 +1126,10 @@
SDL_WM_SetCaption("Asterisk console Video Output", NULL);
env->bmp[0] = SDL_CreateYUVOverlay(env->w, env->h, fmt, env->screen);
env->bmp[1] = SDL_CreateYUVOverlay(env->w, env->h, fmt, env->screen);
- if (env->bmp[0] && env->bmp[1])
+ if (env->bmp[0] && env->bmp[1]) {
+ ast_mutex_init(&env->sdl_lock);
env->sdl_ok = 1;
+ }
/* otherwise should release the screen */
no_sdl:
More information about the asterisk-commits
mailing list