[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