SAT>IP Server: fixed issues for the Elgato SAT>IP Android app

This commit is contained in:
Jaroslav Kysela 2015-03-13 23:59:31 +01:00
parent ce01edeb8c
commit c4adde611f
4 changed files with 92 additions and 64 deletions

View file

@ -949,6 +949,8 @@ http_parse_get_args(http_connection_t *hc, char *args)
{
char *k, *v;
if (args && *args == '&')
args++;
while(args) {
k = args;
if((args = strchr(args, '=')) == NULL)
@ -1008,13 +1010,18 @@ http_serve_requests(http_connection_t *hc)
goto error;
if(!*hdrline)
break; /* header complete */
break; /* header complete */
if((n = http_tokenize(hdrline, argv, 2, -1)) < 2)
continue;
if((c = strrchr(argv[0], ':')) == NULL)
goto error;
if((n = http_tokenize(hdrline, argv, 2, -1)) < 2) {
if ((c = strchr(hdrline, ':')) != NULL) {
*c = '\0';
argv[0] = hdrline;
argv[1] = c + 1;
} else {
continue;
}
} else if((c = strrchr(argv[0], ':')) == NULL)
goto error;
*c = 0;
http_arg_set(&hc->hc_args, argv[0], argv[1]);

View file

@ -48,6 +48,7 @@ typedef struct satip_rtp_session {
int um_packet;
uint16_t seq;
signal_status_t sig;
int sig_lock;
pthread_mutex_t lock;
} satip_rtp_session_t;
@ -114,6 +115,8 @@ satip_rtp_loop(satip_rtp_session_t *rtp, uint8_t *data, int len)
struct iovec *v = rtp->um_iovec + rtp->um_packet;
assert((len % 188) == 0);
if (len > 0)
rtp->sig_lock = 1;
for ( ; len >= 188 ; data += 188, len -= 188) {
pid = ((data[1] & 0x1f) << 8) | data[2];
if (pid != last_pid && !rtp->pids.all) {
@ -372,8 +375,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
const char *bw, *tmode, *gi, *plp, *t2id, *sm, *c2tft, *ds, *specinv;
int i, j, r, level = 0, lock = 0, quality = 0;
if (rtp->sig.snr > 0)
lock = 1;
lock = rtp->sig_lock;
switch (rtp->sig.signal_scale) {
case SIGNAL_STATUS_SCALE_RELATIVE:
level = MIN(240, MAX(0, (rtp->sig.signal * 245) / 0xffff));
@ -382,6 +384,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
level = MIN(240, MAX(0, (rtp->sig.signal + 90000) / 375));
break;
default:
level = lock ? 10 : 0;
break;
}
switch (rtp->sig.snr_scale) {
@ -392,6 +395,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
quality = MIN(15, MAX(0, (rtp->sig.snr / 2000)));
break;
default:
quality = lock ? 1 : 0;
break;
}

View file

@ -300,6 +300,10 @@ rtsp_clean(session_t *rs)
{
slave_subscription_t *sub;
if (rs->run) {
satip_rtp_close((void *)(intptr_t)rs->stream);
rs->run = 0;
}
if (rs->subs) {
while ((sub = LIST_FIRST(&rs->slaves)) != NULL)
rtsp_slave_remove(rs, (mpegts_service_t *)rs->subs->ths_service,
@ -321,6 +325,7 @@ rtsp_clean(session_t *rs)
static int
rtsp_validate_service(mpegts_service_t *s)
{
int av = 0, enc = 0;
elementary_stream_t *st;
pthread_mutex_lock(&s->s_stream_mutex);
@ -328,12 +333,15 @@ rtsp_validate_service(mpegts_service_t *s)
pthread_mutex_unlock(&s->s_stream_mutex);
return 0;
}
TAILQ_FOREACH(st, &s->s_components, es_link)
TAILQ_FOREACH(st, &s->s_components, es_link) {
if (st->es_type == SCT_CA)
enc = 1;
if (st->es_pid > 0 &&
(SCT_ISVIDEO(st->es_type) || SCT_ISAUDIO(st->es_type)))
break;
av = 1;
}
pthread_mutex_unlock(&s->s_stream_mutex);
return st != NULL;
return enc && av;
}
/*
@ -398,7 +406,8 @@ end:
*/
static int
rtsp_start
(http_connection_t *hc, session_t *rs, char *addrbuf, int newmux, int setup)
(http_connection_t *hc, session_t *rs, char *addrbuf,
int newmux, int setup, int oldrun)
{
mpegts_network_t *mn, *mn2;
dvb_network_t *ln;
@ -422,22 +431,24 @@ rtsp_start
}
}
if (mux == NULL && mn2) {
dvb_mux_conf_str(&rs->dmc, buf, sizeof(buf));
tvhwarn("satips", "%i/%s/%i: create mux %s",
rs->frontend, rs->session, rs->stream, buf);
mux = (dvb_mux_t *)
mn2->mn_create_mux(mn2, (void *)(intptr_t)rs->nsession,
MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
&rs->dmc, 0);
&rs->dmc, 1);
if (mux)
created = 1;
}
if (mux == NULL) {
dvb_mux_conf_str(&rs->dmc, buf, sizeof(buf));
tvhwarn("satips", "%i: unable to create mux %s", rs->frontend, buf);
tvhwarn("satips", "%i/%s/%i: unable to create mux %s",
rs->frontend, rs->session, rs->stream, buf);
goto endclean;
}
if (rs->mux == mux)
goto pids;
if (rs->run)
satip_rtp_close((void *)(intptr_t)rs->stream);
rtsp_clean(rs);
rs->mux = mux;
rs->mux_created = created;
@ -452,9 +463,9 @@ rtsp_start
http_arg_get(&hc->hc_args, "User-Agent"),
NULL);
if (!rs->subs)
goto endrtp;
if (rs->run) {
/* restart streaming */
goto endclean;
/* retrigger play when new setup arrived */
if (oldrun) {
setup = 0;
rs->run = 0;
}
@ -466,7 +477,7 @@ pids:
}
if (!setup && !rs->run) {
if (rs->mux == NULL)
goto endrtp;
goto endclean;
satip_rtp_queue((void *)(intptr_t)rs->stream,
rs->subs, &rs->prch.prch_sq,
hc->hc_peer, rs->rtp_peer_port,
@ -481,9 +492,6 @@ pids:
pthread_mutex_unlock(&global_lock);
return 0;
endrtp:
satip_rtp_close((void *)(intptr_t)rs->stream);
rs->run = 0;
endclean:
rtsp_clean(rs);
pthread_mutex_unlock(&global_lock);
@ -598,7 +606,7 @@ rtsp_process_describe(http_connection_t *hc)
session_t *rs;
htsbuf_queue_t q;
char buf[96];
int stream;
int stream, first = 1;
htsbuf_queue_init(&q, 0);
@ -614,27 +622,30 @@ rtsp_process_describe(http_connection_t *hc)
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_lock(&rtsp_lock);
TAILQ_FOREACH(rs, &rtsp_sessions, link) {
if (hc->hc_session) {
if (strcmp(hc->hc_session, rs->session))
continue;
if (stream > 0 && rs->stream != stream)
continue;
}
pthread_mutex_unlock(&rtsp_lock);
if (rs == NULL) {
if (first) {
rtsp_describe_header(hc->hc_session ? rs : NULL, &q);
first = 0;
}
rtsp_describe_session(rs, &q);
}
pthread_mutex_unlock(&rtsp_lock);
if (first) {
if (hc->hc_session) {
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);
@ -875,7 +886,7 @@ static int
rtsp_process_play(http_connection_t *hc, int setup)
{
session_t *rs;
int errcode = HTTP_STATUS_BAD_REQUEST, r, findex = 0, valid;
int errcode = HTTP_STATUS_BAD_REQUEST, r, findex = 0, valid, oldrun = 0;
int stream, delsys = DVB_SYS_NONE, msys, fe, src, freq, pol, sr;
int fec, ro, plts, bw, tmode, mtype, gi, plp, t2id, sm, c2tft, ds, specinv;
char *u, *s;
@ -922,19 +933,22 @@ rtsp_process_play(http_connection_t *hc, int setup)
delsys = rtsp_delsys(fe, &findex);
if (delsys == DVB_SYS_NONE)
goto error;
} else {
delsys = msys;
}
if (setup) {
if (delsys == DVB_SYS_NONE) goto error;
if (msys == DVB_SYS_NONE) goto error;
if (!fe) goto error;
if (!valid) goto error;
if (!rs)
rs = rtsp_new_session(msys, 0, -1);
else if (stream != rs->stream)
rs = rtsp_new_session(msys, rs->nsession, stream);
else
else {
oldrun = rs->run;
rtsp_close_session(rs);
}
r = parse_transport(hc);
if (r < 0) {
errcode = HTTP_STATUS_BAD_TRANSFER;
@ -944,7 +958,7 @@ rtsp_process_play(http_connection_t *hc, int setup)
errcode = HTTP_STATUS_METHOD_INVALID;
goto error;
}
rs->frontend = fe;
rs->frontend = fe > 0 ? fe : 1;
rs->rtp_peer_port = r;
dmc = &rs->dmc;
} else {
@ -953,6 +967,7 @@ rtsp_process_play(http_connection_t *hc, int setup)
errcode = HTTP_STATUS_NOT_FOUND;
goto error;
}
oldrun = rs->run;
dmc = &rs->dmc;
if (rs->mux == NULL) goto error;
if (!fe) {
@ -1106,13 +1121,13 @@ play:
mpegts_pid_del_group(&rs->pids, &delpids);
if (addpids.count > 0)
mpegts_pid_add_group(&rs->pids, &addpids);
if ((r = rtsp_start(hc, rs, addrbuf, valid, setup)) < 0) {
if ((r = rtsp_start(hc, rs, addrbuf, valid, setup, oldrun)) < 0) {
errcode = r;
goto error;
}
if (setup)
tvhdebug("satips", "%i/%s/%d: setup from %s:%d, RTP: %d, RTCP: %d, pids ",
tvhdebug("satips", "%i/%s/%d: setup from %s:%d, RTP: %d, RTCP: %d",
rs->frontend, rs->session, rs->stream,
addrbuf, IP_PORT(*hc->hc_peer),
rs->rtp_peer_port, rs->rtp_peer_port + 1);

View file

@ -60,11 +60,10 @@ satip_server_http_xml(http_connection_t *hc)
<manufacturerURL>http://tvheadend.org</manufacturerURL>\n\
<modelDescription>TVHeadend %s</modelDescription>\n\
<modelName>TVHeadend SAT>IP</modelName>\n\
<modelNumber>1</modelNumber>\n\
<modelURL>http://tvheadend.org</modelURL>\n\
<modelNumber>1.0</modelNumber>\n\
<modelURL></modelURL>\n\
<serialNumber>123456</serialNumber>\n\
<UDN>uuid:%s</UDN>\n\
<UPC>TVHeadend %s</UPC>\n\
<iconList>\n\
<icon>\n\
<mimetype>image/png</mimetype>\n\
@ -74,7 +73,7 @@ satip_server_http_xml(http_connection_t *hc)
<url>http://%s:%d/static/satip-icon40.png</url>\n\
</icon>\n\
<icon>\n\
<mimetype>image/jpg</mimetype>\n\
<mimetype>image/jpeg</mimetype>\n\
<width>40</width>\n\
<height>40</height>\n\
<depth>16</depth>\n\
@ -88,7 +87,7 @@ satip_server_http_xml(http_connection_t *hc)
<url>http://%s:%d/static/satip-icon120.png</url>\n\
</icon>\n\
<icon>\n\
<mimetype>image/jpg</mimetype>\n\
<mimetype>image/jpeg</mimetype>\n\
<width>120</width>\n\
<height>120</height>\n\
<depth>16</depth>\n\
@ -100,7 +99,7 @@ satip_server_http_xml(http_connection_t *hc)
</device>\n\
</root>\n"
char buf[sizeof(MSG) + 1024], buf2[16];
char buf[sizeof(MSG) + 1024], buf2[64];
char *devicelist = NULL;
htsbuf_queue_t q;
mpegts_network_t *mn;
@ -122,18 +121,18 @@ satip_server_http_xml(http_connection_t *hc)
} else if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbc_class))
dvbc++;
}
if (dvbt && (i = config_get_int("satip_dvbt", 0)) > 0) {
htsbuf_qprintf(&q, "DVBT-%d", i);
delim++;
} else {
dvbt = 0;
}
if (dvbs && (i = config_get_int("satip_dvbs", 0)) > 0) {
htsbuf_qprintf(&q, "%sDVBS2-%d", delim ? "," : "", i);
delim++;
} else {
dvbs = 0;
}
if (dvbt && (i = config_get_int("satip_dvbt", 0)) > 0) {
htsbuf_qprintf(&q, "%sDVBT-%d", delim ? "," : "", i);
delim++;
} else {
dvbt = 0;
}
if (dvbc && (i = config_get_int("satip_dvbc", 0)) > 0) {
htsbuf_qprintf(&q, "%sDVBC-%d", delim ? "," : "", i);
delim++;
@ -153,13 +152,14 @@ satip_server_http_xml(http_connection_t *hc)
buf, dvbt + dvbs + dvbc ? "tuner settings - global config" : "network assignment");
}
buf2[0] = '\0';
if (satip_server_rtsp_port != 554)
snprintf(buf2, sizeof(buf2), ":%d", satip_server_rtsp_port);
snprintf(buf2, sizeof(buf2), ":%d %s", satip_server_rtsp_port, satip_server_uuid + 26);
else
snprintf(buf2, sizeof(buf2), " %s", satip_server_uuid + 26);
snprintf(buf, sizeof(buf), MSG,
buf2, tvheadend_version,
satip_server_uuid, tvheadend_version,
satip_server_uuid,
http_server_ip, http_server_port,
http_server_ip, http_server_port,
http_server_ip, http_server_port,
@ -170,8 +170,10 @@ satip_server_http_xml(http_connection_t *hc)
free(devicelist);
http_arg_init(&args);
snprintf(buf2, sizeof(buf2), "%d", satip_server_rtsp_port);
http_arg_set(&args, "X-SATIP-RTSP-Port", buf2);
if (satip_server_rtsp_port != 554) {
snprintf(buf2, sizeof(buf2), "%d", satip_server_rtsp_port);
http_arg_set(&args, "X-SATIP-RTSP-Port", buf2);
}
if (srcs) {
snprintf(buf2, sizeof(buf2), "%d", srcs);
http_arg_set(&args, "X-SATIP-Sources", buf2);
@ -405,9 +407,9 @@ satips_upnp_discovery_received
if (http_tokenize(ptr, argv, 2, ':') == 2) {
if (strcmp(argv[0], "ST") == 0)
st = argv[1];
else if (strcmp(argv[0], "HOST") == 0)
else if (strcasecmp(argv[0], "HOST") == 0)
host = argv[1];
else if (strcmp(argv[0], "MAN") == 0)
else if (strcasecmp(argv[0], "MAN") == 0)
man = argv[1];
else if (strcmp(argv[0], "DEVICEID.SES.COM") == 0)
deviceid = argv[1];