| Index: source/patched-ffmpeg-mt/libavformat/rtsp.c
|
| ===================================================================
|
| --- source/patched-ffmpeg-mt/libavformat/rtsp.c (revision 65184)
|
| +++ source/patched-ffmpeg-mt/libavformat/rtsp.c (working copy)
|
| @@ -44,10 +44,6 @@
|
| //#define DEBUG
|
| //#define DEBUG_RTP_TCP
|
|
|
| -#if LIBAVFORMAT_VERSION_INT < (53 << 16)
|
| -int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
|
| -#endif
|
| -
|
| /* Timeout values for socket select, in ms,
|
| * and read_packet(), in seconds */
|
| #define SELECT_TIMEOUT_MS 100
|
| @@ -87,6 +83,45 @@
|
| get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
|
| }
|
|
|
| +/** Parse a string p in the form of Range:npt=xx-xx, and determine the start
|
| + * and end time.
|
| + * Used for seeking in the rtp stream.
|
| + */
|
| +static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
|
| +{
|
| + char buf[256];
|
| +
|
| + p += strspn(p, SPACE_CHARS);
|
| + if (!av_stristart(p, "npt=", &p))
|
| + return;
|
| +
|
| + *start = AV_NOPTS_VALUE;
|
| + *end = AV_NOPTS_VALUE;
|
| +
|
| + get_word_sep(buf, sizeof(buf), "-", &p);
|
| + *start = parse_date(buf, 1);
|
| + if (*p == '-') {
|
| + p++;
|
| + get_word_sep(buf, sizeof(buf), "-", &p);
|
| + *end = parse_date(buf, 1);
|
| + }
|
| +// av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
|
| +// av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
|
| +}
|
| +
|
| +static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
|
| +{
|
| + struct addrinfo hints, *ai = NULL;
|
| + memset(&hints, 0, sizeof(hints));
|
| + hints.ai_flags = AI_NUMERICHOST;
|
| + if (getaddrinfo(buf, NULL, &hints, &ai))
|
| + return -1;
|
| + memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen));
|
| + freeaddrinfo(ai);
|
| + return 0;
|
| +}
|
| +
|
| +#if CONFIG_RTPDEC
|
| /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
|
| static int sdp_parse_rtpmap(AVFormatContext *s,
|
| AVCodecContext *codec, RTSPStream *rtsp_st,
|
| @@ -186,44 +221,6 @@
|
| return 0;
|
| }
|
|
|
| -/** Parse a string p in the form of Range:npt=xx-xx, and determine the start
|
| - * and end time.
|
| - * Used for seeking in the rtp stream.
|
| - */
|
| -static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
|
| -{
|
| - char buf[256];
|
| -
|
| - p += strspn(p, SPACE_CHARS);
|
| - if (!av_stristart(p, "npt=", &p))
|
| - return;
|
| -
|
| - *start = AV_NOPTS_VALUE;
|
| - *end = AV_NOPTS_VALUE;
|
| -
|
| - get_word_sep(buf, sizeof(buf), "-", &p);
|
| - *start = parse_date(buf, 1);
|
| - if (*p == '-') {
|
| - p++;
|
| - get_word_sep(buf, sizeof(buf), "-", &p);
|
| - *end = parse_date(buf, 1);
|
| - }
|
| -// av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
|
| -// av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
|
| -}
|
| -
|
| -static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
|
| -{
|
| - struct addrinfo hints, *ai = NULL;
|
| - memset(&hints, 0, sizeof(hints));
|
| - hints.ai_flags = AI_NUMERICHOST;
|
| - if (getaddrinfo(buf, NULL, &hints, &ai))
|
| - return -1;
|
| - memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen));
|
| - freeaddrinfo(ai);
|
| - return 0;
|
| -}
|
| -
|
| typedef struct SDPParseState {
|
| /* SDP only */
|
| struct sockaddr_storage default_ip;
|
| @@ -457,6 +454,7 @@
|
| }
|
| return 0;
|
| }
|
| +#endif /* CONFIG_RTPDEC */
|
|
|
| /* close and free RTSP streams */
|
| void ff_rtsp_close_streams(AVFormatContext *s)
|
| @@ -483,9 +481,9 @@
|
| av_metadata_free(&rtpctx->metadata);
|
| av_free(rtpctx->streams[0]);
|
| av_free(rtpctx);
|
| - } else if (rt->transport == RTSP_TRANSPORT_RDT)
|
| + } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
|
| ff_rdt_parse_close(rtsp_st->transport_priv);
|
| - else
|
| + else if (CONFIG_RTPDEC)
|
| rtp_parse_close(rtsp_st->transport_priv);
|
| }
|
| if (rtsp_st->rtp_handle)
|
| @@ -514,17 +512,17 @@
|
| if (!st)
|
| s->ctx_flags |= AVFMTCTX_NOHEADER;
|
|
|
| - if (s->oformat) {
|
| + if (s->oformat && CONFIG_RTSP_MUXER) {
|
| rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st,
|
| rtsp_st->rtp_handle,
|
| RTSP_TCP_MAX_PACKET_SIZE);
|
| /* Ownership of rtp_handle is passed to the rtp mux context */
|
| rtsp_st->rtp_handle = NULL;
|
| - } else if (rt->transport == RTSP_TRANSPORT_RDT)
|
| + } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
|
| rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
|
| rtsp_st->dynamic_protocol_context,
|
| rtsp_st->dynamic_handler);
|
| - else
|
| + else if (CONFIG_RTPDEC)
|
| rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
|
| rtsp_st->sdp_payload_type,
|
| (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
|
| @@ -532,7 +530,7 @@
|
|
|
| if (!rtsp_st->transport_priv) {
|
| return AVERROR(ENOMEM);
|
| - } else if (rt->transport != RTSP_TRANSPORT_RDT) {
|
| + } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
|
| if (rtsp_st->dynamic_handler) {
|
| rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
|
| rtsp_st->dynamic_protocol_context,
|
| @@ -544,13 +542,6 @@
|
| }
|
|
|
| #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
|
| -static int rtsp_probe(AVProbeData *p)
|
| -{
|
| - if (av_strstart(p->filename, "rtsp:", NULL))
|
| - return AVPROBE_SCORE_MAX;
|
| - return 0;
|
| -}
|
| -
|
| static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
|
| {
|
| const char *p;
|
| @@ -1024,7 +1015,7 @@
|
| #endif
|
|
|
| rtp_opened:
|
| - port = rtp_get_local_port(rtsp_st->rtp_handle);
|
| + port = rtp_get_local_rtp_port(rtsp_st->rtp_handle);
|
| have_port:
|
| snprintf(transport, sizeof(transport) - 1,
|
| "%s/UDP;", trans_pref);
|
| @@ -1068,7 +1059,7 @@
|
| snprintf(cmd, sizeof(cmd),
|
| "Transport: %s\r\n",
|
| transport);
|
| - if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
|
| + if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {
|
| char real_res[41], real_csum[9];
|
| ff_rdt_calc_response_and_checksum(real_res, real_csum,
|
| real_challenge);
|
| @@ -1133,7 +1124,8 @@
|
| * potential NAT router by sending dummy packets.
|
| * RTP/RTCP dummy packets are used for RDT, too.
|
| */
|
| - if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat)
|
| + if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&
|
| + CONFIG_RTPDEC)
|
| rtp_send_punch_packets(rtsp_st->rtp_handle);
|
| break;
|
| }
|
| @@ -1232,6 +1224,7 @@
|
| return 0;
|
| }
|
|
|
| +#if CONFIG_RTSP_DEMUXER
|
| static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
|
| {
|
| RTSPState *rt = s->priv_data;
|
| @@ -1268,7 +1261,9 @@
|
|
|
| return 0;
|
| }
|
| +#endif /* CONFIG_RTSP_DEMUXER */
|
|
|
| +#if CONFIG_RTSP_MUXER
|
| static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr)
|
| {
|
| RTSPState *rt = s->priv_data;
|
| @@ -1332,6 +1327,7 @@
|
|
|
| return 0;
|
| }
|
| +#endif /* CONFIG_RTSP_MUXER */
|
|
|
| void ff_rtsp_close_connections(AVFormatContext *s)
|
| {
|
| @@ -1548,9 +1544,9 @@
|
| break;
|
| }
|
|
|
| - if (s->iformat)
|
| + if (s->iformat && CONFIG_RTSP_DEMUXER)
|
| err = rtsp_setup_input_streams(s, reply);
|
| - else
|
| + else if (CONFIG_RTSP_MUXER)
|
| err = rtsp_setup_output_streams(s, host);
|
| if (err)
|
| goto fail;
|
| @@ -1589,6 +1585,7 @@
|
| }
|
| #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */
|
|
|
| +#if CONFIG_RTPDEC
|
| static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
|
| uint8_t *buf, int buf_size, int64_t wait_end)
|
| {
|
| @@ -1777,8 +1774,16 @@
|
|
|
| return ret;
|
| }
|
| +#endif /* CONFIG_RTPDEC */
|
|
|
| #if CONFIG_RTSP_DEMUXER
|
| +static int rtsp_probe(AVProbeData *p)
|
| +{
|
| + if (av_strstart(p->filename, "rtsp:", NULL))
|
| + return AVPROBE_SCORE_MAX;
|
| + return 0;
|
| +}
|
| +
|
| static int rtsp_read_header(AVFormatContext *s,
|
| AVFormatParameters *ap)
|
| {
|
| @@ -2020,6 +2025,7 @@
|
| };
|
| #endif /* CONFIG_RTSP_DEMUXER */
|
|
|
| +#if CONFIG_SDP_DEMUXER
|
| static int sdp_probe(AVProbeData *p1)
|
| {
|
| const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
|
| @@ -2104,3 +2110,110 @@
|
| rtsp_fetch_packet,
|
| sdp_read_close,
|
| };
|
| +#endif /* CONFIG_SDP_DEMUXER */
|
| +
|
| +#if CONFIG_RTP_DEMUXER
|
| +static int rtp_probe(AVProbeData *p)
|
| +{
|
| + if (av_strstart(p->filename, "rtp:", NULL))
|
| + return AVPROBE_SCORE_MAX;
|
| + return 0;
|
| +}
|
| +
|
| +static int rtp_read_header(AVFormatContext *s,
|
| + AVFormatParameters *ap)
|
| +{
|
| + uint8_t recvbuf[1500];
|
| + char host[500], sdp[500];
|
| + int ret, port;
|
| + URLContext* in = NULL;
|
| + int payload_type;
|
| + AVCodecContext codec;
|
| + struct sockaddr_storage addr;
|
| + ByteIOContext pb;
|
| + socklen_t addrlen = sizeof(addr);
|
| +
|
| + if (!ff_network_init())
|
| + return AVERROR(EIO);
|
| +
|
| + ret = url_open(&in, s->filename, URL_RDONLY);
|
| + if (ret)
|
| + goto fail;
|
| +
|
| + while (1) {
|
| + ret = url_read(in, recvbuf, sizeof(recvbuf));
|
| + if (ret == AVERROR(EAGAIN))
|
| + continue;
|
| + if (ret < 0)
|
| + goto fail;
|
| + if (ret < 12) {
|
| + av_log(s, AV_LOG_WARNING, "Received too short packet\n");
|
| + continue;
|
| + }
|
| +
|
| + if ((recvbuf[0] & 0xc0) != 0x80) {
|
| + av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet "
|
| + "received\n");
|
| + continue;
|
| + }
|
| +
|
| + payload_type = recvbuf[1] & 0x7f;
|
| + break;
|
| + }
|
| + getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen);
|
| + url_close(in);
|
| + in = NULL;
|
| +
|
| + memset(&codec, 0, sizeof(codec));
|
| + if (ff_rtp_get_codec_info(&codec, payload_type)) {
|
| + av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
|
| + "without an SDP file describing it\n",
|
| + payload_type);
|
| + goto fail;
|
| + }
|
| + if (codec.codec_type != AVMEDIA_TYPE_DATA) {
|
| + av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
|
| + "properly you need an SDP file "
|
| + "describing it\n");
|
| + }
|
| +
|
| + av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
|
| + NULL, 0, s->filename);
|
| +
|
| + snprintf(sdp, sizeof(sdp),
|
| + "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
|
| + addr.ss_family == AF_INET ? 4 : 6, host,
|
| + codec.codec_type == AVMEDIA_TYPE_DATA ? "application" :
|
| + codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
|
| + port, payload_type);
|
| + av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);
|
| +
|
| + init_put_byte(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
|
| + s->pb = &pb;
|
| +
|
| + /* sdp_read_header initializes this again */
|
| + ff_network_close();
|
| +
|
| + ret = sdp_read_header(s, ap);
|
| + s->pb = NULL;
|
| + return ret;
|
| +
|
| +fail:
|
| + if (in)
|
| + url_close(in);
|
| + ff_network_close();
|
| + return ret;
|
| +}
|
| +
|
| +AVInputFormat rtp_demuxer = {
|
| + "rtp",
|
| + NULL_IF_CONFIG_SMALL("RTP input format"),
|
| + sizeof(RTSPState),
|
| + rtp_probe,
|
| + rtp_read_header,
|
| + rtsp_fetch_packet,
|
| + sdp_read_close,
|
| + .flags = AVFMT_NOFILE,
|
| +};
|
| +#endif /* CONFIG_RTP_DEMUXER */
|
| +
|
|
|