Rename th_stream -> elementary_stream
This commit is contained in:
parent
c304ba5dbc
commit
123a261f4b
22 changed files with 606 additions and 608 deletions
18
src/capmt.c
18
src/capmt.c
|
@ -404,7 +404,7 @@ capmt_thread(void *aux)
|
|||
*/
|
||||
static void
|
||||
capmt_table_input(struct th_descrambler *td, struct service *t,
|
||||
struct th_stream *st, const uint8_t *data, int len)
|
||||
struct elementary_stream *st, const uint8_t *data, int len)
|
||||
{
|
||||
capmt_service_t *ct = (capmt_service_t *)td;
|
||||
capmt_t *capmt = ct->ct_capmt;
|
||||
|
@ -412,7 +412,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t,
|
|||
|
||||
caid_t *c;
|
||||
|
||||
c = LIST_FIRST(&st->st_caids);
|
||||
c = LIST_FIRST(&st->es_caids);
|
||||
if(c == NULL)
|
||||
return;
|
||||
|
||||
|
@ -442,7 +442,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t,
|
|||
/* ecmpid not already seen, add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = c->caid;
|
||||
cce->cce_ecmpid = st->st_pid;
|
||||
cce->cce_ecmpid = st->es_pid;
|
||||
LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
|
||||
}
|
||||
|
||||
|
@ -456,7 +456,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t,
|
|||
}
|
||||
|
||||
uint16_t sid = t->s_dvb_service_id;
|
||||
uint16_t ecmpid = st->st_pid;
|
||||
uint16_t ecmpid = st->es_pid;
|
||||
uint16_t transponder = 0;
|
||||
|
||||
/* don't do too much requests */
|
||||
|
@ -555,7 +555,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t,
|
|||
*
|
||||
*/
|
||||
static int
|
||||
capmt_descramble(th_descrambler_t *td, service_t *t, struct th_stream *st,
|
||||
capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb)
|
||||
{
|
||||
capmt_service_t *ct = (capmt_service_t *)td;
|
||||
|
@ -615,7 +615,7 @@ capmt_service_start(service_t *t)
|
|||
t->s_svcname,
|
||||
t->s_dvb_mux_instance->tdmi_adapter->tda_adapter_num);
|
||||
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
/* create new capmt service */
|
||||
ct = calloc(1, sizeof(capmt_service_t));
|
||||
|
@ -623,8 +623,8 @@ capmt_service_start(service_t *t)
|
|||
ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
|
||||
ct->ct_seq = capmt->capmt_seq++;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
caid_t *c = LIST_FIRST(&st->st_caids);
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
caid_t *c = LIST_FIRST(&st->es_caids);
|
||||
if(c == NULL)
|
||||
continue;
|
||||
|
||||
|
@ -634,7 +634,7 @@ capmt_service_start(service_t *t)
|
|||
/* add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = c->caid;
|
||||
cce->cce_ecmpid = st->st_pid;
|
||||
cce->cce_ecmpid = st->es_pid;
|
||||
LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
|
||||
|
||||
/* sending request will be based on first seen caid */
|
||||
|
|
20
src/cwc.c
20
src/cwc.c
|
@ -1210,7 +1210,7 @@ cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len)
|
|||
*/
|
||||
static void
|
||||
cwc_table_input(struct th_descrambler *td, struct service *t,
|
||||
struct th_stream *st, const uint8_t *data, int len)
|
||||
struct elementary_stream *st, const uint8_t *data, int len)
|
||||
{
|
||||
cwc_service_t *ct = (cwc_service_t *)td;
|
||||
uint16_t sid = t->s_dvb_service_id;
|
||||
|
@ -1229,18 +1229,18 @@ cwc_table_input(struct th_descrambler *td, struct service *t,
|
|||
return;
|
||||
|
||||
LIST_FOREACH(ep, &ct->cs_pids, ep_link) {
|
||||
if(ep->ep_pid == st->st_pid)
|
||||
if(ep->ep_pid == st->es_pid)
|
||||
break;
|
||||
}
|
||||
|
||||
if(ep == NULL) {
|
||||
ep = calloc(1, sizeof(ecm_pid_t));
|
||||
ep->ep_pid = st->st_pid;
|
||||
ep->ep_pid = st->es_pid;
|
||||
LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link);
|
||||
}
|
||||
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
if(cwc->cwc_caid == c->caid)
|
||||
break;
|
||||
}
|
||||
|
@ -1300,7 +1300,7 @@ cwc_table_input(struct th_descrambler *td, struct service *t,
|
|||
tvhlog(LOG_DEBUG, "cwc",
|
||||
"Sending ECM%s section=%d/%d, for service %s (seqno: %d) PID %d",
|
||||
chaninfo, section, ep->ep_last_section, t->s_svcname, es->es_seq,
|
||||
st->st_pid);
|
||||
st->es_pid);
|
||||
es->es_time = getmonoclock();
|
||||
break;
|
||||
|
||||
|
@ -1339,7 +1339,7 @@ update_keys(cwc_service_t *ct)
|
|||
*
|
||||
*/
|
||||
static int
|
||||
cwc_descramble(th_descrambler_t *td, service_t *t, struct th_stream *st,
|
||||
cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb)
|
||||
{
|
||||
cwc_service_t *ct = (cwc_service_t *)td;
|
||||
|
@ -1427,14 +1427,14 @@ cwc_service_destroy(th_descrambler_t *td)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
static inline th_stream_t *
|
||||
static inline elementary_stream_t *
|
||||
cwc_find_stream_by_caid(service_t *t, int caid)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
caid_t *c;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
if(c->caid == caid)
|
||||
return st;
|
||||
}
|
||||
|
|
|
@ -1075,7 +1075,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src)
|
|||
{
|
||||
th_dvb_mux_instance_t *tdmi_dst;
|
||||
service_t *t_src, *t_dst;
|
||||
th_stream_t *st_src, *st_dst;
|
||||
elementary_stream_t *st_src, *st_dst;
|
||||
caid_t *caid_src, *caid_dst;
|
||||
|
||||
tdmi_dst = dvb_mux_create(dst,
|
||||
|
@ -1110,23 +1110,23 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src)
|
|||
pthread_mutex_lock(&t_src->s_stream_mutex);
|
||||
pthread_mutex_lock(&t_dst->s_stream_mutex);
|
||||
|
||||
TAILQ_FOREACH(st_src, &t_src->s_components, st_link) {
|
||||
TAILQ_FOREACH(st_src, &t_src->s_components, es_link) {
|
||||
|
||||
|
||||
st_dst = service_stream_create(t_dst,
|
||||
st_src->st_pid,
|
||||
st_src->st_type);
|
||||
st_src->es_pid,
|
||||
st_src->es_type);
|
||||
|
||||
memcpy(st_dst->st_lang, st_src->st_lang, 4);
|
||||
st_dst->st_frame_duration = st_src->st_frame_duration;
|
||||
memcpy(st_dst->es_lang, st_src->es_lang, 4);
|
||||
st_dst->es_frame_duration = st_src->es_frame_duration;
|
||||
|
||||
LIST_FOREACH(caid_src, &st_src->st_caids, link) {
|
||||
LIST_FOREACH(caid_src, &st_src->es_caids, link) {
|
||||
caid_dst = malloc(sizeof(caid_t));
|
||||
|
||||
caid_dst->caid = caid_src->caid;
|
||||
caid_dst->providerid = caid_src->providerid;
|
||||
caid_dst->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st_dst->st_caids, caid_dst, link);
|
||||
LIST_INSERT_HEAD(&st_dst->es_caids, caid_dst, link);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,29 +52,29 @@ dvb_transport_open_demuxers(th_dvb_adapter_t *tda, service_t *t)
|
|||
{
|
||||
struct dmx_pes_filter_params dmx_param;
|
||||
int fd;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
if(st->st_pid >= 0x2000)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
if(st->es_pid >= 0x2000)
|
||||
continue;
|
||||
|
||||
if(st->st_demuxer_fd != -1)
|
||||
if(st->es_demuxer_fd != -1)
|
||||
continue;
|
||||
|
||||
fd = tvh_open(tda->tda_demux_path, O_RDWR, 0);
|
||||
st->st_cc_valid = 0;
|
||||
st->es_cc_valid = 0;
|
||||
|
||||
if(fd == -1) {
|
||||
st->st_demuxer_fd = -1;
|
||||
st->es_demuxer_fd = -1;
|
||||
tvhlog(LOG_ERR, "dvb",
|
||||
"\"%s\" unable to open demuxer \"%s\" for pid %d -- %s",
|
||||
t->s_identifier, tda->tda_demux_path,
|
||||
st->st_pid, strerror(errno));
|
||||
st->es_pid, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&dmx_param, 0, sizeof(dmx_param));
|
||||
dmx_param.pid = st->st_pid;
|
||||
dmx_param.pid = st->es_pid;
|
||||
dmx_param.input = DMX_IN_FRONTEND;
|
||||
dmx_param.output = DMX_OUT_TS_TAP;
|
||||
dmx_param.pes_type = DMX_PES_OTHER;
|
||||
|
@ -84,12 +84,12 @@ dvb_transport_open_demuxers(th_dvb_adapter_t *tda, service_t *t)
|
|||
tvhlog(LOG_ERR, "dvb",
|
||||
"\"%s\" unable to configure demuxer \"%s\" for pid %d -- %s",
|
||||
t->s_identifier, tda->tda_demux_path,
|
||||
st->st_pid, strerror(errno));
|
||||
st->es_pid, strerror(errno));
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
st->st_demuxer_fd = fd;
|
||||
st->es_demuxer_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ static void
|
|||
dvb_transport_stop(service_t *t)
|
||||
{
|
||||
th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
|
@ -161,10 +161,10 @@ dvb_transport_stop(service_t *t)
|
|||
LIST_REMOVE(t, s_active_link);
|
||||
pthread_mutex_unlock(&tda->tda_delivery_mutex);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
if(st->st_demuxer_fd != -1) {
|
||||
close(st->st_demuxer_fd);
|
||||
st->st_demuxer_fd = -1;
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
if(st->es_demuxer_fd != -1) {
|
||||
close(st->es_demuxer_fd);
|
||||
st->es_demuxer_fd = -1;
|
||||
}
|
||||
}
|
||||
t->s_status = SERVICE_IDLE;
|
||||
|
|
|
@ -220,15 +220,15 @@ decode_scaling_list(bitstream_t *bs, int size)
|
|||
|
||||
|
||||
int
|
||||
h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
||||
h264_decode_seq_parameter_set(elementary_stream_t *st, bitstream_t *bs)
|
||||
{
|
||||
int profile_idc, level_idc, poc_type;
|
||||
unsigned int sps_id, tmp, i, width, height;
|
||||
int cbpsize = -1;
|
||||
h264_private_t *p;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
p = st->st_priv = calloc(1, sizeof(h264_private_t));
|
||||
if((p = st->es_priv) == NULL)
|
||||
p = st->es_priv = calloc(1, sizeof(h264_private_t));
|
||||
|
||||
profile_idc= read_bits(bs, 8);
|
||||
read_bits1(bs); //constraint_set0_flag
|
||||
|
@ -328,13 +328,13 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
|
||||
|
||||
int
|
||||
h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs)
|
||||
h264_decode_pic_parameter_set(elementary_stream_t *st, bitstream_t *bs)
|
||||
{
|
||||
h264_private_t *p;
|
||||
int pps_id, sps_id;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
p = st->st_priv = calloc(1, sizeof(h264_private_t));
|
||||
if((p = st->es_priv) == NULL)
|
||||
p = st->es_priv = calloc(1, sizeof(h264_private_t));
|
||||
|
||||
pps_id = read_golomb_ue(bs);
|
||||
sps_id = read_golomb_ue(bs);
|
||||
|
@ -344,13 +344,13 @@ h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
|
||||
|
||||
int
|
||||
h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype,
|
||||
h264_decode_slice_header(elementary_stream_t *st, bitstream_t *bs, int *pkttype,
|
||||
int *duration, int *isfield)
|
||||
{
|
||||
h264_private_t *p;
|
||||
int slice_type, pps_id, sps_id, fnum;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
if((p = st->es_priv) == NULL)
|
||||
return -1;
|
||||
|
||||
read_golomb_ue(bs); /* first_mb_in_slice */
|
||||
|
@ -400,29 +400,29 @@ h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype,
|
|||
}
|
||||
|
||||
if(p->sps[sps_id].cbpsize != 0)
|
||||
st->st_vbv_size = p->sps[sps_id].cbpsize;
|
||||
st->es_vbv_size = p->sps[sps_id].cbpsize;
|
||||
|
||||
st->st_vbv_delay = -1;
|
||||
st->es_vbv_delay = -1;
|
||||
|
||||
if(p->sps[sps_id].width && p->sps[sps_id].height && !st->st_buf.sb_err)
|
||||
if(p->sps[sps_id].width && p->sps[sps_id].height && !st->es_buf.sb_err)
|
||||
parser_set_stream_vsize(st, p->sps[sps_id].width,
|
||||
p->sps[sps_id].height *
|
||||
(2 - p->sps[sps_id].mbs_only_flag));
|
||||
|
||||
if(p->sps[sps_id].aspect_num && p->sps[sps_id].aspect_den) {
|
||||
|
||||
int w = p->sps[sps_id].aspect_num * st->st_width;
|
||||
int h = p->sps[sps_id].aspect_den * st->st_height;
|
||||
int w = p->sps[sps_id].aspect_num * st->es_width;
|
||||
int h = p->sps[sps_id].aspect_den * st->es_height;
|
||||
|
||||
if(w && h) {
|
||||
int d = gcd(w, h);
|
||||
st->st_aspect_num = w / d;
|
||||
st->st_aspect_den = h / d;
|
||||
st->es_aspect_num = w / d;
|
||||
st->es_aspect_den = h / d;
|
||||
}
|
||||
|
||||
} else {
|
||||
st->st_aspect_num = 0;
|
||||
st->st_aspect_den = 1;
|
||||
st->es_aspect_num = 0;
|
||||
st->es_aspect_den = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
|
||||
void *h264_nal_deescape(bitstream_t *bs, const uint8_t *data, int size);
|
||||
|
||||
int h264_decode_seq_parameter_set(struct th_stream *st, bitstream_t *bs);
|
||||
int h264_decode_seq_parameter_set(struct elementary_stream *st, bitstream_t *bs);
|
||||
|
||||
int h264_decode_pic_parameter_set(struct th_stream *st, bitstream_t *bs);
|
||||
int h264_decode_pic_parameter_set(struct elementary_stream *st, bitstream_t *bs);
|
||||
|
||||
int h264_decode_slice_header(struct th_stream *st, bitstream_t *bs,
|
||||
int h264_decode_slice_header(struct elementary_stream *st, bitstream_t *bs,
|
||||
int *pkttype, int *duration, int *isfield);
|
||||
|
||||
#endif /* PARSER_H264_H_ */
|
||||
|
|
|
@ -57,7 +57,7 @@ latm_get_value(bitstream_t *bs)
|
|||
|
||||
|
||||
static void
|
||||
read_audio_specific_config(th_stream_t *st, latm_private_t *latm,
|
||||
read_audio_specific_config(elementary_stream_t *st, latm_private_t *latm,
|
||||
bitstream_t *bs)
|
||||
{
|
||||
int aot, sr;
|
||||
|
@ -72,7 +72,7 @@ read_audio_specific_config(th_stream_t *st, latm_private_t *latm,
|
|||
return;
|
||||
|
||||
sr = sri_to_rate(latm->sample_rate_index);
|
||||
st->st_frame_duration = 1024 * 90000 / sr;
|
||||
st->es_frame_duration = 1024 * 90000 / sr;
|
||||
|
||||
latm->channel_config = read_bits(bs, 4);
|
||||
|
||||
|
@ -86,7 +86,7 @@ read_audio_specific_config(th_stream_t *st, latm_private_t *latm,
|
|||
|
||||
|
||||
static void
|
||||
read_stream_mux_config(th_stream_t *st, latm_private_t *latm, bitstream_t *bs)
|
||||
read_stream_mux_config(elementary_stream_t *st, latm_private_t *latm, bitstream_t *bs)
|
||||
{
|
||||
int audio_mux_version = read_bits(bs, 1);
|
||||
latm->audio_mux_version_A = 0;
|
||||
|
@ -159,7 +159,7 @@ read_stream_mux_config(th_stream_t *st, latm_private_t *latm, bitstream_t *bs)
|
|||
* Parse AAC LATM
|
||||
*/
|
||||
th_pkt_t *
|
||||
parse_latm_audio_mux_element(service_t *t, th_stream_t *st,
|
||||
parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st,
|
||||
const uint8_t *data, int len)
|
||||
{
|
||||
latm_private_t *latm;
|
||||
|
@ -169,8 +169,8 @@ parse_latm_audio_mux_element(service_t *t, th_stream_t *st,
|
|||
|
||||
init_rbits(&bs, data, len * 8);
|
||||
|
||||
if((latm = st->st_priv) == NULL)
|
||||
latm = st->st_priv = calloc(1, sizeof(latm_private_t));
|
||||
if((latm = st->es_priv) == NULL)
|
||||
latm = st->es_priv = calloc(1, sizeof(latm_private_t));
|
||||
|
||||
if(!read_bits1(&bs))
|
||||
read_stream_mux_config(st, latm, &bs);
|
||||
|
@ -191,13 +191,13 @@ parse_latm_audio_mux_element(service_t *t, th_stream_t *st,
|
|||
if(slot_len * 8 > remaining_bits(&bs))
|
||||
return NULL;
|
||||
|
||||
if(st->st_curdts == PTS_UNSET)
|
||||
if(st->es_curdts == PTS_UNSET)
|
||||
return NULL;
|
||||
|
||||
th_pkt_t *pkt = pkt_alloc(NULL, slot_len + 7, st->st_curdts, st->st_curdts);
|
||||
th_pkt_t *pkt = pkt_alloc(NULL, slot_len + 7, st->es_curdts, st->es_curdts);
|
||||
|
||||
pkt->pkt_commercial = t->s_tt_commercial_advice;
|
||||
pkt->pkt_duration = st->st_frame_duration;
|
||||
pkt->pkt_duration = st->es_frame_duration;
|
||||
pkt->pkt_sri = latm->sample_rate_index;
|
||||
pkt->pkt_channels = latm->channel_config;
|
||||
|
||||
|
@ -228,7 +228,7 @@ parse_latm_audio_mux_element(service_t *t, th_stream_t *st,
|
|||
for(i = 0; i < slot_len; i++)
|
||||
*buf++ = read_bits(&bs, 8);
|
||||
|
||||
st->st_curdts += st->st_frame_duration;
|
||||
st->es_curdts += st->es_frame_duration;
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define PARSER_LATM_H_
|
||||
|
||||
th_pkt_t *parse_latm_audio_mux_element(struct service *t,
|
||||
struct th_stream *st,
|
||||
struct elementary_stream *st,
|
||||
const uint8_t *data, int len);
|
||||
|
||||
#endif /* PARSER_LATM_H_ */
|
||||
|
|
426
src/parsers.c
426
src/parsers.c
|
@ -81,55 +81,55 @@ getpts(const uint8_t *p)
|
|||
}
|
||||
|
||||
|
||||
static int parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
||||
static int parse_mpeg2video(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
static int parse_h264(service_t *t, th_stream_t *st, size_t len,
|
||||
static int parse_h264(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
typedef int (packet_parser_t)(service_t *t, th_stream_t *st, size_t len,
|
||||
typedef int (packet_parser_t)(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
typedef void (aparser_t)(service_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
typedef void (aparser_t)(service_t *t, elementary_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
static void parse_sc(service_t *t, th_stream_t *st, const uint8_t *data,
|
||||
static void parse_sc(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
||||
int len, packet_parser_t *vp);
|
||||
|
||||
|
||||
static void parse_aac(service_t *t, th_stream_t *st, const uint8_t *data,
|
||||
static void parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
||||
int len, int start);
|
||||
|
||||
static void parse_subtitles(service_t *t, th_stream_t *st,
|
||||
static void parse_subtitles(service_t *t, elementary_stream_t *st,
|
||||
const uint8_t *data, int len, int start);
|
||||
|
||||
static int parse_mpa(service_t *t, th_stream_t *st, size_t len,
|
||||
static int parse_mpa(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
static int parse_mpa2(service_t *t, th_stream_t *st);
|
||||
static int parse_mpa2(service_t *t, elementary_stream_t *st);
|
||||
|
||||
static int parse_ac3(service_t *t, th_stream_t *st, size_t len,
|
||||
static int parse_ac3(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
static int parse_eac3(service_t *t, th_stream_t *st, size_t len,
|
||||
static int parse_eac3(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
static void parser_deliver(service_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
static void parser_deliver(service_t *t, elementary_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
static int parse_pes_header(service_t *t, th_stream_t *st,
|
||||
static int parse_pes_header(service_t *t, elementary_stream_t *st,
|
||||
const uint8_t *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Parse raw mpeg data
|
||||
*/
|
||||
void
|
||||
parse_mpeg_ts(service_t *t, th_stream_t *st, const uint8_t *data,
|
||||
parse_mpeg_ts(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
||||
int len, int start, int err)
|
||||
{
|
||||
|
||||
if(err)
|
||||
sbuf_err(&st->st_buf);
|
||||
sbuf_err(&st->es_buf);
|
||||
|
||||
switch(st->st_type) {
|
||||
switch(st->es_type) {
|
||||
case SCT_MPEG2VIDEO:
|
||||
parse_sc(t, st, data, len, parse_mpeg2video);
|
||||
break;
|
||||
|
@ -170,7 +170,7 @@ parse_mpeg_ts(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
* Note: data does not include startcode and packet length
|
||||
*/
|
||||
void
|
||||
parse_mpeg_ps(service_t *t, th_stream_t *st, uint8_t *data, int len)
|
||||
parse_mpeg_ps(service_t *t, elementary_stream_t *st, uint8_t *data, int len)
|
||||
{
|
||||
int hlen;
|
||||
|
||||
|
@ -187,9 +187,9 @@ parse_mpeg_ps(service_t *t, th_stream_t *st, uint8_t *data, int len)
|
|||
if(len < 1)
|
||||
return;
|
||||
|
||||
switch(st->st_type) {
|
||||
switch(st->es_type) {
|
||||
case SCT_MPEG2AUDIO:
|
||||
sbuf_append(&st->st_buf_a, data, len);
|
||||
sbuf_append(&st->es_buf_a, data, len);
|
||||
parse_mpa2(t, st);
|
||||
break;
|
||||
|
||||
|
@ -206,7 +206,7 @@ parse_mpeg_ps(service_t *t, th_stream_t *st, uint8_t *data, int len)
|
|||
* Parse AAC LATM
|
||||
*/
|
||||
static void
|
||||
parse_aac(service_t *t, th_stream_t *st, const uint8_t *data,
|
||||
parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
||||
int len, int start)
|
||||
{
|
||||
int l, muxlen, p;
|
||||
|
@ -214,35 +214,35 @@ parse_aac(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
|
||||
if(start) {
|
||||
/* Payload unit start */
|
||||
st->st_parser_state = 1;
|
||||
st->st_parser_ptr = 0;
|
||||
sbuf_reset(&st->st_buf);
|
||||
st->es_parser_state = 1;
|
||||
st->es_parser_ptr = 0;
|
||||
sbuf_reset(&st->es_buf);
|
||||
}
|
||||
|
||||
if(st->st_parser_state == 0)
|
||||
if(st->es_parser_state == 0)
|
||||
return;
|
||||
|
||||
sbuf_append(&st->st_buf, data, len);
|
||||
sbuf_append(&st->es_buf, data, len);
|
||||
|
||||
|
||||
if(st->st_parser_ptr == 0) {
|
||||
if(st->es_parser_ptr == 0) {
|
||||
int hlen;
|
||||
|
||||
if(st->st_buf.sb_ptr < 9)
|
||||
if(st->es_buf.sb_ptr < 9)
|
||||
return;
|
||||
|
||||
hlen = parse_pes_header(t, st,
|
||||
st->st_buf.sb_data + 6, st->st_buf.sb_ptr - 6);
|
||||
st->es_buf.sb_data + 6, st->es_buf.sb_ptr - 6);
|
||||
if(hlen < 0)
|
||||
return;
|
||||
st->st_parser_ptr += 6 + hlen;
|
||||
st->es_parser_ptr += 6 + hlen;
|
||||
}
|
||||
|
||||
|
||||
p = st->st_parser_ptr;
|
||||
p = st->es_parser_ptr;
|
||||
|
||||
while((l = st->st_buf.sb_ptr - p) > 3) {
|
||||
const uint8_t *d = st->st_buf.sb_data + p;
|
||||
while((l = st->es_buf.sb_ptr - p) > 3) {
|
||||
const uint8_t *d = st->es_buf.sb_data + p;
|
||||
if(d[0] == 0x56 && (d[1] & 0xe0) == 0xe0) {
|
||||
muxlen = (d[1] & 0x1f) << 8 | d[2];
|
||||
|
||||
|
@ -259,7 +259,7 @@ parse_aac(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
p++;
|
||||
}
|
||||
}
|
||||
st->st_parser_ptr = p;
|
||||
st->es_parser_ptr = p;
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,43 +273,43 @@ parse_aac(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
* derive further information.
|
||||
*/
|
||||
static void
|
||||
parse_sc(service_t *t, th_stream_t *st, const uint8_t *data, int len,
|
||||
parse_sc(service_t *t, elementary_stream_t *st, const uint8_t *data, int len,
|
||||
packet_parser_t *vp)
|
||||
{
|
||||
uint32_t sc = st->st_startcond;
|
||||
uint32_t sc = st->es_startcond;
|
||||
int i, r;
|
||||
sbuf_alloc(&st->st_buf, len);
|
||||
sbuf_alloc(&st->es_buf, len);
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
|
||||
if(st->st_ssc_intercept == 1) {
|
||||
if(st->es_ssc_intercept == 1) {
|
||||
|
||||
if(st->st_ssc_ptr < sizeof(st->st_ssc_buf))
|
||||
st->st_ssc_buf[st->st_ssc_ptr] = data[i];
|
||||
st->st_ssc_ptr++;
|
||||
if(st->es_ssc_ptr < sizeof(st->es_ssc_buf))
|
||||
st->es_ssc_buf[st->es_ssc_ptr] = data[i];
|
||||
st->es_ssc_ptr++;
|
||||
|
||||
if(st->st_ssc_ptr < 5)
|
||||
if(st->es_ssc_ptr < 5)
|
||||
continue;
|
||||
|
||||
uint16_t plen = st->st_ssc_buf[0] << 8 | st->st_ssc_buf[1];
|
||||
st->st_incomplete = plen >= 0xffdf;
|
||||
uint16_t plen = st->es_ssc_buf[0] << 8 | st->es_ssc_buf[1];
|
||||
st->es_incomplete = plen >= 0xffdf;
|
||||
|
||||
int hlen = st->st_ssc_buf[4];
|
||||
int hlen = st->es_ssc_buf[4];
|
||||
|
||||
if(st->st_ssc_ptr < hlen + 5)
|
||||
if(st->es_ssc_ptr < hlen + 5)
|
||||
continue;
|
||||
|
||||
parse_pes_header(t, st, st->st_ssc_buf + 2, hlen + 3);
|
||||
st->st_ssc_intercept = 0;
|
||||
if(st->st_buf.sb_ptr > 2)
|
||||
sc = st->st_buf.sb_data[st->st_buf.sb_ptr-3] << 16 |
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr-2] << 8 |
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr-1];
|
||||
parse_pes_header(t, st, st->es_ssc_buf + 2, hlen + 3);
|
||||
st->es_ssc_intercept = 0;
|
||||
if(st->es_buf.sb_ptr > 2)
|
||||
sc = st->es_buf.sb_data[st->es_buf.sb_ptr-3] << 16 |
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr-2] << 8 |
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr-1];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = data[i];
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = data[i];
|
||||
sc = sc << 8 | data[i];
|
||||
|
||||
if((sc & 0xffffff00) != 0x00000100)
|
||||
|
@ -322,16 +322,16 @@ parse_sc(service_t *t, th_stream_t *st, const uint8_t *data, int len,
|
|||
continue;
|
||||
}
|
||||
|
||||
r = st->st_buf.sb_ptr - st->st_startcode_offset - 4;
|
||||
r = st->es_buf.sb_ptr - st->es_startcode_offset - 4;
|
||||
|
||||
if(r > 0 && st->st_startcode != 0) {
|
||||
r = vp(t, st, r, sc, st->st_startcode_offset);
|
||||
if(r > 0 && st->es_startcode != 0) {
|
||||
r = vp(t, st, r, sc, st->es_startcode_offset);
|
||||
if(r == 3)
|
||||
continue;
|
||||
if(r == 4) {
|
||||
st->st_buf.sb_ptr -= 4;
|
||||
st->st_ssc_intercept = 1;
|
||||
st->st_ssc_ptr = 0;
|
||||
st->es_buf.sb_ptr -= 4;
|
||||
st->es_ssc_intercept = 1;
|
||||
st->es_ssc_ptr = 0;
|
||||
sc = -1;
|
||||
continue;
|
||||
}
|
||||
|
@ -339,33 +339,33 @@ parse_sc(service_t *t, th_stream_t *st, const uint8_t *data, int len,
|
|||
r = 1;
|
||||
}
|
||||
|
||||
assert(st->st_buf.sb_data != NULL);
|
||||
assert(st->es_buf.sb_data != NULL);
|
||||
|
||||
if(r == 2) {
|
||||
// Drop packet
|
||||
st->st_buf.sb_ptr = st->st_startcode_offset;
|
||||
st->es_buf.sb_ptr = st->es_startcode_offset;
|
||||
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 24;
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 16;
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 8;
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc;
|
||||
st->st_startcode = sc;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 24;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 16;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 8;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc;
|
||||
st->es_startcode = sc;
|
||||
|
||||
} else {
|
||||
if(r == 1) {
|
||||
/* Reset packet parser upon length error or if parser
|
||||
tells us so */
|
||||
sbuf_reset(&st->st_buf);
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 24;
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 16;
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 8;
|
||||
st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc;
|
||||
sbuf_reset(&st->es_buf);
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 24;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 16;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 8;
|
||||
st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc;
|
||||
}
|
||||
st->st_startcode = sc;
|
||||
st->st_startcode_offset = st->st_buf.sb_ptr - 4;
|
||||
st->es_startcode = sc;
|
||||
st->es_startcode_offset = st->es_buf.sb_ptr - 4;
|
||||
}
|
||||
}
|
||||
st->st_startcond = sc;
|
||||
st->es_startcond = sc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -373,11 +373,11 @@ parse_sc(service_t *t, th_stream_t *st, const uint8_t *data, int len,
|
|||
*
|
||||
*/
|
||||
static int
|
||||
depacketize(service_t *t, th_stream_t *st, size_t len,
|
||||
depacketize(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
const uint8_t *buf = st->st_buf.sb_data + sc_offset;
|
||||
uint32_t sc = st->st_startcode;
|
||||
const uint8_t *buf = st->es_buf.sb_data + sc_offset;
|
||||
uint32_t sc = st->es_startcode;
|
||||
int hlen, plen;
|
||||
|
||||
if((sc != 0x1bd && (sc & ~0x1f) != 0x1c0) || len < 9)
|
||||
|
@ -402,7 +402,7 @@ depacketize(service_t *t, th_stream_t *st, size_t len,
|
|||
buf += hlen;
|
||||
len -= hlen;
|
||||
|
||||
sbuf_append(&st->st_buf_a, buf, len);
|
||||
sbuf_append(&st->es_buf_a, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,7 @@ depacketize(service_t *t, th_stream_t *st, size_t len,
|
|||
*
|
||||
*/
|
||||
static void
|
||||
makeapkt(service_t *t, th_stream_t *st, const void *buf,
|
||||
makeapkt(service_t *t, elementary_stream_t *st, const void *buf,
|
||||
int len, int64_t dts, int duration, int channels, int sri)
|
||||
{
|
||||
|
||||
|
@ -426,8 +426,8 @@ makeapkt(service_t *t, th_stream_t *st, const void *buf,
|
|||
|
||||
parser_deliver(t, st, pkt);
|
||||
|
||||
st->st_curdts = PTS_UNSET;
|
||||
st->st_nextdts = dts + duration;
|
||||
st->es_curdts = PTS_UNSET;
|
||||
st->es_nextdts = dts + duration;
|
||||
}
|
||||
|
||||
|
||||
|
@ -453,14 +453,14 @@ mpa_valid_frame(const uint8_t *buf)
|
|||
*
|
||||
*/
|
||||
static int
|
||||
parse_mpa2(service_t *t, th_stream_t *st)
|
||||
parse_mpa2(service_t *t, elementary_stream_t *st)
|
||||
{
|
||||
int i, len;
|
||||
const uint8_t *buf;
|
||||
|
||||
again:
|
||||
buf = st->st_buf_a.sb_data;
|
||||
len = st->st_buf_a.sb_ptr;
|
||||
buf = st->es_buf_a.sb_data;
|
||||
len = st->es_buf_a.sb_ptr;
|
||||
|
||||
for(i = 0; i < len - 4; i++) {
|
||||
if(mpa_valid_frame(buf + i)) {
|
||||
|
@ -471,10 +471,10 @@ parse_mpa2(service_t *t, th_stream_t *st)
|
|||
if(br && sr) {
|
||||
int fsize = 144000 * br / sr + pad;
|
||||
int duration = 90000 * 1152 / sr;
|
||||
int64_t dts = st->st_curdts;
|
||||
int64_t dts = st->es_curdts;
|
||||
int channels = (buf[i + 3] & 0xc0) == 0xc0 ? 1 : 2;
|
||||
if(dts == PTS_UNSET)
|
||||
dts = st->st_nextdts;
|
||||
dts = st->es_nextdts;
|
||||
|
||||
if(dts != PTS_UNSET &&
|
||||
len >= i + fsize + 4 &&
|
||||
|
@ -482,7 +482,7 @@ parse_mpa2(service_t *t, th_stream_t *st)
|
|||
|
||||
makeapkt(t, st, buf + i, fsize, dts, duration,
|
||||
channels, mpa_sri[(buf[i+2] >> 2) & 3]);
|
||||
sbuf_cut(&st->st_buf_a, i + fsize);
|
||||
sbuf_cut(&st->es_buf_a, i + fsize);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ parse_mpa2(service_t *t, th_stream_t *st)
|
|||
*
|
||||
*/
|
||||
static int
|
||||
parse_mpa(service_t *t, th_stream_t *st, size_t ilen,
|
||||
parse_mpa(service_t *t, elementary_stream_t *st, size_t ilen,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
int r;
|
||||
|
@ -567,7 +567,7 @@ static const char acmodtab[8] = {2,1,2,3,3,4,4,5};
|
|||
|
||||
|
||||
static int
|
||||
parse_ac3(service_t *t, th_stream_t *st, size_t ilen,
|
||||
parse_ac3(service_t *t, elementary_stream_t *st, size_t ilen,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
int i, len;
|
||||
|
@ -577,8 +577,8 @@ parse_ac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
return i;
|
||||
|
||||
again:
|
||||
buf = st->st_buf_a.sb_data;
|
||||
len = st->st_buf_a.sb_ptr;
|
||||
buf = st->es_buf_a.sb_data;
|
||||
len = st->es_buf_a.sb_ptr;
|
||||
|
||||
for(i = 0; i < len - 6; i++) {
|
||||
const uint8_t *p = buf + i;
|
||||
|
@ -595,11 +595,11 @@ parse_ac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
|
||||
if(sr) {
|
||||
int duration = 90000 * 1536 / sr;
|
||||
int64_t dts = st->st_curdts;
|
||||
int64_t dts = st->es_curdts;
|
||||
int sri = rate_to_sri(sr);
|
||||
|
||||
if(dts == PTS_UNSET)
|
||||
dts = st->st_nextdts;
|
||||
dts = st->es_nextdts;
|
||||
|
||||
if(dts != PTS_UNSET && len >= i + fsize + 6 &&
|
||||
ac3_valid_frame(p + fsize)) {
|
||||
|
@ -622,7 +622,7 @@ parse_ac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
int channels = acmodtab[acmod] + lfeon;
|
||||
|
||||
makeapkt(t, st, p, fsize, dts, duration, channels, sri);
|
||||
sbuf_cut(&st->st_buf_a, i + fsize);
|
||||
sbuf_cut(&st->es_buf_a, i + fsize);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
@ -646,7 +646,7 @@ eac3_valid_frame(const uint8_t *buf)
|
|||
}
|
||||
|
||||
static int
|
||||
parse_eac3(service_t *t, th_stream_t *st, size_t ilen,
|
||||
parse_eac3(service_t *t, elementary_stream_t *st, size_t ilen,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
int i, len;
|
||||
|
@ -656,8 +656,8 @@ parse_eac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
return i;
|
||||
|
||||
again:
|
||||
buf = st->st_buf_a.sb_data;
|
||||
len = st->st_buf_a.sb_ptr;
|
||||
buf = st->es_buf_a.sb_data;
|
||||
len = st->es_buf_a.sb_ptr;
|
||||
|
||||
for(i = 0; i < len - 6; i++) {
|
||||
const uint8_t *p = buf + i;
|
||||
|
@ -677,7 +677,7 @@ parse_eac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
}
|
||||
|
||||
|
||||
int64_t dts = st->st_curdts;
|
||||
int64_t dts = st->es_curdts;
|
||||
int sri = rate_to_sri(rate);
|
||||
|
||||
int acmod = (p[4] >> 1) & 0x7;
|
||||
|
@ -687,12 +687,12 @@ parse_eac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
int duration = 90000 * 1536 / rate;
|
||||
|
||||
if(dts == PTS_UNSET)
|
||||
dts = st->st_nextdts;
|
||||
dts = st->es_nextdts;
|
||||
|
||||
if(dts != PTS_UNSET && len >= i + fsize + 6 &&
|
||||
eac3_valid_frame(p + fsize)) {
|
||||
makeapkt(t, st, p, fsize, dts, duration, channels, sri);
|
||||
sbuf_cut(&st->st_buf_a, i + fsize);
|
||||
sbuf_cut(&st->es_buf_a, i + fsize);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ parse_eac3(service_t *t, th_stream_t *st, size_t ilen,
|
|||
* Extract DTS and PTS and update current values in stream
|
||||
*/
|
||||
static int
|
||||
parse_pes_header(service_t *t, th_stream_t *st,
|
||||
parse_pes_header(service_t *t, elementary_stream_t *st,
|
||||
const uint8_t *buf, size_t len)
|
||||
{
|
||||
int64_t dts, pts, d;
|
||||
|
@ -742,19 +742,19 @@ parse_pes_header(service_t *t, th_stream_t *st,
|
|||
} else
|
||||
return hlen + 3;
|
||||
|
||||
if(st->st_buf.sb_err) {
|
||||
st->st_curdts = PTS_UNSET;
|
||||
st->st_curpts = PTS_UNSET;
|
||||
if(st->es_buf.sb_err) {
|
||||
st->es_curdts = PTS_UNSET;
|
||||
st->es_curpts = PTS_UNSET;
|
||||
} else {
|
||||
st->st_curdts = dts;
|
||||
st->st_curpts = pts;
|
||||
st->es_curdts = dts;
|
||||
st->es_curpts = pts;
|
||||
}
|
||||
return hlen + 3;
|
||||
|
||||
err:
|
||||
st->st_curdts = PTS_UNSET;
|
||||
st->st_curpts = PTS_UNSET;
|
||||
limitedlog(&st->st_loglimit_pes, "TS", service_component_nicename(st),
|
||||
st->es_curdts = PTS_UNSET;
|
||||
st->es_curpts = PTS_UNSET;
|
||||
limitedlog(&st->es_loglimit_pes, "TS", service_component_nicename(st),
|
||||
"Corrupted PES header");
|
||||
return -1;
|
||||
}
|
||||
|
@ -780,7 +780,7 @@ const unsigned int mpeg2video_framedurations[16] = {
|
|||
* Parse mpeg2video picture start
|
||||
*/
|
||||
static int
|
||||
parse_mpeg2video_pic_start(service_t *t, th_stream_t *st, int *frametype,
|
||||
parse_mpeg2video_pic_start(service_t *t, elementary_stream_t *st, int *frametype,
|
||||
bitstream_t *bs)
|
||||
{
|
||||
int v, pct;
|
||||
|
@ -798,9 +798,9 @@ parse_mpeg2video_pic_start(service_t *t, th_stream_t *st, int *frametype,
|
|||
|
||||
v = read_bits(bs, 16); /* vbv_delay */
|
||||
if(v == 0xffff)
|
||||
st->st_vbv_delay = -1;
|
||||
st->es_vbv_delay = -1;
|
||||
else
|
||||
st->st_vbv_delay = v;
|
||||
st->es_vbv_delay = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -808,28 +808,28 @@ parse_mpeg2video_pic_start(service_t *t, th_stream_t *st, int *frametype,
|
|||
*
|
||||
*/
|
||||
void
|
||||
parser_set_stream_vsize(th_stream_t *st, int width, int height)
|
||||
parser_set_stream_vsize(elementary_stream_t *st, int width, int height)
|
||||
{
|
||||
int need_save = 0;
|
||||
|
||||
if(st->st_width == 0 && st->st_height == 0) {
|
||||
if(st->es_width == 0 && st->es_height == 0) {
|
||||
need_save = 1;
|
||||
st->st_meta_change = 0;
|
||||
st->es_meta_change = 0;
|
||||
|
||||
} else if(st->st_width != width || st->st_height != height) {
|
||||
} else if(st->es_width != width || st->es_height != height) {
|
||||
|
||||
st->st_meta_change++;
|
||||
if(st->st_meta_change == 2)
|
||||
st->es_meta_change++;
|
||||
if(st->es_meta_change == 2)
|
||||
need_save = 1;
|
||||
|
||||
} else {
|
||||
st->st_meta_change = 0;
|
||||
st->es_meta_change = 0;
|
||||
}
|
||||
|
||||
if(need_save) {
|
||||
st->st_width = width;
|
||||
st->st_height = height;
|
||||
service_request_save(st->st_service, 1);
|
||||
st->es_width = width;
|
||||
st->es_height = height;
|
||||
service_request_save(st->es_service, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,7 +858,7 @@ static const uint8_t mpeg2_aspect[16][2]={
|
|||
* Parse mpeg2video sequence start
|
||||
*/
|
||||
static int
|
||||
parse_mpeg2video_seq_start(service_t *t, th_stream_t *st,
|
||||
parse_mpeg2video_seq_start(service_t *t, elementary_stream_t *st,
|
||||
bitstream_t *bs)
|
||||
{
|
||||
int v, width, height, aspect;
|
||||
|
@ -870,16 +870,16 @@ parse_mpeg2video_seq_start(service_t *t, th_stream_t *st,
|
|||
height = read_bits(bs, 12);
|
||||
aspect = read_bits(bs, 4);
|
||||
|
||||
st->st_aspect_num = mpeg2_aspect[aspect][0];
|
||||
st->st_aspect_den = mpeg2_aspect[aspect][1];
|
||||
st->es_aspect_num = mpeg2_aspect[aspect][0];
|
||||
st->es_aspect_den = mpeg2_aspect[aspect][1];
|
||||
|
||||
st->st_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)];
|
||||
st->es_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)];
|
||||
|
||||
v = read_bits(bs, 18) * 400;
|
||||
skip_bits(bs, 1);
|
||||
|
||||
v = read_bits(bs, 10) * 16 * 1024 / 8;
|
||||
st->st_vbv_size = v;
|
||||
st->es_vbv_size = v;
|
||||
|
||||
parser_set_stream_vsize(st, width, height);
|
||||
return 0;
|
||||
|
@ -902,16 +902,16 @@ drop_trailing_zeroes(const uint8_t *buf, size_t len)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
parser_global_data_move(th_stream_t *st, const uint8_t *data, size_t len)
|
||||
parser_global_data_move(elementary_stream_t *st, const uint8_t *data, size_t len)
|
||||
{
|
||||
int len2 = drop_trailing_zeroes(data, len);
|
||||
|
||||
st->st_global_data = realloc(st->st_global_data,
|
||||
st->st_global_data_len + len2);
|
||||
memcpy(st->st_global_data + st->st_global_data_len, data, len2);
|
||||
st->st_global_data_len += len2;
|
||||
st->es_global_data = realloc(st->es_global_data,
|
||||
st->es_global_data_len + len2);
|
||||
memcpy(st->es_global_data + st->es_global_data_len, data, len2);
|
||||
st->es_global_data_len += len2;
|
||||
|
||||
st->st_buf.sb_ptr -= len;
|
||||
st->es_buf.sb_ptr -= len;
|
||||
}
|
||||
|
||||
|
||||
|
@ -922,14 +922,14 @@ parser_global_data_move(th_stream_t *st, const uint8_t *data, size_t len)
|
|||
*
|
||||
* Extract framerate (or duration to be more specific)
|
||||
*
|
||||
* 'steal' the st->st_buffer and use it as 'pkt' buffer
|
||||
* 'steal' the st->es_buffer and use it as 'pkt' buffer
|
||||
*
|
||||
*/
|
||||
static int
|
||||
parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
||||
parse_mpeg2video(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
const uint8_t *buf = st->st_buf.sb_data + sc_offset;
|
||||
const uint8_t *buf = st->es_buf.sb_data + sc_offset;
|
||||
bitstream_t bs;
|
||||
int frametype;
|
||||
|
||||
|
@ -938,7 +938,7 @@ parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
init_rbits(&bs, buf + 4, (len - 4) * 8);
|
||||
|
||||
switch(st->st_startcode) {
|
||||
switch(st->es_startcode) {
|
||||
case 0x000001e0 ... 0x000001ef:
|
||||
/* System start codes for video */
|
||||
if(len < 9)
|
||||
|
@ -949,24 +949,24 @@ parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
case 0x00000100:
|
||||
/* Picture start code */
|
||||
if(st->st_frame_duration == 0)
|
||||
if(st->es_frame_duration == 0)
|
||||
return 1;
|
||||
|
||||
if(parse_mpeg2video_pic_start(t, st, &frametype, &bs))
|
||||
return 1;
|
||||
|
||||
if(st->st_curpkt != NULL)
|
||||
pkt_ref_dec(st->st_curpkt);
|
||||
if(st->es_curpkt != NULL)
|
||||
pkt_ref_dec(st->es_curpkt);
|
||||
|
||||
st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts);
|
||||
st->st_curpkt->pkt_frametype = frametype;
|
||||
st->st_curpkt->pkt_duration = st->st_frame_duration;
|
||||
st->st_curpkt->pkt_commercial = t->s_tt_commercial_advice;
|
||||
st->es_curpkt = pkt_alloc(NULL, 0, st->es_curpts, st->es_curdts);
|
||||
st->es_curpkt->pkt_frametype = frametype;
|
||||
st->es_curpkt->pkt_duration = st->es_frame_duration;
|
||||
st->es_curpkt->pkt_commercial = t->s_tt_commercial_advice;
|
||||
break;
|
||||
|
||||
case 0x000001b3:
|
||||
/* Sequence start code */
|
||||
if(!st->st_buf.sb_err) {
|
||||
if(!st->es_buf.sb_err) {
|
||||
if(parse_mpeg2video_seq_start(t, st, &bs))
|
||||
return 1;
|
||||
parser_global_data_move(st, buf, len);
|
||||
|
@ -979,12 +979,12 @@ parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
|||
switch(buf[4] >> 4) {
|
||||
case 0x1:
|
||||
// Sequence Extension
|
||||
if(!st->st_buf.sb_err)
|
||||
if(!st->es_buf.sb_err)
|
||||
parser_global_data_move(st, buf, len);
|
||||
return 2;
|
||||
case 0x2:
|
||||
// Sequence Display Extension
|
||||
if(!st->st_buf.sb_err)
|
||||
if(!st->es_buf.sb_err)
|
||||
parser_global_data_move(st, buf, len);
|
||||
return 2;
|
||||
}
|
||||
|
@ -995,46 +995,46 @@ parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
if(next_startcode == 0x100 || next_startcode > 0x1af) {
|
||||
/* Last picture slice (because next not a slice) */
|
||||
th_pkt_t *pkt = st->st_curpkt;
|
||||
th_pkt_t *pkt = st->es_curpkt;
|
||||
if(pkt == NULL) {
|
||||
/* no packet, may've been discarded by sanity checks here */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(st->st_global_data) {
|
||||
pkt->pkt_header = pktbuf_make(st->st_global_data,
|
||||
st->st_global_data_len);
|
||||
st->st_global_data = NULL;
|
||||
st->st_global_data_len = 0;
|
||||
if(st->es_global_data) {
|
||||
pkt->pkt_header = pktbuf_make(st->es_global_data,
|
||||
st->es_global_data_len);
|
||||
st->es_global_data = NULL;
|
||||
st->es_global_data_len = 0;
|
||||
}
|
||||
|
||||
pkt->pkt_payload = pktbuf_make(st->st_buf.sb_data,
|
||||
st->st_buf.sb_ptr - 4);
|
||||
pkt->pkt_duration = st->st_frame_duration;
|
||||
pkt->pkt_payload = pktbuf_make(st->es_buf.sb_data,
|
||||
st->es_buf.sb_ptr - 4);
|
||||
pkt->pkt_duration = st->es_frame_duration;
|
||||
|
||||
parser_deliver(t, st, pkt);
|
||||
st->st_curpkt = NULL;
|
||||
st->es_curpkt = NULL;
|
||||
|
||||
st->st_buf.sb_data = malloc(st->st_buf.sb_size);
|
||||
if(st->st_buf.sb_data == NULL) {
|
||||
st->es_buf.sb_data = malloc(st->es_buf.sb_size);
|
||||
if(st->es_buf.sb_data == NULL) {
|
||||
fprintf(stderr, "Unable to allocate %d bytes\n",
|
||||
st->st_buf.sb_size);
|
||||
st->es_buf.sb_size);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* If we know the frame duration, increase DTS accordingly */
|
||||
if(st->st_curdts != PTS_UNSET)
|
||||
st->st_curdts += st->st_frame_duration;
|
||||
if(st->es_curdts != PTS_UNSET)
|
||||
st->es_curdts += st->es_frame_duration;
|
||||
|
||||
/* PTS cannot be extrapolated (it's not linear) */
|
||||
st->st_curpts = PTS_UNSET;
|
||||
st->es_curpts = PTS_UNSET;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x000001b8:
|
||||
// GOP header
|
||||
if(!st->st_buf.sb_err)
|
||||
if(!st->es_buf.sb_err)
|
||||
parser_global_data_move(st, buf, len);
|
||||
return 2;
|
||||
|
||||
|
@ -1054,11 +1054,11 @@ parse_mpeg2video(service_t *t, th_stream_t *st, size_t len,
|
|||
* H.264 parser
|
||||
*/
|
||||
static int
|
||||
parse_h264(service_t *t, th_stream_t *st, size_t len,
|
||||
parse_h264(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
const uint8_t *buf = st->st_buf.sb_data + sc_offset;
|
||||
uint32_t sc = st->st_startcode;
|
||||
const uint8_t *buf = st->es_buf.sb_data + sc_offset;
|
||||
uint32_t sc = st->es_startcode;
|
||||
int64_t d;
|
||||
int l2, pkttype, duration, isfield;
|
||||
bitstream_t bs;
|
||||
|
@ -1068,23 +1068,23 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
/* System start codes for video */
|
||||
if(len >= 9){
|
||||
uint16_t plen = buf[4] << 8 | buf[5];
|
||||
if(plen >= 0xffe9) st->st_incomplete =1;
|
||||
if(plen >= 0xffe9) st->es_incomplete =1;
|
||||
parse_pes_header(t, st, buf + 6, len - 6);
|
||||
}
|
||||
if(st->st_prevdts != PTS_UNSET && st->st_curdts != PTS_UNSET) {
|
||||
d = (st->st_curdts - st->st_prevdts) & 0x1ffffffffLL;
|
||||
if(st->es_prevdts != PTS_UNSET && st->es_curdts != PTS_UNSET) {
|
||||
d = (st->es_curdts - st->es_prevdts) & 0x1ffffffffLL;
|
||||
|
||||
if(d < 90000)
|
||||
st->st_frame_duration = d;
|
||||
st->es_frame_duration = d;
|
||||
}
|
||||
st->st_prevdts = st->st_curdts;
|
||||
st->es_prevdts = st->es_curdts;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(sc == 0x10c) {
|
||||
// Padding
|
||||
|
||||
st->st_buf.sb_ptr -= len;
|
||||
st->es_buf.sb_ptr -= len;
|
||||
ret = 2;
|
||||
|
||||
} else {
|
||||
|
@ -1092,7 +1092,7 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
switch(sc & 0x1f) {
|
||||
|
||||
case 7:
|
||||
if(!st->st_buf.sb_err) {
|
||||
if(!st->es_buf.sb_err) {
|
||||
void *f = h264_nal_deescape(&bs, buf + 3, len - 3);
|
||||
h264_decode_seq_parameter_set(st, &bs);
|
||||
free(f);
|
||||
|
@ -1102,7 +1102,7 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
break;
|
||||
|
||||
case 8:
|
||||
if(!st->st_buf.sb_err) {
|
||||
if(!st->es_buf.sb_err) {
|
||||
void *f = h264_nal_deescape(&bs, buf + 3, len - 3);
|
||||
h264_decode_pic_parameter_set(st, &bs);
|
||||
free(f);
|
||||
|
@ -1113,7 +1113,7 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
case 5: /* IDR+SLICE */
|
||||
case 1:
|
||||
if(st->st_curpkt != NULL || st->st_frame_duration == 0)
|
||||
if(st->es_curpkt != NULL || st->es_frame_duration == 0)
|
||||
break;
|
||||
|
||||
l2 = len - 3 > 64 ? 64 : len - 3;
|
||||
|
@ -1126,11 +1126,11 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
}
|
||||
free(f);
|
||||
|
||||
st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts);
|
||||
st->st_curpkt->pkt_frametype = pkttype;
|
||||
st->st_curpkt->pkt_field = isfield;
|
||||
st->st_curpkt->pkt_duration = duration ?: st->st_frame_duration;
|
||||
st->st_curpkt->pkt_commercial = t->s_tt_commercial_advice;
|
||||
st->es_curpkt = pkt_alloc(NULL, 0, st->es_curpts, st->es_curdts);
|
||||
st->es_curpkt->pkt_frametype = pkttype;
|
||||
st->es_curpkt->pkt_field = isfield;
|
||||
st->es_curpkt->pkt_duration = duration ?: st->es_frame_duration;
|
||||
st->es_curpkt->pkt_commercial = t->s_tt_commercial_advice;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1140,27 +1140,27 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
if(next_startcode >= 0x000001e0 && next_startcode <= 0x000001ef) {
|
||||
/* Complete frame */
|
||||
if (st->st_incomplete) return 4;
|
||||
th_pkt_t *pkt = st->st_curpkt;
|
||||
if (st->es_incomplete) return 4;
|
||||
th_pkt_t *pkt = st->es_curpkt;
|
||||
|
||||
if(pkt != NULL) {
|
||||
|
||||
if(st->st_global_data) {
|
||||
pkt->pkt_header = pktbuf_make(st->st_global_data,
|
||||
st->st_global_data_len);
|
||||
st->st_global_data = NULL;
|
||||
st->st_global_data_len = 0;
|
||||
if(st->es_global_data) {
|
||||
pkt->pkt_header = pktbuf_make(st->es_global_data,
|
||||
st->es_global_data_len);
|
||||
st->es_global_data = NULL;
|
||||
st->es_global_data_len = 0;
|
||||
}
|
||||
|
||||
pkt->pkt_payload = pktbuf_make(st->st_buf.sb_data,
|
||||
st->st_buf.sb_ptr - 4);
|
||||
pkt->pkt_payload = pktbuf_make(st->es_buf.sb_data,
|
||||
st->es_buf.sb_ptr - 4);
|
||||
parser_deliver(t, st, pkt);
|
||||
|
||||
st->st_curpkt = NULL;
|
||||
st->st_buf.sb_data = malloc(st->st_buf.sb_size);
|
||||
st->es_curpkt = NULL;
|
||||
st->es_buf.sb_data = malloc(st->es_buf.sb_size);
|
||||
|
||||
st->st_curdts = PTS_UNSET;
|
||||
st->st_curpts = PTS_UNSET;
|
||||
st->es_curdts = PTS_UNSET;
|
||||
st->es_curpts = PTS_UNSET;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1172,7 +1172,7 @@ parse_h264(service_t *t, th_stream_t *st, size_t len,
|
|||
* http://broadcasting.ru/pdf-standard-specifications/subtitling/dvb-sub/en300743.v1.2.1.pdf
|
||||
*/
|
||||
static void
|
||||
parse_subtitles(service_t *t, th_stream_t *st, const uint8_t *data,
|
||||
parse_subtitles(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
||||
int len, int start)
|
||||
{
|
||||
th_pkt_t *pkt;
|
||||
|
@ -1181,34 +1181,34 @@ parse_subtitles(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
const uint8_t *d;
|
||||
if(start) {
|
||||
/* Payload unit start */
|
||||
st->st_parser_state = 1;
|
||||
st->st_buf.sb_err = 0;
|
||||
st->st_buf.sb_ptr = 0;
|
||||
st->es_parser_state = 1;
|
||||
st->es_buf.sb_err = 0;
|
||||
st->es_buf.sb_ptr = 0;
|
||||
}
|
||||
|
||||
if(st->st_parser_state == 0)
|
||||
if(st->es_parser_state == 0)
|
||||
return;
|
||||
|
||||
sbuf_append(&st->st_buf, data, len);
|
||||
sbuf_append(&st->es_buf, data, len);
|
||||
|
||||
if(st->st_buf.sb_ptr < 6)
|
||||
if(st->es_buf.sb_ptr < 6)
|
||||
return;
|
||||
d = st->st_buf.sb_data;
|
||||
d = st->es_buf.sb_data;
|
||||
uint32_t startcode = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
|
||||
|
||||
if(startcode == 0x1be) {
|
||||
st->st_parser_state = 0;
|
||||
st->es_parser_state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
psize = d[4] << 8 | d[5];
|
||||
|
||||
if(st->st_buf.sb_ptr != psize + 6)
|
||||
if(st->es_buf.sb_ptr != psize + 6)
|
||||
return;
|
||||
|
||||
st->st_parser_state = 0;
|
||||
st->es_parser_state = 0;
|
||||
|
||||
hlen = parse_pes_header(t, st, d + 6, st->st_buf.sb_ptr - 6);
|
||||
hlen = parse_pes_header(t, st, d + 6, st->es_buf.sb_ptr - 6);
|
||||
if(hlen < 0)
|
||||
return;
|
||||
|
||||
|
@ -1225,7 +1225,7 @@ parse_subtitles(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
|
||||
// end_of_PES_data_field_marker
|
||||
if(buf[psize - 1] == 0xff) {
|
||||
pkt = pkt_alloc(buf, psize - 1, st->st_curpts, st->st_curdts);
|
||||
pkt = pkt_alloc(buf, psize - 1, st->es_curpts, st->es_curdts);
|
||||
pkt->pkt_commercial = t->s_tt_commercial_advice;
|
||||
parser_deliver(t, st, pkt);
|
||||
}
|
||||
|
@ -1237,9 +1237,9 @@ parse_subtitles(service_t *t, th_stream_t *st, const uint8_t *data,
|
|||
*
|
||||
*/
|
||||
static void
|
||||
parser_deliver(service_t *t, th_stream_t *st, th_pkt_t *pkt)
|
||||
parser_deliver(service_t *t, elementary_stream_t *st, th_pkt_t *pkt)
|
||||
{
|
||||
if(SCT_ISAUDIO(st->st_type) && pkt->pkt_pts != PTS_UNSET &&
|
||||
if(SCT_ISAUDIO(st->es_type) && pkt->pkt_pts != PTS_UNSET &&
|
||||
(t->s_current_pts == PTS_UNSET ||
|
||||
pkt->pkt_pts > t->s_current_pts ||
|
||||
pkt->pkt_pts < t->s_current_pts - 180000))
|
||||
|
@ -1247,7 +1247,7 @@ parser_deliver(service_t *t, th_stream_t *st, th_pkt_t *pkt)
|
|||
|
||||
#if 0
|
||||
printf("PARSE: %-12s %d %10"PRId64" %10"PRId64" %10d %10d\n",
|
||||
streaming_component_type2txt(st->st_type),
|
||||
streaming_component_type2txt(st->es_type),
|
||||
pkt->pkt_frametype,
|
||||
pkt->pkt_dts,
|
||||
pkt->pkt_pts,
|
||||
|
@ -1255,10 +1255,10 @@ parser_deliver(service_t *t, th_stream_t *st, th_pkt_t *pkt)
|
|||
pktbuf_len(pkt->pkt_payload));
|
||||
#endif
|
||||
|
||||
pkt->pkt_aspect_num = st->st_aspect_num;
|
||||
pkt->pkt_aspect_den = st->st_aspect_den;
|
||||
pkt->pkt_aspect_num = st->es_aspect_num;
|
||||
pkt->pkt_aspect_den = st->es_aspect_den;
|
||||
|
||||
// avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock);
|
||||
// avgstat_add(&st->es_rate, pkt->pkt_payloadlen, dispatch_clock);
|
||||
|
||||
/**
|
||||
* Input is ok
|
||||
|
@ -1266,7 +1266,7 @@ parser_deliver(service_t *t, th_stream_t *st, th_pkt_t *pkt)
|
|||
service_set_streaming_status_flags(t, TSS_PACKETS);
|
||||
|
||||
/* Forward packet */
|
||||
pkt->pkt_componentindex = st->st_index;
|
||||
pkt->pkt_componentindex = st->es_index;
|
||||
|
||||
streaming_message_t *sm = streaming_msg_create_pkt(pkt);
|
||||
|
||||
|
|
|
@ -21,17 +21,17 @@
|
|||
|
||||
#include "packet.h"
|
||||
|
||||
void parse_mpeg_ts(struct service *t, struct th_stream *st,
|
||||
void parse_mpeg_ts(struct service *t, struct elementary_stream *st,
|
||||
const uint8_t *data,
|
||||
int len, int start, int err);
|
||||
|
||||
void parse_mpeg_ps(struct service *t, struct th_stream *st,
|
||||
void parse_mpeg_ps(struct service *t, struct elementary_stream *st,
|
||||
uint8_t *data, int len);
|
||||
|
||||
void parser_enqueue_packet(struct service *t, struct th_stream *st,
|
||||
void parser_enqueue_packet(struct service *t, struct elementary_stream *st,
|
||||
th_pkt_t *pkt);
|
||||
|
||||
void parser_set_stream_vsize(struct th_stream *st, int width, int height);
|
||||
void parser_set_stream_vsize(struct elementary_stream *st, int width, int height);
|
||||
|
||||
extern const unsigned int mpeg2video_framedurations[16];
|
||||
|
||||
|
|
142
src/psi.c
142
src/psi.c
|
@ -118,7 +118,7 @@ psi_parse_pat(service_t *t, uint8_t *ptr, int len,
|
|||
{
|
||||
uint16_t prognum;
|
||||
uint16_t pid;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
|
@ -136,8 +136,8 @@ psi_parse_pat(service_t *t, uint8_t *ptr, int len,
|
|||
if(prognum != 0) {
|
||||
if(service_stream_find(t, pid) == NULL) {
|
||||
st = service_stream_create(t, pid, SCT_PMT);
|
||||
st->st_section_docrc = 1;
|
||||
st->st_got_section = pmt_callback;
|
||||
st->es_section_docrc = 1;
|
||||
st->es_got_section = pmt_callback;
|
||||
}
|
||||
}
|
||||
ptr += 4;
|
||||
|
@ -226,7 +226,7 @@ psi_build_pat(service_t *t, uint8_t *buf, int maxlen, int pmtpid)
|
|||
static int
|
||||
psi_desc_add_ca(service_t *t, uint16_t caid, uint32_t provid, uint16_t pid)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
caid_t *c;
|
||||
int r = 0;
|
||||
|
||||
|
@ -235,11 +235,11 @@ psi_desc_add_ca(service_t *t, uint16_t caid, uint32_t provid, uint16_t pid)
|
|||
r |= PMT_UPDATE_NEW_CA_STREAM;
|
||||
}
|
||||
|
||||
st->st_delete_me = 0;
|
||||
st->es_delete_me = 0;
|
||||
|
||||
st->st_position = 0x40000;
|
||||
st->es_position = 0x40000;
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
if(c->caid == caid) {
|
||||
c->delete_me = 0;
|
||||
|
||||
|
@ -257,7 +257,7 @@ psi_desc_add_ca(service_t *t, uint16_t caid, uint32_t provid, uint16_t pid)
|
|||
c->providerid = provid;
|
||||
|
||||
c->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st->st_caids, c, link);
|
||||
LIST_INSERT_HEAD(&st->es_caids, c, link);
|
||||
r |= PMT_UPDATE_NEW_CAID;
|
||||
return r;
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ psi_desc_teletext(service_t *t, const uint8_t *ptr, int size,
|
|||
int parent_pid, int *position)
|
||||
{
|
||||
int r = 0;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
while(size >= 5) {
|
||||
int page = (ptr[3] & 0x7 ?: 8) * 100 + (ptr[4] >> 4) * 10 + (ptr[4] & 0xf);
|
||||
|
@ -342,20 +342,20 @@ psi_desc_teletext(service_t *t, const uint8_t *ptr, int size,
|
|||
st = service_stream_create(t, pid, SCT_TEXTSUB);
|
||||
}
|
||||
|
||||
st->st_delete_me = 0;
|
||||
st->es_delete_me = 0;
|
||||
|
||||
if(memcmp(st->st_lang, ptr, 3)) {
|
||||
if(memcmp(st->es_lang, ptr, 3)) {
|
||||
r |= PMT_UPDATE_LANGUAGE;
|
||||
memcpy(st->st_lang, ptr, 3);
|
||||
memcpy(st->es_lang, ptr, 3);
|
||||
}
|
||||
|
||||
if(st->st_parent_pid != parent_pid) {
|
||||
if(st->es_parent_pid != parent_pid) {
|
||||
r |= PMT_UPDATE_PARENT_PID;
|
||||
st->st_parent_pid = parent_pid;
|
||||
st->es_parent_pid = parent_pid;
|
||||
}
|
||||
|
||||
if(st->st_position != *position) {
|
||||
st->st_position = *position;
|
||||
if(st->es_position != *position) {
|
||||
st->es_position = *position;
|
||||
r |= PMT_REORDERED;
|
||||
}
|
||||
(*position)++;
|
||||
|
@ -372,9 +372,9 @@ psi_desc_teletext(service_t *t, const uint8_t *ptr, int size,
|
|||
static int
|
||||
pidcmp(const void *A, const void *B)
|
||||
{
|
||||
th_stream_t *a = *(th_stream_t **)A;
|
||||
th_stream_t *b = *(th_stream_t **)B;
|
||||
return a->st_position - b->st_position;
|
||||
elementary_stream_t *a = *(elementary_stream_t **)A;
|
||||
elementary_stream_t *b = *(elementary_stream_t **)B;
|
||||
return a->es_position - b->es_position;
|
||||
}
|
||||
|
||||
|
||||
|
@ -385,21 +385,21 @@ pidcmp(const void *A, const void *B)
|
|||
static void
|
||||
sort_pids(service_t *t)
|
||||
{
|
||||
th_stream_t *st, **v;
|
||||
elementary_stream_t *st, **v;
|
||||
int num = 0, i = 0;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
num++;
|
||||
|
||||
v = alloca(num * sizeof(th_stream_t *));
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link)
|
||||
v = alloca(num * sizeof(elementary_stream_t *));
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
v[i++] = st;
|
||||
|
||||
qsort(v, num, sizeof(th_stream_t *), pidcmp);
|
||||
qsort(v, num, sizeof(elementary_stream_t *), pidcmp);
|
||||
|
||||
TAILQ_INIT(&t->s_components);
|
||||
for(i = 0; i < num; i++)
|
||||
TAILQ_INSERT_TAIL(&t->s_components, v[i], st_link);
|
||||
TAILQ_INSERT_TAIL(&t->s_components, v[i], es_link);
|
||||
}
|
||||
|
||||
|
||||
|
@ -416,7 +416,7 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
uint8_t dtag, dlen;
|
||||
uint16_t sid;
|
||||
streaming_component_type_t hts_stream_type;
|
||||
th_stream_t *st, *next;
|
||||
elementary_stream_t *st, *next;
|
||||
char lang[4];
|
||||
int update = 0;
|
||||
int had_components;
|
||||
|
@ -459,10 +459,10 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
|
||||
/* Mark all streams for deletion */
|
||||
if(delete) {
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
st->st_delete_me = 1;
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
st->es_delete_me = 1;
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link)
|
||||
LIST_FOREACH(c, &st->es_caids, link)
|
||||
c->delete_me = 1;
|
||||
}
|
||||
}
|
||||
|
@ -604,25 +604,25 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
st = service_stream_create(t, pid, hts_stream_type);
|
||||
}
|
||||
|
||||
st->st_delete_me = 0;
|
||||
st->es_delete_me = 0;
|
||||
|
||||
if(st->st_position != position) {
|
||||
if(st->es_position != position) {
|
||||
update |= PMT_REORDERED;
|
||||
st->st_position = position;
|
||||
st->es_position = position;
|
||||
}
|
||||
|
||||
if(memcmp(st->st_lang, lang, 4)) {
|
||||
if(memcmp(st->es_lang, lang, 4)) {
|
||||
update |= PMT_UPDATE_LANGUAGE;
|
||||
memcpy(st->st_lang, lang, 4);
|
||||
memcpy(st->es_lang, lang, 4);
|
||||
}
|
||||
|
||||
if(composition_id != -1 && st->st_composition_id != composition_id) {
|
||||
st->st_composition_id = composition_id;
|
||||
if(composition_id != -1 && st->es_composition_id != composition_id) {
|
||||
st->es_composition_id = composition_id;
|
||||
update |= PMT_UPDATE_COMPOSITION_ID;
|
||||
}
|
||||
|
||||
if(ancillary_id != -1 && st->st_ancillary_id != ancillary_id) {
|
||||
st->st_ancillary_id = ancillary_id;
|
||||
if(ancillary_id != -1 && st->es_ancillary_id != ancillary_id) {
|
||||
st->es_ancillary_id = ancillary_id;
|
||||
update |= PMT_UPDATE_ANCILLARY_ID;
|
||||
}
|
||||
}
|
||||
|
@ -631,9 +631,9 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
|
||||
/* Scan again to see if any streams should be deleted */
|
||||
for(st = TAILQ_FIRST(&t->s_components); st != NULL; st = next) {
|
||||
next = TAILQ_NEXT(st, st_link);
|
||||
next = TAILQ_NEXT(st, es_link);
|
||||
|
||||
for(c = LIST_FIRST(&st->st_caids); c != NULL; c = cn) {
|
||||
for(c = LIST_FIRST(&st->es_caids); c != NULL; c = cn) {
|
||||
cn = LIST_NEXT(c, link);
|
||||
if(c->delete_me) {
|
||||
LIST_REMOVE(c, link);
|
||||
|
@ -643,7 +643,7 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
}
|
||||
|
||||
|
||||
if(st->st_delete_me) {
|
||||
if(st->es_delete_me) {
|
||||
service_stream_destroy(t, st);
|
||||
update |= PMT_UPDATE_STREAM_DELETED;
|
||||
}
|
||||
|
@ -869,7 +869,7 @@ streaming_component_type2txt(streaming_component_type_t s)
|
|||
void
|
||||
psi_save_service_settings(htsmsg_t *m, service_t *t)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
htsmsg_t *sub;
|
||||
|
||||
htsmsg_add_u32(m, "pcr", t->s_pcr_pid);
|
||||
|
@ -878,22 +878,22 @@ psi_save_service_settings(htsmsg_t *m, service_t *t)
|
|||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
sub = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(sub, "pid", st->st_pid);
|
||||
htsmsg_add_str(sub, "type", val2str(st->st_type, streamtypetab) ?: "?");
|
||||
htsmsg_add_u32(sub, "position", st->st_position);
|
||||
htsmsg_add_u32(sub, "pid", st->es_pid);
|
||||
htsmsg_add_str(sub, "type", val2str(st->es_type, streamtypetab) ?: "?");
|
||||
htsmsg_add_u32(sub, "position", st->es_position);
|
||||
|
||||
if(st->st_lang[0])
|
||||
htsmsg_add_str(sub, "language", st->st_lang);
|
||||
if(st->es_lang[0])
|
||||
htsmsg_add_str(sub, "language", st->es_lang);
|
||||
|
||||
if(st->st_type == SCT_CA) {
|
||||
if(st->es_type == SCT_CA) {
|
||||
|
||||
caid_t *c;
|
||||
htsmsg_t *v = htsmsg_create_list();
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
htsmsg_t *caid = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(caid, "caid", c->caid);
|
||||
|
@ -905,18 +905,18 @@ psi_save_service_settings(htsmsg_t *m, service_t *t)
|
|||
htsmsg_add_msg(sub, "caidlist", v);
|
||||
}
|
||||
|
||||
if(st->st_type == SCT_DVBSUB) {
|
||||
htsmsg_add_u32(sub, "compositionid", st->st_composition_id);
|
||||
htsmsg_add_u32(sub, "ancillartyid", st->st_ancillary_id);
|
||||
if(st->es_type == SCT_DVBSUB) {
|
||||
htsmsg_add_u32(sub, "compositionid", st->es_composition_id);
|
||||
htsmsg_add_u32(sub, "ancillartyid", st->es_ancillary_id);
|
||||
}
|
||||
|
||||
if(st->st_type == SCT_TEXTSUB)
|
||||
htsmsg_add_u32(sub, "parentpid", st->st_parent_pid);
|
||||
if(st->es_type == SCT_TEXTSUB)
|
||||
htsmsg_add_u32(sub, "parentpid", st->es_parent_pid);
|
||||
|
||||
if(st->st_type == SCT_MPEG2VIDEO || st->st_type == SCT_H264) {
|
||||
if(st->st_width && st->st_height) {
|
||||
htsmsg_add_u32(sub, "width", st->st_width);
|
||||
htsmsg_add_u32(sub, "height", st->st_height);
|
||||
if(st->es_type == SCT_MPEG2VIDEO || st->es_type == SCT_H264) {
|
||||
if(st->es_width && st->es_height) {
|
||||
htsmsg_add_u32(sub, "width", st->es_width);
|
||||
htsmsg_add_u32(sub, "height", st->es_height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -929,13 +929,13 @@ psi_save_service_settings(htsmsg_t *m, service_t *t)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
add_caid(th_stream_t *st, uint16_t caid, uint32_t providerid)
|
||||
add_caid(elementary_stream_t *st, uint16_t caid, uint32_t providerid)
|
||||
{
|
||||
caid_t *c = malloc(sizeof(caid_t));
|
||||
c->caid = caid;
|
||||
c->providerid = providerid;
|
||||
c->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st->st_caids, c, link);
|
||||
LIST_INSERT_HEAD(&st->es_caids, c, link);
|
||||
}
|
||||
|
||||
|
||||
|
@ -943,7 +943,7 @@ add_caid(th_stream_t *st, uint16_t caid, uint32_t providerid)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
load_legacy_caid(htsmsg_t *c, th_stream_t *st)
|
||||
load_legacy_caid(htsmsg_t *c, elementary_stream_t *st)
|
||||
{
|
||||
uint32_t a, b;
|
||||
const char *v;
|
||||
|
@ -968,7 +968,7 @@ load_legacy_caid(htsmsg_t *c, th_stream_t *st)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
load_caid(htsmsg_t *m, th_stream_t *st)
|
||||
load_caid(htsmsg_t *m, elementary_stream_t *st)
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *c, *v = htsmsg_get_list(m, "caidlist");
|
||||
|
@ -1002,7 +1002,7 @@ psi_load_service_settings(htsmsg_t *m, service_t *t)
|
|||
htsmsg_t *c;
|
||||
htsmsg_field_t *f;
|
||||
uint32_t u32, pid;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
streaming_component_type_t type;
|
||||
const char *v;
|
||||
|
||||
|
@ -1034,33 +1034,33 @@ psi_load_service_settings(htsmsg_t *m, service_t *t)
|
|||
st = service_stream_create(t, pid, type);
|
||||
|
||||
if((v = htsmsg_get_str(c, "language")) != NULL)
|
||||
snprintf(st->st_lang, 4, "%s", v);
|
||||
snprintf(st->es_lang, 4, "%s", v);
|
||||
|
||||
if(!htsmsg_get_u32(c, "position", &u32))
|
||||
st->st_position = u32;
|
||||
st->es_position = u32;
|
||||
|
||||
load_legacy_caid(c, st);
|
||||
load_caid(c, st);
|
||||
|
||||
if(type == SCT_DVBSUB) {
|
||||
if(!htsmsg_get_u32(c, "compositionid", &u32))
|
||||
st->st_composition_id = u32;
|
||||
st->es_composition_id = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "ancillartyid", &u32))
|
||||
st->st_ancillary_id = u32;
|
||||
st->es_ancillary_id = u32;
|
||||
}
|
||||
|
||||
if(type == SCT_TEXTSUB) {
|
||||
if(!htsmsg_get_u32(c, "parentpid", &u32))
|
||||
st->st_parent_pid = u32;
|
||||
st->es_parent_pid = u32;
|
||||
}
|
||||
|
||||
if(type == SCT_MPEG2VIDEO || type == SCT_H264) {
|
||||
if(!htsmsg_get_u32(c, "width", &u32))
|
||||
st->st_width = u32;
|
||||
st->es_width = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "height", &u32))
|
||||
st->st_height = u32;
|
||||
st->es_height = u32;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ rawts_service_add(rawts_t *rt, uint16_t sid, int pmt_pid)
|
|||
*/
|
||||
|
||||
static void
|
||||
got_pmt(struct service *t, th_stream_t *st,
|
||||
got_pmt(struct service *t, elementary_stream_t *st,
|
||||
const uint8_t *table, int table_len)
|
||||
{
|
||||
if(table[0] != 2)
|
||||
|
@ -177,7 +177,7 @@ got_pat(const uint8_t *ptr, size_t len, void *opaque)
|
|||
{
|
||||
rawts_t *rt = opaque;
|
||||
service_t *t;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
uint16_t prognum;
|
||||
uint16_t pid;
|
||||
|
||||
|
@ -202,8 +202,8 @@ got_pat(const uint8_t *ptr, size_t len, void *opaque)
|
|||
|
||||
if(service_stream_find(t, pid) == NULL) {
|
||||
st = service_stream_create(t, pid, SCT_PMT);
|
||||
st->st_section_docrc = 1;
|
||||
st->st_got_section = got_pmt;
|
||||
st->es_section_docrc = 1;
|
||||
st->es_got_section = got_pmt;
|
||||
}
|
||||
pthread_mutex_unlock(&t->s_stream_mutex);
|
||||
}
|
||||
|
|
164
src/service.c
164
src/service.c
|
@ -58,21 +58,21 @@ static void service_data_timeout(void *aux);
|
|||
*
|
||||
*/
|
||||
static void
|
||||
stream_init(th_stream_t *st)
|
||||
stream_init(elementary_stream_t *st)
|
||||
{
|
||||
st->st_cc_valid = 0;
|
||||
st->es_cc_valid = 0;
|
||||
|
||||
st->st_startcond = 0xffffffff;
|
||||
st->st_curdts = PTS_UNSET;
|
||||
st->st_curpts = PTS_UNSET;
|
||||
st->st_prevdts = PTS_UNSET;
|
||||
st->es_startcond = 0xffffffff;
|
||||
st->es_curdts = PTS_UNSET;
|
||||
st->es_curpts = PTS_UNSET;
|
||||
st->es_prevdts = PTS_UNSET;
|
||||
|
||||
st->st_pcr_real_last = PTS_UNSET;
|
||||
st->st_pcr_last = PTS_UNSET;
|
||||
st->st_pcr_drift = 0;
|
||||
st->st_pcr_recovery_fails = 0;
|
||||
st->es_pcr_real_last = PTS_UNSET;
|
||||
st->es_pcr_last = PTS_UNSET;
|
||||
st->es_pcr_drift = 0;
|
||||
st->es_pcr_recovery_fails = 0;
|
||||
|
||||
st->st_blank = 0;
|
||||
st->es_blank = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,33 +80,33 @@ stream_init(th_stream_t *st)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
stream_clean(th_stream_t *st)
|
||||
stream_clean(elementary_stream_t *st)
|
||||
{
|
||||
if(st->st_demuxer_fd != -1) {
|
||||
if(st->es_demuxer_fd != -1) {
|
||||
// XXX: Should be in DVB-code perhaps
|
||||
close(st->st_demuxer_fd);
|
||||
st->st_demuxer_fd = -1;
|
||||
close(st->es_demuxer_fd);
|
||||
st->es_demuxer_fd = -1;
|
||||
}
|
||||
|
||||
free(st->st_priv);
|
||||
st->st_priv = NULL;
|
||||
free(st->es_priv);
|
||||
st->es_priv = NULL;
|
||||
|
||||
/* Clear reassembly buffers */
|
||||
|
||||
st->st_startcode = 0;
|
||||
st->es_startcode = 0;
|
||||
|
||||
sbuf_free(&st->st_buf);
|
||||
sbuf_free(&st->st_buf_ps);
|
||||
sbuf_free(&st->st_buf_a);
|
||||
sbuf_free(&st->es_buf);
|
||||
sbuf_free(&st->es_buf_ps);
|
||||
sbuf_free(&st->es_buf_a);
|
||||
|
||||
if(st->st_curpkt != NULL) {
|
||||
pkt_ref_dec(st->st_curpkt);
|
||||
st->st_curpkt = NULL;
|
||||
if(st->es_curpkt != NULL) {
|
||||
pkt_ref_dec(st->es_curpkt);
|
||||
st->es_curpkt = NULL;
|
||||
}
|
||||
|
||||
free(st->st_global_data);
|
||||
st->st_global_data = NULL;
|
||||
st->st_global_data_len = 0;
|
||||
free(st->es_global_data);
|
||||
st->es_global_data = NULL;
|
||||
st->es_global_data_len = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,12 +114,12 @@ stream_clean(th_stream_t *st)
|
|||
*
|
||||
*/
|
||||
void
|
||||
service_stream_destroy(service_t *t, th_stream_t *st)
|
||||
service_stream_destroy(service_t *t, elementary_stream_t *st)
|
||||
{
|
||||
if(t->s_status == SERVICE_RUNNING)
|
||||
stream_clean(st);
|
||||
TAILQ_REMOVE(&t->s_components, st, st_link);
|
||||
free(st->st_nicename);
|
||||
TAILQ_REMOVE(&t->s_components, st, es_link);
|
||||
free(st->es_nicename);
|
||||
free(st);
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ static void
|
|||
service_stop(service_t *t)
|
||||
{
|
||||
th_descrambler_t *td;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
gtimer_disarm(&t->s_receive_timer);
|
||||
|
||||
|
@ -149,7 +149,7 @@ service_stop(service_t *t)
|
|||
/**
|
||||
* Clean up each stream
|
||||
*/
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
stream_clean(st);
|
||||
|
||||
t->s_status = SERVICE_IDLE;
|
||||
|
@ -190,7 +190,7 @@ service_remove_subscriber(service_t *t, th_subscription_t *s,
|
|||
int
|
||||
service_start(service_t *t, unsigned int weight, int force_start)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
int r, timeout = 2;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
@ -213,7 +213,7 @@ service_start(service_t *t, unsigned int weight, int force_start)
|
|||
/**
|
||||
* Initialize stream
|
||||
*/
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
stream_init(st);
|
||||
|
||||
pthread_mutex_unlock(&t->s_stream_mutex);
|
||||
|
@ -434,7 +434,7 @@ service_ref(service_t *t)
|
|||
void
|
||||
service_destroy(service_t *t)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
th_subscription_t *s;
|
||||
channel_t *ch = t->s_ch;
|
||||
|
||||
|
@ -467,8 +467,8 @@ service_destroy(service_t *t)
|
|||
free(t->s_provider);
|
||||
|
||||
while((st = TAILQ_FIRST(&t->s_components)) != NULL) {
|
||||
TAILQ_REMOVE(&t->s_components, st, st_link);
|
||||
free(st->st_nicename);
|
||||
TAILQ_REMOVE(&t->s_components, st, es_link);
|
||||
free(st->es_nicename);
|
||||
free(st);
|
||||
}
|
||||
|
||||
|
@ -533,20 +533,20 @@ service_find_by_identifier(const char *identifier)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
service_stream_make_nicename(service_t *t, th_stream_t *st)
|
||||
service_stream_make_nicename(service_t *t, elementary_stream_t *st)
|
||||
{
|
||||
char buf[200];
|
||||
if(st->st_pid != -1)
|
||||
if(st->es_pid != -1)
|
||||
snprintf(buf, sizeof(buf), "%s: %s @ #%d",
|
||||
service_nicename(t),
|
||||
streaming_component_type2txt(st->st_type), st->st_pid);
|
||||
streaming_component_type2txt(st->es_type), st->es_pid);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s: %s",
|
||||
service_nicename(t),
|
||||
streaming_component_type2txt(st->st_type));
|
||||
streaming_component_type2txt(st->es_type));
|
||||
|
||||
free(st->st_nicename);
|
||||
st->st_nicename = strdup(buf);
|
||||
free(st->es_nicename);
|
||||
st->es_nicename = strdup(buf);
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,7 +558,7 @@ service_make_nicename(service_t *t)
|
|||
{
|
||||
char buf[200];
|
||||
source_info_t si;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
|
@ -575,7 +575,7 @@ service_make_nicename(service_t *t)
|
|||
free(t->s_nicename);
|
||||
t->s_nicename = strdup(buf);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
service_stream_make_nicename(t, st);
|
||||
}
|
||||
|
||||
|
@ -583,40 +583,40 @@ service_make_nicename(service_t *t)
|
|||
/**
|
||||
* Add a new stream to a service
|
||||
*/
|
||||
th_stream_t *
|
||||
elementary_stream_t *
|
||||
service_stream_create(service_t *t, int pid,
|
||||
streaming_component_type_t type)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
int i = 0;
|
||||
int idx = 0;
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
if(st->st_index > idx)
|
||||
idx = st->st_index;
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
if(st->es_index > idx)
|
||||
idx = st->es_index;
|
||||
i++;
|
||||
if(pid != -1 && st->st_pid == pid)
|
||||
if(pid != -1 && st->es_pid == pid)
|
||||
return st;
|
||||
}
|
||||
|
||||
st = calloc(1, sizeof(th_stream_t));
|
||||
st->st_index = idx + 1;
|
||||
st->st_type = type;
|
||||
st = calloc(1, sizeof(elementary_stream_t));
|
||||
st->es_index = idx + 1;
|
||||
st->es_type = type;
|
||||
|
||||
TAILQ_INSERT_TAIL(&t->s_components, st, st_link);
|
||||
st->st_service = t;
|
||||
TAILQ_INSERT_TAIL(&t->s_components, st, es_link);
|
||||
st->es_service = t;
|
||||
|
||||
st->st_pid = pid;
|
||||
st->st_demuxer_fd = -1;
|
||||
st->es_pid = pid;
|
||||
st->es_demuxer_fd = -1;
|
||||
|
||||
avgstat_init(&st->st_rate, 10);
|
||||
avgstat_init(&st->st_cc_errors, 10);
|
||||
avgstat_init(&st->es_rate, 10);
|
||||
avgstat_init(&st->es_cc_errors, 10);
|
||||
|
||||
service_stream_make_nicename(t, st);
|
||||
|
||||
if(t->s_flags & S_DEBUG)
|
||||
tvhlog(LOG_DEBUG, "service", "Add stream %s", st->st_nicename);
|
||||
tvhlog(LOG_DEBUG, "service", "Add stream %s", st->es_nicename);
|
||||
|
||||
if(t->s_status == SERVICE_RUNNING)
|
||||
stream_init(st);
|
||||
|
@ -629,15 +629,15 @@ service_stream_create(service_t *t, int pid,
|
|||
/**
|
||||
* Add a new stream to a service
|
||||
*/
|
||||
th_stream_t *
|
||||
elementary_stream_t *
|
||||
service_stream_find(service_t *t, int pid)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
if(st->st_pid == pid)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
if(st->es_pid == pid)
|
||||
return st;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -795,13 +795,13 @@ service_restart(service_t *t, int had_components)
|
|||
streaming_start_t *
|
||||
service_build_stream_start(service_t *t)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
int n = 0;
|
||||
streaming_start_t *ss;
|
||||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link)
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
n++;
|
||||
|
||||
ss = calloc(1, sizeof(streaming_start_t) +
|
||||
|
@ -810,16 +810,16 @@ service_build_stream_start(service_t *t)
|
|||
ss->ss_num_components = n;
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
streaming_start_component_t *ssc = &ss->ss_components[n++];
|
||||
ssc->ssc_index = st->st_index;
|
||||
ssc->ssc_type = st->st_type;
|
||||
memcpy(ssc->ssc_lang, st->st_lang, 4);
|
||||
ssc->ssc_composition_id = st->st_composition_id;
|
||||
ssc->ssc_ancillary_id = st->st_ancillary_id;
|
||||
ssc->ssc_pid = st->st_pid;
|
||||
ssc->ssc_width = st->st_width;
|
||||
ssc->ssc_height = st->st_height;
|
||||
ssc->ssc_index = st->es_index;
|
||||
ssc->ssc_type = st->es_type;
|
||||
memcpy(ssc->ssc_lang, st->es_lang, 4);
|
||||
ssc->ssc_composition_id = st->es_composition_id;
|
||||
ssc->ssc_ancillary_id = st->es_ancillary_id;
|
||||
ssc->ssc_pid = st->es_pid;
|
||||
ssc->ssc_width = st->es_width;
|
||||
ssc->ssc_height = st->es_height;
|
||||
}
|
||||
|
||||
t->s_setsourceinfo(t, &ss->ss_si);
|
||||
|
@ -964,9 +964,9 @@ service_nicename(service_t *t)
|
|||
}
|
||||
|
||||
const char *
|
||||
service_component_nicename(th_stream_t *st)
|
||||
service_component_nicename(elementary_stream_t *st)
|
||||
{
|
||||
return st->st_nicename;
|
||||
return st->es_nicename;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -1034,13 +1034,13 @@ service_refresh_channel(service_t *t)
|
|||
uint16_t
|
||||
service_get_encryption(service_t *t)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
caid_t *c;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
switch(st->st_type) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
switch(st->es_type) {
|
||||
case SCT_CA:
|
||||
LIST_FOREACH(c, &st->st_caids, link)
|
||||
LIST_FOREACH(c, &st->es_caids, link)
|
||||
if(c->caid != 0)
|
||||
return c->caid;
|
||||
break;
|
||||
|
|
146
src/service.h
146
src/service.h
|
@ -34,11 +34,11 @@ typedef struct th_descrambler {
|
|||
LIST_ENTRY(th_descrambler) td_service_link;
|
||||
|
||||
void (*td_table)(struct th_descrambler *d, struct service *t,
|
||||
struct th_stream *st,
|
||||
struct elementary_stream *st,
|
||||
const uint8_t *section, int section_len);
|
||||
|
||||
int (*td_descramble)(struct th_descrambler *d, struct service *t,
|
||||
struct th_stream *st, const uint8_t *tsb);
|
||||
struct elementary_stream *st, const uint8_t *tsb);
|
||||
|
||||
void (*td_stop)(struct th_descrambler *d);
|
||||
|
||||
|
@ -49,7 +49,7 @@ typedef struct th_descrambler {
|
|||
* Section callback, called when a PSI table is fully received
|
||||
*/
|
||||
typedef void (pid_section_callback_t)(struct service *t,
|
||||
struct th_stream *pi,
|
||||
struct elementary_stream *pi,
|
||||
const uint8_t *section, int section_len);
|
||||
|
||||
|
||||
|
@ -66,107 +66,105 @@ typedef struct caid {
|
|||
|
||||
} caid_t;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Stream, one media component for a service.
|
||||
*
|
||||
* XXX: This should be renamed to 'elementary_stream' or something
|
||||
*/
|
||||
typedef struct th_stream {
|
||||
typedef struct elementary_stream {
|
||||
|
||||
TAILQ_ENTRY(th_stream) st_link;
|
||||
int st_position;
|
||||
struct service *st_service;
|
||||
TAILQ_ENTRY(elementary_stream) es_link;
|
||||
int es_position;
|
||||
struct service *es_service;
|
||||
|
||||
streaming_component_type_t st_type;
|
||||
int st_index;
|
||||
streaming_component_type_t es_type;
|
||||
int es_index;
|
||||
|
||||
uint16_t st_aspect_num;
|
||||
uint16_t st_aspect_den;
|
||||
uint16_t es_aspect_num;
|
||||
uint16_t es_aspect_den;
|
||||
|
||||
char st_lang[4]; /* ISO 639 3-letter language code */
|
||||
uint16_t st_composition_id;
|
||||
uint16_t st_ancillary_id;
|
||||
char es_lang[4]; /* ISO 639 3-letter language code */
|
||||
uint16_t es_composition_id;
|
||||
uint16_t es_ancillary_id;
|
||||
|
||||
int16_t st_pid;
|
||||
uint16_t st_parent_pid; /* For subtitle streams originating from
|
||||
int16_t es_pid;
|
||||
uint16_t es_parent_pid; /* For subtitle streams originating from
|
||||
a teletext stream. this is the pid
|
||||
of the teletext stream */
|
||||
|
||||
uint8_t st_cc; /* Last CC */
|
||||
uint8_t st_cc_valid; /* Is CC valid at all? */
|
||||
uint8_t es_cc; /* Last CC */
|
||||
uint8_t es_cc_valid; /* Is CC valid at all? */
|
||||
|
||||
avgstat_t st_cc_errors;
|
||||
avgstat_t st_rate;
|
||||
avgstat_t es_cc_errors;
|
||||
avgstat_t es_rate;
|
||||
|
||||
int st_demuxer_fd;
|
||||
int st_peak_presentation_delay; /* Max seen diff. of DTS and PTS */
|
||||
int es_demuxer_fd;
|
||||
int es_peak_presentation_delay; /* Max seen diff. of DTS and PTS */
|
||||
|
||||
struct psi_section *st_section;
|
||||
int st_section_docrc; /* Set if we should verify CRC on tables */
|
||||
pid_section_callback_t *st_got_section;
|
||||
void *st_got_section_opaque;
|
||||
struct psi_section *es_section;
|
||||
int es_section_docrc; /* Set if we should verify CRC on tables */
|
||||
pid_section_callback_t *es_got_section;
|
||||
void *es_got_section_opaque;
|
||||
|
||||
/* PCR recovery */
|
||||
|
||||
int st_pcr_recovery_fails;
|
||||
int64_t st_pcr_real_last; /* realtime clock when we saw last PCR */
|
||||
int64_t st_pcr_last; /* PCR clock when we saw last PCR */
|
||||
int64_t st_pcr_drift;
|
||||
int es_pcr_recovery_fails;
|
||||
int64_t es_pcr_real_last; /* realtime clock when we saw last PCR */
|
||||
int64_t es_pcr_last; /* PCR clock when we saw last PCR */
|
||||
int64_t es_pcr_drift;
|
||||
|
||||
/* For service stream packet reassembly */
|
||||
|
||||
sbuf_t st_buf;
|
||||
sbuf_t es_buf;
|
||||
|
||||
uint32_t st_startcond;
|
||||
uint32_t st_startcode;
|
||||
uint32_t st_startcode_offset;
|
||||
int st_parser_state;
|
||||
int st_parser_ptr;
|
||||
void *st_priv; /* Parser private data */
|
||||
uint32_t es_startcond;
|
||||
uint32_t es_startcode;
|
||||
uint32_t es_startcode_offset;
|
||||
int es_parser_state;
|
||||
int es_parser_ptr;
|
||||
void *es_priv; /* Parser private data */
|
||||
|
||||
sbuf_t st_buf_ps; // program stream reassembly (analogue adapters)
|
||||
sbuf_t st_buf_a; // Audio packet reassembly
|
||||
sbuf_t es_buf_ps; // program stream reassembly (analogue adapters)
|
||||
sbuf_t es_buf_a; // Audio packet reassembly
|
||||
|
||||
uint8_t *st_global_data;
|
||||
int st_global_data_len;
|
||||
int st_incomplete;
|
||||
int st_ssc_intercept;
|
||||
int st_ssc_ptr;
|
||||
uint8_t st_ssc_buf[32];
|
||||
uint8_t *es_global_data;
|
||||
int es_global_data_len;
|
||||
int es_incomplete;
|
||||
int es_ssc_intercept;
|
||||
int es_ssc_ptr;
|
||||
uint8_t es_ssc_buf[32];
|
||||
|
||||
struct th_pkt *st_curpkt;
|
||||
int64_t st_curpts;
|
||||
int64_t st_curdts;
|
||||
int64_t st_prevdts;
|
||||
int64_t st_nextdts;
|
||||
int st_frame_duration;
|
||||
int st_width;
|
||||
int st_height;
|
||||
struct th_pkt *es_curpkt;
|
||||
int64_t es_curpts;
|
||||
int64_t es_curdts;
|
||||
int64_t es_prevdts;
|
||||
int64_t es_nextdts;
|
||||
int es_frame_duration;
|
||||
int es_width;
|
||||
int es_height;
|
||||
|
||||
int st_meta_change;
|
||||
int es_meta_change;
|
||||
|
||||
/* CA ID's on this stream */
|
||||
struct caid_list st_caids;
|
||||
struct caid_list es_caids;
|
||||
|
||||
int st_vbv_size; /* Video buffer size (in bytes) */
|
||||
int st_vbv_delay; /* -1 if CBR */
|
||||
int es_vbv_size; /* Video buffer size (in bytes) */
|
||||
int es_vbv_delay; /* -1 if CBR */
|
||||
|
||||
/* */
|
||||
|
||||
int st_delete_me; /* Temporary flag for deleting streams */
|
||||
int es_delete_me; /* Temporary flag for deleting streams */
|
||||
|
||||
/* Error log limiters */
|
||||
|
||||
loglimiter_t st_loglimit_cc;
|
||||
loglimiter_t st_loglimit_pes;
|
||||
loglimiter_t es_loglimit_cc;
|
||||
loglimiter_t es_loglimit_pes;
|
||||
|
||||
char *st_nicename;
|
||||
char *es_nicename;
|
||||
|
||||
/* Teletext subtitle */
|
||||
char st_blank; // Last subtitle was blank
|
||||
char es_blank; // Last subtitle was blank
|
||||
|
||||
|
||||
} th_stream_t;
|
||||
} elementary_stream_t;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -399,7 +397,7 @@ typedef struct service {
|
|||
|
||||
/**
|
||||
* Mutex to be held during streaming.
|
||||
* This mutex also protects all th_stream_t instances for this
|
||||
* This mutex also protects all elementary_stream_t instances for this
|
||||
* transport.
|
||||
*/
|
||||
pthread_mutex_t s_stream_mutex;
|
||||
|
@ -434,8 +432,8 @@ typedef struct service {
|
|||
* For simple streaming sources (such as video4linux) keeping
|
||||
* track of the video and audio stream is convenient.
|
||||
*/
|
||||
th_stream_t *s_video;
|
||||
th_stream_t *s_audio;
|
||||
elementary_stream_t *s_video;
|
||||
elementary_stream_t *s_audio;
|
||||
|
||||
/**
|
||||
* Average continuity errors
|
||||
|
@ -464,7 +462,7 @@ typedef struct service {
|
|||
/**
|
||||
* List of all components.
|
||||
*/
|
||||
struct th_stream_queue s_components;
|
||||
struct elementary_stream_queue s_components;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -505,9 +503,9 @@ service_t *service_find(struct channel *ch, unsigned int weight,
|
|||
const char *loginfo, int *errorp,
|
||||
service_t *skip);
|
||||
|
||||
th_stream_t *service_stream_find(service_t *t, int pid);
|
||||
elementary_stream_t *service_stream_find(service_t *t, int pid);
|
||||
|
||||
th_stream_t *service_stream_create(service_t *t, int pid,
|
||||
elementary_stream_t *service_stream_create(service_t *t, int pid,
|
||||
streaming_component_type_t type);
|
||||
|
||||
void service_set_priority(service_t *t, int prio);
|
||||
|
@ -532,7 +530,7 @@ void service_set_enable(service_t *t, int enabled);
|
|||
|
||||
void service_restart(service_t *t, int had_components);
|
||||
|
||||
void service_stream_destroy(service_t *t, th_stream_t *st);
|
||||
void service_stream_destroy(service_t *t, elementary_stream_t *st);
|
||||
|
||||
void service_request_save(service_t *t, int restart);
|
||||
|
||||
|
@ -544,7 +542,7 @@ void service_make_nicename(service_t *t);
|
|||
|
||||
const char *service_nicename(service_t *t);
|
||||
|
||||
const char *service_component_nicename(th_stream_t *st);
|
||||
const char *service_component_nicename(elementary_stream_t *st);
|
||||
|
||||
const char *service_tss2text(int flags);
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ update_tt_clock(service_t *t, const uint8_t *buf)
|
|||
|
||||
|
||||
static void
|
||||
extract_subtitle(service_t *t, th_stream_t *st,
|
||||
extract_subtitle(service_t *t, elementary_stream_t *st,
|
||||
tt_mag_t *ttm, int64_t pts)
|
||||
{
|
||||
int i, j, off = 0;
|
||||
|
@ -299,20 +299,20 @@ extract_subtitle(service_t *t, th_stream_t *st,
|
|||
sub[off++] = '\n';
|
||||
}
|
||||
|
||||
if(off == 0 && st->st_blank)
|
||||
if(off == 0 && st->es_blank)
|
||||
return; // Avoid multiple blank subtitles
|
||||
|
||||
st->st_blank = !off;
|
||||
st->es_blank = !off;
|
||||
|
||||
if(st->st_curpts == pts)
|
||||
if(st->es_curpts == pts)
|
||||
pts++; // Avoid non-monotonic PTS
|
||||
|
||||
st->st_curpts = pts;
|
||||
st->es_curpts = pts;
|
||||
|
||||
sub[off++] = 0;
|
||||
|
||||
th_pkt_t *pkt = pkt_alloc(sub, off, pts, pts);
|
||||
pkt->pkt_componentindex = st->st_index;
|
||||
pkt->pkt_componentindex = st->es_index;
|
||||
|
||||
streaming_message_t *sm = streaming_msg_create_pkt(pkt);
|
||||
streaming_pad_deliver(&t->s_streaming_pad, sm);
|
||||
|
@ -354,16 +354,16 @@ dump_page(tt_mag_t *ttm)
|
|||
|
||||
|
||||
static void
|
||||
tt_subtitle_deliver(service_t *t, th_stream_t *parent, tt_mag_t *ttm)
|
||||
tt_subtitle_deliver(service_t *t, elementary_stream_t *parent, tt_mag_t *ttm)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
if(ttm->ttm_current_pts == PTS_UNSET)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
if(parent->st_pid == st->st_parent_pid &&
|
||||
ttm->ttm_curpage == st->st_pid - PID_TELETEXT_BASE) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
if(parent->es_pid == st->es_parent_pid &&
|
||||
ttm->ttm_curpage == st->es_pid - PID_TELETEXT_BASE) {
|
||||
extract_subtitle(t, st, ttm, ttm->ttm_current_pts);
|
||||
}
|
||||
}
|
||||
|
@ -373,18 +373,18 @@ tt_subtitle_deliver(service_t *t, th_stream_t *parent, tt_mag_t *ttm)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
tt_decode_line(service_t *t, th_stream_t *st, uint8_t *buf)
|
||||
tt_decode_line(service_t *t, elementary_stream_t *st, uint8_t *buf)
|
||||
{
|
||||
uint8_t mpag, line, s12, s34, c;
|
||||
int page, magidx, i;
|
||||
tt_mag_t *ttm;
|
||||
tt_private_t *ttp;
|
||||
|
||||
if(st->st_priv == NULL) {
|
||||
if(st->es_priv == NULL) {
|
||||
/* Allocate privdata for reassembly */
|
||||
ttp = st->st_priv = calloc(1, sizeof(tt_private_t));
|
||||
ttp = st->es_priv = calloc(1, sizeof(tt_private_t));
|
||||
} else {
|
||||
ttp = st->st_priv;
|
||||
ttp = st->es_priv;
|
||||
}
|
||||
|
||||
mpag = ham_decode(buf[0], buf[1]);
|
||||
|
@ -453,9 +453,9 @@ tt_decode_line(service_t *t, th_stream_t *st, uint8_t *buf)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
teletext_scan_stream(service_t *t, th_stream_t *st)
|
||||
teletext_scan_stream(service_t *t, elementary_stream_t *st)
|
||||
{
|
||||
tt_private_t *ttp = st->st_priv;
|
||||
tt_private_t *ttp = st->es_priv;
|
||||
tt_mag_t *ttm;
|
||||
int i;
|
||||
|
||||
|
@ -475,7 +475,7 @@ teletext_scan_stream(service_t *t, th_stream_t *st)
|
|||
*
|
||||
*/
|
||||
void
|
||||
teletext_input(service_t *t, th_stream_t *st, const uint8_t *tsb)
|
||||
teletext_input(service_t *t, elementary_stream_t *st, const uint8_t *tsb)
|
||||
{
|
||||
int i, j;
|
||||
const uint8_t *x;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef TELETEXT_H
|
||||
#define TELETEXT_H
|
||||
|
||||
void teletext_input(struct service *t, struct th_stream *st,
|
||||
void teletext_input(struct service *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb);
|
||||
|
||||
#endif /* TELETEXT_H */
|
||||
|
|
|
@ -49,14 +49,14 @@ static void
|
|||
got_section(const uint8_t *data, size_t len, void *opaque)
|
||||
{
|
||||
th_descrambler_t *td;
|
||||
th_stream_t *st = opaque;
|
||||
service_t *t = st->st_service;
|
||||
elementary_stream_t *st = opaque;
|
||||
service_t *t = st->es_service;
|
||||
|
||||
if(st->st_type == SCT_CA) {
|
||||
if(st->es_type == SCT_CA) {
|
||||
LIST_FOREACH(td, &t->s_descramblers, td_service_link)
|
||||
td->td_table(td, t, st, data, len);
|
||||
} else if(st->st_got_section != NULL) {
|
||||
st->st_got_section(t, st, data, len);
|
||||
} else if(st->es_got_section != NULL) {
|
||||
st->es_got_section(t, st, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ got_section(const uint8_t *data, size_t len, void *opaque)
|
|||
* Continue processing of transport stream packets
|
||||
*/
|
||||
static void
|
||||
ts_recv_packet0(service_t *t, th_stream_t *st, const uint8_t *tsb)
|
||||
ts_recv_packet0(service_t *t, elementary_stream_t *st, const uint8_t *tsb)
|
||||
{
|
||||
int off, pusi, cc, error;
|
||||
|
||||
|
@ -81,32 +81,32 @@ ts_recv_packet0(service_t *t, th_stream_t *st, const uint8_t *tsb)
|
|||
|
||||
if(tsb[3] & 0x10) {
|
||||
cc = tsb[3] & 0xf;
|
||||
if(st->st_cc_valid && cc != st->st_cc) {
|
||||
if(st->es_cc_valid && cc != st->es_cc) {
|
||||
/* Incorrect CC */
|
||||
limitedlog(&st->st_loglimit_cc, "TS", service_component_nicename(st),
|
||||
limitedlog(&st->es_loglimit_cc, "TS", service_component_nicename(st),
|
||||
"Continuity counter error");
|
||||
avgstat_add(&t->s_cc_errors, 1, dispatch_clock);
|
||||
avgstat_add(&st->st_cc_errors, 1, dispatch_clock);
|
||||
avgstat_add(&st->es_cc_errors, 1, dispatch_clock);
|
||||
|
||||
// Mark as error if this is not the first packet of a payload
|
||||
if(!pusi)
|
||||
error |= 0x2;
|
||||
}
|
||||
st->st_cc_valid = 1;
|
||||
st->st_cc = (cc + 1) & 0xf;
|
||||
st->es_cc_valid = 1;
|
||||
st->es_cc = (cc + 1) & 0xf;
|
||||
}
|
||||
|
||||
off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
|
||||
|
||||
switch(st->st_type) {
|
||||
switch(st->es_type) {
|
||||
|
||||
case SCT_CA:
|
||||
case SCT_PAT:
|
||||
case SCT_PMT:
|
||||
if(st->st_section == NULL)
|
||||
st->st_section = calloc(1, sizeof(struct psi_section));
|
||||
if(st->es_section == NULL)
|
||||
st->es_section = calloc(1, sizeof(struct psi_section));
|
||||
|
||||
psi_section_reassemble(st->st_section, tsb, st->st_section_docrc,
|
||||
psi_section_reassemble(st->es_section, tsb, st->es_section_docrc,
|
||||
got_section, st);
|
||||
break;
|
||||
|
||||
|
@ -127,11 +127,11 @@ ts_recv_packet0(service_t *t, th_stream_t *st, const uint8_t *tsb)
|
|||
/**
|
||||
* Recover PCR
|
||||
*
|
||||
* st->st_pcr_drift will increase if our (system clock) runs faster
|
||||
* st->es_pcr_drift will increase if our (system clock) runs faster
|
||||
* than the stream PCR
|
||||
*/
|
||||
static void
|
||||
ts_extract_pcr(service_t *t, th_stream_t *st, const uint8_t *tsb,
|
||||
ts_extract_pcr(service_t *t, elementary_stream_t *st, const uint8_t *tsb,
|
||||
int64_t *pcrp)
|
||||
{
|
||||
int64_t real, pcr, d;
|
||||
|
@ -152,29 +152,29 @@ ts_extract_pcr(service_t *t, th_stream_t *st, const uint8_t *tsb,
|
|||
|
||||
real = getmonoclock();
|
||||
|
||||
if(st->st_pcr_real_last != PTS_UNSET) {
|
||||
d = (real - st->st_pcr_real_last) - (pcr - st->st_pcr_last);
|
||||
if(st->es_pcr_real_last != PTS_UNSET) {
|
||||
d = (real - st->es_pcr_real_last) - (pcr - st->es_pcr_last);
|
||||
|
||||
if(d < -90000LL || d > 90000LL) {
|
||||
st->st_pcr_recovery_fails++;
|
||||
if(st->st_pcr_recovery_fails > 10) {
|
||||
st->st_pcr_recovery_fails = 0;
|
||||
st->st_pcr_real_last = PTS_UNSET;
|
||||
st->es_pcr_recovery_fails++;
|
||||
if(st->es_pcr_recovery_fails > 10) {
|
||||
st->es_pcr_recovery_fails = 0;
|
||||
st->es_pcr_real_last = PTS_UNSET;
|
||||
}
|
||||
return;
|
||||
}
|
||||
st->st_pcr_recovery_fails = 0;
|
||||
st->st_pcr_drift += d;
|
||||
st->es_pcr_recovery_fails = 0;
|
||||
st->es_pcr_drift += d;
|
||||
|
||||
if(t->s_pcr_pid == st->st_pid) {
|
||||
if(t->s_pcr_pid == st->es_pid) {
|
||||
/* This is the registered PCR PID, adjust service PCR drift
|
||||
via an IIR filter */
|
||||
|
||||
t->s_pcr_drift = (t->s_pcr_drift * 255 + st->st_pcr_drift) / 256;
|
||||
t->s_pcr_drift = (t->s_pcr_drift * 255 + st->es_pcr_drift) / 256;
|
||||
}
|
||||
}
|
||||
st->st_pcr_last = pcr;
|
||||
st->st_pcr_real_last = real;
|
||||
st->es_pcr_last = pcr;
|
||||
st->es_pcr_real_last = real;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,7 +183,7 @@ ts_extract_pcr(service_t *t, th_stream_t *st, const uint8_t *tsb,
|
|||
void
|
||||
ts_recv_packet1(service_t *t, const uint8_t *tsb, int64_t *pcrp)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
int pid, n, m, r;
|
||||
th_descrambler_t *td;
|
||||
int error = 0;
|
||||
|
@ -221,8 +221,8 @@ ts_recv_packet1(service_t *t, const uint8_t *tsb, int64_t *pcrp)
|
|||
avgstat_add(&t->s_rate, 188, dispatch_clock);
|
||||
|
||||
if((tsb[3] & 0xc0) ||
|
||||
(t->s_scrambled_seen && st->st_type != SCT_CA &&
|
||||
st->st_type != SCT_PAT && st->st_type != SCT_PMT)) {
|
||||
(t->s_scrambled_seen && st->es_type != SCT_CA &&
|
||||
st->es_type != SCT_PAT && st->es_type != SCT_PMT)) {
|
||||
|
||||
/**
|
||||
* Lock for descrambling, but only if packet was not in error
|
||||
|
@ -267,7 +267,7 @@ ts_recv_packet1(service_t *t, const uint8_t *tsb, int64_t *pcrp)
|
|||
void
|
||||
ts_recv_packet2(service_t *t, const uint8_t *tsb)
|
||||
{
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
int pid = (tsb[1] & 0x1f) << 8 | tsb[2];
|
||||
|
||||
if((st = service_stream_find(t, pid)) != NULL)
|
||||
|
|
|
@ -750,7 +750,7 @@ ts_muxer_add_packet(ts_muxer_t *ts, void *data, uint16_t pid)
|
|||
*/
|
||||
static void
|
||||
ts_muxer_raw_input(struct th_subscription *s, void *data, int len,
|
||||
th_stream_t *st, void *opaque)
|
||||
elementary_stream_t *st, void *opaque)
|
||||
{
|
||||
th_muxer_t *tm = s->ths_muxer;
|
||||
ts_muxer_t *ts = opaque;
|
||||
|
@ -988,7 +988,7 @@ ts_check_deliver(ts_muxer_t *ts, th_muxstream_t *tms)
|
|||
static void
|
||||
lookahead_dequeue(ts_muxer_t *ts, th_muxstream_t *tms)
|
||||
{
|
||||
// th_stream_t *st = tms->tms_stream;
|
||||
// elementary_stream_t *st = tms->tms_stream;
|
||||
th_pkt_t *pkt;
|
||||
th_muxpkt_t *tm;
|
||||
th_refpkt_t *o;
|
||||
|
@ -1232,7 +1232,7 @@ static void
|
|||
ts_mux_packet_input(void *opaque, th_muxstream_t *tms, th_pkt_t *pkt)
|
||||
{
|
||||
ts_muxer_t *ts = opaque;
|
||||
th_stream_t *st = tms->tms_stream;
|
||||
elementary_stream_t *st = tms->tms_stream;
|
||||
th_refpkt_t *trp;
|
||||
|
||||
if(tms->tms_index == 0)
|
||||
|
@ -1265,7 +1265,7 @@ ts_muxer_init(th_subscription_t *s, ts_mux_output_t *output,
|
|||
int pididx = PID_ES_BASE;
|
||||
th_muxstream_t *tms;
|
||||
th_muxer_t *tm;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
|
||||
ts->ts_output = output;
|
||||
|
|
|
@ -110,8 +110,8 @@ TAILQ_HEAD(ref_update_queue, ref_update);
|
|||
LIST_HEAD(service_list, service);
|
||||
RB_HEAD(service_tree, service);
|
||||
TAILQ_HEAD(service_queue, service);
|
||||
LIST_HEAD(th_stream_list, th_stream);
|
||||
TAILQ_HEAD(th_stream_queue, th_stream);
|
||||
LIST_HEAD(elementary_stream_list, elementary_stream);
|
||||
TAILQ_HEAD(elementary_stream_queue, elementary_stream);
|
||||
LIST_HEAD(th_muxer_list, th_muxer);
|
||||
LIST_HEAD(th_muxstream_list, th_muxstream);
|
||||
LIST_HEAD(th_descrambler_list, th_descrambler);
|
||||
|
|
24
src/v4l.c
24
src/v4l.c
|
@ -53,7 +53,7 @@ static void
|
|||
v4l_input(v4l_adapter_t *va)
|
||||
{
|
||||
service_t *t = va->va_current_service;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
uint8_t buf[4000];
|
||||
uint8_t *ptr, *pkt;
|
||||
int len, l, r;
|
||||
|
@ -87,36 +87,36 @@ v4l_input(v4l_adapter_t *va)
|
|||
}
|
||||
|
||||
if(va->va_lenlock == 2) {
|
||||
l = st->st_buf_ps.sb_size;
|
||||
st->st_buf_ps.sb_data = pkt = realloc(st->st_buf_ps.sb_data, l);
|
||||
l = st->es_buf_ps.sb_size;
|
||||
st->es_buf_ps.sb_data = pkt = realloc(st->es_buf_ps.sb_data, l);
|
||||
|
||||
r = l - st->st_buf_ps.sb_ptr;
|
||||
r = l - st->es_buf_ps.sb_ptr;
|
||||
if(r > len)
|
||||
r = len;
|
||||
memcpy(pkt + st->st_buf_ps.sb_ptr, ptr, r);
|
||||
memcpy(pkt + st->es_buf_ps.sb_ptr, ptr, r);
|
||||
|
||||
ptr += r;
|
||||
len -= r;
|
||||
|
||||
st->st_buf_ps.sb_ptr += r;
|
||||
if(st->st_buf_ps.sb_ptr == l) {
|
||||
st->es_buf_ps.sb_ptr += r;
|
||||
if(st->es_buf_ps.sb_ptr == l) {
|
||||
|
||||
service_set_streaming_status_flags(t, TSS_MUX_PACKETS);
|
||||
|
||||
parse_mpeg_ps(t, st, pkt + 6, l - 6);
|
||||
|
||||
st->st_buf_ps.sb_size = 0;
|
||||
st->es_buf_ps.sb_size = 0;
|
||||
va->va_startcode = 0;
|
||||
} else {
|
||||
assert(st->st_buf_ps.sb_ptr < l);
|
||||
assert(st->es_buf_ps.sb_ptr < l);
|
||||
}
|
||||
|
||||
} else {
|
||||
st->st_buf_ps.sb_size = st->st_buf_ps.sb_size << 8 | *ptr;
|
||||
st->es_buf_ps.sb_size = st->es_buf_ps.sb_size << 8 | *ptr;
|
||||
va->va_lenlock++;
|
||||
if(va->va_lenlock == 2) {
|
||||
st->st_buf_ps.sb_size += 6;
|
||||
st->st_buf_ps.sb_ptr = 6;
|
||||
st->es_buf_ps.sb_size += 6;
|
||||
st->es_buf_ps.sb_ptr = 6;
|
||||
}
|
||||
ptr++; len--;
|
||||
}
|
||||
|
|
|
@ -1122,7 +1122,7 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
htsmsg_t *out, *streams, *c;
|
||||
service_t *t;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
caid_t *ca;
|
||||
char buf[128];
|
||||
|
||||
|
@ -1135,14 +1135,14 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
|
||||
streams = htsmsg_create_list();
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
c = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(c, "pid", st->st_pid);
|
||||
htsmsg_add_u32(c, "pid", st->es_pid);
|
||||
|
||||
htsmsg_add_str(c, "type", streaming_component_type2txt(st->st_type));
|
||||
htsmsg_add_str(c, "type", streaming_component_type2txt(st->es_type));
|
||||
|
||||
switch(st->st_type) {
|
||||
switch(st->es_type) {
|
||||
default:
|
||||
htsmsg_add_str(c, "details", "");
|
||||
break;
|
||||
|
@ -1150,7 +1150,7 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
case SCT_CA:
|
||||
buf[0] = 0;
|
||||
|
||||
LIST_FOREACH(ca, &st->st_caids, link) {
|
||||
LIST_FOREACH(ca, &st->es_caids, link) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||
"%s (0x%04x) [0x%08x]",
|
||||
psi_caid2name(ca->caid), ca->caid, ca->providerid);
|
||||
|
@ -1162,21 +1162,21 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
case SCT_AC3:
|
||||
case SCT_AAC:
|
||||
case SCT_MPEG2AUDIO:
|
||||
htsmsg_add_str(c, "details", st->st_lang);
|
||||
htsmsg_add_str(c, "details", st->es_lang);
|
||||
break;
|
||||
|
||||
case SCT_DVBSUB:
|
||||
snprintf(buf, sizeof(buf), "%s (%04x %04x)",
|
||||
st->st_lang, st->st_composition_id, st->st_ancillary_id);
|
||||
st->es_lang, st->es_composition_id, st->es_ancillary_id);
|
||||
htsmsg_add_str(c, "details", buf);
|
||||
break;
|
||||
|
||||
case SCT_MPEG2VIDEO:
|
||||
case SCT_H264:
|
||||
buf[0] = 0;
|
||||
if(st->st_frame_duration)
|
||||
if(st->es_frame_duration)
|
||||
snprintf(buf, sizeof(buf), "%2.2f Hz",
|
||||
90000.0 / st->st_frame_duration);
|
||||
90000.0 / st->es_frame_duration);
|
||||
htsmsg_add_str(c, "details", buf);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ static void
|
|||
dumptransports(htsbuf_queue_t *hq, struct service_list *l, int indent)
|
||||
{
|
||||
service_t *t;
|
||||
th_stream_t *st;
|
||||
elementary_stream_t *st;
|
||||
|
||||
outputtitle(hq, indent, "Transports (or services)");
|
||||
LIST_FOREACH(t, l, s_group_link) {
|
||||
|
@ -104,14 +104,14 @@ dumptransports(htsbuf_queue_t *hq, struct service_list *l, int indent)
|
|||
htsbuf_qprintf(hq, "%*.s-------------------------------------------\n",
|
||||
indent + 4, "");
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, st_link) {
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
caid_t *caid;
|
||||
htsbuf_qprintf(hq, "%*.s%-16s %-5d %-5d %-5s\n", indent + 4, "",
|
||||
streaming_component_type2txt(st->st_type),
|
||||
st->st_index,
|
||||
st->st_pid,
|
||||
st->st_lang[0] ? st->st_lang : "");
|
||||
LIST_FOREACH(caid, &st->st_caids, link) {
|
||||
streaming_component_type2txt(st->es_type),
|
||||
st->es_index,
|
||||
st->es_pid,
|
||||
st->es_lang[0] ? st->es_lang : "");
|
||||
LIST_FOREACH(caid, &st->es_caids, link) {
|
||||
htsbuf_qprintf(hq, "%*.sCAID %04x (%s) %08x\n", indent + 6, "",
|
||||
caid->caid,
|
||||
psi_caid2name(caid->caid),
|
||||
|
|
Loading…
Add table
Reference in a new issue