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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Oct 23 09:39:42 CDT 2007


Author: rizzo
Date: Tue Oct 23 09:39:41 2007
New Revision: 86873

URL: http://svn.digium.com/view/asterisk?view=rev&rev=86873
Log:
revised h264 encapsulation, still no fragmentation support.


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=86873&r1=86872&r2=86873
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Tue Oct 23 09:39:41 2007
@@ -1181,103 +1181,82 @@
 	struct ast_frame **tail)
 {
 	struct ast_frame *f = NULL, *cur = NULL, *first = NULL;
-	uint8_t *d = out->enc_out.data;
-	int len = out->enc_out.used;
-	int l, start = 0, end = 0;
-
-	/* Search the first start code prefix - ITU-T H.264 sec. B.2 */
-	for (l = 0; l < len-3; l++)
-		if (d[l] == 0x00 && d[l+1] == 0x00 &&
-		    d[l+2] == 0x00 && d[l+3] == 0x01)
+	uint8_t *d, *start = out->enc_out.data;
+	uint8_t *end = start + out->enc_out.used;
+
+	/* Search the first start code prefix - ITU-T H.264 sec. B.2,
+	 * and move start right after that, on the NAL header byte.
+	 */
+#define HAVE_NAL(x) (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1)
+	for (start += 4; start < end; start++) {
+		int ty = start[0] & 0x1f;
+		if (HAVE_NAL(start) && ty != 0 && ty != 31)
 			break;
-
-	if (len-l < 7) {	/* not enough data, discard */
-		*tail = NULL;
-		ast_log(LOG_NOTICE, "too few data\n");
-		return NULL;
-	}
-
-	/* move to the NAL header */
-	d += l+4;
-	len -= l+4;
-	if ((d[0] & 0x1f) == 0)
-		ast_log(LOG_WARNING, "Invalid type: 0x%02x\n", d[0]);
-	for (l = 3; l < len; l++) {
-		int size;
-		int h = 1;
-		uint8_t *data = NULL;
-		uint8_t nal_header;
-
-		/* check for the next start code prefix (or the end of stream)
-		* and for a valid NAL type (only Single NAL Unit allowed).
-		* actually, the check for NAL type is useful
-		* only for bridging packets... I guess!
-		*/
-		if (len-l > 7) {
-			if (d[l-3] != 0x00 ||
-				d[l-2] != 0x00 || d[l-1] != 0x01 ||
-				(d[l] & 0x1f) < 1 || (d[l] & 0x1f) > 23)
-				continue;
-			ast_log(LOG_WARNING, "Another NAL\n");
-			end = l-3;
-		} else
-			end = l = len;
-
-		size = end-start;
-		//if (size < out->mtu) {
-		if (1) {	// test - don't fragment
-			// Single NAL Unit
-			f = create_video_frame(d+start, d+end, AST_FORMAT_H264, 0, cur);
-			if (!f)
-				break;
-			if (!first)
-				first = f;
-
-			cur = f;
-			start = end+3;
-			continue;
-		}
-
-		// Fragmented Unit (Mode A: no DON)
-		nal_header = d[0];
-		while (size) {
-			int frag_size;
-
-			frag_size = MIN(size, out->mtu);
-			f = create_video_frame(d+start, d+start+frag_size, AST_FORMAT_H264, h, cur);
-			if (!f) {
-				l = len;
-				break;
-			}
-
-			data = f->data;
-			/* FU Indicator:
-			 * - the encoder should set F to 0
-			 * - NRI MUST be set to the value of the NRI
-			 *   field in the fragmented NAL unit
-			 * - type == 28 (FU-A)
-			 */
-			data[0] = (nal_header & 0xe0) | 28;
-			/* FU header:
-			 * - S == 1 if the first fragment
-			 * - E == 1 for the last fragment
-			 * - type == to the value of the
-			 *   type field in the fragmented NAL unit
-			 */
-			data[1] = (h == 1 ? 0x80 : 0x00) | (nal_header & 0x1f);
-			h = 2;
-
-			if (!first)
-				first = f;
-			cur = f;
-			size -= frag_size;
-			start += frag_size;
-		}
-		// set end bit for the last frag in FU header
-		if (data)
-			data[1] = 0x40 | (data[1] & ~0x40);
-		start = end+3;
-	}
+	}
+	/* if not found, or too short, we just skip the next loop and are done. */
+
+	/* Here follows the main loop to create frames. Search subsequent start
+	 * codes, and then possibly fragment the unit into smaller fragments.
+	 */
+   for (;start < end - 4; start = d) {
+	int size;		/* size of current block */
+	uint8_t hdr[2];		/* add-on header when fragmenting */
+	int ty = 0;
+
+	/* now search next nal */
+	for (d = start + 4; d < end; d++) {
+		ty = d[0] & 0x1f;
+		if (HAVE_NAL(d))
+			break;	/* found NAL */
+	}
+	/* have a block to send. d past the start code unless we overflow */
+	if (d >= end) {	/* NAL not found */
+		d = end + 4;
+	} else if (ty == 0 || ty == 31) { /* found but invalid type, skip */
+		ast_log(LOG_WARNING, "skip invalid nal type %d at %d of %d\n",
+			ty, d - out->enc_out.data, out->enc_out.used);
+		continue;
+	}
+
+	size = d - start - 4;	/* don't count the end */
+	ast_log(LOG_WARNING, "block at %d size %d of %d\n",
+		start - out->enc_out.data, size, out->enc_out.used);
+
+	if (1 /* size < out->mtu */) {	// test - don't fragment
+		// Single NAL Unit
+		f = create_video_frame(start, d - 4, AST_FORMAT_H264, 0, cur);
+		if (!f)
+			break;
+		if (!first)
+			first = f;
+
+		cur = f;
+		continue;
+	}
+
+	// Fragmented Unit (Mode A: no DON, very weak)
+	hdr[0] = (*start & 0xe0) | 28;	/* mark as a fragmentation unit */
+	hdr[1] = (*start++ & 0x1f) | 0x80 ;	/* keep type and set START bit */
+	size--;		/* skip the NAL header */
+	while (size) {
+		uint8_t *data;
+		int frag_size = MIN(size, out->mtu);
+
+		f = create_video_frame(start, start+frag_size, AST_FORMAT_H264, 2, cur);
+		if (!f)
+			break;
+		size -= frag_size;	/* skip this data block */
+		start += frag_size;
+
+		data = f->data;
+		data[0] = hdr[0];
+		data[1] = hdr[1] | (size == 0 ? 0x40 : 0);	/* end bit if we are done */
+		hdr[1] &= ~0x80;	/* clear start bit for subsequent frames */
+		if (!first)
+			first = f;
+		cur = f;
+	}
+    }
 
 	if (cur)
 		cur->subclass |= 1;     // RTP Marker
@@ -1289,25 +1268,23 @@
 
 static int h264_decap(struct fbuf_t *b, uint8_t *data, int len)
 {
-	uint8_t fu_indicator = data[0];
-	uint8_t fu_header;
-	uint8_t type;
 	/* Start Code Prefix (Annex B in specification) */
 	uint8_t scp[] = { 0x00, 0x00, 0x00, 0x01 };
 	int retval = 0;
-	int h;
-	uint8_t *buf;
-
-	/*
-	* first of all, check if the packet has F == 0
-	*/
-	if (fu_indicator & 0x80) {
+	int type, ofs = 0;
+
+	if (len < 2) {
+		ast_log(LOG_WARNING, "--- invalid len %d\n", len);
+		return 1;
+	}
+	/* first of all, check if the packet has F == 0 */
+	if (data[0] & 0x80) {
 		ast_log(LOG_WARNING, "--- forbidden packet; nal: %02x\n",
-			fu_indicator);
+			data[0]);
 		return 1;
 	}
 
-	type = fu_indicator & 0x1f;
+	type = data[0] & 0x1f;
 	switch (type) {
 	case 0:
 	case 31:
@@ -1319,31 +1296,27 @@
 	case 27:
 	case 29:
 		ast_log(LOG_WARNING, "--- encapsulation not supported : %d\n", type);
+		return 1;
+	case 28:	/* FU-A Unit */
+		if (data[1] & 0x80) { // S == 1, import F and NRI from next
+			data[1] &= 0x1f;	/* preserve type */
+			data[1] |= (data[0] & 0xe0);	/* import F & NRI */
+			retval = fbuf_append(b, scp, sizeof(scp), 0, 0);
+			ofs = 1;
+		} else {
+			ofs = 2;
+		}
 		break;
-	case 28:
-		/* FU-A Unit */
-		fu_header = data[1];
-		if (fu_header & 0x80) { // S == 1
-			data[1] = (fu_indicator & 0xe0) | // F & NRI
-				(fu_header & 0x1f); // type
-			retval = fbuf_append(b, scp, sizeof(scp), 0, 0);
-			h = 1;
-		} else
-			h = 2;
-		retval |= fbuf_append(b, data+h, len-h, 0, 0);
-		break;
-	default:
-		/* From 1 to 23 (Single NAL Unit) */
-		buf = calloc(1, len+sizeof(scp));
-		memcpy(buf, scp, sizeof(scp));
-		memcpy(buf+sizeof(scp), data, len);
-		retval = fbuf_append(b, buf, len+sizeof(scp), 0, 0);
-		free(buf);
-	}
+	default:	/* From 1 to 23 (Single NAL Unit) */
+		retval = fbuf_append(b, scp, sizeof(scp), 0, 0);
+	}
+	if (!retval)
+		retval = fbuf_append(b, data + ofs, len - ofs, 0, 0);
+	if (retval)
+		ast_log(LOG_WARNING, "result %d\n", retval);
 	return retval;
 }
 
-/* XXX placeholder for h264, does not work yet. */
 static struct video_codec_desc h264_codec = {
 	.name = "h264",
 	.format = AST_FORMAT_H264,




More information about the asterisk-commits mailing list