rtp_parser_err_t rtp_packet_parse(struct rtp_packet *pkt) { int padding_size; rtp_hdr_ext_t *hdr_ext_ptr; padding_size = 0; pkt->data_size = 0; pkt->data_offset = 0; pkt->appendable = 1; pkt->nsamples = RTP_NSAMPLES_UNKNOWN; if (pkt->size < sizeof(pkt->data.header)) return RTP_PARSER_PTOOSHRT; if (pkt->data.header.version != 2) return RTP_PARSER_IHDRVER; pkt->data_offset = RTP_HDR_LEN(&pkt->data.header); if (pkt->data.header.x != 0) { if (pkt->size < pkt->data_offset + sizeof(*hdr_ext_ptr)) return RTP_PARSER_PTOOSHRTXS; hdr_ext_ptr = (rtp_hdr_ext_t *)&pkt->data.buf[pkt->data_offset]; pkt->data_offset += sizeof(rtp_hdr_ext_t) + (ntohs(hdr_ext_ptr->length) * sizeof(hdr_ext_ptr->extension[0])); } if (pkt->size < pkt->data_offset) return RTP_PARSER_PTOOSHRTXH; if (pkt->data.header.p != 0) { if (pkt->data_offset == pkt->size) return RTP_PARSER_PTOOSHRTPS; padding_size = pkt->data.buf[pkt->size - 1]; if (padding_size == 0) return RTP_PARSER_IPS; } if (pkt->size < pkt->data_offset + padding_size) return RTP_PARSER_PTOOSHRTP; pkt->data_size = pkt->size - pkt->data_offset - padding_size; pkt->ts = ntohl(pkt->data.header.ts); pkt->seq = ntohs(pkt->data.header.seq); if (pkt->data_size == 0) return RTP_PARSER_OK; pkt->nsamples = rtp_calc_samples(pkt->data.header.pt, pkt->data_size, &pkt->data.buf[pkt->data_offset]); /* * G.729 comfort noise frame as the last frame causes * packet to be non-appendable */ if (pkt->data.header.pt == RTP_G729 && (pkt->data_size % 10) != 0) pkt->appendable = 0; return RTP_PARSER_OK; }
struct rtp_server * rtp_server_new(const char *name, rtp_type_t codec, int loop, double dtime, int ptime) { struct rtp_server *rp; int fd; char path[PATH_MAX + 1]; sprintf(path, "%s.%d", name, codec); fd = open(path, O_RDONLY); if (fd == -1) return NULL; rp = rtpp_zmalloc(sizeof(*rp)); if (rp == NULL) { close(fd); return NULL; } rp->btime = dtime; rp->dts = 0; rp->fd = fd; rp->loop = (loop > 0) ? loop - 1 : loop; rp->ptime = (ptime > 0) ? ptime : RTPS_TICKS_MIN; rp->rtp = (rtp_hdr_t *)rp->buf; rp->rtp->version = 2; rp->rtp->p = 0; rp->rtp->x = 0; rp->rtp->cc = 0; rp->rtp->mbt = 1; rp->rtp->pt = codec; rp->rtp->ts = 0; rp->rtp->seq = random() & 0xffff; rp->rtp->ssrc = random(); rp->pload = rp->buf + RTP_HDR_LEN(rp->rtp); return rp; }
struct rtp_server * rtp_server_new(const char *name, rtp_type_t codec, int loop) { struct rtp_server *rp; int fd; char path[PATH_MAX + 1]; sprintf(path, "%s.%d", name, codec); fd = open(path, O_RDONLY); if (fd == -1) return NULL; rp = malloc(sizeof(*rp)); if (rp == NULL) { close(fd); return NULL; } memset(rp, 0, sizeof(*rp)); rp->btime = -1; rp->fd = fd; rp->loop = (loop > 0) ? loop - 1 : loop; rp->rtp = (rtp_hdr_t *)rp->buf; rp->rtp->version = 2; rp->rtp->p = 0; rp->rtp->x = 0; rp->rtp->cc = 0; rp->rtp->m = 1; rp->rtp->pt = codec; rp->rtp->ts = 0; rp->rtp->seq = 0; rp->rtp->ssrc = random(); rp->pload = rp->buf + RTP_HDR_LEN(rp->rtp); return rp; }
struct rtp_packet * rtp_server_get(struct rtp_server *rp, double dtime, int *rval) { struct rtp_packet *pkt; uint32_t ts; int rlen, rticks, bytes_per_frame, ticks_per_frame, number_of_frames; int hlen; if (rp->btime == -1) rp->btime = dtime; ts = ntohl(rp->rtp->ts); if (rp->btime + ((double)ts / RTPS_SRATE) > dtime) { *rval = RTPS_LATER; return (NULL); } switch (rp->rtp->pt) { case RTP_PCMU: case RTP_PCMA: bytes_per_frame = 8; ticks_per_frame = 1; break; case RTP_G729: /* 10 ms per 8 kbps G.729 frame */ bytes_per_frame = 10; ticks_per_frame = 10; break; case RTP_G723: /* 30 ms per 6.3 kbps G.723 frame */ bytes_per_frame = 24; ticks_per_frame = 30; break; case RTP_GSM: /* 20 ms per 13 kbps GSM frame */ bytes_per_frame = 33; ticks_per_frame = 20; break; case RTP_G722: bytes_per_frame = 8; ticks_per_frame = 1; break; default: *rval = RTPS_ERROR; return (NULL); } number_of_frames = RTPS_TICKS_MIN / ticks_per_frame; if (RTPS_TICKS_MIN % ticks_per_frame != 0) number_of_frames++; rlen = bytes_per_frame * number_of_frames; rticks = ticks_per_frame * number_of_frames; pkt = rtp_packet_alloc(); if (pkt == NULL) { *rval = RTPS_ENOMEM; return (NULL); } hlen = RTP_HDR_LEN(rp->rtp); if (read(rp->fd, pkt->data.buf + hlen, rlen) != rlen) { if (rp->loop == 0 || lseek(rp->fd, 0, SEEK_SET) == -1 || read(rp->fd, pkt->data.buf + hlen, rlen) != rlen) { *rval = RTPS_EOF; rtp_packet_free(pkt); return (NULL); } if (rp->loop != -1) rp->loop -= 1; } if (rp->rtp->m != 0 && ntohs(rp->rtp->seq) != 0) { rp->rtp->m = 0; } rp->rtp->ts = htonl(ts + (RTPS_SRATE * rticks / 1000)); rp->rtp->seq = htons(ntohs(rp->rtp->seq) + 1); memcpy(&pkt->data.header, rp->rtp, hlen); pkt->size = hlen + rlen; return (pkt); }
rtp_parser_err_t rtp_packet_parse_raw(unsigned char *buf, size_t size, struct rtp_info *rinfo) { int padding_size; rtp_hdr_ext_t *hdr_ext_ptr; rtp_hdr_t *header; header = (rtp_hdr_t *)buf; padding_size = 0; rinfo->data_size = 0; rinfo->data_offset = 0; rinfo->appendable = 1; rinfo->nsamples = RTP_NSAMPLES_UNKNOWN; if (size < sizeof(*header)) return RTP_PARSER_PTOOSHRT; if (header->version != 2) return RTP_PARSER_IHDRVER; rinfo->data_offset = RTP_HDR_LEN(header); if (header->x != 0) { if (size < rinfo->data_offset + sizeof(*hdr_ext_ptr)) return RTP_PARSER_PTOOSHRTXS; hdr_ext_ptr = (rtp_hdr_ext_t *)&buf[rinfo->data_offset]; rinfo->data_offset += sizeof(rtp_hdr_ext_t) + (ntohs(hdr_ext_ptr->length) * sizeof(hdr_ext_ptr->extension[0])); } if (size < rinfo->data_offset) return RTP_PARSER_PTOOSHRTXH; if (header->p != 0) { if (rinfo->data_offset == size) return RTP_PARSER_PTOOSHRTPS; padding_size = buf[size - 1]; if (padding_size == 0) return RTP_PARSER_IPS; } if (size < rinfo->data_offset + padding_size) return RTP_PARSER_PTOOSHRTP; rinfo->data_size = size - rinfo->data_offset - padding_size; rinfo->ts = ntohl(header->ts); rinfo->seq = ntohs(header->seq); rinfo->ssrc = ntohl(header->ssrc); rinfo->rtp_profile = &rtp_profiles[header->pt]; if (rinfo->data_size == 0) return RTP_PARSER_OK; rinfo->nsamples = rtp_calc_samples(header->pt, rinfo->data_size, &buf[rinfo->data_offset]); /* * G.729 comfort noise frame as the last frame causes * packet to be non-appendable */ if (header->pt == RTP_G729 && (rinfo->data_size % 10) != 0) rinfo->appendable = 0; return RTP_PARSER_OK; }