libdvbv5: produce dvb data from the new structures
authorMauro Carvalho Chehab <m.chehab@samsung.com>
Sun, 17 Nov 2013 15:49:44 +0000 (13:49 -0200)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Wed, 27 Nov 2013 11:24:40 +0000 (09:24 -0200)
Now that dvb-scan uses the new descriptor structures, convert
dvb-file to rely on them to produce the scanned file data.

Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
lib/include/descriptors/pat.h
lib/include/descriptors/pmt.h
lib/include/descriptors/sdt.h
lib/include/dvb-scan-table-handler.h
lib/libdvbv5/dvb-file.c
lib/libdvbv5/dvb-scan.c
utils/dvb/dvbv5-scan.c

index b37ae40..419e342 100644 (file)
@@ -49,7 +49,7 @@ struct dvb_table_pat {
 
 #define dvb_pat_program_foreach(_program, _pat) \
        struct dvb_table_pat_program *_program; \
-       for(int _i = 0; _i < _pat->programs && (_program = _pat->program + _i); _i++) \
+       for (int _i = 0; _i < _pat->programs && (_program = _pat->program + _i); _i++) \
 
 struct dvb_v5_fe_parms;
 
index 3a585fa..79a6172 100644 (file)
@@ -100,7 +100,7 @@ struct dvb_table_pmt {
 } __attribute__((packed));
 
 #define dvb_pmt_stream_foreach(_stream, _pmt) \
-  for( struct dvb_table_pmt_stream *_stream = _pmt->stream; _stream; _stream = _stream->next ) \
+  for (struct dvb_table_pmt_stream *_stream = _pmt->stream; _stream; _stream = _stream->next) \
 
 struct dvb_v5_fe_parms;
 
index d94c23c..493b853 100644 (file)
@@ -57,7 +57,7 @@ struct dvb_table_sdt {
 } __attribute__((packed));
 
 #define dvb_sdt_service_foreach(_service, _sdt) \
-       forstruct dvb_table_sdt_service *_service = _sdt->service; _service; _service = _service->next ) \
+       for (struct dvb_table_sdt_service *_service = _sdt->service; _service; _service = _service->next ) \
 
 struct dvb_v5_fe_parms;
 
index 81ced1f..cadf03b 100644 (file)
 #include "descriptors/desc_atsc_service_location.h"
 #include "descriptors/desc_hierarchy.h"
 
-struct pmt_table {
-       uint16_t program_number, pcr_pid;
-       unsigned char version;
-};
-
 struct el_pid {
        uint8_t  type;
        uint16_t pid;
 };
 
-struct pid_table {
-       uint16_t service_id;
-       uint16_t pid;
-       struct pmt_table pmt_table;
-       unsigned video_pid_len, audio_pid_len, other_el_pid_len;
-       uint16_t *video_pid;
-       uint16_t *audio_pid;
-       struct el_pid *other_el_pid;
-};
-
-struct pat_table {
-       uint16_t  ts_id;
-       unsigned char version;
-       struct pid_table *pid_table;
-       unsigned pid_table_len;
-};
-
 struct transport_table {
        uint16_t tr_id;
 };
@@ -147,25 +125,24 @@ struct sdt_table {
        unsigned service_table_len;
 };
 
+
 struct dvb_v5_descriptors_program {
-       struct dvb_table_pat_program *program;
+       struct dvb_table_pat_program *pat_pgm;
        struct dvb_table_pmt *pmt;
 };
+
 struct dvb_v5_descriptors {
        int verbose;
        uint32_t delivery_system;
 
-       struct pat_table pat_table;
        struct nit_table nit_table;
        struct sdt_table sdt_table;
 
-       /* Used by descriptors to know where to update a PMT/Service/TS */
-       unsigned cur_pmt;
-       unsigned cur_service;
-       unsigned cur_ts;
-
        /* New data */
 
+       struct dvb_entry *entry;
+       unsigned num_entry;
+
        struct dvb_table_pat *pat;
        struct dvb_table_vct *vct;
        struct dvb_v5_descriptors_program *program;
index b5b276b..fe715d5 100644 (file)
@@ -27,6 +27,7 @@
 #include "dvb-v5-std.h"
 #include "dvb-scan.h"
 #include "dvb-scan-table-handler.h"
+#include "dvb-log.h"
 
 /*
  * Generic parse function for all formats each channel is contained into
@@ -887,119 +888,205 @@ static int sort_other_el_pid(const void *a_arg, const void *b_arg)
        return b->pid - a->pid;
 }
 
+
+static void get_pmt_descriptors(struct dvb_entry *entry,
+                               struct dvb_table_pmt *pmt)
+{
+       int has_ac3 = 0;
+       int video_len = 0, audio_len = 0, other_len = 0;
+
+       dvb_pmt_stream_foreach(stream, pmt) {
+               uint16_t  pid = stream->elementary_pid;
+
+               switch(stream->type) {
+               case 0x01: /* ISO/IEC 11172-2 Video */
+               case 0x02: /* H.262, ISO/IEC 13818-2 or ISO/IEC 11172-2 video */
+               case 0x1b: /* H.264 AVC */
+                       entry->video_pid = realloc(entry->video_pid,
+                                                  sizeof(*entry->video_pid) *
+                                                  (video_len + 1));
+                       entry->video_pid[video_len] = pid;
+                       video_len++;
+                       break;
+               case 0x03: /* ISO/IEC 11172-3 Audio */
+               case 0x04: /* ISO/IEC 13818-3 Audio */
+               case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS (AAC) */
+               case 0x11: /* ISO/IEC 14496-3 Audio with the LATM */
+               case 0x81: /* user private - in general ATSC Dolby - AC-3 */
+                       entry->audio_pid = realloc(entry->audio_pid,
+                                                  sizeof(*entry->audio_pid) *
+                                                  (audio_len + 1));
+                       entry->audio_pid[audio_len] = pid;
+                       audio_len++;
+                       break;
+               case 0x05: /* private sections */
+               case 0x06: /* private data */
+                       /*
+                       * Those can be used by sub-titling, teletext and/or
+                       * DVB AC-3. So, need to seek for the AC-3 descriptors
+                       */
+                       dvb_desc_find(struct dvb_desc_service, desc, stream, AC_3_descriptor)
+                               has_ac3 = 1;
+
+                       dvb_desc_find(struct dvb_desc_service, desc, stream, enhanced_AC_3_descriptor)
+                               has_ac3 = 1;
+
+                       if (has_ac3) {
+                               entry->audio_pid = realloc(entry->audio_pid,
+                                                          sizeof(*entry->audio_pid) *
+                                                          (audio_len + 1));
+                               entry->audio_pid[audio_len] = pid;
+                               audio_len++;
+                       } else {
+                               entry->other_el_pid = realloc(entry->other_el_pid,
+                                                          sizeof(*entry->other_el_pid) *
+                                                          (other_len + 1));
+                               entry->other_el_pid[other_len].type = stream->type;
+                               entry->other_el_pid[other_len].pid = pid;
+                               other_len++;
+                       }
+                       break;
+               default:
+                       entry->other_el_pid = realloc(entry->other_el_pid,
+                                                  sizeof(*entry->other_el_pid) *
+                                                  (other_len + 1));
+                       entry->other_el_pid[other_len].type = stream->type;
+                       entry->other_el_pid[other_len].pid = pid;
+                       other_len++;
+                       break;
+               }
+       }
+
+       entry->video_pid_len = video_len;
+       entry->audio_pid_len = audio_len;
+       entry->other_el_pid_len = other_len;
+
+       qsort(entry->other_el_pid, entry->other_el_pid_len,
+             sizeof(*entry->other_el_pid), sort_other_el_pid);
+}
+
+static int get_program_and_store(struct dvb_v5_fe_parms *parms,
+                                struct dvb_file *dvb_file,
+                                struct dvb_v5_descriptors *dvb_scan_handler,
+                                uint16_t service_id, char *channel,
+                                int get_detected, int get_nit)
+{
+       struct dvb_entry *entry;
+       int i, j;
+
+       /* Go to the last entry */
+
+       if (dvb_file->first_entry) {
+               entry = dvb_file->first_entry;
+               while (entry && entry->next)
+                       entry = entry->next;
+       }
+
+       for (i = 0; i < dvb_scan_handler->num_program; i++) {
+               if (!dvb_scan_handler->program[i].pmt)
+                       continue;
+
+               if (service_id == dvb_scan_handler->program[i].pat_pgm->service_id)
+                       break;
+       }
+
+       if (service_id != dvb_scan_handler->program[i].pat_pgm->service_id) {
+               fprintf(stderr, "Service ID %d not found on PMT!\n",
+                       service_id);
+               return 0;
+       }
+
+
+       /* Create an entry to store the data */
+       if (!dvb_file->first_entry) {
+               dvb_file->first_entry = calloc(sizeof(*entry), 1);
+               entry = dvb_file->first_entry;
+       } else {
+               entry->next = calloc(sizeof(*entry), 1);
+               entry = entry->next;
+       }
+       if (!entry) {
+               fprintf(stderr, "Not enough memory\n");
+               return -1;
+       }
+
+       /* Initialize data */
+       entry->channel = channel;
+       entry->service_id = service_id;
+       entry->vchannel = dvb_vchannel(dvb_scan_handler, i);
+       entry->sat_number = parms->sat_number;
+       entry->freq_bpf = parms->freq_bpf;
+       entry->diseqc_wait = parms->diseqc_wait;
+       if (parms->lnb)
+               entry->lnb = strdup(parms->lnb->alias);
+
+       /* Get PIDs for each elementary inside the service ID */
+       get_pmt_descriptors(entry, dvb_scan_handler->program[i].pmt);
+
+       /* Copy data from parms */
+       if (get_detected) {
+               int rc;
+               do {
+                       rc = dvb_fe_get_parms(parms);
+                       if (rc == EAGAIN)
+                               usleep(100000);
+               } while (rc == EAGAIN);
+       }
+       for (j = 0; j < parms->n_props; j++) {
+               entry->props[j].cmd = parms->dvb_prop[j].cmd;
+               entry->props[j].u.data = parms->dvb_prop[j].u.data;
+       }
+       entry->n_props = parms->n_props;
+
+       if (get_nit)
+               handle_std_specific_parms(entry, dvb_scan_handler);
+
+       return 0;
+}
+
 int store_dvb_channel(struct dvb_file **dvb_file,
                      struct dvb_v5_fe_parms *parms,
                      struct dvb_v5_descriptors *dvb_scan_handler,
                      int get_detected, int get_nit)
 {
-       struct dvb_entry *entry;
-       int i, j, has_detected = 1;
+       int rc;
 
        if (!*dvb_file) {
                *dvb_file = calloc(sizeof(*dvb_file), 1);
                if (!*dvb_file) {
-                       perror("Allocating memory for dvb_file");
+                       dvb_perror("Allocating memory for dvb_file");
                        return -1;
                }
        }
 
-       /* Go to the last entry */
-       entry = (*dvb_file)->first_entry;
-       while (entry && entry->next)
-               entry = entry->next;
-
-       for (i = 0; i < dvb_scan_handler->sdt_table.service_table_len; i++) {
-               struct service_table *service_table = &dvb_scan_handler->sdt_table.service_table[i];
-               struct pat_table *pat_table = &dvb_scan_handler->pat_table;
-               struct pid_table *pid_table = NULL;
-
-               if (!entry) {
-                       (*dvb_file)->first_entry = calloc(sizeof(*entry), 1);
-                       entry = (*dvb_file)->first_entry;
-               } else {
-                       entry->next = calloc(sizeof(*entry), 1);
-                       entry = entry->next;
-               }
-               if (!entry) {
-                       fprintf(stderr, "Not enough memory\n");
-                       return -1;
-               }
-               entry->sat_number = -1;
-
-               if (service_table->service_name) {
-                       entry->channel = calloc(strlen(service_table->service_name) + 1, 1);
-                       strcpy(entry->channel, service_table->service_name);
-               } else {
-                       asprintf(&entry->channel, "#%d",
-                                service_table->service_id);
-               }
-               entry->service_id = service_table->service_id;
-
-               entry->vchannel = dvb_vchannel(dvb_scan_handler, i);
-
-               /*entry->pol = parms->pol;*/
-               entry->sat_number = parms->sat_number;
-               entry->freq_bpf = parms->freq_bpf;
-               entry->diseqc_wait = parms->diseqc_wait;
-               if (parms->lnb)
-                       entry->lnb = strdup(parms->lnb->alias);
+       if (!dvb_scan_handler->sdt) {
+               dvb_logerr("no SDT table - can't store channels");
+               return -1;
+       }
+       dvb_sdt_service_foreach(service, dvb_scan_handler->sdt) {
+               char *channel = NULL;
 
-               for (j = 0; j < pat_table->pid_table_len; j++) {
-                       pid_table = &pat_table->pid_table[j];
-                       if (service_table->service_id == pid_table->service_id)
-                               break;
-               }
-               if (j == pat_table->pid_table_len) {
-                       fprintf(stderr, "Service ID %d not found on PMT!\n",
-                             service_table->service_id);
-                       has_detected = 0;
-               } else has_detected = 1;
-
-               /*
-                * Video/audio/other pid's can only be filled if the service
-                * was found.
-                */
-               if (has_detected) {
-                       entry->video_pid = calloc(sizeof(*entry[i].video_pid),
-                                               pid_table->video_pid_len);
-                       for (j = 0; j < pid_table->video_pid_len; j++)
-                               entry->video_pid[j] = pid_table->video_pid[j];
-                       entry->video_pid_len = pid_table->video_pid_len;
-
-                       entry->audio_pid = calloc(sizeof(*entry[i].audio_pid),
-                                               pid_table->audio_pid_len);
-                       for (j = 0; j < pid_table->audio_pid_len; j++)
-                               entry->audio_pid[j] = pid_table->audio_pid[j];
-                       entry->audio_pid_len = pid_table->audio_pid_len;
-
-                       entry->other_el_pid = calloc(sizeof(*entry->other_el_pid),
-                                               pid_table->other_el_pid_len);
-                       memcpy(entry->other_el_pid, pid_table->other_el_pid,
-                       pid_table->other_el_pid_len * sizeof(*entry->other_el_pid));
-                       entry->other_el_pid_len = pid_table->other_el_pid_len;
-                       qsort(entry->other_el_pid, entry->other_el_pid_len,
-                       sizeof(*entry->other_el_pid), sort_other_el_pid);
+               dvb_desc_find(struct dvb_desc_service, desc, service, service_descriptor) {
+                       if (desc->name) {
+                               channel = calloc(strlen(desc->name) + 1, 1);
+                               strcpy(channel, desc->name);
+                       }
+                       dvb_log("Found service %s, provider %s, type %d",
+                               desc->name, desc->provider, desc->service_type);
+                       break;
                }
 
-               /* Copy data from parms */
-               if (get_detected) {
-                       int rc;
-                       do {
-                               rc = dvb_fe_get_parms(parms);
-                               if (rc == EAGAIN)
-                                       usleep(100000);
-                       } while (rc == EAGAIN);
-               }
-               for (j = 0; j < parms->n_props; j++) {
-                       entry->props[j].cmd = parms->dvb_prop[j].cmd;
-                       entry->props[j].u.data = parms->dvb_prop[j].u.data;
-               }
-               entry->n_props = parms->n_props;
+               if (!channel)
+                       asprintf(&channel, "#%d", service->service_id);
 
-               if (get_nit)
-                       handle_std_specific_parms(entry, dvb_scan_handler);
+               rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
+                                          service->service_id,
+                                          channel, get_detected, get_nit);
+               if (rc < 0)
+                       return rc;
        }
 
+
        return 0;
 }
 
index 3d34c3e..99a4596 100644 (file)
@@ -310,7 +310,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
                                           sizeof(*dvb_scan_handler->program));
 
        dvb_pat_program_foreach(program, dvb_scan_handler->pat) {
-               dvb_scan_handler->program->program = program;
+               dvb_scan_handler->program[num_pmt].pat_pgm = program;
 
                if (!program->service_id) {
                        dvb_log("Program ID %d has service ID 0. discarding",
index 1c1adce..dccb907 100644 (file)
@@ -482,19 +482,6 @@ static int run_scan(struct arguments *args,
                if (!dvb_scan_handler)
                        continue;
 
-               for (i = 0; i < dvb_scan_handler->sdt_table.service_table_len; i++) {
-                       struct service_table *service_table = &dvb_scan_handler->sdt_table.service_table[i];
-
-                       entry->vchannel = dvb_vchannel(dvb_scan_handler, i);
-                       printf("Service #%d (%d)", i,
-                               service_table->service_id);
-                       if (service_table->service_name)
-                               printf(" %s", service_table->service_name);
-                       if (entry->vchannel)
-                               printf(" channel %s", entry->vchannel);
-                       printf("\n");
-               }
-
                store_dvb_channel(&dvb_file_new, parms, dvb_scan_handler,
                                  args->get_detected, args->get_nit);