SAT>IP Server: improve PID handling (using new fcn set)

This commit is contained in:
Jaroslav Kysela 2015-03-04 10:27:09 +01:00
parent c522d71ed0
commit 9a6d0961e4
6 changed files with 258 additions and 114 deletions

View file

@ -230,6 +230,7 @@ SRCS-$(CONFIG_MPEGTS) += \
src/descrambler/descrambler.c \
src/descrambler/caclient.c \
src/input/mpegts.c \
src/input/mpegts/mpegts_pid.c \
src/input/mpegts/mpegts_input.c \
src/input/mpegts/mpegts_network.c \
src/input/mpegts/mpegts_mux.c \

View file

@ -37,6 +37,8 @@
#define MPEGTS_PID_NONE 0xFFFF
/* Types */
typedef int16_t mpegts_apid_t;
typedef struct mpegts_apids mpegts_apids_t;
typedef struct mpegts_table mpegts_table_t;
typedef struct mpegts_psi_section mpegts_psi_section_t;
typedef struct mpegts_network mpegts_network_t;
@ -73,6 +75,31 @@ void mpegts_init ( int linuxdvb_mask, str_list_t *satip_client,
str_list_t *tsfiles, int tstuners );
void mpegts_done ( void );
/* **************************************************************************
* PIDs
* *************************************************************************/
struct mpegts_apids {
mpegts_apid_t *pids;
int alloc;
int count;
int all;
};
int mpegts_pid_init ( mpegts_apids_t *pids, mpegts_apid_t *vals, int count );
void mpegts_pid_done ( mpegts_apids_t *pids );
void mpegts_pid_reset ( mpegts_apids_t *pids );
int mpegts_pid_add ( mpegts_apids_t *pids, mpegts_apid_t pid );
int mpegts_pid_add_group ( mpegts_apids_t *pids, mpegts_apids_t *vals );
int mpegts_pid_del ( mpegts_apids_t *pids, mpegts_apid_t pid );
int mpegts_pid_del_group ( mpegts_apids_t *pids, mpegts_apids_t *vals );
int mpegts_pid_find_index ( mpegts_apids_t *pids, mpegts_apid_t pid );
static inline int mpegts_pid_exists ( mpegts_apids_t *pids, mpegts_apid_t pid )
{ return pids->all || mpegts_pid_find_index(pids, pid) >= 0; }
int mpegts_pid_copy ( mpegts_apids_t *dst, mpegts_apids_t *src );
int mpegts_pid_compare ( mpegts_apids_t *dst, mpegts_apids_t *src,
mpegts_apids_t *add, mpegts_apids_t *del );
/* **************************************************************************
* Data / SI processing
* *************************************************************************/
@ -920,6 +947,7 @@ static inline mpegts_service_t *mpegts_service_find_by_uuid(const char *uuid)
void mpegts_service_delete ( service_t *s, int delconf );
/*
* MPEG-TS event handler
*/

View file

@ -0,0 +1,172 @@
/*
* MPEGTS PID list management
* Copyright (C) 2015 Jaroslav Kysela
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "input.h"
int
mpegts_pid_init(mpegts_apids_t *pids, mpegts_apid_t *vals, int count)
{
int alloc = count + 32;
mpegts_apid_t *p = calloc(alloc, sizeof(*pids));
if (p == NULL)
return -1;
pids->pids = p;
pids->alloc = alloc;
pids->all = 0;
if (vals) {
memcpy(p, vals, count * sizeof(*pids));
pids->count = count;
}
return 0;
}
void
mpegts_pid_done(mpegts_apids_t *pids)
{
free(pids->pids);
pids->pids = NULL;
pids->alloc = pids->count = 0;
}
void
mpegts_pid_reset(mpegts_apids_t *pids)
{
pids->alloc = pids->count = 0;
}
int
mpegts_pid_add(mpegts_apids_t *pids, mpegts_apid_t pid)
{
mpegts_apid_t *p;
int i;
assert(pids);
assert(pid >= 0 && pid <= 8191);
if (pids->alloc == pids->count) {
i = pids->alloc + 32;
p = realloc(pids->pids, i * sizeof(*p));
if (p == NULL)
return -1;
pids->pids = p;
pids->alloc = i;
}
p = pids->pids;
for (i = pids->count++; i > 0 && p[i - 1] > pid; i--)
p[i] = p[i - 1];
p[i] = pid;
return 0;
}
int
mpegts_pid_add_group(mpegts_apids_t *pids, mpegts_apids_t *vals)
{
int i, r;
for (i = 0; i < vals->count; i++) {
r = mpegts_pid_add(pids, vals->pids[i]);
if (r)
return r;
}
return 0;
}
int
mpegts_pid_find_index(mpegts_apids_t *pids, mpegts_apid_t pid)
{
mpegts_apid_t *p = pids->pids;
int first = 0, last = pids->count - 1, i;
for (i = last / 2; first <= last; i = (first + last) / 2) {
if (p[i] < pid)
first = i + 1;
else if (p[i] == pid)
return i;
else
last = i - 1;
}
return -1;
}
int
mpegts_pid_del(mpegts_apids_t *pids, mpegts_apid_t pid)
{
int i;
assert(pids);
assert(pid >= 0 && pid <= 8191);
if ((i = mpegts_pid_find_index(pids, pid)) >= 0) {
memmove(&pids->pids[i], &pids->pids[i+1],
(pids->count - i - 1) * sizeof(mpegts_apid_t));
pids->count--;
return 0;
} else {
return -1;
}
}
int
mpegts_pid_del_group(mpegts_apids_t *pids, mpegts_apids_t *vals)
{
int i, r;
for (i = 0; i < vals->count; i++) {
r = mpegts_pid_del(pids, vals->pids[i]);
if (r)
return r;
}
return 0;
}
int
mpegts_pid_copy(mpegts_apids_t *dst, mpegts_apids_t *src)
{
mpegts_apid_t *p;
int i;
if (dst->alloc < src->alloc) {
i = src->alloc;
p = realloc(dst->pids, i * sizeof(*p));
if (p == NULL)
return -1;
dst->pids = p;
dst->alloc = i;
}
dst->count = src->count;
dst->all = src->all;
memcpy(dst->pids, src->pids, src->count * sizeof(mpegts_apid_t));
return 0;
}
int
mpegts_pid_compare(mpegts_apids_t *dst, mpegts_apids_t *src,
mpegts_apids_t *add, mpegts_apids_t *del)
{
int i;
if (mpegts_pid_init(add, NULL, 0) ||
mpegts_pid_init(del, NULL, 0))
return -1;
for (i = 0; i < src->count; i++)
if (mpegts_pid_find_index(dst, src->pids[i]) < 0)
mpegts_pid_add(del, src->pids[i]);
for (i = 0; i < dst->count; i++)
if (mpegts_pid_find_index(src, dst->pids[i]) < 0)
mpegts_pid_add(add, dst->pids[i]);
return add->count || del->count;
}

View file

@ -41,7 +41,7 @@ typedef struct satip_rtp_session {
int frontend;
int source;
dvb_mux_conf_t dmc;
int16_t pids[RTSP_PIDS];
mpegts_apids_t pids;
udp_multisend_t um;
struct iovec *um_iovec;
int um_packet;
@ -109,15 +109,18 @@ static int
satip_rtp_loop(satip_rtp_session_t *rtp, uint8_t *data, int len)
{
int i, j, pid, last_pid = -1, r;
int16_t *pids = rtp->pids;
mpegts_apid_t *pids = rtp->pids.pids;
struct iovec *v = rtp->um_iovec + rtp->um_packet;
assert((len % 188) == 0);
for ( ; len >= 188 ; data += 188, len -= 188) {
pid = ((data[1] & 0x1f) << 8) | data[2];
if (pid != last_pid) {
for (i = 0, j = -1; i < RTSP_PIDS && (j = pids[i]) >= 0; i++)
if (pid != last_pid && !rtp->pids.all) {
for (i = 0; i < rtp->pids.count; i++) {
j = pids[i];
if (pid < j) break;
if (j == pid) goto found;
}
continue;
found:
last_pid = pid;
@ -238,7 +241,7 @@ void satip_rtp_queue(void *id, th_subscription_t *subs,
struct sockaddr_storage *peer, int port,
int fd_rtp, int fd_rtcp,
int frontend, int source, dvb_mux_conf_t *dmc,
int16_t *pids)
mpegts_apids_t *pids)
{
satip_rtp_session_t *rtp = calloc(1, sizeof(*rtp));
@ -254,7 +257,8 @@ void satip_rtp_queue(void *id, th_subscription_t *subs,
rtp->fd_rtcp = fd_rtcp;
rtp->subs = subs;
rtp->sq = sq;
memcpy(rtp->pids, pids, sizeof(*pids)*RTSP_PIDS);
mpegts_pid_init(&rtp->pids, NULL, pids->count);
mpegts_pid_copy(&rtp->pids, pids);
udp_multisend_init(&rtp->um, RTP_PACKETS, RTP_PAYLOAD, &rtp->um_iovec);
satip_rtp_header(rtp);
rtp->frontend = frontend;
@ -268,7 +272,7 @@ void satip_rtp_queue(void *id, th_subscription_t *subs,
pthread_mutex_unlock(&satip_rtp_lock);
}
void satip_rtp_update_pids(void *id, int16_t *pids)
void satip_rtp_update_pids(void *id, mpegts_apids_t *pids)
{
satip_rtp_session_t *rtp;
@ -276,7 +280,7 @@ void satip_rtp_update_pids(void *id, int16_t *pids)
rtp = satip_rtp_find(id);
if (rtp) {
pthread_mutex_lock(&rtp->lock);
memcpy(rtp->pids, pids, sizeof(*pids)*RTSP_PIDS);
mpegts_pid_copy(&rtp->pids, pids);
pthread_mutex_unlock(&rtp->lock);
}
pthread_mutex_unlock(&satip_rtp_lock);
@ -299,6 +303,7 @@ void satip_rtp_close(void *id)
pthread_mutex_unlock(&satip_rtp_lock);
pthread_join(rtp->tid, NULL);
udp_multisend_free(&rtp->um);
mpegts_pid_done(&rtp->pids);
free(rtp);
} else {
pthread_mutex_unlock(&satip_rtp_lock);
@ -365,8 +370,8 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
}
pids[0] = 0;
for (i = len = 0; i < RTSP_PIDS && rtp->pids[i] >= 0; i++)
len += snprintf(pids + len, sizeof(pids) - len, "%d,", rtp->pids[i]);
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';

View file

@ -40,7 +40,7 @@ typedef struct session {
uint32_t nsession;
char session[9];
dvb_mux_conf_t dmc;
int16_t pids[RTSP_PIDS];
mpegts_apids_t pids;
gtimer_t timer;
dvb_mux_t *mux;
int mux_created;
@ -106,7 +106,6 @@ static struct session *
rtsp_new_session(int delsys, uint32_t nsession, int session)
{
struct session *rs = calloc(1, sizeof(*rs));
int i;
if (rs == NULL)
return NULL;
@ -118,8 +117,7 @@ rtsp_new_session(int delsys, uint32_t nsession, int session)
if (session_number == 0)
session_number += 9876;
}
for (i = 0; i < RTSP_PIDS; i++)
rs->pids[i] = -1;
mpegts_pid_init(&rs->pids, NULL, 0);
TAILQ_INSERT_TAIL(&rtsp_sessions, rs, link);
return rs;
}
@ -221,69 +219,6 @@ rtsp_parse_args(http_connection_t *hc, char *u)
return stream;
}
/*
*
*/
static void
rtsp_clrpids(session_t *rs)
{
int16_t *pids = rs->pids;
int i = RTSP_PIDS;
while (*pids >= 0 && i-- > 0)
*pids++ = -1;
}
/*
*
*/
static int
rtsp_addpids(session_t *rs, int16_t *pids)
{
int pid, i, j;
while ((pid = *pids++) >= 0) {
for (i = 0; i < RTSP_PIDS; i++) {
if (rs->pids[i] > pid) {
if (rs->pids[RTSP_PIDS-1] >= 0)
return -1;
for (j = RTSP_PIDS-1; j != i; j--)
rs->pids[j] = rs->pids[j-1];
rs->pids[i] = pid;
break;
} else if (rs->pids[i] == pid) {
break;
} else if (rs->pids[i] < 0) {
rs->pids[i] = pid;
break;
}
}
}
return 0;
}
/*
*
*/
static int
rtsp_delpids(session_t *rs, int16_t *pids)
{
int pid, i, j;
while ((pid = *pids++) >= 0) {
for (i = 0; i < RTSP_PIDS; i++) {
if (rs->pids[i] > pid)
break;
else if (rs->pids[i] == pid) {
for (j = i; rs->pids[j] >= 0 && j + 1 < RTSP_PIDS; j++)
rs->pids[j] = rs->pids[j+1];
rs->pids[RTSP_PIDS-1] = -1;
break;
}
}
}
return 0;
}
/*
*
*/
@ -368,7 +303,7 @@ rtsp_start
}
} else {
pids:
satip_rtp_update_pids((void *)(intptr_t)rs->stream, rs->pids);
satip_rtp_update_pids((void *)(intptr_t)rs->stream, &rs->pids);
}
if (!setup && !rs->run) {
if (rs->mux == NULL)
@ -377,7 +312,8 @@ pids:
rs->subs, &rs->prch.prch_sq,
hc->hc_peer, rs->rtp_peer_port,
rs->udp_rtp->fd, rs->udp_rtcp->fd,
rs->frontend, rs->findex, &rs->mux->lm_tuning, rs->pids);
rs->frontend, rs->findex, &rs->mux->lm_tuning,
&rs->pids);
rs->run = 1;
}
pthread_mutex_unlock(&global_lock);
@ -597,32 +533,32 @@ gi_to_tvh(http_connection_t *hc)
}
static int
parse_pids(char *p, int16_t *pids)
parse_pids(char *p, mpegts_apids_t *pids)
{
char *x, *saveptr;
int i = 0;
int i = 0, pid;
if (p == NULL || *p == '\0') {
pids[0] = -1;
mpegts_pid_reset(pids);
if (p == NULL || *p == '\0')
return 0;
}
x = strtok_r(p, ",", &saveptr);
while (1) {
if (x == NULL)
break;
if (i >= RTSP_PIDS)
return -1;
pids[i] = atoi(x);
if (pids[i] < 0 || pids[i] > 8191) {
pids[i] = -1;
return -1;
if (strcmp(x, "all") == 0) {
pids->all = 1;
} else {
pids->all = 0;
pid = atoi(x);
if (pid < 0 || pid > 8191)
return -1;
mpegts_pid_add(pids, pid);
}
x = strtok_r(NULL, ",", &saveptr);
i++;
}
if (i == 0)
return -1;
pids[i] = -1;
return 0;
}
@ -658,11 +594,15 @@ rtsp_process_play(http_connection_t *hc, int setup)
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;
int16_t pids[RTSP_PIDS+1], addpids[RTSP_PIDS+1], delpids[RTSP_PIDS+1];
mpegts_apids_t pids, addpids, delpids;
dvb_mux_conf_t *dmc;
char buf[256], addrbuf[50];
http_arg_list_t args;
mpegts_pid_init(&pids, NULL, 0);
mpegts_pid_init(&addpids, NULL, 0);
mpegts_pid_init(&delpids, NULL, 0);
http_arg_init(&args);
tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, sizeof(addrbuf));
@ -673,15 +613,15 @@ rtsp_process_play(http_connection_t *hc, int setup)
fe = atoi(http_arg_get_remove(&hc->hc_req_args, "fe"));
s = http_arg_get_remove(&hc->hc_req_args, "addpids");
if (parse_pids(s, addpids)) goto error2;
if (parse_pids(s, &addpids)) goto error2;
s = http_arg_get_remove(&hc->hc_req_args, "delpids");
if (parse_pids(s, delpids)) goto error2;
if (parse_pids(s, &delpids)) goto error2;
s = http_arg_get_remove(&hc->hc_req_args, "pids");
if (parse_pids(s, pids)) goto error2;
if (parse_pids(s, &pids)) goto error2;
msys = msys_to_tvh(hc);
freq = atof(http_arg_get_remove(&hc->hc_req_args, "freq")) * 1000000;
if (addpids[0] >= 0 || delpids[0] >= 0) {
if (addpids.count > 0 || delpids.count > 0) {
if (setup)
goto error2;
if (!stream)
@ -872,14 +812,12 @@ rtsp_process_play(http_connection_t *hc, int setup)
}
play:
if (pids[0] >= 0) {
rtsp_clrpids(rs);
rtsp_addpids(rs, pids);
}
if (delpids[0] >= 0)
rtsp_delpids(rs, delpids);
if (addpids[0] >= 0)
rtsp_addpids(rs, addpids);
if (pids.count > 0)
mpegts_pid_copy(&rs->pids, &pids);
if (delpids.count > 0)
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, freq >= 10000000, setup)) < 0) {
errcode = r;
goto error;
@ -891,10 +829,9 @@ play:
rs->rtp_peer_port, rs->rtp_peer_port + 1);
dvb_mux_conf_str(dmc, buf, sizeof(buf));
s = buf + strlen(buf);
for (r = 0; r < RTSP_PIDS; r++) {
if (rs->pids[r] < 0) break;
for (r = 0; r < rs->pids.count; r++) {
s += snprintf(s, sizeof(buf) - (s - buf), "%s%i",
r > 0 ? "," : " pids ", rs->pids[r]);
r > 0 ? "," : " pids ", rs->pids.pids[r]);
}
tvhdebug("satips", "%i/%s/%d: %s %s",
rs->frontend, rs->session, rs->stream,
@ -916,14 +853,17 @@ play:
pthread_mutex_unlock(&rtsp_lock);
http_arg_flush(&args);
return 0;
goto end;
error:
pthread_mutex_unlock(&rtsp_lock);
error2:
http_error(hc, errcode);
end:
http_arg_flush(&args);
mpegts_pid_done(&pids);
mpegts_pid_done(&addpids);
mpegts_pid_done(&delpids);
return 0;
}

View file

@ -29,21 +29,19 @@
#include "udp.h"
#include "http.h"
#define RTSP_PIDS 128
void satip_rtp_queue(void *id, th_subscription_t *subs,
streaming_queue_t *sq,
struct sockaddr_storage *peer, int port,
int fd_rtp, int fd_rtcp,
int frontend, int source,
dvb_mux_conf_t *dmc,
int16_t *pids);
mpegts_apids_t *pids);
void satip_rtp_update(void *id, th_subscription_t *subs,
streaming_queue_t *sq,
int frontend, int source,
dvb_mux_conf_t *dmc,
int16_t *pids);
void satip_rtp_update_pids(void *id, int16_t *pids);
mpegts_apids_t *pids);
void satip_rtp_update_pids(void *id, mpegts_apids_t *pids);
void satip_rtp_close(void *id);
void satip_rtp_init(void);