1. 背景
在测试 ffmpeg接收 ts over rtp流时,使用工具发了几个连续端口的rtp流,比如:rtp://192.168.1.11:1234, rtp://192.168.1.11:1235等,结果发现ffmpeg在接收纯rtp流时,也将rtcp的端口开启了。看样子是继承了rtsp的做法。
代码如下:
rtpproto.c
static int rtp_open(URLContext *h, const char *uri, int flags)
{
RTPContext *s = h->priv_data;
......
av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
path, sizeof(path), uri);
printf("rtp url:%s\n", uri);
/* extract parameters */
if (s->rtcp_port < 0)
s->rtcp_port = rtp_port + 1;
......
if (s->local_rtcpport < 0) {
s->local_rtcpport = s->local_rtpport + 1;
build_udp_url(s, buf, sizeof(buf),
hostname, s->rtcp_port, s->local_rtcpport,
sources, block);
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags,
&h->interrupt_callback, NULL,
h->protocol_whitelist, h->protocol_blacklist, h) < 0) {
s->local_rtpport = s->local_rtcpport = -1;
continue;
}
break;
}
build_udp_url(s, buf, sizeof(buf),
hostname, s->rtcp_port, s->local_rtcpport,
sources, block);
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
goto fail;
break;
2. 分析
需要将输入流 rtsp://xxx 和 rtp://xxx 区分开处理, rtsp流需要开起rtp和rtcp两个端口; rtp只需要开起一个端口。在RTPContext新加一个参数rtcp_need用来区分输入流。
3. 代码示例
rtpproto.c
typedef struct RTPContext {
......
int rtcp_port, local_rtpport, local_rtcpport;
int rtcp_need;
......
} RTPContext;
rtpproto.c
static int rtp_open(URLContext *h, const char *uri, int flags)
{
RTPContext *s = h->priv_data;
......
/* extract parameters */
if (s->rtcp_port < 0)
s->rtcp_port = rtp_port + 1;
if (s->rtcp_need < 0)
s->rtcp_need = 0;
......
if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
s->connect = strtol(buf, NULL, 10);
}
if (av_find_info_tag(buf, sizeof(buf), "rtcp_need", p)) {
s->rtcp_need = strtol(buf, NULL, 10);
}
if (s->rtcp_need == 1)
{
if (s->local_rtcpport < 0) {
s->local_rtcpport = s->local_rtpport + 1;
.....
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
goto fail;
break;
}
break;
rtsp.c
int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
int lower_transport, const char *real_challenge)
{
RTSPState *rt = s->priv_data;
......
/* first try in specified port range */
while (j <= rt->rtp_port_max) {
AVDictionary *opts = map_to_opts(rt);
ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
"?localport=%d&rtcp_need=1", (rtsp_st->sdp_port)?rtsp_st->sdp_port:j);
......
4. 总结
这个问题本身比较好解决,对熟悉ffmpeg的代码也很有帮助。
版权声明:本文为wlj1012原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。