/***************************************************************************** * handle_sdt *****************************************************************************/ static void handle_sdt(void) { if (psi_table_validate(pp_current_sdt_sections) && psi_table_compare(pp_current_sdt_sections, pp_next_sdt_sections)) { /* Identical SDT. Shortcut. */ psi_table_free(pp_next_sdt_sections); psi_table_init(pp_next_sdt_sections); return; } if (!sdt_table_validate(pp_next_sdt_sections)) { printf("<ERROR type=\"invalid_sdt\"/>\n"); psi_table_free(pp_next_sdt_sections); psi_table_init(pp_next_sdt_sections); return; } /* Switch tables. */ psi_table_free(pp_current_sdt_sections); psi_table_copy(pp_current_sdt_sections, pp_next_sdt_sections); psi_table_init(pp_next_sdt_sections); if (pb_print_table[TABLE_SDT]) sdt_table_print(pp_current_sdt_sections, print_wrapper, NULL, iconv_wrapper, NULL, i_print_type); }
/***************************************************************************** * handle_pmt *****************************************************************************/ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) { uint16_t i_sid = pmt_get_program(p_pmt); sid_t *p_sid; int i; /* we do this before checking the service ID */ if (!pmt_validate(p_pmt)) { printf("<ERROR type=\"invalid_pmt_section\" pid=\"%hu\"/>\n", i_pid); free(p_pmt); return; } for (i = 0; i < i_nb_sids; i++) if (pp_sids[i]->i_sid && pp_sids[i]->i_sid == i_sid) break; if (i == i_nb_sids) { printf("<ERROR type=\"ghost_pmt\" program=\"%hu\" pid=\"%hu\"/>\n", i_sid, i_pid); p_sid = malloc(sizeof(sid_t)); pp_sids = realloc(pp_sids, ++i_nb_sids * sizeof(sid_t *)); pp_sids[i] = p_sid; p_sid->i_sid = i_sid; p_sid->i_pmt_pid = i_pid; p_sid->p_current_pmt = NULL; psi_table_init(p_sid->pp_eit_sections); } else { p_sid = pp_sids[i]; if (i_pid != p_sid->i_pmt_pid) { printf("<ERROR type=\"ghost_pmt\" program=\"%hu\" pid=\"%hu\"/>\n", i_sid, i_pid); } } if (p_sid->p_current_pmt != NULL && psi_compare(p_sid->p_current_pmt, p_pmt)) { /* Identical PMT. Shortcut. */ free(p_pmt); return; } free(p_sid->p_current_pmt); p_sid->p_current_pmt = p_pmt; if (pb_print_table[TABLE_PMT]) pmt_print(p_pmt, print_wrapper, NULL, iconv_wrapper, NULL, i_print_type); got_pmt = 1; }
void sdt_pid_init(struct epgdump_s *epgd) { epgd->sdt.complete = 0; psi_table_init(epgd->sdt.sdt_current); demux_add_psi_pid(&epgd->demux, SDT_PID, sdt_pid_parse, epgd); }
int mediainfo (char *uri) { int i; struct sockaddr_in si_other; struct ip_mreq group; int s, slen = sizeof (si_other); char *server; int port; time_t start_time; if (strncmp (uri, "udp://", 6) != 0) { exit (1); } server = uri + 6; for (i = 6; i < strlen (uri); i++) { if (*(uri + i) == ':') { *(uri + i) = '\0'; } port = atoi (uri + i + 1); } if (i == strlen (uri)) { exit (1); } setvbuf(stdout, NULL, _IOLBF, 0); memset(p_pids, 0, sizeof(p_pids)); if ((s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { exit (1); } if (is_multicast (uri) == 1) { int reuse = 1; if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0){ perror("Setting SO_REUSEADDR error"); close(s); exit(1); } } memset ((char *)&si_other, 0, sizeof (si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons (port); if (is_multicast (uri) == 1) { si_other.sin_addr.s_addr = INADDR_ANY; } else { if (inet_aton (server, &si_other.sin_addr) == 0) { exit (1); } } if (bind (s, (struct sockaddr *)&si_other, sizeof (si_other)) == -1) { exit (1); } if (is_multicast (uri) == 1) { group.imr_multiaddr.s_addr = inet_addr(server); //group.imr_interface.s_addr = inet_addr("172.16.0.10"); if(setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0){ perror("Adding multicast group error"); close(s); exit(1); } } for (i = 0; i < 8192; i++) { p_pids[i].i_last_cc = -1; psi_assemble_init(&p_pids[i].p_psi_buffer, &p_pids[i].i_psi_buffer_used); } p_pids[PAT_PID].i_psi_refcount++; p_pids[TSDT_PID].i_psi_refcount++; p_pids[NIT_PID].i_psi_refcount++; p_pids[SDT_PID].i_psi_refcount++; psi_table_init(pp_current_pat_sections); psi_table_init(pp_next_pat_sections); psi_table_init(pp_current_tsdt_sections); psi_table_init(pp_next_tsdt_sections); psi_table_init(pp_current_nit_sections); psi_table_init(pp_next_nit_sections); psi_table_init(pp_current_sdt_sections); psi_table_init(pp_next_sdt_sections); for (i = 0; i < TABLE_END; i++) pb_print_table[i] = true; printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); printf("<TS>\n"); start_time = time (NULL); while (got_pmt == 0) { uint8_t p_ts[TS_SIZE*10]; uint8_t *p; size_t i_ret = recvfrom (s, p_ts, sizeof (p_ts), MSG_CMSG_CLOEXEC | MSG_DONTWAIT, (struct sockaddr *)&si_other, &slen); if (i_ret == -1) { usleep (10000); } p = p_ts; while (p < p_ts + i_ret) { if (!ts_validate(p)) { printf("<ERROR type=\"invalid_ts\"/>\n"); } else { uint16_t i_pid = ts_get_pid(p); ts_pid_t *p_pid = &p_pids[i_pid]; if (p_pid->i_psi_refcount) handle_psi_packet(p); p_pid->i_last_cc = ts_get_cc(p); } p = p + TS_SIZE; } if (difftime (time (NULL), start_time) > 60) { printf ("Timeout\n"); break; } } printf("</TS>\n"); if (iconv_handle != (iconv_t)-1) iconv_close(iconv_handle); psi_table_free(pp_current_pat_sections); psi_table_free(pp_next_pat_sections); psi_table_free(pp_current_tsdt_sections); psi_table_free(pp_next_tsdt_sections); psi_table_free(pp_current_nit_sections); psi_table_free(pp_next_nit_sections); psi_table_free(pp_current_sdt_sections); psi_table_free(pp_next_sdt_sections); for (i = 0; i < i_nb_sids; i++) { psi_table_free(pp_sids[i]->pp_eit_sections); free(pp_sids[i]->p_current_pmt); free(pp_sids[i]); } free(pp_sids); for (i = 0; i < 8192; i++) psi_assemble_reset(&p_pids[i].p_psi_buffer, &p_pids[i].i_psi_buffer_used); close (s); return EXIT_SUCCESS; }
/***************************************************************************** * handle_pat *****************************************************************************/ static void handle_pat(void) { PSI_TABLE_DECLARE(pp_old_pat_sections); uint8_t i_last_section = psi_table_get_lastsection(pp_next_pat_sections); uint8_t i; if (psi_table_validate(pp_current_pat_sections) && psi_table_compare(pp_current_pat_sections, pp_next_pat_sections)) { /* Identical PAT. Shortcut. */ psi_table_free(pp_next_pat_sections); psi_table_init(pp_next_pat_sections); return; } if (!pat_table_validate(pp_next_pat_sections)) { printf("<ERROR type=\"invalid_pat\"/>\n"); psi_table_free(pp_next_pat_sections); psi_table_init(pp_next_pat_sections); return; } /* Switch tables. */ psi_table_copy(pp_old_pat_sections, pp_current_pat_sections); psi_table_copy(pp_current_pat_sections, pp_next_pat_sections); psi_table_init(pp_next_pat_sections); for (i = 0; i <= i_last_section; i++) { uint8_t *p_section = psi_table_get_section(pp_current_pat_sections, i); const uint8_t *p_program; int j = 0; while ((p_program = pat_get_program(p_section, j)) != NULL) { const uint8_t *p_old_program = NULL; uint16_t i_sid = patn_get_program(p_program); uint16_t i_pid = patn_get_pid(p_program); j++; if (i_sid == 0) { if (i_pid != NIT_PID) fprintf(stderr, "NIT is carried on PID %hu which isn't DVB compliant\n", i_pid); continue; /* NIT */ } if (!psi_table_validate(pp_old_pat_sections) || (p_old_program = pat_table_find_program(pp_old_pat_sections, i_sid)) == NULL || patn_get_pid(p_old_program) != i_pid) { sid_t *p_sid; int i_pmt; if (p_old_program != NULL) p_pids[patn_get_pid(p_old_program)].i_psi_refcount--; p_pids[i_pid].i_psi_refcount++; for (i_pmt = 0; i_pmt < i_nb_sids; i_pmt++) if (pp_sids[i_pmt]->i_sid == i_sid || pp_sids[i_pmt]->i_sid == 0) break; if (i_pmt == i_nb_sids) { p_sid = malloc(sizeof(sid_t)); pp_sids = realloc(pp_sids, ++i_nb_sids * sizeof(sid_t *)); pp_sids[i_pmt] = p_sid; p_sid->p_current_pmt = NULL; psi_table_init(p_sid->pp_eit_sections); } else p_sid = pp_sids[i_pmt]; p_sid->i_sid = i_sid; p_sid->i_pmt_pid = i_pid; } } } if (psi_table_validate(pp_old_pat_sections)) { i_last_section = psi_table_get_lastsection( pp_old_pat_sections ); for (i = 0; i <= i_last_section; i++) { uint8_t *p_section = psi_table_get_section(pp_old_pat_sections, i); const uint8_t *p_program; int j = 0; while ((p_program = pat_get_program(p_section, j)) != NULL) { uint16_t i_sid = patn_get_program(p_program); j++; if (i_sid == 0) continue; /* NIT */ if (pat_table_find_program(pp_current_pat_sections, i_sid) == NULL) { int i_pmt; for (i_pmt = 0; i_pmt < i_nb_sids; i_pmt++) if (pp_sids[i_pmt]->i_sid == i_sid) { pp_sids[i_pmt]->i_sid = 0; free(pp_sids[i_pmt]->p_current_pmt); pp_sids[i_pmt]->p_current_pmt = NULL; psi_table_free(pp_sids[i]->pp_eit_sections); psi_table_init(pp_sids[i]->pp_eit_sections); break; } } } } psi_table_free(pp_old_pat_sections); } if (pb_print_table[TABLE_PAT]) pat_table_print(pp_current_pat_sections, print_wrapper, NULL, i_print_type); }