📄 rtsp.c
字号:
static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, uint8_t *buf, int buf_size){ RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; fd_set rfds; int fd1, fd2, fd_max, n, i, ret; struct timeval tv; for(;;) { if (url_interrupt_cb()) return AVERROR(EINTR); FD_ZERO(&rfds); fd_max = -1; for(i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; /* currently, we cannot probe RTCP handle because of blocking restrictions */ rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); if (fd1 > fd_max) fd_max = fd1; FD_SET(fd1, &rfds); } tv.tv_sec = 0; tv.tv_usec = 100 * 1000; n = select(fd_max + 1, &rfds, NULL, NULL, &tv); if (n > 0) { for(i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2); if (FD_ISSET(fd1, &rfds)) { ret = url_read(rtsp_st->rtp_handle, buf, buf_size); if (ret > 0) { *prtsp_st = rtsp_st; return ret; } } } } }}static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt){ RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; int ret, len; uint8_t buf[RTP_MAX_PACKET_LENGTH]; /* get next frames from the same RTP packet */ if (rt->cur_rtp) { ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0); if (ret == 0) { rt->cur_rtp = NULL; return 0; } else if (ret == 1) { return 0; } else { rt->cur_rtp = NULL; } } /* read next RTP packet */ redo: switch(rt->protocol) { default: case RTSP_PROTOCOL_RTP_TCP: len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf)); break; case RTSP_PROTOCOL_RTP_UDP: case RTSP_PROTOCOL_RTP_UDP_MULTICAST: len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf)); if (len >=0 && rtsp_st->rtp_ctx) rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len); break; } if (len < 0) return len; ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len); if (ret < 0) goto redo; if (ret == 1) { /* more packets may follow, so we save the RTP context */ rt->cur_rtp = rtsp_st->rtp_ctx; } return 0;}static int rtsp_read_play(AVFormatContext *s){ RTSPState *rt = s->priv_data; RTSPHeader reply1, *reply = &reply1; char cmd[1024]; av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); if (rt->state == RTSP_STATE_PAUSED) { snprintf(cmd, sizeof(cmd), "PLAY %s RTSP/1.0\r\n", s->filename); } else { snprintf(cmd, sizeof(cmd), "PLAY %s RTSP/1.0\r\n" "Range: npt=%0.3f-\r\n", s->filename, (double)rt->seek_timestamp / AV_TIME_BASE); } rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { return -1; } else { rt->state = RTSP_STATE_PLAYING; return 0; }}/* pause the stream */static int rtsp_read_pause(AVFormatContext *s){ RTSPState *rt = s->priv_data; RTSPHeader reply1, *reply = &reply1; char cmd[1024]; rt = s->priv_data; if (rt->state != RTSP_STATE_PLAYING) return 0; snprintf(cmd, sizeof(cmd), "PAUSE %s RTSP/1.0\r\n", s->filename); rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { return -1; } else { rt->state = RTSP_STATE_PAUSED; return 0; }}static int rtsp_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags){ RTSPState *rt = s->priv_data; rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q); switch(rt->state) { default: case RTSP_STATE_IDLE: break; case RTSP_STATE_PLAYING: if (rtsp_read_play(s) != 0) return -1; break; case RTSP_STATE_PAUSED: rt->state = RTSP_STATE_IDLE; break; } return 0;}static int rtsp_read_close(AVFormatContext *s){ RTSPState *rt = s->priv_data; RTSPHeader reply1, *reply = &reply1; char cmd[1024];#if 0 /* NOTE: it is valid to flush the buffer here */ if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { url_fclose(&rt->rtsp_gb); }#endif snprintf(cmd, sizeof(cmd), "TEARDOWN %s RTSP/1.0\r\n", s->filename); rtsp_send_cmd(s, cmd, reply, NULL); rtsp_close_streams(rt); url_close(rt->rtsp_hd); return 0;}#ifdef CONFIG_RTSP_DEMUXERAVInputFormat rtsp_demuxer = { "rtsp", NULL_IF_CONFIG_SMALL("RTSP input format"), sizeof(RTSPState), rtsp_probe, rtsp_read_header, rtsp_read_packet, rtsp_read_close, rtsp_read_seek,#ifdef __CW32__ 0, AVFMT_NOFILE, 0, 0, rtsp_read_play, rtsp_read_pause,#else .flags = AVFMT_NOFILE, .read_play = rtsp_read_play, .read_pause = rtsp_read_pause,#endif};#endifstatic int sdp_probe(AVProbeData *p1){#ifdef __CW32__ const char *p = (const char*)p1->buf, *p_end = (const char*)(p1->buf + p1->buf_size);#else const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;#endif /* we look for a line beginning "c=IN IP4" */ while (p < p_end && *p != '\0') { if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL)) return AVPROBE_SCORE_MAX / 2; while(p < p_end - 1 && *p != '\n') p++; if (++p >= p_end) break; if (*p == '\r') p++; } return 0;}#define SDP_MAX_SIZE 8192static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap){ RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; int size, i, err; char *content; char url[1024]; AVStream *st; /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE);#ifdef __CW32__ size = get_buffer(s->pb, (unsigned char*)content, SDP_MAX_SIZE - 1);#else size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);#endif if (size <= 0) { av_free(content); return AVERROR_INVALIDDATA; } content[size] ='\0'; sdp_parse(s, content); av_free(content); /* open each RTP stream */ for(i=0;i<rt->nb_rtsp_streams;i++) { rtsp_st = rt->rtsp_streams[i]; snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d", inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port, rtsp_st->sdp_port, rtsp_st->sdp_ttl); if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; } /* open the RTP context */ st = NULL; if (rtsp_st->stream_index >= 0) st = s->streams[rtsp_st->stream_index]; if (!st) s->ctx_flags |= AVFMTCTX_NOHEADER; rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data); if (!rtsp_st->rtp_ctx) { err = AVERROR(ENOMEM); goto fail; } else { if(rtsp_st->dynamic_handler) { rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context; rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet; } } } return 0; fail: rtsp_close_streams(rt); return err;}static int sdp_read_packet(AVFormatContext *s, AVPacket *pkt){ return rtsp_read_packet(s, pkt);}static int sdp_read_close(AVFormatContext *s){ RTSPState *rt = s->priv_data; rtsp_close_streams(rt); return 0;}#ifdef CONFIG_SDP_DEMUXERAVInputFormat sdp_demuxer = { "sdp", NULL_IF_CONFIG_SMALL("SDP"), sizeof(RTSPState), sdp_probe, sdp_read_header, sdp_read_packet, sdp_read_close,};#endif#ifdef CONFIG_REDIR_DEMUXER/* dummy redirector format (used directly in av_open_input_file now) */static int redir_probe(AVProbeData *pd){ const char *p;#ifdef __CW32__ p = (const char*)pd->buf;#else p = pd->buf;#endif while (redir_isspace(*p)) p++; if (av_strstart(p, "http://", NULL) || av_strstart(p, "rtsp://", NULL)) return AVPROBE_SCORE_MAX; return 0;}static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap){ char buf[4096], *q; int c; AVFormatContext *ic = NULL; ByteIOContext *f = s->pb; /* parse each URL and try to open it */ c = url_fgetc(f); while (c != URL_EOF) { /* skip spaces */ for(;;) { if (!redir_isspace(c)) break; c = url_fgetc(f); } if (c == URL_EOF) break; /* record url */ q = buf; for(;;) { if (c == URL_EOF || redir_isspace(c)) break; if ((q - buf) < sizeof(buf) - 1) *q++ = c; c = url_fgetc(f); } *q = '\0'; //printf("URL='%s'\n", buf); /* try to open the media file */ if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0) break; } if (!ic) return AVERROR(EIO); *s = *ic; url_fclose(f); return 0;}AVInputFormat redir_demuxer = { "redir", NULL_IF_CONFIG_SMALL("Redirector format"), 0, redir_probe, redir_read_header, NULL, NULL,};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -