SAT>IP server: implement DESCRIBE RTSP command
This commit is contained in:
parent
be3749f45c
commit
c66213c745
3 changed files with 205 additions and 16 deletions
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include "tvheadend.h"
|
||||
#include "input.h"
|
||||
#include "streaming.h"
|
||||
|
@ -148,7 +149,9 @@ found:
|
|||
static void
|
||||
satip_rtp_signal_status(satip_rtp_session_t *rtp, signal_status_t *sig)
|
||||
{
|
||||
pthread_mutex_lock(&rtp->lock);
|
||||
rtp->sig = *sig;
|
||||
pthread_mutex_unlock(&rtp->lock);
|
||||
}
|
||||
|
||||
static void *
|
||||
|
@ -304,12 +307,35 @@ void satip_rtp_close(void *id)
|
|||
pthread_join(rtp->tid, NULL);
|
||||
udp_multisend_free(&rtp->um);
|
||||
mpegts_pid_done(&rtp->pids);
|
||||
pthread_mutex_destroy(&rtp->lock);
|
||||
free(rtp);
|
||||
} else {
|
||||
pthread_mutex_unlock(&satip_rtp_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static const char *
|
||||
satip_rtcp_pol(int pol)
|
||||
{
|
||||
switch (pol) {
|
||||
case DVB_POLARISATION_HORIZONTAL:
|
||||
return "h";
|
||||
case DVB_POLARISATION_VERTICAL:
|
||||
return "v";
|
||||
case DVB_POLARISATION_CIRCULAR_LEFT:
|
||||
return "l";
|
||||
case DVB_POLARISATION_CIRCULAR_RIGHT:
|
||||
return "r";
|
||||
case DVB_POLARISATION_OFF:
|
||||
return "off";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
@ -332,19 +358,19 @@ satip_rtcp_fec(int fec)
|
|||
*p = *(p+1);
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
||||
satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
|
||||
{
|
||||
char buf[1500], pids[1400];
|
||||
char pids[1400];
|
||||
const char *delsys, *msys, *pilot, *rolloff;
|
||||
const char *bw, *tmode, *gi, *plp, *t2id, *sm, *c2tft, *ds, *specinv;
|
||||
int i, len, len2, level = 0, lock = 0, quality = 0;
|
||||
int i, j, r, level = 0, lock = 0, quality = 0;
|
||||
|
||||
if (rtp->sig.snr > 0)
|
||||
lock = 1;
|
||||
|
@ -370,10 +396,10 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
|||
}
|
||||
|
||||
pids[0] = 0;
|
||||
for (i = len = 0; i < rtp->pids.count; i++)
|
||||
len += snprintf(pids + len, sizeof(pids) - len, "%d,", rtp->pids.pids[i]);
|
||||
if (len && pids[len-1] == ',')
|
||||
pids[len-1] = '\0';
|
||||
for (i = j = 0; i < rtp->pids.count; i++)
|
||||
j += snprintf(pids + j, sizeof(pids) - j, "%d,", rtp->pids.pids[i]);
|
||||
if (j && pids[j-1] == ',')
|
||||
pids[j-1] = '\0';
|
||||
|
||||
switch (rtp->dmc.dmc_fe_delsys) {
|
||||
case DVB_SYS_DVBS:
|
||||
|
@ -398,11 +424,11 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
|||
/* ver=<major>.<minor>;src=<srcID>;tuner=<feID>,<level>,<lock>,<quality>,<frequency>,<polarisation>,\
|
||||
* <system>,<type>,<pilots>,<roll_off>,<symbol_rate>,<fec_inner>;pids=<pid0>,...,<pidn>
|
||||
*/
|
||||
snprintf(buf, sizeof(buf),
|
||||
r = snprintf(buf, len,
|
||||
"ver=1.0;src=%d;tuner=%d,%d,%d,%d,%.f,%s,%s,%s,%s,%s,%.f,%s;pids=%s",
|
||||
rtp->source, rtp->frontend, level, lock, quality,
|
||||
(float)rtp->dmc.dmc_fe_freq / 1000000.0,
|
||||
dvb_pol2str(rtp->dmc.u.dmc_fe_qpsk.polarisation),
|
||||
(float)rtp->dmc.dmc_fe_freq / 1000.0,
|
||||
satip_rtcp_pol(rtp->dmc.u.dmc_fe_qpsk.polarisation),
|
||||
delsys, msys, pilot, rolloff,
|
||||
(float)rtp->dmc.u.dmc_fe_qpsk.symbol_rate / 1000.0,
|
||||
satip_rtcp_fec(rtp->dmc.u.dmc_fe_qpsk.fec_inner),
|
||||
|
@ -452,7 +478,7 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
|||
/* ver=1.1;tuner=<feID>,<level>,<lock>,<quality>,<freq>,<bw>,<msys>,<tmode>,<mtype>,<gi>,\
|
||||
* <fec>,<plp>,<t2id>,<sm>;pids=<pid0>,...,<pidn>
|
||||
*/
|
||||
snprintf(buf, sizeof(buf),
|
||||
r = snprintf(buf, len,
|
||||
"ver=1.1;tuner=%d,%d,%d,%d,%.f,%s,%s,%s,%s,%s,%s,%s,%s,%s;pids=%s",
|
||||
rtp->frontend, level, lock, quality,
|
||||
(float)rtp->dmc.dmc_fe_freq / 1000000.0,
|
||||
|
@ -478,7 +504,7 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
|||
/* ver=1.2;tuner=<feID>,<level>,<lock>,<quality>,<freq>,<bw>,<msys>,<mtype>,<sr>,<c2tft>,<ds>,<plp>,
|
||||
* <specinv>;pids=<pid0>,...,<pidn>
|
||||
*/
|
||||
snprintf(buf, sizeof(buf),
|
||||
r = snprintf(buf, len,
|
||||
"ver=1.1;tuner=%d,%d,%d,%d,%.f,%s,%s,%s,%.f,%s,%s,%s,%s;pids=%s",
|
||||
rtp->frontend, level, lock, quality,
|
||||
(float)rtp->dmc.dmc_fe_freq / 1000000.0,
|
||||
|
@ -490,7 +516,44 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
len = len2 = MIN(strlen(buf), RTCP_PAYLOAD - 16);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int satip_rtp_status(void *id, char *buf, int len)
|
||||
{
|
||||
satip_rtp_session_t *rtp;
|
||||
int r = 0;
|
||||
|
||||
if (buf)
|
||||
buf[0] = '\0';
|
||||
pthread_mutex_lock(&satip_rtp_lock);
|
||||
rtp = satip_rtp_find(id);
|
||||
if (rtp) {
|
||||
pthread_mutex_lock(&rtp->lock);
|
||||
r = satip_status_build(rtp, buf, len);
|
||||
pthread_mutex_unlock(&rtp->lock);
|
||||
}
|
||||
pthread_mutex_unlock(&satip_rtp_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
|
||||
{
|
||||
char buf[1500];
|
||||
int len, len2;
|
||||
|
||||
pthread_mutex_lock(&rtp->lock);
|
||||
len = satip_status_build(rtp, buf, sizeof(buf));
|
||||
pthread_mutex_unlock(&rtp->lock);
|
||||
|
||||
len = len2 = MIN(len, RTCP_PAYLOAD - 16);
|
||||
if (len == 0)
|
||||
len++;
|
||||
while ((len % 4) != 0)
|
||||
|
|
129
src/satip/rtsp.c
129
src/satip/rtsp.c
|
@ -366,7 +366,8 @@ rtsp_process_options(http_connection_t *hc)
|
|||
}
|
||||
http_arg_init(&args);
|
||||
http_arg_set(&args, "Public", "OPTIONS,DESCRIBE,SETUP,PLAY,TEARDOWN");
|
||||
http_arg_set(&args, "Session", hc->hc_session);
|
||||
if (hc->hc_session)
|
||||
http_arg_set(&args, "Session", hc->hc_session);
|
||||
http_send_header(hc, HTTP_STATUS_OK, NULL, 0, NULL, NULL, 0, NULL, NULL, &args);
|
||||
http_arg_flush(&args);
|
||||
return 0;
|
||||
|
@ -376,6 +377,129 @@ error:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
rtsp_describe_header(session_t *rs, htsbuf_queue_t *q)
|
||||
{
|
||||
unsigned long mono = getmonoclock();
|
||||
int dvbt, dvbc;
|
||||
|
||||
htsbuf_qprintf(q, "v=0\r\n");
|
||||
htsbuf_qprintf(q, "o=- %lu %lu IN %s %s\r\n",
|
||||
rs ? (unsigned long)rs->nsession : mono - 123,
|
||||
mono,
|
||||
strchr(rtsp_ip, ':') ? "IP6" : "IP4",
|
||||
rtsp_ip);
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
htsbuf_qprintf(q, "s=SatIPServer:1 %d",
|
||||
config_get_int("satip_dvbs", 0));
|
||||
dvbt = config_get_int("satip_dvbt", 0);
|
||||
dvbc = config_get_int("satip_dvbc", 0);
|
||||
if (dvbc)
|
||||
htsbuf_qprintf(q, " %d %d\r\n", dvbt, dvbc);
|
||||
else if (dvbt)
|
||||
htsbuf_qprintf(q, " %d\r\n", dvbt);
|
||||
else
|
||||
htsbuf_append(q, "\r\n", 1);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
htsbuf_qprintf(q, "t=0 0\r\n");
|
||||
htsbuf_qprintf(q, "a=tool:tvheadend\r\n");
|
||||
}
|
||||
|
||||
static void
|
||||
rtsp_describe_session(session_t *rs, htsbuf_queue_t *q)
|
||||
{
|
||||
char buf[4096];
|
||||
|
||||
htsbuf_qprintf(q, "m=video 0 RTP/AVP 33\r\n");
|
||||
if (strchr(rtsp_ip, ':'))
|
||||
htsbuf_qprintf(q, "c=IN IP6 ::0\r\n");
|
||||
else
|
||||
htsbuf_qprintf(q, "c=IN IP4 0.0.0.0\r\n");
|
||||
htsbuf_qprintf(q, "a=control:stream=%d\r\n", rs->stream);
|
||||
if (rs->run) {
|
||||
satip_rtp_status((void *)(intptr_t)rs->stream, buf, sizeof(buf));
|
||||
htsbuf_qprintf(q, "a=fmtp:33 %s\r\n", buf);
|
||||
htsbuf_qprintf(q, "a=sendonly\r\n");
|
||||
} else {
|
||||
htsbuf_qprintf(q, "a=inactive\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
rtsp_process_describe(http_connection_t *hc)
|
||||
{
|
||||
http_arg_list_t args;
|
||||
const char *arg;
|
||||
char *u = tvh_strdupa(hc->hc_url);
|
||||
session_t *rs;
|
||||
htsbuf_queue_t q;
|
||||
char buf[96];
|
||||
int stream;
|
||||
|
||||
htsbuf_queue_init(&q, 0);
|
||||
|
||||
arg = http_arg_get(&hc->hc_args, "Accept");
|
||||
if (strcmp(arg, "application/sdp"))
|
||||
goto error;
|
||||
|
||||
if ((u = rtsp_check_urlbase(u)) == NULL)
|
||||
goto error;
|
||||
|
||||
stream = rtsp_parse_args(hc, u);
|
||||
|
||||
if (TAILQ_FIRST(&hc->hc_req_args))
|
||||
goto error;
|
||||
|
||||
if (hc->hc_session) {
|
||||
pthread_mutex_lock(&rtsp_lock);
|
||||
TAILQ_FOREACH(rs, &rtsp_sessions, link)
|
||||
if (rs->stream == stream)
|
||||
break;
|
||||
if (rs) {
|
||||
rtsp_describe_header(rs, &q);
|
||||
rtsp_describe_session(rs, &q);
|
||||
}
|
||||
pthread_mutex_unlock(&rtsp_lock);
|
||||
if (rs == NULL) {
|
||||
http_error(hc, HTTP_STATUS_BAD_SESSION);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pthread_mutex_lock(&rtsp_lock);
|
||||
rtsp_describe_header(NULL, &q);
|
||||
TAILQ_FOREACH(rs, &rtsp_sessions, link)
|
||||
rtsp_describe_session(rs, &q);
|
||||
pthread_mutex_unlock(&rtsp_lock);
|
||||
}
|
||||
http_arg_init(&args);
|
||||
if (hc->hc_session)
|
||||
http_arg_set(&args, "Session", hc->hc_session);
|
||||
if (stream > 0)
|
||||
snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", rtsp_ip, stream);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "rtsp://%s", rtsp_ip);
|
||||
http_arg_set(&args, "Content-Base", buf);
|
||||
http_send_header(hc, HTTP_STATUS_OK, "application/sdp", q.hq_size,
|
||||
NULL, NULL, 0, NULL, NULL, &args);
|
||||
tcp_write_queue(hc->hc_fd, &q);
|
||||
http_arg_flush(&args);
|
||||
htsbuf_queue_flush(&q);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
htsbuf_queue_flush(&q);
|
||||
http_error(hc, HTTP_STATUS_BAD_REQUEST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
@ -925,6 +1049,8 @@ rtsp_process_request(http_connection_t *hc, htsbuf_queue_t *spill)
|
|||
switch (hc->hc_cmd) {
|
||||
case RTSP_CMD_OPTIONS:
|
||||
return rtsp_process_options(hc);
|
||||
case RTSP_CMD_DESCRIBE:
|
||||
return rtsp_process_describe(hc);
|
||||
case RTSP_CMD_SETUP:
|
||||
case RTSP_CMD_PLAY:
|
||||
return rtsp_process_play(hc, hc->hc_cmd == RTSP_CMD_SETUP);
|
||||
|
@ -972,7 +1098,6 @@ static void
|
|||
rtsp_close_session(session_t *rs)
|
||||
{
|
||||
satip_rtp_close((void *)(intptr_t)rs->stream);
|
||||
rs->stream = 0;
|
||||
rs->run = 0;
|
||||
udp_close(rs->udp_rtp);
|
||||
rs->udp_rtp = NULL;
|
||||
|
|
|
@ -42,6 +42,7 @@ void satip_rtp_update(void *id, th_subscription_t *subs,
|
|||
dvb_mux_conf_t *dmc,
|
||||
mpegts_apids_t *pids);
|
||||
void satip_rtp_update_pids(void *id, mpegts_apids_t *pids);
|
||||
int satip_rtp_status(void *id, char *buf, int len);
|
||||
void satip_rtp_close(void *id);
|
||||
|
||||
void satip_rtp_init(void);
|
||||
|
|
Loading…
Add table
Reference in a new issue