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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Oct 23 03:33:36 CDT 2007


Author: rizzo
Date: Tue Oct 23 03:33:35 2007
New Revision: 86871

URL: http://svn.digium.com/view/asterisk?view=rev&rev=86871
Log:
add h264 support.
Fragmentation not supported yet.


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=86871&r1=86870&r2=86871
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Tue Oct 23 03:33:35 2007
@@ -1068,6 +1068,7 @@
 /* mpeg4 support */
 static int mpeg4_enc_init(struct video_out_desc *v)
 {
+#if 0
 	//v->enc_ctx->flags |= CODEC_FLAG_LOW_DELAY; /*don't use b frames ?*/
 	v->enc_ctx->flags |= CODEC_FLAG_AC_PRED;
 	v->enc_ctx->flags |= CODEC_FLAG_H263P_UMV;
@@ -1076,6 +1077,8 @@
 	v->enc_ctx->flags |= CODEC_FLAG_GMC;
 	v->enc_ctx->flags |= CODEC_FLAG_LOOP_FILTER;
 	v->enc_ctx->flags |= CODEC_FLAG_H263P_SLICE_STRUCT;
+#endif
+	v->enc_ctx->rtp_payload_size = 0; /* important - ffmpeg fails otherwise */
 	return 0;
 }
 
@@ -1128,6 +1131,218 @@
 	.dec_init = NULL,
 	.dec_decap = mpeg4_decap,
 	.dec_run = mpeg4_decode
+};
+
+static int h264_enc_init(struct video_out_desc *v)
+{
+	v->enc_ctx->flags |= CODEC_FLAG_TRUNCATED;
+	//v->enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+	//v->enc_ctx->flags2 |= CODEC_FLAG2_FASTPSKIP;
+	/* TODO: Maybe we need to add some other flags */
+	v->enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
+	v->enc_ctx->rtp_mode = 0;
+	v->enc_ctx->rtp_payload_size = 0;
+	v->enc_ctx->bit_rate_tolerance = v->enc_ctx->bit_rate;
+	return 0;
+}
+
+static int h264_dec_init(struct video_in_desc *v)
+{
+	v->dec_ctx->flags |= CODEC_FLAG_TRUNCATED;
+
+	return 0;
+}
+
+/*
+ * The structure of a generic H.264 stream is:
+ * - 0..n 0-byte(s), unused, optional. one zero-byte is always present
+ *   in the first NAL before the start code prefix.
+ * - start code prefix (3 bytes): 0x000001
+ *   (the first bytestream has a 
+ *   like these 0x00000001!)
+ * - NAL header byte ( F[1] | NRI[2] | Type[5] ) where type != 0
+ * - byte-stream
+ * - 0..n 0-byte(s) (padding, unused).
+ * Segmentation in RTP only needs to be done on start code prefixes.
+ * If fragments are too long... we don't support it yet.
+ * - encapsulate (or fragment) the byte-stream (with NAL header included)
+ */
+static struct ast_frame *h264_encap(struct video_out_desc *out,
+	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)
+			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 (cur)
+		cur->subclass |= 1;     // RTP Marker
+
+	*tail = cur;
+
+	return first;
+}
+
+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) {
+		ast_log(LOG_WARNING, "--- forbidden packet; nal: %02x\n",
+			fu_indicator);
+		return 1;
+	}
+
+	type = fu_indicator & 0x1f;
+	switch (type) {
+	case 0:
+	case 31:
+		ast_log(LOG_WARNING, "--- invalid type: %d\n", type);
+		return 1;
+	case 24:
+	case 25:
+	case 26:
+	case 27:
+	case 29:
+		ast_log(LOG_WARNING, "--- encapsulation not supported : %d\n", type);
+		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);
+	}
+	return retval;
+}
+
+/* XXX placeholder for h264, does not work yet. */
+static struct video_codec_desc h264_codec = {
+	.name = "h264",
+	.format = AST_FORMAT_H264,
+	.enc_init = h264_enc_init,
+	.enc_encap = h264_encap,
+	.enc_run = ffmpeg_encode,
+	.dec_init = h264_dec_init,
+	.dec_decap = h264_decap,
+	.dec_run = ffmpeg_decode
 };
 
 /*------ end codec specific code -----*/
@@ -1364,18 +1579,6 @@
 	return CODEC_ID_NONE;
 }
 
-/* XXX placeholder for h264, does not work yet. */
-static struct video_codec_desc h264_codec = {
-	.name = "h264",
-	.format = AST_FORMAT_H264,
-	.enc_init = h263p_enc_init,
-	.enc_encap = h263p_encap,
-	.enc_run = ffmpeg_encode,
-	.dec_init = NULL,
-	.dec_decap = h263p_decap,
-	.dec_run = ffmpeg_decode
-};
-
 /* pointers to supported codecs. We assume the first one to be non null. */
 static struct video_codec_desc *supported_codecs[] = {
 	&h263p_codec,




More information about the asterisk-commits mailing list