[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