|
@@ -2104,3 +2104,107 @@ AVInputFormat sdp_demuxer = {
|
|
|
rtsp_fetch_packet,
|
|
|
sdp_read_close,
|
|
|
};
|
|
|
+
|
|
|
+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,
|
|
|
+};
|
|
|
+
|