Skip to content
Commits on Source (7)
......@@ -1419,7 +1419,8 @@ static void DumpTeletextDescriptor(const void *p_descriptor)
p_teletext_descriptor->p_pages[i].i_iso6392_language_code[1],
p_teletext_descriptor->p_pages[i].i_iso6392_language_code[2]);
printf("\t\tteletext type : %d\n", p_teletext_descriptor->p_pages[i].i_teletext_type);
printf("\t\tteletext magazine : %d\n", p_teletext_descriptor->p_pages[i].i_teletext_magazine_number);
printf("\t\tteletext magazine : %d\n", p_teletext_descriptor->p_pages[i].i_teletext_magazine_number ?
p_teletext_descriptor->p_pages[i].i_teletext_magazine_number : 8 );
printf("\t\tteletext page : %d\n", p_teletext_descriptor->p_pages[i].i_teletext_page_number);
}
}
......@@ -2211,7 +2212,7 @@ static void handle_atsc_MGT(void *p_data, dvbpsi_atsc_mgt_t *p_mgt)
ts_atsc_eit_t *p = calloc(1, sizeof(ts_atsc_eit_t));
if (p)
{
/* PMT */
/* EIT */
p->handle = dvbpsi_new(&dvbpsi_message, p_stream->level);
if (p->handle == NULL)
{
......
......@@ -284,16 +284,17 @@ int udp_open(const char *interface, const char *ipaddress, int port)
continue;
}
const struct sockaddr_storage *saddr = (const struct sockaddr_storage *)&ptr->ai_addr;
if (is_multicast(saddr, ptr->ai_addrlen) &&
mcast_connect(s_ctl, interface, saddr, ptr->ai_addrlen))
const struct sockaddr_storage *saddr = (const struct sockaddr_storage *)ptr->ai_addr;
if (is_multicast(saddr, ptr->ai_addrlen))
{
close(s_ctl);
s_ctl = -1;
perror("mcast connect error");
continue;
if (!mcast_connect(s_ctl, interface, saddr, ptr->ai_addrlen))
{
close(s_ctl);
s_ctl = -1;
perror("mcast connect error");
continue;
}
}
break;
}
......
......@@ -42,17 +42,18 @@
* - dvbpsi_Demux | no replacement -
* - dvbpsi_demuxGetSubDecoder | @see dvbpsi_decoder_chain_get -
* - dvbpsi_NewDemuxSubDecoder | no replacement -
* - dvbpsi_AttachDemuxSubDecoder | no replacement -
* - dvbspi_DetachDemuxSubDecoder | no replacement -
* - dvbpsi_AttachDemuxSubDecoder | @see dvbpsi_decoder_chain_add -
* - dvbspi_DetachDemuxSubDecoder | @see dvbpsi_decoder_chain_remove -
* -----------------------------------------------------------------------------------
*
* Note that for dvbpsi_Demux(), dvbpsi_NewDemuxSubDecoder(), dvbpsi_AttachDemuxSubDecoder(),
* and dvbspi_DetachDemuxSubDecoder() no replacement API is available. These functions are
* discontinued since the dvbpsi_subdec_t indirection has been removed. A dvbpsi_decoder_t
* can be added in a demux chain directly. It is important to use the API call
* dvbpsi_demux_chain_new(), since that will install the callback function
* dvbpsi_decoder_chain_demux(). This will do the same job dvbpsi_Demux() function had in
* the subsdecoder architecture of demux.h.
* can be added in a demux chain directly using dvbpsi_decoder_chain_add() or removed using
* dvbpsi_decoder_chain_remove() API.
* It is IMPORTANT to use the API call dvbpsi_demux_chain_new(), since that will install
* the callback function dvbpsi_decoder_chain_demux(). This will do the same job dvbpsi_Demux()
* function had in the subsdecoder architecture of demux.h.
*/
#ifndef _DVBPSI_CHAIN_H_
......@@ -131,7 +132,7 @@ bool dvbpsi_decoder_chain_remove(dvbpsi_t *p_dvbpsi, const dvbpsi_decoder_t *p_d
* \param p_dvbpsi pointer to dvbpsi_t handle
* \param table_id PSI table id to get
* \param extension PSI subtable id to get
* \return true on success, false on failure
* \return returns pointer to dvbpsi_decoder_t on success, or NULL on failure
*/
dvbpsi_decoder_t *dvbpsi_decoder_chain_get(dvbpsi_t *p_dvbpsi, const uint16_t table_id, const uint16_t extension);
......
......@@ -39,6 +39,8 @@
#include "dr_41.h"
#define DVBPSI_SLS_DR_MAX (84)
/*****************************************************************************
* dvbpsi_decode_dvb_service_list_dr
*****************************************************************************/
......@@ -59,7 +61,7 @@ dvbpsi_dvb_service_list_dr_t* dvbpsi_decode_dvb_service_list_dr(
unsigned int service_count = p_descriptor->i_length / 3;
if ((p_descriptor->i_length < 1) ||
(p_descriptor->i_length % 3 != 0) ||
(service_count>63))
(service_count > DVBPSI_SLS_DR_MAX - 1))
return NULL;
/* Allocate memory */
......@@ -91,7 +93,7 @@ dvbpsi_descriptor_t * dvbpsi_gen_dvb_service_list_dr(
bool b_duplicate)
{
/* Check the length */
if (p_decoded->i_service_count > 63)
if (p_decoded->i_service_count > DVBPSI_SLS_DR_MAX - 1)
return NULL;
/* Create the descriptor */
......
......@@ -59,7 +59,7 @@ typedef struct dvbpsi_dvb_service_list_dr_s
struct dvbpsi_service_list_service_s {
uint16_t i_service_id; /*!< service id */
uint8_t i_service_type; /*!< service type */
} i_service[64]; /*!< array of services */
} i_service[84]; /*!< array of services */
} dvbpsi_dvb_service_list_dr_t;
......
......@@ -411,6 +411,54 @@ void dvbpsi_sis_sections_gather(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t * p_sec
}
}
/*****************************************************************************
* dvbpsi_sis_utc_splice_time
*****************************************************************************
* extract UTC time
*****************************************************************************/
static inline uint64_t dvbpsi_sis_utc_splice_time(uint8_t *p_data)
{
return (((uint32_t)p_data[0] << 24) |
((uint32_t)p_data[1] << 16) |
((uint32_t)p_data[2] << 8) |
(uint32_t)p_data[3]);
}
/*****************************************************************************
* dvbpsi_sis_splice_time
*****************************************************************************
* decode splice time in 90kHz clock
*****************************************************************************/
static void dvbpsi_sis_splice_time(uint8_t *p_data, dvbpsi_sis_splice_time_t *p_splice_time)
{
p_splice_time->b_time_specified_flag = (p_data[0] & 0x80);
if (p_splice_time->b_time_specified_flag) {
p_splice_time->i_pts_time =
(((uint64_t)(p_data[0] & 0x01) << 32) |
((uint64_t)p_data[1] << 24) |
((uint64_t)p_data[2] << 16) |
((uint64_t)p_data[3] << 8) |
(uint64_t)p_data[4]);
}
}
/*****************************************************************************
* dvbpsi_sis_break_duration
*****************************************************************************
* * decode break duration in 90kHz clock
*****************************************************************************/
static void dvbpsi_sis_break_duration(uint8_t *p_data, dvbpsi_sis_break_duration_t *p_break_duration)
{
p_break_duration->b_auto_return = (p_data[0] & 0x80);
p_break_duration->i_duration =
((((uint64_t)p_data[0] & 0x01) << 32) |
((uint64_t)p_data[1] << 24) |
((uint64_t)p_data[2] << 16) |
((uint64_t)p_data[3] << 8) |
(uint64_t)p_data[4]);
}
/*****************************************************************************
* dvbpsi_sis_cmd_splice_insert_decode
*****************************************************************************
......@@ -454,16 +502,9 @@ static dvbpsi_sis_cmd_splice_insert_t *
goto error;
/* splice_time () */
p_cmd->i_splice_time.b_time_specified_flag = (p_data[pos] & 0x80);
if (p_cmd->i_splice_time.b_time_specified_flag) {
p_cmd->i_splice_time.i_pts_time =
(((uint64_t)(p_data[pos] & 0x01) << 32) |
((uint64_t)p_data[pos + 1] << 24) |
((uint64_t)p_data[pos + 2] << 16) |
((uint64_t)p_data[pos + 3] << 8) |
(uint64_t)p_data[pos + 4]);
dvbpsi_sis_splice_time(&p_data[pos], &p_cmd->i_splice_time);
if (p_cmd->i_splice_time.b_time_specified_flag)
pos += 5;
}
else
pos++;
p_cmd->i_splice_time.p_next = NULL;
......@@ -475,7 +516,7 @@ static dvbpsi_sis_cmd_splice_insert_t *
i_needed += p_data[pos] * 6;
else
i_needed += p_data[pos];
if (i_needed + pos >+ i_length)
if (i_needed + pos >= i_length)
goto error;
p_cmd->i_component_count = p_data[pos];
......@@ -493,16 +534,9 @@ static dvbpsi_sis_cmd_splice_insert_t *
p_splice_time->i_component_tag = p_data[pos++];
if (!p_cmd->b_splice_immediate_flag) {
/* splice_time */
p_splice_time->i_splice_time.b_time_specified_flag = (p_data[pos] & 0x80);
if (p_splice_time->i_splice_time.b_time_specified_flag) {
p_splice_time->i_splice_time.i_pts_time =
(((uint64_t)(p_data[pos] & 0x01) << 32) |
((uint64_t)p_data[pos + 1] << 24) |
((uint64_t)p_data[pos + 2] << 16) |
((uint64_t)p_data[pos + 3] << 8) |
(uint64_t)p_data[pos + 4]);
dvbpsi_sis_splice_time(&p_data[pos], &p_splice_time->i_splice_time);
if (p_splice_time->i_splice_time.b_time_specified_flag)
pos += 5;
}
else
pos++;
}
......@@ -518,13 +552,7 @@ static dvbpsi_sis_cmd_splice_insert_t *
}
if (p_cmd->b_duration_flag) {
/* break duration */
p_cmd->i_break_duration.b_auto_return = (p_data[pos] & 0x80);
p_cmd->i_break_duration.i_duration =
((((uint64_t)p_data[pos] & 0x01) << 32) |
((uint64_t)p_data[pos + 1] << 24) |
((uint64_t)p_data[pos + 2] << 16) |
((uint64_t)p_data[pos + 3] << 8) |
(uint64_t)p_data[pos + 4]);
dvbpsi_sis_break_duration(&p_data[pos], &p_cmd->i_break_duration);
pos += 5;
}
p_cmd->i_unique_program_id = (((uint16_t)p_data[pos] << 8) |
......@@ -597,10 +625,7 @@ static dvbpsi_sis_cmd_splice_schedule_t *
/* 5 reserved bits */
if (p_event->b_program_splice_flag) {
/* utc_splice_time */
p_event->i_utc_splice_time = (((uint32_t)p_data[pos ] << 24) |
((uint32_t)p_data[pos+1] << 16) |
((uint32_t)p_data[pos+2] << 8) |
(uint32_t)p_data[pos+3]);
p_event->i_utc_splice_time = dvbpsi_sis_utc_splice_time(&p_data[pos]);
pos += 4;
}
else { /* component */
......@@ -623,7 +648,8 @@ static dvbpsi_sis_cmd_splice_schedule_t *
return NULL;
}
p_time->i_tag = p_data[pos++];
p_time->i_utc_splice_time = p_data[pos]; /* GPS_UTC time */
/* GPS_UTC time */
p_time->i_utc_splice_time = dvbpsi_sis_utc_splice_time(&p_data[pos]);
pos += 4;
if (!p_event->p_component)
p_event->p_component = p_list = p_time;
......@@ -635,13 +661,7 @@ static dvbpsi_sis_cmd_splice_schedule_t *
}
if (p_event->b_duration_flag) {
/* break duration */
p_event->i_break_duration.b_auto_return = (p_data[pos] & 0x80);
p_event->i_break_duration.i_duration =
((((uint64_t)p_data[pos] & 0x01) << 32) |
((uint64_t)p_data[pos + 1] << 24) |
((uint64_t)p_data[pos + 2] << 16) |
((uint64_t)p_data[pos + 3] << 8) |
(uint64_t)p_data[pos + 4]);
dvbpsi_sis_break_duration(&p_data[pos], &p_event->i_break_duration);
pos += 5;
}
p_event->i_unique_program_id = p_data[pos];
......@@ -682,6 +702,10 @@ void dvbpsi_sis_sections_decode(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis,
p_sis->b_encrypted_packet = ((p_byte[4] & 0x80) == 0x80);
/* NOTE: cannot handle encrypted packet */
assert(p_sis->b_encrypted_packet);
if (p_sis->b_encrypted_packet) {
dvbpsi_error(p_dvbpsi, "SIS decoder", "cannot handle encrypted packets");
break;
}
p_sis->i_encryption_algorithm = ((p_byte[4] & 0x7E) >> 1);
p_sis->i_pts_adjustment = ((((uint64_t)p_byte[4] & 0x01) << 32) |
((uint64_t)p_byte[5] << 24) |
......@@ -774,6 +798,168 @@ void dvbpsi_sis_sections_decode(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis,
}
}
/*****************************************************************************
* Generate SIS tables
*****************************************************************************/
static uint32_t dvbpsi_sis_generate_utc_splice_time(uint8_t *p_data, const uint32_t i_time)
{
p_data[0] = (i_time >> 24);
p_data[1] = (i_time >> 16);
p_data[2] = (i_time >> 8);
p_data[3] = (i_time & 0xff);
return 4;
}
static uint32_t dvbpsi_sis_generate_splice_time(uint8_t *p_data, const dvbpsi_sis_splice_time_t *p_splice_time)
{
uint32_t i_pos = 1;
p_data[0] = p_splice_time->b_time_specified_flag ? 0x80 : 0x00;
if (p_splice_time->b_time_specified_flag)
{
p_data[0] |= ((p_splice_time->i_pts_time >> 32) & 0x01);
p_data[1] = (p_splice_time->i_pts_time >> 24);
p_data[2] = (p_splice_time->i_pts_time >> 16);
p_data[3] = (p_splice_time->i_pts_time >> 8);
p_data[4] = (p_splice_time->i_pts_time & 0xff);
i_pos += 4;
}
return i_pos;
}
static uint32_t dvbpsi_sis_generate_break_duration(uint8_t *p_data, const dvbpsi_sis_break_duration_t *p_break_duration)
{
p_data[0] = p_break_duration->b_auto_return ? 0x80 : 0x00;
p_data[0] |= ((p_break_duration->i_duration >> 32) & 0x01);
p_data[1] = (p_break_duration->i_duration >> 24);
p_data[2] = (p_break_duration->i_duration >> 16);
p_data[3] = (p_break_duration->i_duration >> 8);
p_data[4] = (p_break_duration->i_duration & 0xff);
return 5;
}
static uint32_t dvbpsi_sis_generate_splice_cmd_schedule(uint8_t *p_data,
const dvbpsi_sis_cmd_splice_schedule_t *p_schedule)
{
uint32_t i_pos = 0, i_event = 0;
p_data[i_pos] = p_schedule->i_splice_count;
i_pos++;
dvbpsi_sis_splice_event_t *p_event = p_schedule->p_splice_event;
while (p_event)
{
p_data[i_pos + 0] = (p_event->i_splice_event_id >> 24);
p_data[i_pos + 1] = (p_event->i_splice_event_id >> 16);
p_data[i_pos + 2] = (p_event->i_splice_event_id >> 8);
p_data[i_pos + 3] = (p_event->i_splice_event_id);
p_data[i_pos + 4] = p_event->b_splice_event_cancel_indicator ? 0x80 : 0x00;
i_pos += 5;
if (!p_event->b_splice_event_cancel_indicator)
{
p_data[i_pos] = p_event->b_out_of_network_indicator ? 0x80 : 0x00;
p_data[i_pos] |= p_event->b_program_splice_flag ? 0x40 : 0x00;
p_data[i_pos] |= p_event->b_duration_flag ? 0x20 : 0x00;
i_pos++;
if (p_event->b_program_splice_flag)
i_pos += dvbpsi_sis_generate_utc_splice_time(p_data + i_pos, p_event->i_utc_splice_time);
else
{
/* component loop */
p_data[i_pos] = p_event->i_component_count;
i_pos++;
int count = p_event->i_component_count;
dvbpsi_sis_component_t *p_comp = p_event->p_component;
while (p_comp && count > 0)
{
p_data[i_pos] = p_comp->i_tag;
i_pos++;
i_pos += dvbpsi_sis_generate_utc_splice_time(p_data + i_pos, p_comp->i_utc_splice_time);
p_comp = p_comp->p_next;
count--;
}
assert(count == 0);
assert(p_comp == NULL);
}
if (p_event->b_duration_flag)
i_pos += dvbpsi_sis_generate_break_duration(p_data + i_pos, &p_event->i_break_duration);
p_data[i_pos + 0] = (p_event->i_unique_program_id >> 8);
p_data[i_pos + 1] = (p_event->i_unique_program_id & 0x00ff);
p_data[i_pos + 2] = p_event->i_avail_num;
p_data[i_pos + 3] = p_event->i_avails_expected;
i_pos += 4;
}
p_event = p_event->p_next;
i_event++;
}
assert(i_event == p_schedule->i_splice_count);
return i_pos;
}
static uint32_t dvbpsi_sis_generate_splice_cmd_insert(uint8_t *p_data,
const dvbpsi_sis_cmd_splice_insert_t *p_insert)
{
p_data[0] = (p_insert->i_splice_event_id >> 24);
p_data[1] = (p_insert->i_splice_event_id >> 16);
p_data[2] = (p_insert->i_splice_event_id >> 8);
p_data[3] = (p_insert->i_splice_event_id & 0x000000ff);
p_data[4] = p_insert->b_splice_event_cancel_indicator ? 0x01 : 0x00;
if (p_insert->b_splice_event_cancel_indicator)
return 5;
p_data[5] = p_insert->b_out_of_network_indicator ? 0x80 : 0x00;
p_data[5] |= p_insert->b_program_splice_flag ? 0x40 : 0x00;
p_data[5] |= p_insert->b_duration_flag ? 0x20 : 0x00;
p_data[5] |= p_insert->b_splice_immediate_flag ? 0x10 : 0x00;
uint8_t i_pos = 6;
if (p_insert->b_program_splice_flag && !p_insert->b_splice_immediate_flag)
{
i_pos += dvbpsi_sis_generate_splice_time(p_data + i_pos, &p_insert->i_splice_time);
}
if (!p_insert->b_program_splice_flag)
{
p_data[i_pos] = p_insert->i_component_count;
i_pos++;
int count = p_insert->i_component_count;
dvbpsi_sis_component_splice_time_t *p_comp = p_insert->p_splice_time;
while (p_comp && count > 0)
{
p_data[i_pos] = p_comp->i_component_tag;
i_pos++;
i_pos += dvbpsi_sis_generate_splice_time(p_data + i_pos, &p_comp->i_splice_time);
p_comp = p_comp->p_next;
count--;
}
assert(count == 0);
assert(p_comp == NULL);
}
if (p_insert->b_duration_flag)
{
i_pos += dvbpsi_sis_generate_break_duration(p_data + i_pos, &p_insert->i_break_duration);
}
p_data[i_pos + 0] = (p_insert->i_unique_program_id >> 8);
p_data[i_pos + 1] = (p_insert->i_unique_program_id & 0x00ff);
p_data[i_pos + 2] = p_insert->i_avail_num;
p_data[i_pos + 3] = p_insert->i_avails_expected;
i_pos += 4;
return i_pos;
}
static uint32_t dvbpsi_sis_generate_splice_cmd_time_signal(uint8_t *p_data,
const dvbpsi_sis_cmd_time_signal_t *p_signal)
{
return dvbpsi_sis_generate_splice_time(p_data, p_signal->p_splice_time);
}
static uint32_t dvbpsi_sis_generate_splice_cmd_bandwidth_reservation(uint8_t *p_data,
const dvbpsi_sis_cmd_bandwidth_reservation_t *p_bandwidth)
{
return 0;
}
/*****************************************************************************
* dvbpsi_sis_sections_generate
*****************************************************************************
......@@ -817,23 +1003,39 @@ dvbpsi_psi_section_t *dvbpsi_sis_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_si
if (p_sis->i_splice_command_length > 0xfff)
p_sis->i_splice_command_length = 0xfff; /* truncate */
/* Handle splice_command_sections */
/* TODO: FIXME: Handle splice_command_sections */
uint32_t i_cmd_start = 14;
uint32_t i_pos = 0;
switch(p_sis->i_splice_command_type)
{
case 0x00: /* splice_null */
assert(p_sis->i_splice_command_length == 0);
break;
case 0x04: /* splice_schedule */
i_pos = dvbpsi_sis_generate_splice_cmd_schedule(p_current->p_data + i_cmd_start,
(dvbpsi_sis_cmd_splice_schedule_t *)p_sis->p_splice_command);
break;
case 0x05: /* splice_insert */
i_pos = dvbpsi_sis_generate_splice_cmd_insert(p_current->p_data + i_cmd_start,
(dvbpsi_sis_cmd_splice_insert_t *)p_sis->p_splice_command);
break;
case 0x06: /* time_signal */
i_pos = dvbpsi_sis_generate_splice_cmd_time_signal(p_current->p_data + i_cmd_start,
(dvbpsi_sis_cmd_time_signal_t *) p_sis->p_splice_command);
break;
case 0x07: /* bandwidth_reservation */
i_pos = dvbpsi_sis_generate_splice_cmd_bandwidth_reservation(p_current->p_data + i_cmd_start,
(dvbpsi_sis_cmd_bandwidth_reservation_t *) p_sis->p_splice_command);
break;
default:
dvbpsi_error(p_dvbpsi, "SIS decoder", "invalid SIS Command found");
break;
}
if (i_pos > 0)
i_cmd_start += i_pos;
/* The splice command may not overrun the start of the descriptor loop */
assert(i_cmd_start < i_desc_start);
......