[svn-commits] rizzo: trunk r95262 - /trunk/channels/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Dec 28 16:37:41 CST 2007


Author: rizzo
Date: Fri Dec 28 16:37:40 2007
New Revision: 95262

URL: http://svn.digium.com/view/asterisk?view=rev&rev=95262
Log:
various rearrangements and renaming of console_video stuff


Modified:
    trunk/channels/console_gui.c
    trunk/channels/console_video.c
    trunk/channels/console_video.h
    trunk/channels/vcodecs.c

Modified: trunk/channels/console_gui.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/console_gui.c?view=diff&rev=95262&r1=95261&r2=95262
==============================================================================
--- trunk/channels/console_gui.c (original)
+++ trunk/channels/console_gui.c Fri Dec 28 16:37:40 2007
@@ -96,6 +96,8 @@
 	if ( TTF_WasInit() )
 		TTF_Quit();
 #endif
+	if (gui->outfd > -1)
+		close(gui->outfd);
 	if (gui->keypad)
 		SDL_FreeSurface(gui->keypad);
 	gui->keypad = NULL;
@@ -134,19 +136,22 @@
 		return;
 
 	if (out == WIN_LOCAL) {	/* webcam/x11 to sdl */
-		b_in = &env->out.enc_in;
-		b_out = &env->out.loc_dpy;
+		b_in = &env->enc_in;
+		b_out = &env->loc_dpy;
 		p_in = NULL;
 	} else {
 		/* copy input format from the decoding context */
-		AVCodecContext *c = env->in.dec_ctx;
-		b_in = &env->in.dec_out;
+		AVCodecContext *c;
+		if (env->in == NULL)	/* XXX should not happen - decoder not ready */
+			return;
+		c = env->in->dec_ctx;
+		b_in = &env->in->dec_out;
                 b_in->pix_fmt = c->pix_fmt;
                 b_in->w = c->width;
                 b_in->h = c->height;
 
-		b_out = &env->in.rem_dpy;
-		p_in = (AVPicture *)env->in.d_frame;
+		b_out = &env->rem_dpy;
+		p_in = (AVPicture *)env->in->d_frame;
 	}
 	bmp = gui->win[out].bmp;
 	SDL_LockYUVOverlay(bmp);
@@ -391,16 +396,16 @@
 	gui->text_mode = 0;
 
 	/* define keypad boundary */
-	if (button.x < env->in.rem_dpy.w)
+	if (button.x < env->rem_dpy.w)
 		index = KEY_REM_DPY; /* click on remote video */
-	else if (button.x > env->in.rem_dpy.w + gui->keypad->w)
+	else if (button.x > env->rem_dpy.w + gui->keypad->w)
 		index = KEY_LOC_DPY; /* click on local video */
 	else if (button.y > gui->keypad->h)
 		index = KEY_OUT_OF_KEYPAD; /* click outside the keypad */
 	else if (gui->kp) {
 		int i;
 		for (i = 0; i < gui->kp_used; i++) {
-			if (kp_match_area(&gui->kp[i], button.x - env->in.rem_dpy.w, button.y)) {
+			if (kp_match_area(&gui->kp[i], button.x - env->rem_dpy.w, button.y)) {
 				index = gui->kp[i].c;
 				break;
 			}
@@ -452,7 +457,7 @@
 			break;
 		} else {
 			char buf[128];
-			struct fbuf_t *fb = index == KEY_LOC_DPY ? &env->out.loc_dpy : &env->in.rem_dpy;
+			struct fbuf_t *fb = index == KEY_LOC_DPY ? &env->loc_dpy : &env->rem_dpy;
 			sprintf(buf, "%c%dx%d", button.button == SDL_BUTTON_RIGHT ? '>' : '<',
 				fb->w, fb->h);
 			video_geom(fb, buf);
@@ -619,9 +624,11 @@
 	return temp;
 }
 
+static void keypad_setup(struct gui_info *gui, const char *kp_file);
+
 /* TODO: consistency checks, check for bpp, widht and height */
 /* Init the mask image used to grab the action. */
-static struct gui_info *gui_init(void)
+static struct gui_info *gui_init(const char *keypad_file)
 {
 	struct gui_info *gui = ast_calloc(1, sizeof(*gui));
 
@@ -630,11 +637,15 @@
 	/* initialize keypad status */
 	gui->text_mode = 0;
 	gui->drag_mode = 0;
+	gui->outfd = -1;
 
 	/* initialize keyboard buffer */
 	append_char(gui->inbuf, &gui->inbuf_pos, '\0');
 	append_char(gui->msgbuf, &gui->msgbuf_pos, '\0');
 
+	keypad_setup(gui, keypad_file);
+	if (gui->keypad == NULL)	/* no keypad, we are done */
+		return gui;
 #ifdef HAVE_SDL_TTF
 	/* Initialize SDL_ttf library and load font */
 	if (TTF_Init() == -1) {
@@ -771,22 +782,17 @@
 	if (depth < 16)
 		depth = 16;
 	if (!gui)
-		env->gui = gui = gui_init();
+		env->gui = gui = gui_init(env->keypad_file);
 	if (!gui)
 		goto no_sdl;
 
-	keypad_setup(gui, env->keypad_file);
-#if 0
-	ast_log(LOG_WARNING, "keypad_setup returned %p %d\n",
-		gui->keypad, gui->kp_used);
-#endif
 	if (gui->keypad) {
 		kp_w = gui->keypad->w;
 		kp_h = gui->keypad->h;
 	}
 #define BORDER	5	/* border around our windows */
-	maxw = env->in.rem_dpy.w + env->out.loc_dpy.w + kp_w;
-	maxh = MAX( MAX(env->in.rem_dpy.h, env->out.loc_dpy.h), kp_h);
+	maxw = env->rem_dpy.w + env->loc_dpy.w + kp_w;
+	maxh = MAX( MAX(env->rem_dpy.h, env->loc_dpy.h), kp_h);
 	maxw += 4 * BORDER;
 	maxh += 2 * BORDER;
 	gui->screen = SDL_SetVideoMode(maxw, maxh, depth, 0);
@@ -797,11 +803,11 @@
 
 	SDL_WM_SetCaption("Asterisk console Video Output", NULL);
 	if (set_win(gui->screen, &gui->win[WIN_REMOTE], dpy_fmt,
-			env->in.rem_dpy.w, env->in.rem_dpy.h, BORDER, BORDER))
+			env->rem_dpy.w, env->rem_dpy.h, BORDER, BORDER))
 		goto no_sdl;
 	if (set_win(gui->screen, &gui->win[WIN_LOCAL], dpy_fmt,
-			env->out.loc_dpy.w, env->out.loc_dpy.h,
-			3*BORDER+env->in.rem_dpy.w + kp_w, BORDER))
+			env->loc_dpy.w, env->loc_dpy.h,
+			3*BORDER+env->rem_dpy.w + kp_w, BORDER))
 		goto no_sdl;
 
 	/* display the skin, but do not free it as we need it later to
@@ -809,7 +815,7 @@
 	 */
 	if (gui->keypad) {
 		struct SDL_Rect *dest = &gui->win[WIN_KEYPAD].rect;
-		dest->x = 2*BORDER + env->in.rem_dpy.w;
+		dest->x = 2*BORDER + env->rem_dpy.w;
 		dest->y = BORDER;
 		dest->w = gui->keypad->w;
 		dest->h = gui->keypad->h;

Modified: trunk/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/console_video.c?view=diff&rev=95262&r1=95261&r2=95262
==============================================================================
--- trunk/channels/console_video.c (original)
+++ trunk/channels/console_video.c Fri Dec 28 16:37:40 2007
@@ -127,24 +127,6 @@
 	AST_FORMAT_MP4_VIDEO | AST_FORMAT_H264 | AST_FORMAT_H261 ;
 
 
-/*
- * In many places we use buffers to store the raw frames (but not only),
- * so here is a structure to keep all the info. data = NULL means the
- * structure is not initialized, so the other fields are invalid.
- * size = 0 means the buffer is not malloc'ed so we don't have to free it.
- */
-struct fbuf_t {		/* frame buffers, dynamically allocated */
-	uint8_t	*data;	/* memory, malloced if size > 0, just reference
-			 * otherwise */
-	int	size;	/* total size in bytes */
-	int	used;	/* space used so far */
-	int	ebit;	/* bits to ignore at the end */
-	int	x;	/* origin, if necessary */
-	int	y;
-	int	w;	/* size */ 
-	int	h;
-	int	pix_fmt;
-};
 
 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
 	struct fbuf_t *out, AVPicture *p_out);
@@ -177,9 +159,7 @@
 	int sendvideo;
 
 	struct fbuf_t	loc_src;	/* local source buffer, allocated in video_open() */
-	struct fbuf_t	enc_in;		/* encoder input buffer, allocated in video_out_init() */
 	struct fbuf_t	enc_out;	/* encoder output buffer, allocated in video_out_init() */
-	struct fbuf_t	loc_dpy;	/* display source buffer, no buffer (managed by SDL in bmp[1]) */
 
 	struct video_codec_desc *enc;	/* encoder */
 	void		*enc_ctx;	/* encoding context */
@@ -200,59 +180,35 @@
 };
 
 /*
- * Descriptor for the incoming stream, with a buffer for the bitstream
- * extracted by the RTP packets, RTP reassembly info, and a frame buffer
- * for the decoded frame (buf).
- * 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. These buffers are organized in a circular
- * queue, with dec_in_cur being the buffer in use by the incoming stream,
- * and dec_in_dpy is the one being displayed. When the pointers need to
- * be changed, we synchronize the access to them with dec_in_lock.
- * When the list is full dec_in_cur = NULL (we cannot store new data),
- * when the list is empty dec_in_dpy is NULL (we cannot display frames).
- */
-struct video_in_desc {
-	struct video_codec_desc *dec;	/* decoder */
-	AVCodecContext          *dec_ctx;	/* information about the codec in the stream */
-	AVCodec                 *codec;		/* reference to the codec */
-	AVFrame                 *d_frame;	/* place to store the decoded frame */
-	AVCodecParserContext    *parser;
-	uint16_t 		next_seq;	/* must be 16 bit */
-	int                     discard;	/* flag for discard status */
-#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 (it is in win[WIN_REMOTE].bmp) */
-};
-
-
-/*
  * The overall descriptor, with room for config info, video source and
  * received data descriptors, SDL info, etc.
+ * This should be globally visible to all modules (grabber, vcodecs, gui)
+ * and contain all configurtion info.
  */
 struct video_desc {
 	char			codec_name[64];	/* the codec we use */
 
 	pthread_t		vthread;	/* video thread */
+	ast_mutex_t		dec_lock;	/* sync decoder and video thread */
 	int			shutdown;	/* set to shutdown vthread */
 	struct ast_channel	*owner;		/* owner channel */
 
-	struct video_in_desc	in;		/* remote video descriptor */
-	struct video_out_desc	out;		/* local video descriptor */
-
-	struct gui_info		*gui;
+
+	struct fbuf_t	enc_in;		/* encoder input buffer, allocated in video_out_init() */
 
 	char			keypad_file[256];	/* image for the keypad */
 	char                    keypad_font[256];       /* font for the keypad */
 
 	char			sdl_videodriver[256];
+
+	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]) */
+
+
+	/* local information for grabbers, codecs, gui */
+	struct gui_info		*gui;
+	struct video_dec_desc	*in;		/* remote video descriptor */
+	struct video_out_desc	out;		/* local video descriptor */
 };
 
 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
@@ -604,84 +560,12 @@
 	return supported_codecs[i];
 }
 
-/*! \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;
-	}
-	if (v->dec_ctx) {
-		avcodec_close(v->dec_ctx);
-		av_free(v->dec_ctx);
-		v->dec_ctx = NULL;
-	}
-	if (v->d_frame) {
-		av_free(v->d_frame);
-		v->d_frame = NULL;
-	}
-	v->codec = NULL;	/* only a reference */
-	v->dec = NULL;		/* forget the decoder */
-	v->discard = 1;		/* start in discard mode */
-	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 */
-}
-
-/*
- * initialize ffmpeg resources used for decoding frames from the network.
- */
-static int video_in_init(struct video_in_desc *v, uint32_t format)
-{
-	enum CodecID codec;
-
-	/* XXX should check that these are already set */
-	v->codec = NULL;
-	v->dec_ctx = NULL;
-	v->d_frame = NULL;
-	v->parser = NULL;
-	v->discard = 1;
-
-	codec = map_video_format(format, CM_RD);
-
-	v->codec = avcodec_find_decoder(codec);
-	if (!v->codec) {
-		ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec);
-		return video_in_uninit(v);
-	}
-	/*
-	* Initialize the codec context.
-	*/
-	v->dec_ctx = avcodec_alloc_context();
-	/* XXX call dec_init() ? */
-	if (avcodec_open(v->dec_ctx, v->codec) < 0) {
-		ast_log(LOG_WARNING, "Cannot open the codec context\n");
-		av_free(v->dec_ctx);
-		v->dec_ctx = NULL;
-		return video_in_uninit(v);
-	}
-
-	v->parser = av_parser_init(codec);
-	if (!v->parser) {
-		ast_log(LOG_WARNING, "Cannot initialize the decoder parser\n");
-		return video_in_uninit(v);
-	}
-
-	v->d_frame = avcodec_alloc_frame();
-	if (!v->d_frame) {
-		ast_log(LOG_WARNING, "Cannot allocate decoding video frame\n");
-		return video_in_uninit(v);
-	}
-	return 0;	/* ok */
-}
 
 /*! \brief uninitialize the descriptor for local video stream */
-static int video_out_uninit(struct video_out_desc *v)
-{
+static int video_out_uninit(struct video_desc *env)
+{
+	struct video_out_desc *v = &env->out;
+
 	/* XXX this should be a codec callback */
 	if (v->enc_ctx) {
 		AVCodecContext *enc_ctx = (AVCodecContext *)v->enc_ctx;
@@ -696,9 +580,8 @@
 	v->codec = NULL;	/* only a reference */
 	
 	fbuf_free(&v->loc_src);
-	fbuf_free(&v->enc_in);
+	fbuf_free(&env->enc_in);
 	fbuf_free(&v->enc_out);
-	fbuf_free(&v->loc_dpy);
 	if (v->image) {	/* X11 grabber */
 		XCloseDisplay(v->dpy);
 		v->dpy = NULL;
@@ -732,14 +615,14 @@
 
 	if (v->loc_src.data == NULL) {
 		ast_log(LOG_WARNING, "No local source active\n");
-		return video_out_uninit(v);
+		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) {
 		ast_log(LOG_WARNING, "Cannot find the encoder for format %d\n",
 			codec);
-		return video_out_uninit(v);
+		return -1;	/* error, but nothing to undo yet */
 	}
 
 	v->mtu = 1400;	/* set it early so the encoder can use it */
@@ -747,19 +630,19 @@
 	/* allocate the input buffer for encoding.
 	 * ffmpeg only supports PIX_FMT_YUV420P for the encoding.
 	 */
-	enc_in = &v->enc_in;
+	enc_in = &env->enc_in;
 	enc_in->pix_fmt = PIX_FMT_YUV420P;
 	enc_in->size = (enc_in->w * enc_in->h * 3)/2;
 	enc_in->data = ast_calloc(1, enc_in->size);
 	if (!enc_in->data) {
 		ast_log(LOG_WARNING, "Cannot allocate encoder input buffer\n");
-		return video_out_uninit(v);
+		return video_out_uninit(env);
 	}
 	/* construct an AVFrame that points into buf_in */
 	v->enc_in_frame = avcodec_alloc_frame();
 	if (!v->enc_in_frame) {
 		ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
-		return video_out_uninit(v);
+		return video_out_uninit(env);
 	}
 
 	/* parameters for PIX_FMT_YUV420P */
@@ -798,7 +681,7 @@
 			codec);
 		av_free(enc_ctx);
 		v->enc_ctx = NULL;
-		return video_out_uninit(v);
+		return video_out_uninit(env);
 	}
     }
 	/*
@@ -927,26 +810,16 @@
 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
 {
 	struct video_desc *env = get_video_desc(chan);
-	struct video_in_desc *v = &env->in;
+	struct video_dec_desc *v = env->in;
 
 	if (!env->gui)	/* no gui, no rendering */
 		return 0;
-	if (v->dec == NULL) {	/* try to get the codec */
-		v->dec = map_video_codec(f->subclass & ~1);
-		if (v->dec == NULL) {
-			ast_log(LOG_WARNING, "cannot find video codec, drop input 0x%x\n", f->subclass);
-			return 0;
-		}
-		if (video_in_init(v, v->dec->format)) {
-			/* This is not fatal, but we won't have incoming video */
-			ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
-			v->dec = NULL;
-			return 0;
-		}
-	}
-	if (v->dec_ctx == NULL) {
-		ast_log(LOG_WARNING, "cannot decode, dropping frame\n");
-		return 0;	/* error */
+	if (v == NULL)
+		env->in = v = dec_init(f->subclass & ~1);
+	if (v == NULL) {
+		/* This is not fatal, but we won't have incoming video */
+		ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
+		return 0;
 	}
 
 	if (v->dec_in_cur == NULL)	/* no buffer for incoming frames, drop */
@@ -993,14 +866,14 @@
 		ast_log(LOG_WARNING, "empty video frame, discard\n");
 		return 0;
 	}
-	if (v->dec->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
+	if (v->d_callbacks->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
 		/* 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);
+		ast_mutex_lock(&env->dec_lock);
 		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 */
@@ -1008,7 +881,7 @@
 		} 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);
+		ast_mutex_unlock(&env->dec_lock);
 	}
 	return 0;
 }
@@ -1040,7 +913,7 @@
 	/* 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, &v->enc_in, NULL);
+	my_scale(&v->loc_src, NULL, &env->enc_in, NULL);
 	show_frame(env, WIN_LOCAL);
 	if (!v->sendvideo)
 		return NULL;
@@ -1086,10 +959,7 @@
         env->out.loc_src.x = 0;
         env->out.loc_src.y = 0;
 
-	/* reset the pointers to the current decoded image */
-	env->in.dec_in_cur = &env->in.dec_in[0];
-	env->in.dec_in_dpy = NULL;	/* nothing to display */
-	ast_mutex_init(&env->in.dec_in_lock);	/* used to sync decoder and renderer */
+	ast_mutex_init(&env->dec_lock);	/* used to sync decoder and renderer */
 
 	if (video_open(&env->out)) {
 		ast_log(LOG_WARNING, "cannot open local video source\n");
@@ -1105,7 +975,6 @@
 	for (;;) {
 		struct timeval t = { 0, 50000 };	/* XXX 20 times/sec */
 		struct ast_frame *p, *f;
-		struct video_in_desc *v = &env->in;
 		struct ast_channel *chan = env->owner;
 		int fd = chan->alertpipe[1];
 		char *caption = NULL, buf[160];
@@ -1115,7 +984,7 @@
 			if (env->out.sendvideo)
 			    sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
 				env->out.videodevice, env->codec_name,
-				env->out.enc_in.w, env->out.enc_in.h,
+				env->enc_in.w, env->enc_in.h,
 				env->out.fps, env->out.bitrate/1000);
 			else
 			    sprintf(buf, "hold");
@@ -1131,6 +1000,9 @@
 		/* sleep for a while */
 		ast_select(0, NULL, NULL, NULL, &t);
 
+	    if (env->in) {
+		struct video_dec_desc *v = env->in;
+		
 		/*
 		 * While there is something to display, call the decoder and free
 		 * the buffer, possibly enabling the receiver to store new data.
@@ -1138,11 +1010,11 @@
 		while (v->dec_in_dpy) {
 			struct fbuf_t *tmp = v->dec_in_dpy;	/* store current pointer */
 
-			if (v->dec->dec_run(v, tmp))
+			if (v->d_callbacks->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);
+			ast_mutex_lock(&env->dec_lock);
 			if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN])	/* advance to next, circular */
 				v->dec_in_dpy = &v->dec_in[0];
 
@@ -1150,9 +1022,9 @@
 				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);
+			ast_mutex_unlock(&env->dec_lock);
 		}
-
+	    }
 
 		f = get_video_frames(env, &p);	/* read and display */
 		if (!f)
@@ -1185,12 +1057,12 @@
 	}
 	/* thread terminating, here could call the uninit */
 	/* uninitialize the local and remote video environments */
-	video_in_uninit(&env->in);
-	video_out_uninit(&env->out);
+	env->in = dec_uninit(env->in);
+	video_out_uninit(env);
 
 	if (env->gui)
 		env->gui = cleanup_sdl(env->gui);
-	ast_mutex_destroy(&(env->in.dec_in_lock));
+	ast_mutex_destroy(&env->dec_lock);
 	env->shutdown = 0;
 	return NULL;
 }
@@ -1210,9 +1082,9 @@
 static void init_env(struct video_desc *env)
 {
 	struct fbuf_t *c = &(env->out.loc_src);		/* local source */
-	struct fbuf_t *ei = &(env->out.enc_in);		/* encoder input */
-	struct fbuf_t *ld = &(env->out.loc_dpy);	/* local display */
-	struct fbuf_t *rd = &(env->in.rem_dpy);		/* remote display */
+	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 */
 
 	c->pix_fmt = PIX_FMT_YUV420P;	/* default - camera format */
 	ei->pix_fmt = PIX_FMT_YUV420P;	/* encoder input */
@@ -1245,7 +1117,7 @@
 	env->out.enc = map_config_video_format(env->codec_name);
 
 	ast_log(LOG_WARNING, "start video out %s %dx%d\n",
-		env->codec_name, env->out.enc_in.w,  env->out.enc_in.h);
+		env->codec_name, env->enc_in.w,  env->enc_in.h);
 	/*
 	 * Register all codecs supported by the ffmpeg library.
 	 * We only need to do it once, but probably doesn't
@@ -1329,12 +1201,17 @@
         } else if (!strcasecmp(var, "sendvideo")) {
 		ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
         } else if (!strcasecmp(var, "video_size")) {
+		int in_w = 0, in_h = 0;
+		if (env->in) {
+			in_w = env->in->dec_out.w;
+			in_h = env->in->dec_out.h;
+		}
 		ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
-			env->out.enc_in.w, env->out.enc_in.h,
+			env->enc_in.w, env->enc_in.h,
 			env->out.loc_src.w, env->out.loc_src.h,
-			env->out.loc_dpy.w, env->out.loc_dpy.h,
-			env->in.rem_dpy.w, env->in.rem_dpy.h,
-			env->in.dec_out.w, env->in.dec_out.h);
+			env->loc_dpy.w, env->loc_dpy.h,
+			env->rem_dpy.w, env->rem_dpy.h,
+			in_w, in_h);
         } else if (!strcasecmp(var, "bitrate")) {
 		ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
         } else if (!strcasecmp(var, "qmin")) {
@@ -1376,10 +1253,10 @@
 	CV_START(var, val);
 	CV_STR("videodevice", env->out.videodevice);
 	CV_BOOL("sendvideo", env->out.sendvideo);
-	CV_F("video_size", video_geom(&env->out.enc_in, val));
+	CV_F("video_size", video_geom(&env->enc_in, val));
 	CV_F("camera_size", video_geom(&env->out.loc_src, val));
-	CV_F("local_size", video_geom(&env->out.loc_dpy, val));
-	CV_F("remote_size", video_geom(&env->in.rem_dpy, 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);
 	CV_F("region", keypad_cfg_read(env->gui, val));
 	CV_STR("keypad_font", env->keypad_font);

Modified: trunk/channels/console_video.h
URL: http://svn.digium.com/view/asterisk/trunk/channels/console_video.h?view=diff&rev=95262&r1=95261&r2=95262
==============================================================================
--- trunk/channels/console_video.h (original)
+++ trunk/channels/console_video.h Fri Dec 28 16:37:40 2007
@@ -47,6 +47,25 @@
 
 #endif	/* HAVE_VIDEO_CONSOLE and others */
 
+/*
+ * In many places we use buffers to store the raw frames (but not only),
+ * so here is a structure to keep all the info. data = NULL means the
+ * structure is not initialized, so the other fields are invalid.
+ * size = 0 means the buffer is not malloc'ed so we don't have to free it.
+ */
+struct fbuf_t {		/* frame buffers, dynamically allocated */
+	uint8_t	*data;	/* memory, malloced if size > 0, just reference
+			 * otherwise */
+	int	size;	/* total size in bytes */
+	int	used;	/* space used so far */
+	int	ebit;	/* bits to ignore at the end */
+	int	x;	/* origin, if necessary */
+	int	y;
+	int	w;	/* size */ 
+	int	h;
+	int	pix_fmt;
+};
+
 struct video_desc;		/* opaque type for video support */
 struct video_desc *get_video_desc(struct ast_channel *c);
 

Modified: trunk/channels/vcodecs.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/vcodecs.c?view=diff&rev=95262&r1=95261&r2=95262
==============================================================================
--- trunk/channels/vcodecs.c (original)
+++ trunk/channels/vcodecs.c Fri Dec 28 16:37:40 2007
@@ -8,7 +8,7 @@
 #include "asterisk/frame.h"
 
 struct video_out_desc;
-struct video_in_desc;
+struct video_dec_desc;
 struct fbuf_t;
 
 /*
@@ -34,7 +34,7 @@
 typedef int (*decoder_decap_f)(struct fbuf_t *b, uint8_t *data, int len);
 
 /*! \brief actually call the decoder */
-typedef int (*decoder_decode_f)(struct video_in_desc *v, struct fbuf_t *b);
+typedef int (*decoder_decode_f)(struct video_dec_desc *v, struct fbuf_t *b);
 
 struct video_codec_desc {
 	const char		*name;		/* format name */
@@ -45,6 +45,35 @@
 	decoder_init_f		dec_init;
 	decoder_decap_f		dec_decap;
 	decoder_decode_f	dec_run;
+};
+
+/*
+ * Descriptor for the incoming stream, with multiple buffers for the bitstream
+ * extracted from the RTP packets, RTP reassembly info, and a frame buffer
+ * for the decoded frame (buf).
+ * The descriptor is allocated as the first frame comes in.
+ *
+ * Incoming payload is stored in one of the dec_in[] buffers, which are
+ * emptied by the video thread. These buffers are organized in a circular
+ * queue, with dec_in_cur being the buffer in use by the incoming stream,
+ * and dec_in_dpy is the one being displayed. When the pointers need to
+ * be changed, we synchronize the access to them with dec_lock.
+ * When the list is full dec_in_cur = NULL (we cannot store new data),
+ * when the list is empty dec_in_dpy = NULL (we cannot display frames).
+ */
+struct video_dec_desc {
+	struct video_codec_desc *d_callbacks;	/* decoder callbacks */
+	AVCodecContext          *dec_ctx;	/* information about the codec in the stream */
+	AVCodec                 *codec;		/* reference to the codec */
+	AVFrame                 *d_frame;	/* place to store the decoded frame */
+	AVCodecParserContext    *parser;
+	uint16_t 		next_seq;	/* must be 16 bit */
+	int                     discard;	/* flag for discard status */
+#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 */
+	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) */
 };
 
 #ifdef debugging_only
@@ -170,6 +199,8 @@
 		ast_log(LOG_WARNING, "%s\n", buf);
 }
 #endif /* debugging_only */
+
+
 /*
  * Here starts the glue code for the various supported video codecs.
  * For each of them, we need to provide routines for initialization,
@@ -327,7 +358,7 @@
  * proper frames. After that, if we have a valid frame, we decode it
  * until the entire frame is processed.
  */
-static int ffmpeg_decode(struct video_in_desc *v, struct fbuf_t *b)
+static int ffmpeg_decode(struct video_dec_desc *v, struct fbuf_t *b)
 {
 	uint8_t *src = b->data;
 	int srclen = b->used;
@@ -743,7 +774,7 @@
 	return fbuf_append(b, data, len, 0, 0);
 }
 
-static int mpeg4_decode(struct video_in_desc *v, struct fbuf_t *b)
+static int mpeg4_decode(struct video_dec_desc *v, struct fbuf_t *b)
 {
 	int full_frame = 0, datalen = b->used;
 	int ret = avcodec_decode_video(v->dec_ctx, v->d_frame, &full_frame,
@@ -1015,4 +1046,89 @@
 	return NULL;
 }
 
+/*! \brief uninitialize the descriptor for remote video stream */
+static struct video_dec_desc *dec_uninit(struct video_dec_desc *v)
+{
+	int i;
+
+	if (v->parser) {
+		av_parser_close(v->parser);
+		v->parser = NULL;
+	}
+	if (v->dec_ctx) {
+		avcodec_close(v->dec_ctx);
+		av_free(v->dec_ctx);
+		v->dec_ctx = NULL;
+	}
+	if (v->d_frame) {
+		av_free(v->d_frame);
+		v->d_frame = NULL;
+	}
+	v->codec = NULL;	/* only a reference */
+	v->d_callbacks = NULL;		/* forget the decoder */
+	v->discard = 1;		/* start in discard mode */
+	for (i = 0; i < N_DEC_IN; i++)
+		fbuf_free(&v->dec_in[i]);
+	fbuf_free(&v->dec_out);
+	ast_free(v);
+	return NULL;	/* error, in case someone cares */
+}
+
+/*
+ * initialize ffmpeg resources used for decoding frames from the network.
+ */
+static struct video_dec_desc *dec_init(uint32_t the_ast_format)
+{
+	enum CodecID codec;
+	struct video_dec_desc *v = ast_calloc(1, sizeof(*v));
+	if (v == NULL)
+		return NULL;
+
+	v->discard = 1;
+
+	v->d_callbacks = map_video_codec(the_ast_format);
+	if (v->d_callbacks == NULL) {
+		ast_log(LOG_WARNING, "cannot find video codec, drop input 0x%x\n", the_ast_format);
+		return dec_uninit(v);
+	}
+
+	codec = map_video_format(v->d_callbacks->format, CM_RD);
+
+	v->codec = avcodec_find_decoder(codec);
+	if (!v->codec) {
+		ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec);
+		return dec_uninit(v);
+	}
+	/*
+	 * Initialize the codec context.
+	 */
+	v->dec_ctx = avcodec_alloc_context();
+	if (!v->dec_ctx) {
+		ast_log(LOG_WARNING, "Cannot allocate the decoder context\n");
+		return dec_uninit(v);
+	}
+	/* XXX call dec_init() ? */
+	if (avcodec_open(v->dec_ctx, v->codec) < 0) {
+		ast_log(LOG_WARNING, "Cannot open the decoder context\n");
+		av_free(v->dec_ctx);
+		v->dec_ctx = NULL;
+		return dec_uninit(v);
+	}
+
+	v->parser = av_parser_init(codec);
+	if (!v->parser) {
+		ast_log(LOG_WARNING, "Cannot initialize the decoder parser\n");
+		return dec_uninit(v);
+	}
+
+	v->d_frame = avcodec_alloc_frame();
+	if (!v->d_frame) {
+		ast_log(LOG_WARNING, "Cannot allocate decoding video frame\n");
+		return dec_uninit(v);
+	}
+        v->dec_in_cur = &v->dec_in[0];	/* buffer for incoming frames */
+        v->dec_in_dpy = NULL;      /* nothing to display */
+
+	return v;	/* ok */
+}
 /*------ end codec specific code -----*/




More information about the svn-commits mailing list