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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Sep 17 10:28:45 CDT 2007


Author: rizzo
Date: Mon Sep 17 10:28:44 2007
New Revision: 82585

URL: http://svn.digium.com/view/asterisk?view=rev&rev=82585
Log:
more cleanup of this code, while still struggling with
properly segmenting frames


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=82585&r1=82584&r2=82585
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Mon Sep 17 10:28:44 2007
@@ -128,7 +128,7 @@
 	AVCodecParserContext    *parser;
 	int                     completed;	/* probably unnecessary */
 	struct dbuf_t buf;
-	int                     lastrxframe;
+	uint16_t 		next_seq;	/* must be 16 bit */
 	int                     discard;
 	struct timeval	ts;
 	int received;
@@ -397,7 +397,7 @@
 	v->parser = NULL;
 	v->buf.data = NULL;
 	v->completed = 0;
-	v->lastrxframe        = -1;
+	v->discard = 1;
 
 	v->ts = ast_tvnow();
 	codec = map_video_format(format);
@@ -638,19 +638,19 @@
 	int PLEN;
 	int P;
 
-	if(data == NULL)
-		return NULL;
-	if(*len < 2)
-		return NULL;
-
+	if (*len < 2) {
+		ast_log(LOG_WARNING, "invalid framesize %d\n", *len);
+		*len = 0;
+		return data;
+	}
 	PLEN = rfc2429_get_PLEN(data);
 	P = rfc2429_get_P(data);
 
-	if(PLEN > 0) {
+	if (PLEN > 0) {
 		data += PLEN;
 		(*len) -= PLEN;
 	}
-	if(P)
+	if (P)
 		data[0] = data[1] = 0;
 	else {
 		data += 2;
@@ -820,21 +820,14 @@
 	uint8_t *data;
 	int len;
 	struct video_desc *env = get_video_desc(chan);
-	struct timeval now = ast_tvnow();
-	int i;
+	struct video_in_desc *v = &env->in;
 
 	if(!env->initialized) {
 		ast_log(LOG_WARNING, "here env should be already initialized\n");
 		return -1;	/* error */
 	}
 
-	i = ast_tvdiff_ms(now, env->in.ts);
-	if (i > 1000) {
-		//ast_log(LOG_WARNING, "received %d video frames in %d ms\n", env->in.received, i);
-		env->in.received = 0;
-		env->in.ts = now;
-	}
-	env->in.received++;
+	v->received++;
 #if defined(DROP_PACKETS) && DROP_PACKETS > 0
 	/*
 	* Fragment of code to simulate lost/delayed packets
@@ -844,64 +837,78 @@
 		return 0;
 	}
 #endif
+	if (v->discard) {
+		ast_log(LOG_WARNING, "discard mode, drop frame %d\n", f->seqno);
+		/*
+		 * In discard mode, drop packets until we find one with
+		 * the RTP marker set (which is the end of frame).
+		 * XXX note that the RTP marker flag is sent as the LSB of the
+		 * subclass. This is slightly annoying as it goes to overwrite
+		 * the payload type entry.
+		 */
+		if (f->subclass & 0x01) {
+			v->buf.used = 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);
+		}
+		return 0;
+	}
+
 	/*
-	 * If there is the discard flag, every packet must be discarded.
-	 * When a marked packet arrive we can restart the decoding.
-	 * XXX note that the RTP marker flag is sent as the LSB of the
-	 * subclass. This is slightly annoying as it goes to overwrite
-	 * the payload type entry.
+	 * Only in-order fragments will be accepted. Remember seqno
+	 * has 16 bit so there is wraparound. Also, ideally we could
+	 * accept a bit of reordering, but at the moment wr don't.
 	 */
-	if(env->in.discard) {
-		if(f->subclass & 0x01) {
-			free(env->in.buf.data);
-			env->in.buf.data = NULL;
-			env->in.buf.used = 0;
-			env->in.lastrxframe = f->seqno;
-			env->in.discard = 0;
-			ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
-		}
-		ast_log(LOG_WARNING, "discard mode, drop frame %d\n", f->seqno);
+	if (v->next_seq != f->seqno) {
+		ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
+			v->next_seq, f->seqno);
+		v->discard = 1;
 		return 0;
 	}
-
-	/*
-	* Only ordered fragment will be accepted.
-	* We can handle the circular seqno with the following operation
-	* (seqno is a 16 bits number)
-	*/
-	if((env->in.lastrxframe+1)%0x10000 != f->seqno && env->in.lastrxframe != -1) {
-		ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
-			env->in.lastrxframe, f->seqno);
-		env->in.discard = 1;
+	v->next_seq++;
+
+	if (f->data == NULL || f->datalen < 2) {
+		ast_log(LOG_WARNING, "empty video frame, discard\n");
 		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);
+		v->discard = 1;
+		return 0;
+	}
 
 	/* allocate buffer as we see fit. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE
 	 * and a 0 as a buffer terminator to prevent trouble.
 	 */
-	if(env->in.buf.data == NULL) {
-		env->in.buf.size = len + FF_INPUT_BUFFER_PADDING_SIZE;
-		env->in.buf.used = 0;
-		env->in.buf.data = malloc(len);
-	} else if (env->in.buf.used + len + FF_INPUT_BUFFER_PADDING_SIZE> env->in.buf.size) {
-		env->in.buf.size = env->in.buf.used + len + FF_INPUT_BUFFER_PADDING_SIZE;
-		env->in.buf.data = realloc(env->in.buf.data, env->in.buf.size);
-	}
-	memcpy(env->in.buf.data+env->in.buf.used, data, len);
-	env->in.buf.used += len;
-	env->in.buf.data[env->in.buf.used] = '\0';
-	if(f->subclass & 0x01) // RTP Marker
-		if(decode_video(&env->in)) {
+	if (v->buf.data == NULL) {
+		v->buf.size = len + FF_INPUT_BUFFER_PADDING_SIZE;
+		v->buf.used = 0;
+		v->buf.data = ast_malloc(len);
+	} else if (v->buf.used + len + FF_INPUT_BUFFER_PADDING_SIZE> v->buf.size) {
+		v->buf.size = v->buf.used + len + FF_INPUT_BUFFER_PADDING_SIZE;
+		v->buf.data = ast_realloc(v->buf.data, v->buf.size);
+	}
+	if (v->buf.data == NULL) {
+		ast_log(LOG_WARNING, "alloc failure for %d, discard\n",
+			v->buf.size);
+		v->discard = 1;
+		return 0;
+	}
+	memcpy(v->buf.data + v->buf.used, data, len);
+	v->buf.used += len;
+	v->buf.data[v->buf.used] = '\0';
+	v->buf.data[v->buf.used+1] = '\0';	/* just in case... */
+	if (f->subclass & 0x01) {	// RTP Marker
+		if (decode_video(v)) {
 			show_frame(env, 0);
-			env->in.completed = 0;
-			env->in.buf.used = 0;
-		}
-	env->in.lastrxframe = f->seqno;
-
+			v->completed = 0;
+			v->buf.used = 0;
+		}
+	}
 	return 0;
 }
 
@@ -920,6 +927,7 @@
 	uint8_t *start = out->decbuf.data;
 	int have_psc = 0;	/* did we skip 2 bytes for this frame ? */
 	int l;	/* size of the current fragment */
+	l = len;
 
 	for (;len > 0; start += l, len -= l) {
 		/* First try to split on a psc. If not, create an artificial break */
@@ -942,19 +950,27 @@
 		}
 #endif
 		/* temporary - assume we have psc, drop first 2 bytes, send one large packet */
-		have_psc = 1;
-		start += 2;
-		l = len - 2;
 
 		ast_log(LOG_WARNING, "len %d\n", l);
 		f = ast_calloc(1, sizeof(*f));
 		data = ast_calloc(1, l+2);
+		if (l < 1 || l > 128*1024 || f == NULL || data == NULL) {
+			ast_log(LOG_WARNING, "--- frame error f %p d %p l %d\n",
+				f, data, l);
+			break;
+		}
 		f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR;
-
-		data[0] = data[1] = 0; // P == 0
-		if (have_psc)
+		f->data = data;
+
+		if (data[0] == 0 && data[1] == 0) { /* a psc */
+			memcpy(data, start, l);
 			data[0] |= 0x04; // P == 1
-		memcpy(data+2, start, l);
+			f->datalen = l;
+		} else {
+			data[0] = data[1] = 0; // P == 0
+			memcpy(data + 2, start, l);
+			f->datalen = l + 2;
+		}
 
 		f->has_timing_info = 1;
 		f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
@@ -968,8 +984,6 @@
 		f->delivery.tv_sec = 0;
 		f->delivery.tv_usec = 0;
 		f->seqno = ++(out->lasttxframe);
-		f->datalen = l + 2;
-		f->data = data;
 		AST_LIST_NEXT(f, frame_list) = NULL;
 
 		if (cur)
@@ -983,7 +997,7 @@
 	if (cur)
 		cur->subclass |= 1; // RTP Marker
 
-	ast_log(LOG_WARNING, "done, first %p\n", first);
+	// ast_log(LOG_WARNING, "done, first %p\n", first);
 	return first;
 }
 




More information about the asterisk-commits mailing list