dect
/
asterisk
Archived
13
0
Fork 0

Add video support to IAX2 (theoretically)

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1141 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
markster 2003-06-30 00:48:27 +00:00
parent a85e253481
commit a0da9453b6
2 changed files with 85 additions and 15 deletions

View File

@ -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;

View File

@ -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];