[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