[dvblast-devel] [PATCH 5/9] dvblastctl: Add support for getting EIT present/following/schedule for chosen service
Georgi Chorbadzhiyski
gf at unixsol.org
Thu Jan 25 01:20:58 CET 2018
From c6ccc522b6ae8d03020354fb07df6c4224d964c0 Mon Sep 17 00:00:00 2001
From: Georgi Chorbadzhiyski <gf at unixsol.org>
Date: Sun, 19 Nov 2017 17:03:35 +0200
Subject: [PATCH 5/9] dvblastctl: Add support for getting EIT
present/following/schedule for chosen service
New 'dvblastctl' commands:
dvblastctl get_eit_pf <service_id> - Print EIT present/following events and descriptors.
dvblastctl get_eit_schedule <service_id> - Print EIT schedule events and descriptors.
---
NEWS | 5 +++
comm.c | 14 ++++++-
comm.h | 6 ++-
demux.c | 55 ++++++++++++++++++++++++++
dvblast.h | 2 +
dvblastctl.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 202 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 8a0b979..92b3926 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Changes between 3.2 and -next
+-----------------------------
+ * Add support for getting EIT present/following for chosen service in dvblastctl
+ * Add support for getting EIT schedule for chosen service in dvblastctl
+
Changes between 3.1 and 3.2:
----------------------------
* Fix HEVC support
diff --git a/comm.c b/comm.c
index f75f566..8f353a3 100644
--- a/comm.c
+++ b/comm.c
@@ -224,6 +224,8 @@ static void comm_Read(struct ev_loop *loop, struct ev_io *w, int revents)
break;
}
+ case CMD_GET_EIT_PF:
+ case CMD_GET_EIT_SCHEDULE:
case CMD_GET_PMT:
{
if ( i_size < COMM_HEADER_SIZE + 2 )
@@ -233,11 +235,19 @@ static void comm_Read(struct ev_loop *loop, struct ev_io *w, int revents)
}
uint16_t i_sid = (uint16_t)((p_input[0] << 8) | p_input[1]);
- p_packed_section = demux_get_packed_PMT(i_sid, &i_packed_section_size);
+ if ( i_command == CMD_GET_EIT_PF ) {
+ i_answer = RET_EIT_PF;
+ p_packed_section = demux_get_packed_EIT_pf( i_sid, &i_packed_section_size );
+ } else if ( i_command == CMD_GET_EIT_SCHEDULE ) {
+ i_answer = RET_EIT_SCHEDULE;
+ p_packed_section = demux_get_packed_EIT_schedule( i_sid, &i_packed_section_size );
+ } else {
+ i_answer = RET_PMT;
+ p_packed_section = demux_get_packed_PMT(i_sid, &i_packed_section_size);
+ }
if ( p_packed_section && i_packed_section_size )
{
- i_answer = RET_PMT;
i_answer_size = i_packed_section_size;
memcpy( p_answer + COMM_HEADER_SIZE, p_packed_section, i_packed_section_size );
free( p_packed_section );
diff --git a/comm.h b/comm.h
index fe58e3e..3cf97e2 100644
--- a/comm.h
+++ b/comm.h
@@ -23,7 +23,7 @@
#include <bitstream/mpeg/psi.h>
#define COMM_HEADER_SIZE 8
-#define COMM_BUFFER_SIZE (COMM_HEADER_SIZE + ((PSI_PRIVATE_MAX_SIZE + PSI_HEADER_SIZE) * (PSI_TABLE_MAX_SECTIONS / 2)))
+#define COMM_BUFFER_SIZE (COMM_HEADER_SIZE + ((PSI_PRIVATE_MAX_SIZE + PSI_HEADER_SIZE) * PSI_TABLE_MAX_SECTIONS))
#define COMM_HEADER_MAGIC 0x49
#define COMM_MAX_MSG_CHUNK 4096
@@ -47,6 +47,8 @@ typedef enum {
CMD_GET_PID = 16, /* arg: pid (uint16_t) */
CMD_MMI_SEND_TEXT = 17, /* arg: slot, en50221_mmi_object_t */
CMD_MMI_SEND_CHOICE = 18, /* arg: slot, en50221_mmi_object_t */
+ CMD_GET_EIT_PF = 19, /* arg: service_id (uint16_t) */
+ CMD_GET_EIT_SCHEDULE = 20, /* arg: service_id (uint16_t) */
} ctl_cmd_t;
typedef enum {
@@ -65,6 +67,8 @@ typedef enum {
RET_PMT = 12,
RET_PIDS = 13,
RET_PID = 14,
+ RET_EIT_PF = 15,
+ RET_EIT_SCHEDULE = 16,
RET_HUH = 255,
} ctl_cmd_answer_t;
diff --git a/demux.c b/demux.c
index c32ae9c..5e9c570 100644
--- a/demux.c
+++ b/demux.c
@@ -3361,6 +3361,61 @@ uint8_t *demux_get_current_packed_SDT( unsigned int *pi_pack_size ) {
return psi_pack_sections( pp_current_sdt_sections, pi_pack_size );
}
+uint8_t *demux_get_packed_EIT( uint16_t i_sid, uint8_t start_table, uint8_t end_table, unsigned int *eit_size ) {
+ unsigned int i, r;
+
+ *eit_size = 0;
+ sid_t *p_sid = FindSID( i_sid );
+ if ( p_sid == NULL )
+ return NULL;
+
+ /* Calculate eit table size (sum of all sections in all tables between start_start and end_table) */
+ for ( i = start_table; i <= end_table; i++ ) {
+ uint8_t eit_table_idx = i - EIT_TABLE_ID_PF_ACTUAL;
+ if ( eit_table_idx >= MAX_EIT_TABLES )
+ continue;
+ uint8_t **eit_sections = p_sid->eit_table[eit_table_idx].data;
+ for ( r = 0; r < PSI_TABLE_MAX_SECTIONS; r++ ) {
+ uint8_t *p_eit = eit_sections[r];
+ if ( !p_eit )
+ continue;
+ uint16_t psi_length = psi_get_length( p_eit ) + PSI_HEADER_SIZE;
+ *eit_size += psi_length;
+ }
+ }
+
+ uint8_t *p_flat_section = malloc( *eit_size );
+ if ( !p_flat_section )
+ return NULL;
+
+ /* Copy sections */
+ unsigned int i_pos = 0;
+ for ( i = start_table; i <= end_table; i++ ) {
+ uint8_t eit_table_idx = i - EIT_TABLE_ID_PF_ACTUAL;
+ if ( eit_table_idx >= MAX_EIT_TABLES )
+ continue;
+ uint8_t **eit_sections = p_sid->eit_table[eit_table_idx].data;
+ for ( r = 0; r < PSI_TABLE_MAX_SECTIONS; r++ ) {
+ uint8_t *p_eit = eit_sections[r];
+ if ( !p_eit )
+ continue;
+ uint16_t psi_length = psi_get_length( p_eit ) + PSI_HEADER_SIZE;
+ memcpy( p_flat_section + i_pos, p_eit, psi_length );
+ i_pos += psi_length;
+ /* eit_print( p_eit, msg_Dbg, NULL, demux_Iconv, NULL, PRINT_TEXT ); */
+ }
+ }
+ return p_flat_section;
+}
+
+uint8_t *demux_get_packed_EIT_pf( uint16_t service_id, unsigned int *pi_pack_size ) {
+ return demux_get_packed_EIT( service_id, EIT_TABLE_ID_PF_ACTUAL, EIT_TABLE_ID_PF_ACTUAL, pi_pack_size );
+}
+
+uint8_t *demux_get_packed_EIT_schedule( uint16_t service_id, unsigned int *pi_pack_size ) {
+ return demux_get_packed_EIT( service_id, EIT_TABLE_ID_SCHED_ACTUAL_FIRST, EIT_TABLE_ID_SCHED_ACTUAL_LAST, pi_pack_size );
+}
+
uint8_t *demux_get_packed_PMT( uint16_t i_sid, unsigned int *pi_pack_size ) {
sid_t *p_sid = FindSID( i_sid );
if ( p_sid != NULL && p_sid->p_current_pmt && pmt_validate( p_sid->p_current_pmt ) )
diff --git a/dvblast.h b/dvblast.h
index a8d51e2..8434880 100644
--- a/dvblast.h
+++ b/dvblast.h
@@ -342,6 +342,8 @@ uint8_t *demux_get_current_packed_CAT( unsigned int *pi_pack_size );
uint8_t *demux_get_current_packed_NIT( unsigned int *pi_pack_size );
uint8_t *demux_get_current_packed_SDT( unsigned int *pi_pack_size );
uint8_t *demux_get_packed_PMT( uint16_t service_id, unsigned int *pi_pack_size );
+uint8_t *demux_get_packed_EIT_pf( uint16_t service_id, unsigned int *pi_pack_size );
+uint8_t *demux_get_packed_EIT_schedule( uint16_t service_id, unsigned int *pi_pack_size );
void demux_get_PID_info( uint16_t i_pid, uint8_t *p_data );
void demux_get_PIDS_info( uint8_t *p_data );
diff --git a/dvblastctl.c b/dvblastctl.c
index 4137e1f..d1386e8 100644
--- a/dvblastctl.c
+++ b/dvblastctl.c
@@ -210,6 +210,114 @@ void print_pids( uint8_t *p_data )
print_pids_footer();
}
+void print_eit_events(uint8_t *p_eit, f_print pf_print, void *print_opaque, f_iconv pf_iconv, void *iconv_opaque, print_type_t i_print_type)
+{
+ uint8_t *p_event;
+ uint8_t j = 0;
+ while ((p_event = eit_get_event(p_eit, j)) != NULL) {
+ j++;
+ char start_str[24], duration_str[10];
+ int duration, hour, min, sec;
+ time_t start_ts;
+
+ start_ts = dvb_time_format_UTC(eitn_get_start_time(p_event), NULL, start_str);
+
+ dvb_time_decode_bcd(eitn_get_duration_bcd(p_event), &duration, &hour, &min, &sec);
+ sprintf(duration_str, "%02d:%02d:%02d", hour, min, sec);
+
+ switch (i_print_type) {
+ case PRINT_XML:
+ pf_print(print_opaque, "<EVENT id=\"%u\" start_time=\"%ld\" start_time_dec=\"%s\""
+ " duration=\"%u\" duration_dec=\"%s\""
+ " running=\"%d\" free_CA=\"%d\">",
+ eitn_get_event_id(p_event),
+ start_ts, start_str,
+ duration, duration_str,
+ eitn_get_running(p_event),
+ eitn_get_ca(p_event)
+ );
+ break;
+ default:
+ pf_print(print_opaque, " * EVENT id=%u start_time=%ld start_time_dec=\"%s\" duration=%u duration_dec=%s running=%d free_CA=%d",
+ eitn_get_event_id(p_event),
+ start_ts, start_str,
+ duration, duration_str,
+ eitn_get_running(p_event),
+ eitn_get_ca(p_event)
+ );
+ }
+
+ descs_print(eitn_get_descs(p_event), pf_print, print_opaque,
+ pf_iconv, iconv_opaque, i_print_type);
+
+ switch (i_print_type) {
+ case PRINT_XML:
+ pf_print(print_opaque, "</EVENT>");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void print_eit(uint8_t *p_eit, unsigned int i_eit_size, f_print pf_print, void *print_opaque, f_iconv pf_iconv, void *iconv_opaque, print_type_t i_print_type)
+{
+ uint8_t *p_eit_end = p_eit + i_eit_size;
+ uint8_t i_tid = psi_get_tableid(p_eit);
+ const char *psz_tid = "unknown";
+
+ if (i_tid == EIT_TABLE_ID_PF_ACTUAL)
+ psz_tid = "actual_pf";
+ else if (i_tid == EIT_TABLE_ID_PF_OTHER)
+ psz_tid = "other_pf";
+ else if (i_tid >= EIT_TABLE_ID_SCHED_ACTUAL_FIRST && i_tid <= EIT_TABLE_ID_SCHED_ACTUAL_LAST)
+ psz_tid = "actual_schedule";
+ else if (i_tid >= EIT_TABLE_ID_SCHED_OTHER_FIRST && i_tid <= EIT_TABLE_ID_SCHED_OTHER_LAST)
+ psz_tid = "other_schedule";
+
+ switch (i_print_type) {
+ case PRINT_XML:
+ pf_print(print_opaque,
+ "<EIT tableid=\"0x%02x\" type=\"%s\" service_id=\"%u\""
+ " version=\"%u\""
+ " current_next=\"%u\""
+ " tsid=\"%u\" onid=\"%u\">",
+ i_tid, psz_tid,
+ eit_get_sid(p_eit),
+ psi_get_version(p_eit),
+ !psi_get_current(p_eit) ? 0 : 1,
+ eit_get_tsid(p_eit),
+ eit_get_onid(p_eit)
+ );
+ break;
+ default:
+ pf_print(print_opaque,
+ "new EIT tableid=0x%02x type=%s service_id=%u version=%u%s"
+ " tsid=%u"
+ " onid=%u",
+ i_tid, psz_tid,
+ eit_get_sid(p_eit),
+ psi_get_version(p_eit),
+ !psi_get_current(p_eit) ? " (next)" : "",
+ eit_get_tsid(p_eit),
+ eit_get_onid(p_eit)
+ );
+ }
+
+ while (p_eit < p_eit_end) {
+ print_eit_events(p_eit, pf_print, print_opaque, pf_iconv, iconv_opaque, i_print_type);
+ p_eit += psi_get_length( p_eit ) + PSI_HEADER_SIZE;
+ }
+
+ switch (i_print_type) {
+ case PRINT_XML:
+ pf_print(print_opaque, "</EIT>");
+ break;
+ default:
+ pf_print(print_opaque, "end EIT");
+ }
+}
+
struct dvblastctl_option {
char * opt;
int nparams;
@@ -235,6 +343,8 @@ static const struct dvblastctl_option options[] =
{ "get_cat", 0, CMD_GET_CAT },
{ "get_nit", 0, CMD_GET_NIT },
{ "get_sdt", 0, CMD_GET_SDT },
+ { "get_eit_pf", 1, CMD_GET_EIT_PF }, /* arg: service_id (uint16_t) */
+ { "get_eit_schedule", 1, CMD_GET_EIT_SCHEDULE }, /* arg: service_id (uint16_t) */
{ "get_pmt", 1, CMD_GET_PMT }, /* arg: service_id (uint16_t) */
{ "get_pids", 0, CMD_GET_PIDS },
{ "get_pid", 1, CMD_GET_PID }, /* arg: pid (uint16_t) */
@@ -269,6 +379,8 @@ void usage()
printf(" get_cat Return last CAT table.\n");
printf(" get_nit Return last NIT table.\n");
printf(" get_sdt Return last SDT table.\n");
+ printf(" get_eit_pf <service_id> Return last EIT present/following data.\n");
+ printf(" get_eit_schedule <service_id> Return last EIT schedule data.\n");
printf(" get_pmt <service_id> Return last PMT table.\n");
printf(" get_pids Return info about all pids.\n");
printf(" get_pid <pid> Return info for chosen pid only.\n");
@@ -417,6 +529,8 @@ int main( int i_argc, char **ppsz_argv )
case CMD_GET_PIDS:
/* These commands need no special handling because they have no parameters */
break;
+ case CMD_GET_EIT_PF:
+ case CMD_GET_EIT_SCHEDULE:
case CMD_GET_PMT:
{
uint16_t i_sid = atoi(p_arg1);
@@ -567,6 +681,15 @@ int main( int i_argc, char **ppsz_argv )
break;
}
+ case RET_EIT_PF:
+ case RET_EIT_SCHEDULE:
+ {
+ uint8_t *p_eit_data = p_buffer + COMM_HEADER_SIZE;
+ unsigned int i_eit_data_size = i_received - COMM_HEADER_SIZE;
+ print_eit( p_eit_data, i_eit_data_size, psi_print, NULL, psi_iconv, NULL, i_print_type );
+ break;
+ }
+
case RET_PMT:
{
pmt_print( p_data, psi_print, NULL, psi_iconv, NULL, i_print_type );
--
2.16.0
More information about the dvblast-devel
mailing list