static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; fd_set rfds; int n, tcp_fd; struct timeval tv; AVFormatContext *rtpctx; AVPacket local_pkt; int ret; tcp_fd = url_get_file_handle(rt->rtsp_hd); while (1) { FD_ZERO(&rfds); FD_SET(tcp_fd, &rfds); tv.tv_sec = 0; tv.tv_usec = 0; n = select(tcp_fd + 1, &rfds, NULL, NULL, &tv); if (n <= 0) break; if (FD_ISSET(tcp_fd, &rfds)) { RTSPMessageHeader reply; /* Don't let ff_rtsp_read_reply handle interleaved packets, * since it would block and wait for an RTSP reply on the socket * (which may not be coming any time soon) if it handles * interleaved packets internally. */ ret = ff_rtsp_read_reply(s, &reply, NULL, 1); if (ret < 0) return AVERROR(EPIPE); if (ret == 1) ff_rtsp_skip_packet(s); /* XXX: parse message */ if (rt->state != RTSP_STATE_STREAMING) return AVERROR(EPIPE); } } if (pkt->stream_index < 0 || pkt->stream_index >= rt->nb_rtsp_streams) return AVERROR_INVALIDDATA; rtsp_st = rt->rtsp_streams[pkt->stream_index]; rtpctx = rtsp_st->transport_priv; /* Use a local packet for writing to the chained muxer, otherwise * the internal stream_index = 0 becomes visible to the muxer user. */ local_pkt = *pkt; local_pkt.stream_index = 0; ret = av_write_frame(rtpctx, &local_pkt); /* av_write_frame does all the RTP packetization. If using TCP as * transport, rtpctx->pb is only a dyn_packet_buf that queues up the * packets, so we need to send them out on the TCP connection separately. */ if (!ret && rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) ret = tcp_write_packet(s, rtsp_st); return ret; }
static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt) { struct SAPState *sap = s->priv_data; int fd = url_get_file_handle(sap->ann_fd); int n, ret; fd_set rfds; struct timeval tv; uint8_t recvbuf[1500]; if (sap->eof) return AVERROR_EOF; while (1) { FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = tv.tv_usec = 0; n = select(fd + 1, &rfds, NULL, NULL, &tv); if (n <= 0 || !FD_ISSET(fd, &rfds)) break; ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf)); if (ret >= 8) { uint16_t hash = AV_RB16(&recvbuf[2]); /* Should ideally check the source IP address, too */ if (recvbuf[0] & 0x04 && hash == sap->hash) { /* Stream deletion */ sap->eof = 1; return AVERROR_EOF; } } } ret = av_read_frame(sap->sdp_ctx, pkt); if (ret < 0) return ret; if (s->ctx_flags & AVFMTCTX_NOHEADER) { while (sap->sdp_ctx->nb_streams > s->nb_streams) { int i = s->nb_streams; AVStream *st = av_new_stream(s, i); if (!st) { av_free_packet(pkt); return AVERROR(ENOMEM); } avcodec_copy_context(st->codec, sap->sdp_ctx->streams[i]->codec); st->time_base = sap->sdp_ctx->streams[i]->time_base; } } return ret; }
static int rtp_open(URLContext *h, const char *uri, int flags) { RTPContext *s; int rtp_port, rtcp_port, is_output, ttl, local_rtp_port, local_rtcp_port, max_packet_size; char hostname[256]; char buf[1024]; char path[1024]; const char *p; is_output = (flags & URL_WRONLY); s = av_mallocz(sizeof(RTPContext)); if (!s) return AVERROR(ENOMEM); h->priv_data = s; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); /* extract parameters */ ttl = -1; rtcp_port = rtp_port+1; local_rtp_port = -1; local_rtcp_port = -1; max_packet_size = -1; p = strchr(uri, '?'); if (p) { if (find_info_tag(buf, sizeof(buf), "ttl", p)) { ttl = strtol(buf, NULL, 10); } if (find_info_tag(buf, sizeof(buf), "rtcpport", p)) { rtcp_port = strtol(buf, NULL, 10); } if (find_info_tag(buf, sizeof(buf), "localport", p)) { local_rtp_port = strtol(buf, NULL, 10); } if (find_info_tag(buf, sizeof(buf), "localrtpport", p)) { local_rtp_port = strtol(buf, NULL, 10); } if (find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { local_rtcp_port = strtol(buf, NULL, 10); } if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) { max_packet_size = strtol(buf, NULL, 10); } } build_udp_url(buf, sizeof(buf), hostname, rtp_port, local_rtp_port, ttl, max_packet_size); if (url_open(&s->rtp_hd, buf, flags) < 0) goto fail; if (local_rtp_port>=0 && local_rtcp_port<0) local_rtcp_port = udp_get_local_port(s->rtp_hd) + 1; build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size); if (url_open(&s->rtcp_hd, buf, flags) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle access */ s->rtp_fd = url_get_file_handle(s->rtp_hd); s->rtcp_fd = url_get_file_handle(s->rtcp_hd); h->max_packet_size = url_get_max_packet_size(s->rtp_hd); h->is_streamed = 1; return 0; fail: if (s->rtp_hd) url_close(s->rtp_hd); if (s->rtcp_hd) url_close(s->rtcp_hd); av_free(s); return AVERROR(EIO); }
static int http_get_file_handle(URLContext *h) { HTTPContext *s = h->priv_data; return url_get_file_handle(s->hd); }