[asterisk-commits] rizzo: branch rizzo/video_v2 r82624 - /team/rizzo/video_v2/channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Sep 17 12:33:17 CDT 2007


Author: rizzo
Date: Mon Sep 17 12:33:17 2007
New Revision: 82624

URL: http://svn.digium.com/view/asterisk?view=rev&rev=82624
Log:
Finally, found out the bug that caused the crash when sending video.

In order to handle H263+,
ffmpeg apparently requires CODEC_ID_H263P for encoding,
but CODEC_ID_H263 for decoding!

To fix this, i have implemented a video formats table that has separate entries
for encoding and decoding.
All the rest is misc cleanup for debugging code that i put in while
trying to figure out what was wrong.

Index: channels/console_video.c
===================================================================
--- channels/console_video.c	(revision 82591)
+++ channels/console_video.c	(working copy)
@@ -112,8 +112,6 @@
 	int		fps;
 	int		bitrate;
 	struct dbuf_t	decbuf;
-	struct timeval	ts;
-	struct timeval	msts;
 	int		mtu;
 
 	struct timeval	last_frame;
@@ -157,14 +155,16 @@
 struct _cm {	/* map ffmpeg codec types to asterisk formats */
 	uint32_t	ast_format;	/* 0 is a terminator */
 	enum CodecID	codec;
+	enum { CM_RD = 1, CM_WR = 2, CM_RDWD = 3 } rw;	/* read or write or both ? */
 };
 
 /*! the list of video formats we support */
 #define CONSOLE_FORMAT_VIDEO	AST_FORMAT_H263_PLUS
 
 static struct _cm video_formats[] = {
-	{ AST_FORMAT_H263_PLUS,	CODEC_ID_H263 }, /* XXX H263P ? */
-	{ 0,			0 },
+	{ AST_FORMAT_H263_PLUS,	CODEC_ID_H263, CM_RD }, /* XXX H263P ? */
+	{ AST_FORMAT_H263_PLUS,	CODEC_ID_H263P, CM_WR }, /* XXX H263P ? */
+	{ 0,			0, 0 },
 };
 
 #if defined(HAVE_V4L) && HAVE_V4L > 0
@@ -285,21 +285,19 @@
  */
 static int video_read(struct video_out_desc *v)
 {
+	struct timeval now = ast_tvnow();
 	// fprintf(stderr, "video_read %p buf %p image %p\n", v, v->buf.data, v->image);
 	if (v->buf.data == NULL)	/* not initialized */
 		return 0;
 
-	if (v->image) {	// X11 grabber
-		struct timeval now = ast_tvnow();
-		int td = 1000/v->fps;
+	/* check if it is time to read */
+	if (ast_tvzero(v->last_frame))
+		v->last_frame = now;
+	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 */
 
-		/* check if it is time to read */
-		if (ast_tvzero(v->last_frame))
-			v->last_frame = now;
-		if (ast_tvdiff_ms(now, v->last_frame) < td) {
-			return 0;	/* too early */
-		}
-		v->last_frame = now; /* XXX actually, should correct for drift */
+	if (v->image) {	// X11 grabber
 		/* read frame from X11 */
 		XGetSubImage(v->dpy,
 		    RootWindow(v->dpy, DefaultScreen(v->dpy)),
@@ -360,12 +358,12 @@
 static struct video_desc *get_video_desc(struct ast_channel *c);
 
 /*! \brief map an asterisk format into an ffmpeg one */
-static enum CodecID map_video_format(uint32_t ast_format)
+static enum CodecID map_video_format(uint32_t ast_format, int rw)
 {
 	struct _cm *i;
 
 	for (i = video_formats; i->ast_format != 0; i++)
-		if (ast_format & i->ast_format)
+		if (ast_format & i->ast_format && rw & i->rw && rw & i->rw)
 			return i->codec;
 	return CODEC_ID_NONE;
 }
@@ -400,7 +398,7 @@
 	v->discard = 1;
 
 	v->ts = ast_tvnow();
-	codec = map_video_format(format);
+	codec = map_video_format(format, CM_RD);
 	ast_log(LOG_WARNING, "init for format 0x%x gives %d\n", format, codec);
 
 	v->codec = avcodec_find_decoder(codec);
@@ -482,7 +480,7 @@
 	v->lasttxframe		= -1;
 	v->decbuf.data		= NULL;
 
-	codec = map_video_format(format);
+	codec = map_video_format(format, CM_WR);
 	v->codec = avcodec_find_encoder(codec);
 	if (!v->codec) {
 		ast_log(LOG_WARNING, "Unable to find the encoder for format %d\n", codec);
@@ -541,8 +539,6 @@
 	v->decbuf.size = v->buf.size;
 	v->decbuf.used = 0;
 
-	v->msts = ast_tvnow();
-
 	v->mtu = 1400;
 
 	return 0;
@@ -758,11 +754,11 @@
 	bmp = env->bmp[out];
 	SDL_LockYUVOverlay(bmp);
 	pict.data[0] = bmp->pixels[0];
-	pict.data[1] = bmp->pixels[2];
-	pict.data[2] = bmp->pixels[1];
+	pict.data[1] = bmp->pixels[1];
+	pict.data[2] = bmp->pixels[2];
 	pict.linesize[0] = bmp->pitches[0];
-	pict.linesize[1] = bmp->pitches[2];
-	pict.linesize[2] = bmp->pitches[1];
+	pict.linesize[1] = bmp->pitches[1];
+	pict.linesize[2] = bmp->pitches[2];
 
 	if (pict_in == NULL) {	/* raw stream in YUV format, usually from camera */
 		int l4 = w*h/4;	/* size of U or V frame */
@@ -770,8 +766,8 @@
 			ast_log(LOG_WARNING, "no buffer for show frame\n");
 		} else {
 			bcopy(src, bmp->pixels[0], 4*l4);
-			bcopy(src + 5*l4, bmp->pixels[2], l4);
 			bcopy(src + 4*l4, bmp->pixels[1], l4);
+			bcopy(src + 5*l4, bmp->pixels[2], l4);
 		}
 	} else {	/* decode */
 #ifdef OLD_FFMPEG /* XXX img_convert is deprecated */
@@ -873,7 +869,7 @@
 		return 0;
 	}
 	len = f->datalen;
-	ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, 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);
@@ -925,7 +921,7 @@
 	struct ast_frame *cur = NULL, *first = NULL;
 	uint8_t *d = out->decbuf.data;
 	int l = len; /* size of the current fragment. If 0, must look for a psc */
-	int totlen = len, frags = 0;
+	int frags = 0;
 
 	for (;len > 0; len -= l, d += l) {
 		uint8_t *data;
@@ -941,12 +937,11 @@
 				}
 			}
 		}
-		if (l > out->mtu || l > len) {
-			/* psc not found, split */
-			ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
+		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 > 128*1024) {
+		if (l < 1 || l > out->mtu) {
 			ast_log(LOG_WARNING, "--- frame error l %d\n", l);
 			break;
 		}
@@ -974,8 +969,8 @@
 			f->datalen = l + 2;
 		}
 
-		f->has_timing_info = 1;
-		f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
+		//f->has_timing_info = 1;
+		//f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
 		f->frametype = AST_FRAME_VIDEO;
 		f->subclass = CONSOLE_FORMAT_VIDEO;
 		f->samples = 0;
@@ -992,44 +987,30 @@
 			first = f;
 		cur = f;
 		frags++;
-		ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
+		// ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
 	}
 
 	if (cur)
 		cur->subclass |= 1; // RTP Marker
 
-	ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
+	// ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
 	return first;
 }
 
 static struct ast_frame *get_video_frames(struct video_desc *env)
 {
-	int webcam_buflen;
-	struct timeval tvnow;
-	int period, fdiff;
+	int buflen;
 
 	if (!video_read(&env->out))
 		return NULL;
 	// fprintf(stderr, "video read\n");
 
-	// XXX - questa porzione di codice limita la generazione dei
-	// frame al framerate specificato nel file di configurazione
-	// I frame della webcam che non rientrano nel framerate
-	// vengono scartati.
-	tvnow = ast_tvnow();
-	period = 1000/env->out.fps;
-	fdiff = ast_tvdiff_ms(tvnow, env->out.msts);
-	if (fdiff < period)	/* drop frame if too early */
-		return NULL;
-
-	env->out.msts.tv_sec = tvnow.tv_sec;
-	env->out.msts.tv_usec = tvnow.tv_usec;
 	/* get frame and put them in the queue */
 	show_frame(env, 1);
-	webcam_buflen = avcodec_encode_video(env->out.context,
+	buflen = avcodec_encode_video(env->out.context,
 		env->out.decbuf.data, env->out.decbuf.size, env->out.frame);
-	// fprintf(stderr, "avcodec_encode_video returns %d\n", webcam_buflen);
-	return split_frame(&(env->out), webcam_buflen);
+	// fprintf(stderr, "avcodec_encode_video returns %d\n", buflen);
+	return split_frame(&(env->out), buflen);
 }
 
 /*!
@@ -1069,11 +1050,10 @@
 	show_frame(env, 1);
 
 	if (env->out.buf.data && owner) {  /* talk to the local video source */
-		if (env->out.fd >= 0)
+		if (0 && env->out.fd >= 0)
 			ast_channel_set_fd(owner, 1, env->out.fd);
 		fprintf(stderr, "video_out_init fd %d\n", env->out.fd);
 		video_out_init(&env->out, CONSOLE_FORMAT_VIDEO);
 	}
-	env->out.ts = ast_tvnow(); 
 }
 #endif	/* video support */
diff: missing operand
diff: Try `diff --help' for more information.


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=82624&r1=82623&r2=82624
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Mon Sep 17 12:33:17 2007
@@ -112,8 +112,6 @@
 	int		fps;
 	int		bitrate;
 	struct dbuf_t	decbuf;
-	struct timeval	ts;
-	struct timeval	msts;
 	int		mtu;
 
 	struct timeval	last_frame;
@@ -157,14 +155,16 @@
 struct _cm {	/* map ffmpeg codec types to asterisk formats */
 	uint32_t	ast_format;	/* 0 is a terminator */
 	enum CodecID	codec;
+	enum { CM_RD = 1, CM_WR = 2, CM_RDWD = 3 } rw;	/* read or write or both ? */
 };
 
 /*! the list of video formats we support */
 #define CONSOLE_FORMAT_VIDEO	AST_FORMAT_H263_PLUS
 
 static struct _cm video_formats[] = {
-	{ AST_FORMAT_H263_PLUS,	CODEC_ID_H263 }, /* XXX H263P ? */
-	{ 0,			0 },
+	{ AST_FORMAT_H263_PLUS,	CODEC_ID_H263, CM_RD }, /* XXX H263P ? */
+	{ AST_FORMAT_H263_PLUS,	CODEC_ID_H263P, CM_WR }, /* XXX H263P ? */
+	{ 0,			0, 0 },
 };
 
 #if defined(HAVE_V4L) && HAVE_V4L > 0
@@ -285,21 +285,19 @@
  */
 static int video_read(struct video_out_desc *v)
 {
+	struct timeval now = ast_tvnow();
 	// fprintf(stderr, "video_read %p buf %p image %p\n", v, v->buf.data, v->image);
 	if (v->buf.data == NULL)	/* not initialized */
 		return 0;
 
+	/* check if it is time to read */
+	if (ast_tvzero(v->last_frame))
+		v->last_frame = now;
+	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 */
+
 	if (v->image) {	// X11 grabber
-		struct timeval now = ast_tvnow();
-		int td = 1000/v->fps;
-
-		/* check if it is time to read */
-		if (ast_tvzero(v->last_frame))
-			v->last_frame = now;
-		if (ast_tvdiff_ms(now, v->last_frame) < td) {
-			return 0;	/* too early */
-		}
-		v->last_frame = now; /* XXX actually, should correct for drift */
 		/* read frame from X11 */
 		XGetSubImage(v->dpy,
 		    RootWindow(v->dpy, DefaultScreen(v->dpy)),
@@ -360,12 +358,12 @@
 static struct video_desc *get_video_desc(struct ast_channel *c);
 
 /*! \brief map an asterisk format into an ffmpeg one */
-static enum CodecID map_video_format(uint32_t ast_format)
+static enum CodecID map_video_format(uint32_t ast_format, int rw)
 {
 	struct _cm *i;
 
 	for (i = video_formats; i->ast_format != 0; i++)
-		if (ast_format & i->ast_format)
+		if (ast_format & i->ast_format && rw & i->rw && rw & i->rw)
 			return i->codec;
 	return CODEC_ID_NONE;
 }
@@ -400,7 +398,7 @@
 	v->discard = 1;
 
 	v->ts = ast_tvnow();
-	codec = map_video_format(format);
+	codec = map_video_format(format, CM_RD);
 	ast_log(LOG_WARNING, "init for format 0x%x gives %d\n", format, codec);
 
 	v->codec = avcodec_find_decoder(codec);
@@ -482,7 +480,7 @@
 	v->lasttxframe		= -1;
 	v->decbuf.data		= NULL;
 
-	codec = map_video_format(format);
+	codec = map_video_format(format, CM_WR);
 	v->codec = avcodec_find_encoder(codec);
 	if (!v->codec) {
 		ast_log(LOG_WARNING, "Unable to find the encoder for format %d\n", codec);
@@ -540,8 +538,6 @@
 	v->decbuf.data = ast_calloc(1, v->buf.size);
 	v->decbuf.size = v->buf.size;
 	v->decbuf.used = 0;
-
-	v->msts = ast_tvnow();
 
 	v->mtu = 1400;
 
@@ -758,11 +754,11 @@
 	bmp = env->bmp[out];
 	SDL_LockYUVOverlay(bmp);
 	pict.data[0] = bmp->pixels[0];
-	pict.data[1] = bmp->pixels[2];
-	pict.data[2] = bmp->pixels[1];
+	pict.data[1] = bmp->pixels[1];
+	pict.data[2] = bmp->pixels[2];
 	pict.linesize[0] = bmp->pitches[0];
-	pict.linesize[1] = bmp->pitches[2];
-	pict.linesize[2] = bmp->pitches[1];
+	pict.linesize[1] = bmp->pitches[1];
+	pict.linesize[2] = bmp->pitches[2];
 
 	if (pict_in == NULL) {	/* raw stream in YUV format, usually from camera */
 		int l4 = w*h/4;	/* size of U or V frame */
@@ -770,8 +766,8 @@
 			ast_log(LOG_WARNING, "no buffer for show frame\n");
 		} else {
 			bcopy(src, bmp->pixels[0], 4*l4);
+			bcopy(src + 4*l4, bmp->pixels[1], l4);
 			bcopy(src + 5*l4, bmp->pixels[2], l4);
-			bcopy(src + 4*l4, bmp->pixels[1], l4);
 		}
 	} else {	/* decode */
 #ifdef OLD_FFMPEG /* XXX img_convert is deprecated */
@@ -873,7 +869,7 @@
 		return 0;
 	}
 	len = f->datalen;
-	ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, 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);
@@ -925,7 +921,7 @@
 	struct ast_frame *cur = NULL, *first = NULL;
 	uint8_t *d = out->decbuf.data;
 	int l = len; /* size of the current fragment. If 0, must look for a psc */
-	int totlen = len, frags = 0;
+	int frags = 0;
 
 	for (;len > 0; len -= l, d += l) {
 		uint8_t *data;
@@ -941,12 +937,11 @@
 				}
 			}
 		}
-		if (l > out->mtu || l > len) {
-			/* psc not found, split */
-			ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
+		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 > 128*1024) {
+		if (l < 1 || l > out->mtu) {
 			ast_log(LOG_WARNING, "--- frame error l %d\n", l);
 			break;
 		}
@@ -974,8 +969,8 @@
 			f->datalen = l + 2;
 		}
 
-		f->has_timing_info = 1;
-		f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
+		//f->has_timing_info = 1;
+		//f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
 		f->frametype = AST_FRAME_VIDEO;
 		f->subclass = CONSOLE_FORMAT_VIDEO;
 		f->samples = 0;
@@ -992,44 +987,30 @@
 			first = f;
 		cur = f;
 		frags++;
-		ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
+		// ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
 	}
 
 	if (cur)
 		cur->subclass |= 1; // RTP Marker
 
-	ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
+	// ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
 	return first;
 }
 
 static struct ast_frame *get_video_frames(struct video_desc *env)
 {
-	int webcam_buflen;
-	struct timeval tvnow;
-	int period, fdiff;
+	int buflen;
 
 	if (!video_read(&env->out))
 		return NULL;
 	// fprintf(stderr, "video read\n");
 
-	// XXX - questa porzione di codice limita la generazione dei
-	// frame al framerate specificato nel file di configurazione
-	// I frame della webcam che non rientrano nel framerate
-	// vengono scartati.
-	tvnow = ast_tvnow();
-	period = 1000/env->out.fps;
-	fdiff = ast_tvdiff_ms(tvnow, env->out.msts);
-	if (fdiff < period)	/* drop frame if too early */
-		return NULL;
-
-	env->out.msts.tv_sec = tvnow.tv_sec;
-	env->out.msts.tv_usec = tvnow.tv_usec;
 	/* get frame and put them in the queue */
 	show_frame(env, 1);
-	webcam_buflen = avcodec_encode_video(env->out.context,
+	buflen = avcodec_encode_video(env->out.context,
 		env->out.decbuf.data, env->out.decbuf.size, env->out.frame);
-	// fprintf(stderr, "avcodec_encode_video returns %d\n", webcam_buflen);
-	return split_frame(&(env->out), webcam_buflen);
+	// fprintf(stderr, "avcodec_encode_video returns %d\n", buflen);
+	return split_frame(&(env->out), buflen);
 }
 
 /*!
@@ -1069,11 +1050,10 @@
 	show_frame(env, 1);
 
 	if (env->out.buf.data && owner) {  /* talk to the local video source */
-		if (env->out.fd >= 0)
+		if (0 && env->out.fd >= 0)
 			ast_channel_set_fd(owner, 1, env->out.fd);
 		fprintf(stderr, "video_out_init fd %d\n", env->out.fd);
 		video_out_init(&env->out, CONSOLE_FORMAT_VIDEO);
 	}
-	env->out.ts = ast_tvnow(); 
 }
 #endif	/* video support */




More information about the asterisk-commits mailing list