📄 rtp.c
字号:
if (!filter_event(session, sd->ssrc)) { event.ssrc = sd->ssrc; event.type = RX_SDES; event.data = (void *) rsp; event.ts = event_ts; session->callback(session, &event); } } else { debug_msg("Invalid sdes item for source 0x%08x, skipping...\n", sd->ssrc); } } } sd = (struct rtcp_sdes_t *) ((uint32_t *)sd + (((char *)rsp - (char *)sd) >> 2)+1); } if (count >= 0) { debug_msg("Invalid RTCP SDES packet, some items ignored.\n"); }}static void process_rtcp_bye(struct rtp *session, rtcp_t *packet, struct timeval *event_ts){ int i; uint32_t ssrc; rtp_event event; source *s; for (i = 0; i < packet->common.count; i++) { ssrc = ntohl(packet->r.bye.ssrc[i]); /* This is kind-of strange, since we create a source we are about to delete. */ /* This is done to ensure that the source mentioned in the event which is */ /* passed to the user of the RTP library is valid, and simplify client code. */ create_source(session, ssrc, FALSE); /* Call the event handler... */ if (!filter_event(session, ssrc)) { event.ssrc = ssrc; event.type = RX_BYE; event.data = NULL; event.ts = event_ts; session->callback(session, &event); } /* Mark the source as ready for deletion. Sources are not deleted immediately */ /* since some packets may be delayed and arrive after the BYE... */ s = get_source(session, ssrc); s->got_bye = TRUE; check_source(s); session->bye_count++; }}static void process_rtcp_app(struct rtp *session, rtcp_t *packet, struct timeval *event_ts){ uint32_t ssrc; rtp_event event; rtcp_app *app; source *s; int data_len; /* Update the database for this source. */ ssrc = ntohl(packet->r.app.ssrc); create_source(session, ssrc, FALSE); s = get_source(session, ssrc); if (s == NULL) { /* This should only occur in the event of database malfunction. */ debug_msg("Source 0x%08x invalid, skipping...\n", ssrc); return; } check_source(s); /* Copy the entire packet, converting the header (only) into host byte order. */ app = (rtcp_app *) xmalloc(RTP_MAX_PACKET_LEN); app->version = packet->common.version; app->p = packet->common.p; app->subtype = packet->common.count; app->pt = packet->common.pt; app->length = ntohs(packet->common.length); app->ssrc = ssrc; app->name[0] = packet->r.app.name[0]; app->name[1] = packet->r.app.name[1]; app->name[2] = packet->r.app.name[2]; app->name[3] = packet->r.app.name[3]; data_len = (app->length - 2) * 4; memcpy(app->data, packet->r.app.data, data_len); /* Callback to the application to process the app packet... */ if (!filter_event(session, ssrc)) { event.ssrc = ssrc; event.type = RX_APP; event.data = (void *) app; /* The callback function MUST free this! */ event.ts = event_ts; session->callback(session, &event); }}static void rtp_process_ctrl(struct rtp *session, uint8_t *buffer, int buflen){ /* This routine processes incoming RTCP packets */ rtp_event event; struct timeval event_ts; rtcp_t *packet; uint8_t initVec[8] = {0,0,0,0,0,0,0,0}; int first; uint32_t packet_ssrc = rtp_my_ssrc(session); gettimeofday(&event_ts, NULL); if (buflen > 0) { if (session->encryption_enabled) { /* Decrypt the packet... */ (session->decrypt_func)(session, buffer, buflen, initVec); buffer += 4; /* Skip the random prefix... */ buflen -= 4; } if (validate_rtcp(buffer, buflen)) { first = TRUE; packet = (rtcp_t *) buffer; while (packet < (rtcp_t *) (buffer + buflen)) { switch (packet->common.pt) { case RTCP_SR: if (first && !filter_event(session, ntohl(packet->r.sr.sr.ssrc))) { event.ssrc = ntohl(packet->r.sr.sr.ssrc); event.type = RX_RTCP_START; event.data = &buflen; event.ts = &event_ts; packet_ssrc = event.ssrc; session->callback(session, &event); } process_rtcp_sr(session, packet, &event_ts); break; case RTCP_RR: if (first && !filter_event(session, ntohl(packet->r.rr.ssrc))) { event.ssrc = ntohl(packet->r.rr.ssrc); event.type = RX_RTCP_START; event.data = &buflen; event.ts = &event_ts; packet_ssrc = event.ssrc; session->callback(session, &event); } process_rtcp_rr(session, packet, &event_ts); break; case RTCP_SDES: if (first && !filter_event(session, ntohl(packet->r.sdes.ssrc))) { event.ssrc = ntohl(packet->r.sdes.ssrc); event.type = RX_RTCP_START; event.data = &buflen; event.ts = &event_ts; packet_ssrc = event.ssrc; session->callback(session, &event); } process_rtcp_sdes(session, packet, &event_ts); break; case RTCP_BYE: if (first && !filter_event(session, ntohl(packet->r.bye.ssrc[0]))) { event.ssrc = ntohl(packet->r.bye.ssrc[0]); event.type = RX_RTCP_START; event.data = &buflen; event.ts = &event_ts; packet_ssrc = event.ssrc; session->callback(session, &event); } process_rtcp_bye(session, packet, &event_ts); break; case RTCP_APP: if (first && !filter_event(session, ntohl(packet->r.app.ssrc))) { event.ssrc = ntohl(packet->r.app.ssrc); event.type = RX_RTCP_START; event.data = &buflen; event.ts = &event_ts; packet_ssrc = event.ssrc; session->callback(session, &event); } process_rtcp_app(session, packet, &event_ts); break; default: debug_msg("RTCP packet with unknown type (%d) ignored.\n", packet->common.pt); break; } packet = (rtcp_t *) ((char *) packet + (4 * (ntohs(packet->common.length) + 1))); first = FALSE; } if (session->avg_rtcp_size < 0) { /* This is the first RTCP packet we've received, set our initial estimate */ /* of the average packet size to be the size of this packet. */ session->avg_rtcp_size = buflen + RTP_LOWER_LAYER_OVERHEAD; } else { /* Update our estimate of the average RTCP packet size. The constants are */ /* 1/16 and 15/16 (section 6.3.3 of draft-ietf-avt-rtp-new-02.txt). */ session->avg_rtcp_size = (0.0625 * (buflen + RTP_LOWER_LAYER_OVERHEAD)) + (0.9375 * session->avg_rtcp_size); } /* Signal that we've finished processing this packet */ if (!filter_event(session, packet_ssrc)) { event.ssrc = packet_ssrc; event.type = RX_RTCP_FINISH; event.data = NULL; event.ts = &event_ts; session->callback(session, &event); } } else { debug_msg("Invalid RTCP packet discarded\n"); session->invalid_rtcp_count++; } }}/** * rtp_recv: * @session: the session pointer (returned by rtp_init()) * @timeout: the amount of time that rtcp_recv() is allowed to block * @curr_rtp_ts: the current time expressed in units of the media * timestamp. * * Receive RTP packets and dispatch them. * * Returns: TRUE if data received, FALSE if the timeout occurred. */int rtp_recv(struct rtp *session, struct timeval *timeout, uint32_t curr_rtp_ts){ check_database(session); udp_fd_zero(); udp_fd_set(session->rtp_socket); udp_fd_set(session->rtcp_socket); if (udp_select(timeout) > 0) { if (udp_fd_isset(session->rtp_socket)) { rtp_recv_data(session, curr_rtp_ts); } if (udp_fd_isset(session->rtcp_socket)) { uint8_t buffer[RTP_MAX_PACKET_LEN]; int buflen; buflen = udp_recv(session->rtcp_socket, buffer, RTP_MAX_PACKET_LEN); rtp_process_ctrl(session, buffer, buflen); } check_database(session); return TRUE; } check_database(session); return FALSE;}/** * rtp_add_csrc: * @session: the session pointer (returned by rtp_init()) * @csrc: Constributing SSRC identifier * * Adds @csrc to list of contributing sources used in SDES items. * Used by mixers and transcoders. * * Return value: TRUE. **/int rtp_add_csrc(struct rtp *session, uint32_t csrc){ /* Mark csrc as something for which we should advertise RTCP SDES items, */ /* in addition to our own SDES. */ source *s; check_database(session); s = get_source(session, csrc); if (s == NULL) { s = create_source(session, csrc, FALSE); debug_msg("Created source 0x%08x as CSRC\n", csrc); } check_source(s); if (!s->should_advertise_sdes) { s->should_advertise_sdes = TRUE; session->csrc_count++; debug_msg("Added CSRC 0x%08lx as CSRC %d\n", csrc, session->csrc_count); } return TRUE;}/** * rtp_del_csrc: * @session: the session pointer (returned by rtp_init()) * @csrc: Constributing SSRC identifier * * Removes @csrc from list of contributing sources used in SDES items. * Used by mixers and transcoders. * * Return value: TRUE on success, FALSE if @csrc is not a valid source. **/int rtp_del_csrc(struct rtp *session, uint32_t csrc){ source *s; check_database(session); s = get_source(session, csrc); if (s == NULL) { debug_msg("Invalid source 0x%08x\n", csrc); return FALSE; } check_source(s); s->should_advertise_sdes = FALSE; session->csrc_count--; if (session->last_advertised_csrc >= session->csrc_count) { session->last_advertised_csrc = 0; } return TRUE;}/** * rtp_set_sdes: * @session: the session pointer (returned by rtp_init()) * @ssrc: the SSRC identifier of a participant * @type: the SDES type represented by @value * @value: the SDES description * @length: the length of the description * * Sets session description information associated with participant * @ssrc. Under normal circumstances applications always use the * @ssrc of the local participant, this SDES information is * transmitted in receiver reports. Setting SDES information for * other participants affects the local SDES entries, but are not * transmitted onto the network. * * Return value: Returns TRUE if participant exists, FALSE otherwise. **/int rtp_set_sdes(struct rtp *session, uint32_t ssrc, rtcp_sdes_type type, const char *value, int length){ source *s; char *v; check_database(session); s = get_source(session, ssrc); if (s == NULL) { debug_msg("Invalid source 0x%08x\n", ssrc); return FALSE; } check_source(s); v = (char *) xmalloc(length + 1); memset(v, '\0', length + 1); memcpy(v, value, length); switch (type) { case RTCP_SDES_CNAME: if (s->cname) xfree(s->cname); s->cname = v; break; case RTCP_SDES_NAME: if (s->name) xfree(s->name); s->name = v; break; case RTCP_SDES_EMAIL: if (s->email) xfree(s->email); s->email = v; break; case RTCP_SDES_PHONE: if (s->phone) xfree(s->phone); s->phone = v; break; case RTCP_SDES_LOC: if (s->loc) xfree(s->loc); s->loc = v; break; case RTCP_SDES_TOOL: if (s->tool) xfree(s->tool); s->tool = v; break; case RTCP_SDES_NOTE: if (s->note) xfree(s->note); s->note = v; break; case RTCP_SDES_PRIV: if (s->priv) xfree(s->priv); s->priv = v; break; default : debug_msg("Unknown SDES item (type=%d, value=%s)\n", type, v); xfree(v); check_database(session); return FALSE; } check_database(session); return TRUE;}/** * rtp_get_sdes: * @session: the session pointer (returned by rtp_init()) * @ssrc: the SSRC identifier of a participant * @type: the SDES information to retrieve * * Recovers session description (SDES) information on participant * identified with @ssrc. The SDES information associated with a * source is updated when receiver reports are received. There are * several different types of SDES information, e.g. username, * location, phone, email. These are enumerated by #rtcp_sdes_type. * * Return value: pointer to string containing SDES description if * received, NULL otherwise. */const char *rtp_get_sdes(struct rtp *session, uint32_t ssrc, rtcp_sdes_type type){ source *s; check_database(session); s = get_source(session, ssrc); if (s == NULL) { debug_msg("Invalid source 0x%08x\n", ssrc); return NULL; } check_source(s); switch (type) { case RTCP_SDES_CNAME: return s->cname; case RTCP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -