|
|
|
@@ -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, |
|
|
|
}; |
|
|
|
|