diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2003-06-30 00:48:27 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2003-06-30 00:48:27 +0000 |
commit | a0da9453b67595b1cafefccaba23d7bf68d56e4a (patch) | |
tree | 34c362608ba22f633c0d032c93578513be10a360 | |
parent | a85e25348119219e90ca3ec3895653dc80b0dc42 (diff) |
Add video support to IAX2 (theoretically)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1141 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-x | channels/chan_iax2.c | 93 | ||||
-rwxr-xr-x | channels/iax2.h | 7 |
2 files changed, 85 insertions, 15 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 661ed9767..59dfd3c77 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -267,8 +267,12 @@ struct chan_iax2_pvt { int quelch; /* Last received voice format */ int voiceformat; + /* Last received voice format */ + int videoformat; /* Last sent voice format */ int svoiceformat; + /* Last sent video format */ + int svideoformat; /* What we are capable of sending */ int capability; /* Last received timestamp */ @@ -1983,6 +1987,7 @@ static struct ast_channel *ast_iax2_new(struct chan_iax2_pvt *i, int state, int tmp->pvt->answer = iax2_answer; tmp->pvt->read = iax2_read; tmp->pvt->write = iax2_write; + tmp->pvt->write_video = iax2_write; tmp->pvt->indicate = iax2_indicate; tmp->pvt->setoption = iax2_setoption; tmp->pvt->bridge = iax2_bridge; @@ -2127,17 +2132,17 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in or delayed, with retransmission */ struct ast_iax2_full_hdr *fh; struct ast_iax2_mini_hdr *mh; - unsigned char buffer[4096]; /* Buffer -- must preceed fr2 */ - struct iax_frame fr2; + struct ast_iax2_video_hdr *vh; + struct { + struct iax_frame fr2; + unsigned char buffer[4096]; + } frb; struct iax_frame *fr; int res; int sendmini=0; unsigned int lastsent; unsigned int fts; - - /* Shut up GCC */ - buffer[0] = 0; - + if (!pvt) { ast_log(LOG_WARNING, "No private structure for packet?\n"); return -1; @@ -2158,9 +2163,15 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in /* Mark that mini-style frame is appropriate */ sendmini = 1; } + if (((fts & 0xFFFF8000L) == (lastsent & 0xFFFF8000L)) && + (f->frametype == AST_FRAME_VIDEO) && + ((f->subclass & ~0x1) == pvt->svideoformat)) { + now = 1; + sendmini = 1; + } /* Allocate an iax_frame */ if (now) { - fr = &fr2; + fr = &frb.fr2; } else fr = iax_frame_new(DIRECTION_OUTGRESS, f->datalen); if (!fr) { @@ -2198,7 +2209,10 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in /* Keep track of the last thing we've acknowledged */ pvt->aseqno = fr->iseqno; fh->type = fr->af.frametype & 0xFF; - fh->csub = compress_subclass(fr->af.subclass); + if (fr->af.frametype == AST_FRAME_VIDEO) + fh->csub = compress_subclass(fr->af.subclass & ~0x1) | (fr->af.subclass & 0x1); + else + fh->csub = compress_subclass(fr->af.subclass); if (transfer) { fr->dcallno = pvt->transfercallno; } else @@ -2219,6 +2233,9 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in if (f->frametype == AST_FRAME_VOICE) { pvt->svoiceformat = f->subclass; } + if (f->frametype == AST_FRAME_VIDEO) { + pvt->svideoformat = f->subclass & ~0x1; + } if (now) { res = send_packet(fr); } else @@ -2237,6 +2254,18 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in pvt->trunkerror = 1; } res = 0; + } else if (fr->af.frametype == AST_FRAME_VIDEO) { + /* Video frame have no sequence number */ + fr->oseqno = -1; + fr->iseqno = -1; + vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr)); + vh->zeros = 0; + vh->callno = htons(0x8000 | fr->callno); + vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); + fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); + fr->data = vh; + fr->retries = -1; + res = send_packet(fr); } else { /* Mini-frames have no sequence number */ fr->oseqno = -1; @@ -3055,6 +3084,8 @@ static int complete_transfer(int callno, struct iax_ies *ies) pvt->transferring = TRANSFER_NONE; pvt->svoiceformat = -1; pvt->voiceformat = 0; + pvt->svideoformat = -1; + pvt->videoformat = 0; pvt->transfercallno = -1; memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); memset(&pvt->offset, 0, sizeof(pvt->offset)); @@ -3528,6 +3559,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata) struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)buf; struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)buf; struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)buf; + struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)buf; struct ast_iax2_meta_trunk_hdr *mth; struct ast_iax2_meta_trunk_entry *mte; char dblbuf[4096]; /* Declaration of dblbuf must immediately *preceed* fr on the stack */ @@ -3542,9 +3574,13 @@ static int socket_read(int *id, int fd, short events, void *cbdata) int format; int exists; int mm; + int minivid = 0; unsigned int ts; char empty[32]=""; /* Safety measure */ dblbuf[0] = 0; /* Keep GCC from whining */ + + fr.callno = 0; + res = recvfrom(netsocket, buf, sizeof(buf), 0,(struct sockaddr *) &sin, &len); if (res < 0) { if (errno != ECONNREFUSED) @@ -3556,7 +3592,11 @@ static int socket_read(int *id, int fd, short events, void *cbdata) ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, sizeof(struct ast_iax2_mini_hdr)); return 1; } - if (meta->zeros == 0) { + if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { + /* This is a video frame, get call number */ + fr.callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, 1); + minivid = 1; + } else if (meta->zeros == 0) { /* This is a a meta header */ switch(meta->metacmd) { case IAX_META_TRUNK: @@ -3655,11 +3695,11 @@ static int socket_read(int *id, int fd, short events, void *cbdata) dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; /* Retrieve the type and subclass */ f.frametype = fh->type; - f.subclass = uncompress_subclass(fh->csub); -#if 0 - f.subclass = fh->subclasshigh << 16; - f.subclass += ntohs(fh->subclasslow); -#endif + if (f.frametype == AST_FRAME_VOICE) { + f.subclass = uncompress_subclass(fh->csub & ~0x1) | (fh->csub & 0x1); + } else { + f.subclass = uncompress_subclass(fh->csub); + } if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || (f.subclass == IAX_COMMAND_POKE))) new = NEW_ALLOW; @@ -3669,7 +3709,8 @@ static int socket_read(int *id, int fd, short events, void *cbdata) f.subclass = 0; } - fr.callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, 1); + if (!fr.callno) + fr.callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, 1); if (fr.callno > 0) ast_pthread_mutex_lock(&iaxsl[fr.callno]); @@ -3853,6 +3894,12 @@ retryowner: } } } + if (f.frametype == AST_FRAME_VIDEO) { + if (f.subclass != iaxs[fr.callno]->videoformat) { + ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1); + iaxs[fr.callno]->videoformat = f.subclass & ~0x1; + } + } if (f.frametype == AST_FRAME_IAX) { if (iaxs[fr.callno]->initid > -1) { /* Don't auto congest anymore since we've gotten something usefulb ack */ @@ -4363,6 +4410,22 @@ retryowner: /* Unless this is an ACK or INVAL frame, ack it */ if (iaxs[fr.callno]->aseqno != iaxs[fr.callno]->iseqno) send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno); + } else if (minivid) { + f.frametype = AST_FRAME_VIDEO; + if (iaxs[fr.callno]->videoformat > 0) + f.subclass = iaxs[fr.callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); + else { + ast_log(LOG_WARNING, "Received mini frame before first full voice frame\n "); + iax2_vnak(fr.callno); + ast_pthread_mutex_unlock(&iaxsl[fr.callno]); + return 1; + } + f.datalen = res - sizeof(struct ast_iax2_video_hdr); + if (f.datalen) + f.data = buf + sizeof(struct ast_iax2_video_hdr); + else + f.data = NULL; + fr.ts = (iaxs[fr.callno]->last & 0xFFFF8000L) | (ntohs(mh->ts) & 0x7fff); } else { /* A mini frame */ f.frametype = AST_FRAME_VOICE; diff --git a/channels/iax2.h b/channels/iax2.h index d69459999..1a14759bb 100755 --- a/channels/iax2.h +++ b/channels/iax2.h @@ -142,6 +142,13 @@ struct ast_iax2_meta_hdr { unsigned char data[0]; } __attribute__ ((__packed__)); +struct ast_iax2_video_hdr { + unsigned short zeros; /* Zeros field -- must be zero */ + unsigned short callno; /* Video call number */ + unsigned short ts; /* Timestamp and mark if present */ + unsigned char data[0]; +} __attribute__ ((__packed__)); + struct ast_iax2_meta_trunk_hdr { unsigned int ts; /* 32-bit timestamp for all messages */ unsigned char data[0]; |