int hc_reconnected:1;
int hc_keepalive:1;
int hc_in_data:1;
+ int hc_in_rtp_data:1;
int hc_chunked:1;
int hc_chunk_trails:1;
int hc_running:1;
char *hc_rtp_dest;
int hc_rtp_port;
int hc_rtpc_port;
+ int hc_rtp_tcp;
+ int hc_rtcp_tcp;
int hc_rtcp_server_port;
int hc_rtp_multicast:1;
long hc_rtsp_stream_id;
int (*hc_hdr_received) (http_client_t *hc);
int (*hc_data_received)(http_client_t *hc, void *buf, size_t len);
int (*hc_data_complete)(http_client_t *hc);
+ int (*hc_rtp_data_received)(http_client_t *hc, void *buf, size_t len);
+ int (*hc_rtp_data_complete)(http_client_t *hc);
void (*hc_conn_closed) (http_client_t *hc, int err);
};
if (result < 0)
http_client_shutdown(hc, 0, 0);
hc->hc_in_data = 0;
+ hc->hc_in_rtp_data = 0;
hc->hc_hsize = 0;
hc->hc_csize = 0;
hc->hc_rpos = 0;
tvhtrace("httpc", "%04X: received %s data", shortid(hc), http_ver2str(hc->hc_version));
tvhlog_hexdump("httpc", hc->hc_data, hc->hc_csize);
}
- if (hc->hc_data_complete) {
+ if (hc->hc_in_rtp_data && hc->hc_rtp_data_complete) {
+ res = hc->hc_rtp_data_complete(hc);
+ if (res < 0)
+ return http_client_flush(hc, res);
+ } else if (hc->hc_data_complete) {
res = hc->hc_data_complete(hc);
if (res < 0)
return http_client_flush(hc, res);
char *buf, *saveptr, *argv[3], *d, *p;
int ver, res, delimsize = 4;
ssize_t r;
- size_t len;
+ size_t len, limit;
if (hc == NULL)
return 0;
}
buf = alloca(hc->hc_io_size);
-
- if (!hc->hc_in_data && hc->hc_rpos > 3) {
- if ((d = strstr(hc->hc_rbuf, "\r\n\r\n")) != NULL)
+ if (!hc->hc_in_data && !hc->hc_in_rtp_data && hc->hc_rpos > 3) {
+ if (hc->hc_version == RTSP_VERSION_1_0 && hc->hc_rbuf[0] == '$')
+ goto rtsp_data;
+ else if ((d = strstr(hc->hc_rbuf, "\r\n\r\n")) != NULL)
goto header;
if ((d = strstr(hc->hc_rbuf, "\n\n")) != NULL) {
delimsize = 2;
r = http_client_ssl_recv(hc, buf, hc->hc_io_size);
else
r = recv(hc->hc_fd, buf, hc->hc_io_size, MSG_DONTWAIT);
- tvhtrace("httpc", "%04X: recv %zi", shortid(hc), r);
if (r == 0) {
if (hc->hc_in_data && !hc->hc_keepalive)
return http_client_finish(hc);
return http_client_flush(hc, -errno);
}
if (r > 0 && tvhtrace_enabled()) {
- tvhtrace("httpc", "%04X: received %s answer", shortid(hc), http_ver2str(hc->hc_version));
- tvhlog_hexdump("httpc", buf, r);
+ tvhtrace("httpc", "%04X: received %s answer (len = %zd)", shortid(hc), http_ver2str(hc->hc_version), r);
+ tvhlog_hexdump("httpc", buf, MIN(64, r));
}
- if (hc->hc_in_data) {
+ limit = hc->hc_version == RTSP_VERSION_1_0 ? hc->hc_io_size * 2 : 16*1024;
+ if (hc->hc_in_data && !hc->hc_in_rtp_data) {
res = http_client_data_received(hc, buf, r, 0);
if (res < 0)
return http_client_flush(hc, res);
}
if (hc->hc_rsize < r + hc->hc_rpos) {
- if (hc->hc_rsize + r > 16*1024)
+ if (hc->hc_rsize + r > limit)
return http_client_flush(hc, -EMSGSIZE);
hc->hc_rsize += r;
hc->hc_rbuf = realloc(hc->hc_rbuf, hc->hc_rsize + 1);
next_header:
if (hc->hc_rpos < 3)
return HTTP_CON_RECEIVING;
+ if (hc->hc_version == RTSP_VERSION_1_0 && hc->hc_rbuf[0] == '$')
+ goto rtsp_data;
if ((d = strstr(hc->hc_rbuf, "\r\n\r\n")) == NULL) {
delimsize = 2;
if ((d = strstr(hc->hc_rbuf, "\n\n")) == NULL)
if (res < 0)
return http_client_flush(hc, -EINVAL);
}
+ tvhtrace("httpc", "header parse1");
p = http_arg_get(&hc->hc_args, "Content-Length");
if (p) {
hc->hc_csize = atoll(p);
if (res < 0)
return http_client_flush(hc, res);
}
- hc->hc_rpos -= hc->hc_hsize;
- len = hc->hc_rpos;
+ len = hc->hc_rpos - hc->hc_hsize;
+ hc->hc_rpos = 0;
if (hc->hc_code == HTTP_STATUS_CONTINUE) {
memmove(hc->hc_rbuf, hc->hc_rbuf + hc->hc_hsize, len);
+ hc->hc_rpos = len;
goto next_header;
}
- hc->hc_rpos = 0;
if (hc->hc_version == RTSP_VERSION_1_0 && !hc->hc_csize) {
hc->hc_csize = -1;
hc->hc_in_data = 0;
+ memmove(hc->hc_rbuf, hc->hc_rbuf + hc->hc_hsize, len);
+ hc->hc_rpos = len;
+ return http_client_finish(hc);
} else {
hc->hc_in_data = 1;
}
if (res > 0)
return http_client_finish(hc);
goto retry;
+
+rtsp_data:
+ /* RTSP embedded data */
+ r = 0;
+ res = HTTP_CON_RECEIVING;
+ hc->hc_in_data = 0;
+ hc->hc_in_rtp_data = 0;
+ while (hc->hc_rpos > r + 3) {
+ hc->hc_csize = 4 + ((hc->hc_rbuf[r+2] << 8) | hc->hc_rbuf[r+3]);
+ hc->hc_chunked = 0;
+ if (r + hc->hc_csize > hc->hc_rpos) {
+ memmove(hc->hc_rbuf, hc->hc_rbuf + r, hc->hc_rpos - r);
+ hc->hc_rpos -= r;
+ hc->hc_in_rtp_data = 1;
+ if (r == 0)
+ goto retry;
+ return HTTP_CON_RECEIVING;
+ }
+ if (hc->hc_rtp_data_received) {
+ res = hc->hc_rtp_data_received(hc, hc->hc_rbuf + r, hc->hc_csize);
+ if (res < 0)
+ return res;
+ } else {
+ res = 0;
+ }
+ r += hc->hc_csize;
+ if (res < 0)
+ return http_client_flush(hc, res);
+ hc->hc_in_rtp_data = 1;
+ res = http_client_finish(hc);
+ hc->hc_in_rtp_data = 0;
+ if (res < 0)
+ return http_client_flush(hc, res);
+ res = HTTP_CON_RECEIVING;
+ if (hc->hc_rpos < r + 4 || hc->hc_rbuf[r] != '$') {
+ memcpy(hc->hc_rbuf, hc->hc_rbuf + r, hc->hc_rpos - r);
+ hc->hc_rpos -= r;
+ goto next_header;
+ }
+ }
+ return res;
}
/*
tsdebug_write(mpegts_mux_t *mm, uint8_t *buf, size_t len)
{
#if ENABLE_TSDEBUG
- if (mm->mm_tsdebug_fd2 >= 0)
+ if (mm && mm->mm_tsdebug_fd2 >= 0)
if (write(mm->mm_tsdebug_fd2, buf, len) != len)
tvherror("tsdebug", "unable to write input data (%i)", errno);
#endif
.notify = satip_device_class_tunercfg_notify,
.def.s = "Auto"
},
+ {
+ .type = PT_BOOL,
+ .id = "tcp_mode",
+ .name = N_("RTSP/TCP (embedded data)"),
+ .opts = PO_ADVANCED,
+ .off = offsetof(satip_device_t, sd_tcp_mode),
+ },
{
.type = PT_BOOL,
.id = "fast_switch",
efd = tvhpoll_create(1);
rtsp = http_client_connect(lfe, RTSP_VERSION_1_0, "rstp",
- lfe->sf_device->sd_info.addr,
- lfe->sf_device->sd_info.rtsp_port,
- satip_frontend_bindaddr(lfe));
+ lfe->sf_device->sd_info.addr,
+ lfe->sf_device->sd_info.rtsp_port,
+ satip_frontend_bindaddr(lfe));
if (rtsp == NULL)
goto done;
*rtsp = NULL;
}
+static int
+satip_frontend_rtp_data_received( http_client_t *hc, void *buf, size_t len )
+{
+ int c, pos;
+ uint32_t nseq, unc;
+ uint8_t *b = buf, *p;
+ satip_frontend_t *lfe = hc->hc_aux;
+ mpegts_mux_instance_t *mmi;
+
+ if (len < 4)
+ return -EINVAL;
+
+ if (b[1] == 0) {
+
+ p = b + 4;
+ c = len - 4;
+
+ /* Strip RTP header */
+ if (c < 12)
+ return 0;
+ if ((p[0] & 0xc0) != 0x80)
+ return 0;
+ if ((p[1] & 0x7f) != 33)
+ return 0;
+ pos = ((p[0] & 0x0f) * 4) + 12;
+ if (p[0] & 0x10) {
+ if (c < pos + 4)
+ return 0;
+ pos += (((p[pos+2] << 8) | p[pos+3]) + 1) * 4;
+ }
+ if (c <= pos || ((c - pos) % 188) != 0)
+ return 0;
+ /* Use uncorrectable value to notify RTP delivery issues */
+ nseq = (p[2] << 8) | p[3];
+ unc = 0;
+ if (lfe->sf_seq == -1)
+ lfe->sf_seq = nseq;
+ else if (((lfe->sf_seq + 1) & 0xffff) != nseq) {
+ unc = ((c - pos) / 188) * (uint32_t)((uint16_t)nseq-(uint16_t)(lfe->sf_seq+1));
+ tvhtrace("satip", "TCP/RTP discontinuity (%i != %i)", lfe->sf_seq + 1, nseq);
+ }
+ lfe->sf_seq = nseq;
+
+ /* Process */
+ tsdebug_write((mpegts_mux_t *)lfe->sf_curmux, p + pos, c - pos);
+ sbuf_append(&lfe->sf_sbuf, p + pos, c - pos);
+
+ if (lfe->sf_sbuf.sb_ptr > 64 * 1024 ||
+ lfe->sf_last_data_tstamp != dispatch_clock) {
+ pthread_mutex_lock(&lfe->sf_dvr_lock);
+ if (lfe->sf_req == lfe->sf_req_thread) {
+ mmi = lfe->sf_req->sf_mmi;
+ mmi->tii_stats.unc += unc;
+ mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi,
+ &lfe->sf_sbuf, NULL, NULL);
+ }
+ pthread_mutex_unlock(&lfe->sf_dvr_lock);
+ lfe->sf_last_data_tstamp = dispatch_clock;
+ }
+
+ } else if (b[1] == 1) {
+
+ /* note: satip_frontend_decode_rtcp puts '\0' at the end (string termination) */
+ len -= 4;
+ memmove(b, b + 4, len);
+
+ pthread_mutex_lock(&lfe->sf_dvr_lock);
+ if (lfe->sf_req == lfe->sf_req_thread)
+ satip_frontend_decode_rtcp(lfe, lfe->sf_display_name,
+ lfe->sf_req->sf_mmi, b, len);
+ pthread_mutex_unlock(&lfe->sf_dvr_lock);
+
+ }
+ return 0;
+}
+
static void *
satip_frontend_input_thread ( void *aux )
{
struct iovec *iovec;
uint8_t b[2048], session[32];
uint8_t *p;
- sbuf_t sb;
+ sbuf_t *sb;
int pos, nfds, i, r, tc, rtp_port, start = 0;
size_t c;
tvhpoll_event_t ev[3];
rtsp = NULL;
/* Setup buffers */
- sbuf_init(&sb);
+ sbuf_init(sb = &lfe->sf_sbuf);
udp_multirecv_init(&um, 0, 0);
/*
* New tune
*/
new_tune:
- sbuf_free(&sb);
+ sbuf_free(sb);
udp_multirecv_free(&um);
udp_close(rtcp);
udp_close(rtp);
if (rtsp && !lfe->sf_device->sd_fast_switch)
satip_frontend_close_rtsp(lfe, efd, &rtsp);
+ if (rtsp)
+ rtsp->hc_rtp_data_received = NULL;
+
memset(ev, 0, sizeof(ev));
ev[0].events = TVHPOLL_IN;
ev[0].fd = lfe->sf_dvr_pipe.rd;
tvhpoll_add(efd, ev, 1);
lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
+ lfe->sf_display_name = buf;
while (!start) {
if (!lfe->sf_req_thread)
goto new_tune;
- mmi = tr->sf_mmi;
- changing = 0;
- ms = 500;
- fatal = 0;
- running = 1;
- seq = -1;
- play2 = 1;
- rtsp_flags = 0;
-
- if (udp_bind_double(&rtp, &rtcp,
- "satip", "rtp", "rtpc",
- satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port,
- NULL, SATIP_BUF_SIZE, 16384, 4*1024, 4*1024) < 0) {
- satip_frontend_tuning_error(lfe, tr);
- goto done;
- }
+ mmi = tr->sf_mmi;
+ changing = 0;
+ ms = 500;
+ fatal = 0;
+ running = 1;
+ seq = -1;
+ lfe->sf_seq = -1;
+ play2 = 1;
+ rtsp_flags = lfe->sf_device->sd_tcp_mode ? SATIP_SETUP_TCP : 0;
+
+ if ((rtsp_flags & SATIP_SETUP_TCP) == 0) {
+ if (udp_bind_double(&rtp, &rtcp,
+ "satip", "rtp", "rtpc",
+ satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port,
+ NULL, SATIP_BUF_SIZE, 16384, 4*1024, 4*1024) < 0) {
+ satip_frontend_tuning_error(lfe, tr);
+ goto done;
+ }
- rtp_port = ntohs(IP_PORT(rtp->ip));
+ rtp_port = ntohs(IP_PORT(rtp->ip));
- tvhtrace("satip", "%s - local RTP port %i RTCP port %i",
- lfe->mi_name,
- ntohs(IP_PORT(rtp->ip)),
- ntohs(IP_PORT(rtcp->ip)));
+ tvhtrace("satip", "%s - local RTP port %i RTCP port %i",
+ lfe->mi_name,
+ ntohs(IP_PORT(rtp->ip)),
+ ntohs(IP_PORT(rtcp->ip)));
- if (rtp == NULL || rtcp == NULL || mmi == NULL) {
+ if (rtp == NULL || rtcp == NULL) {
+ satip_frontend_tuning_error(lfe, tr);
+ goto done;
+ }
+ } else {
+ rtp_port = -1;
+ }
+
+ if (mmi == NULL) {
satip_frontend_tuning_error(lfe, tr);
goto done;
}
- lm = (dvb_mux_t *)mmi->mmi_mux;
+ lfe->sf_curmux = lm = (dvb_mux_t *)mmi->mmi_mux;
lfe_master = lfe;
if (lfe->sf_master)
/* Setup poll */
memset(ev, 0, sizeof(ev));
- ev[0].events = TVHPOLL_IN;
- ev[0].fd = rtp->fd;
- ev[0].data.ptr = rtp;
- ev[1].events = TVHPOLL_IN;
- ev[1].fd = rtcp->fd;
- ev[1].data.ptr = rtcp;
+ nfds = 0;
+ if ((rtsp_flags & SATIP_SETUP_TCP) == 0) {
+ ev[nfds].events = TVHPOLL_IN;
+ ev[nfds].fd = rtp->fd;
+ ev[nfds].data.ptr = rtp;
+ nfds++;
+ ev[nfds].events = TVHPOLL_IN;
+ ev[nfds].fd = rtcp->fd;
+ ev[nfds].data.ptr = rtcp;
+ nfds++;
+ } else {
+ rtsp->hc_io_size = 128 * 1024;
+ rtsp->hc_rtp_data_received = satip_frontend_rtp_data_received;
+ }
if (i) {
- ev[2].events = TVHPOLL_IN;
- ev[2].fd = rtsp->hc_fd;
- ev[2].data.ptr = rtsp;
+ ev[nfds].events = TVHPOLL_IN;
+ ev[nfds].fd = rtsp->hc_fd;
+ ev[nfds].data.ptr = rtsp;
+ nfds++;
}
- tvhpoll_add(efd, ev, i ? 3 : 2);
+ tvhpoll_add(efd, ev, nfds);
rtsp->hc_efd = efd;
position = lfe_master->sf_position;
reply = 1;
udp_multirecv_init(&um, RTP_PKTS, RTP_PKT_SIZE);
- sbuf_init_fixed(&sb, RTP_PKTS * RTP_PKT_SIZE);
+ sbuf_init_fixed(sb, RTP_PKTS * RTP_PKT_SIZE);
while ((reply || running) && !fatal) {
r = rtsp_setup_decode(rtsp, 1);
if (!running)
break;
- if (r < 0 || rtsp->hc_rtp_port != rtp_port ||
- rtsp->hc_rtpc_port != rtp_port + 1) {
+ if (r < 0 || ((rtsp_flags & SATIP_SETUP_TCP) == 0 &&
+ (rtsp->hc_rtp_port != rtp_port ||
+ rtsp->hc_rtpc_port != rtp_port + 1)) ||
+ ((rtsp_flags & SATIP_SETUP_TCP) != 0 &&
+ (rtsp->hc_rtp_tcp < 0 || rtsp->hc_rtcp_tcp < 0))) {
tvhlog(LOG_ERR, "satip", "%s - RTSP SETUP error %d (%s) [%i-%i]",
buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code);
satip_frontend_tuning_error(lfe, tr);
seq = nseq;
/* Process */
tsdebug_write((mpegts_mux_t *)lm, p + pos, c - pos);
- sbuf_append(&sb, p + pos, c - pos);
+ sbuf_append(sb, p + pos, c - pos);
}
pthread_mutex_lock(&lfe->sf_dvr_lock);
if (lfe->sf_req == lfe->sf_req_thread) {
mmi->tii_stats.unc += unc;
mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi,
- &sb, NULL, NULL);
+ sb, NULL, NULL);
} else
fatal = 1;
pthread_mutex_unlock(&lfe->sf_dvr_lock);
/* Do not send the SMT_SIGNAL_STATUS packets - we are out of service */
gtimer_disarm(&lfe->sf_monitor_timer);
- sbuf_free(&sb);
+ sbuf_free(sb);
udp_multirecv_free(&um);
-
- ev[0].events = TVHPOLL_IN;
- ev[0].fd = rtp->fd;
- ev[0].data.ptr = rtp;
- ev[1].events = TVHPOLL_IN;
- ev[1].fd = rtcp->fd;
- ev[1].data.ptr = rtcp;
- ev[2].events = TVHPOLL_IN;
- ev[2].fd = lfe->sf_dvr_pipe.rd;
- ev[2].data.ptr = NULL;
- tvhpoll_rem(efd, ev, 3);
+ lfe->sf_curmux = NULL;
+
+ nfds = 0;
+ if ((rtsp_flags & SATIP_SETUP_TCP) == 0) {
+ ev[nfds].events = TVHPOLL_IN;
+ ev[nfds].fd = rtp->fd;
+ ev[nfds].data.ptr = rtp;
+ nfds++;
+ ev[nfds].events = TVHPOLL_IN;
+ ev[nfds].fd = rtcp->fd;
+ ev[nfds].data.ptr = rtcp;
+ nfds++;
+ }
+ ev[nfds].events = TVHPOLL_IN;
+ ev[nfds].fd = lfe->sf_dvr_pipe.rd;
+ ev[nfds].data.ptr = NULL;
+ nfds++;
+ tvhpoll_rem(efd, ev, nfds);
if (exit_flag) {
satip_frontend_shutdown(rtsp, efd);
http_client_close(rtsp);
tvhpoll_destroy(efd);
+ lfe->sf_display_name = NULL;
+ lfe->sf_curmux = NULL;
return NULL;
#undef PKTS
}
#ifndef __TVH_SATIP_PRIVATE_H__
#define __TVH_SATIP_PRIVATE_H__
+#include "tvheadend.h"
#include "input.h"
#include "htsbuf.h"
#include "udp.h"
* RTSP
*/
char *sd_bindaddr;
+ int sd_tcp_mode;
int sd_fast_switch;
int sd_fullmux_ok;
int sd_pids_max;
uint64_t sf_last_tune;
satip_tune_req_t *sf_req;
satip_tune_req_t *sf_req_thread;
+ sbuf_t sf_sbuf;
+ const char * sf_display_name;
+ uint32_t sf_seq;
+ dvb_mux_t *sf_curmux;
+ time_t sf_last_data_tstamp;
/*
* Configuration
* RTSP part
*/
-#define SATIP_SETUP_PLAY (1<<0)
-#define SATIP_SETUP_PIDS0 (1<<1)
-#define SATIP_SETUP_PILOT_ON (1<<2)
-#define SATIP_SETUP_PIDS21 (1<<3)
+#define SATIP_SETUP_TCP (1<<0)
+#define SATIP_SETUP_PLAY (1<<1)
+#define SATIP_SETUP_PIDS0 (1<<2)
+#define SATIP_SETUP_PILOT_ON (1<<3)
+#define SATIP_SETUP_PIDS21 (1<<4)
int
satip_rtsp_setup( http_client_t *hc,
hc->hc_rtsp_stream_id);
if (flags & SATIP_SETUP_PLAY)
return rtsp_play(hc, stream, buf);
+ if (flags & SATIP_SETUP_TCP)
+ return rtsp_setup(hc, stream, buf, NULL, 0, -1);
return rtsp_setup(hc, stream, buf, NULL, udp_port, udp_port + 1);
}
if (p == NULL)
return -EIO;
n = http_tokenize(p, argv, 32, ';');
- if (n < 3)
+ if (n < 2)
return -EIO;
- if (strcasecmp(argv[0], "RTP/AVP"))
- return -EIO;
- hc->hc_rtp_multicast = strcasecmp(argv[1], "multicast") == 0;
- if (strcasecmp(argv[1], "unicast") && !hc->hc_rtp_multicast)
- return -EIO;
- for (i = 2; i < n; i++) {
- if (strncmp(argv[i], "destination=", 12) == 0)
- hc->hc_rtp_dest = strdup(argv[i] + 12);
- else if (strncmp(argv[i], "client_port=", 12) == 0) {
- j = http_tokenize(argv[i] + 12, argv2, 2, '-');
- if (j > 0) {
- hc->hc_rtp_port = atoi(argv2[0]);
- if (hc->hc_rtp_port <= 0)
- return -EIO;
- if (j > 1) {
- hc->hc_rtpc_port = atoi(argv2[1]);
- if (hc->hc_rtpc_port <= 0)
+ hc->hc_rtp_tcp = -1;
+ hc->hc_rtcp_tcp = -1;
+ hc->hc_rtp_port = -1;
+ hc->hc_rtpc_port = -1;
+ if (!strcasecmp(argv[0], "RTP/AVP/TCP")) {
+ for (i = 1; i < n; i++) {
+ if (strncmp(argv[i], "interleaved=", 12) == 0) {
+ j = http_tokenize(argv[i] + 12, argv2, 2, '-');
+ if (j > 0) {
+ hc->hc_rtp_tcp = atoi(argv2[0]);
+ if (hc->hc_rtp_tcp < 0)
return -EIO;
+ if (j > 1) {
+ hc->hc_rtcp_tcp = atoi(argv2[1]);
+ if (hc->hc_rtcp_tcp < 0)
+ return -EIO;
+ }
+ } else {
+ return -EIO;
}
- } else {
- return -EIO;
}
}
- else if (strncmp(argv[i], "server_port=", 12) == 0) {
- j = http_tokenize(argv[i] + 12, argv2, 2, '-');
- if (j > 1) {
- hc->hc_rtcp_server_port = atoi(argv2[1]);
- if (hc->hc_rtcp_server_port <= 0)
+ } else if (!strcasecmp(argv[0], "RTP/AVP")) {
+ if (n < 3)
+ return -EIO;
+ hc->hc_rtp_multicast = strcasecmp(argv[1], "multicast") == 0;
+ if (strcasecmp(argv[1], "unicast") && !hc->hc_rtp_multicast)
+ return -EIO;
+ for (i = 2; i < n; i++) {
+ if (strncmp(argv[i], "destination=", 12) == 0)
+ hc->hc_rtp_dest = strdup(argv[i] + 12);
+ else if (strncmp(argv[i], "client_port=", 12) == 0) {
+ j = http_tokenize(argv[i] + 12, argv2, 2, '-');
+ if (j > 0) {
+ hc->hc_rtp_port = atoi(argv2[0]);
+ if (hc->hc_rtp_port <= 0)
+ return -EIO;
+ if (j > 1) {
+ hc->hc_rtpc_port = atoi(argv2[1]);
+ if (hc->hc_rtpc_port <= 0)
+ return -EIO;
+ }
+ } else {
return -EIO;
- } else {
- return -EIO;
+ }
+ }
+ else if (strncmp(argv[i], "server_port=", 12) == 0) {
+ j = http_tokenize(argv[i] + 12, argv2, 2, '-');
+ if (j > 1) {
+ hc->hc_rtcp_server_port = atoi(argv2[1]);
+ if (hc->hc_rtcp_server_port <= 0)
+ return -EIO;
+ } else {
+ return -EIO;
+ }
}
}
+ } else {
+ return -EIO;
}
return HTTP_CON_OK;
}
http_arg_list_t h;
char transport[256];
- if (multicast_addr) {
+ if (rtpc_port < 0) {
+ snprintf(transport, sizeof(transport),
+ "RTP/AVP/TCP;interleaved=%d-%d", rtp_port, rtp_port + 1);
+ } else if (multicast_addr) {
snprintf(transport, sizeof(transport),
"RTP/AVP;multicast;destination=%s;ttl=1;client_port=%i-%i",
multicast_addr, rtp_port, rtpc_port);