libtsfuncs is a library for mpeg PSI parsing and generation. https://georgi.unixsol.org/programs/libtsfuncs/

tsfuncs_cat.c 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <netdb.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "tsfuncs.h"
  7. struct ts_cat *ts_cat_alloc() {
  8. struct ts_cat *cat = calloc(1, sizeof(struct ts_cat));
  9. cat->section_header = ts_section_data_alloc();
  10. return cat;
  11. }
  12. void ts_cat_free(struct ts_cat **pcat) {
  13. struct ts_cat *cat = *pcat;
  14. if (cat) {
  15. ts_section_data_free(&cat->section_header);
  16. FREE(cat->program_info);
  17. FREE(*pcat);
  18. }
  19. }
  20. static struct ts_cat *ts_cat_reset(struct ts_cat *cat) {
  21. struct ts_cat *newcat = ts_cat_alloc();
  22. ts_cat_free(&cat);
  23. return newcat;
  24. }
  25. struct ts_cat *ts_cat_push_packet(struct ts_cat *cat, uint8_t *ts_packet) {
  26. struct ts_header ts_header;
  27. memset(&ts_header, 0, sizeof(struct ts_header));
  28. if (ts_packet_header_parse(ts_packet, &ts_header)) {
  29. if (!cat->ts_header.pusi)
  30. cat->ts_header = ts_header;
  31. }
  32. if (ts_header.pusi) {
  33. struct ts_section_header section_header;
  34. memset(&section_header, 0, sizeof(struct ts_section_header));
  35. uint8_t *section_data = ts_section_header_parse(ts_packet, &cat->ts_header, &section_header);
  36. if (!section_data || !section_header.section_syntax_indicator) {
  37. memset(&cat->ts_header, 0, sizeof(struct ts_header));
  38. goto OUT;
  39. }
  40. // table_id should be 0x01 (ca_map_section)
  41. if (section_header.table_id != 0x01) {
  42. memset(&cat->ts_header, 0, sizeof(struct ts_header));
  43. goto OUT;
  44. }
  45. // Set correct section_header
  46. ts_section_header_parse(ts_packet, &cat->ts_header, cat->section_header);
  47. }
  48. if (!cat->initialized) {
  49. if (cat->section_header->section_syntax_indicator) {
  50. ts_section_add_packet(cat->section_header, &ts_header, ts_packet);
  51. if (cat->section_header->initialized) {
  52. if (!ts_cat_parse(cat))
  53. goto ERROR;
  54. }
  55. }
  56. }
  57. OUT:
  58. return cat;
  59. ERROR:
  60. return ts_cat_reset(cat);
  61. }
  62. int ts_cat_parse(struct ts_cat *cat) {
  63. uint8_t *section_data = cat->section_header->section_data + 8; // + 8 to compensate for section table header
  64. int section_len = cat->section_header->packet_section_len;
  65. /* Handle streams */
  66. uint8_t *stream_data = section_data;
  67. cat->program_info_size = section_len;
  68. cat->program_info = malloc(cat->program_info_size);
  69. memcpy(cat->program_info, stream_data, cat->program_info_size);
  70. // ts_print_bytes("DEBUG", cat->program_info, cat->program_info_size);
  71. stream_data += cat->program_info_size;
  72. cat->CRC = (cat->CRC << 8) | stream_data[3];
  73. cat->CRC = (cat->CRC << 8) | stream_data[2];
  74. cat->CRC = (cat->CRC << 8) | stream_data[1];
  75. cat->CRC = (cat->CRC << 8) | stream_data[0];
  76. u_int32_t check_crc = ts_crc32(cat->section_header->section_data, cat->section_header->data_size);
  77. if (check_crc != 0) {
  78. ts_LOGf("!!! Wrong cat CRC! It should be 0 but it is %08x (CRC in data is 0x%08x)\n", check_crc, cat->CRC);
  79. return 0;
  80. }
  81. cat->initialized = 1;
  82. return 1;
  83. }
  84. void ts_cat_generate(struct ts_cat *cat, uint8_t **ts_packets, int *num_packets) {
  85. uint8_t *secdata = ts_section_data_alloc_section();
  86. ts_section_header_generate(secdata, cat->section_header, 0);
  87. int curpos = 8; // Compensate for the section header, frist data byte is at offset 8
  88. memcpy(secdata + curpos, cat->program_info, cat->program_info_size);
  89. curpos += cat->program_info_size;
  90. cat->CRC = ts_section_data_calculate_crc(secdata, curpos);
  91. curpos += 4; // CRC
  92. ts_section_data_gen_ts_packets(&cat->ts_header, secdata, curpos, cat->section_header->pointer_field, ts_packets, num_packets);
  93. FREE(secdata);
  94. }
  95. void ts_cat_regenerate_packets(struct ts_cat *cat) {
  96. uint8_t *ts_packets;
  97. int num_packets;
  98. ts_cat_generate(cat, &ts_packets, &num_packets);
  99. FREE(cat->section_header->packet_data);
  100. cat->section_header->packet_data = ts_packets;
  101. cat->section_header->num_packets = num_packets;
  102. }
  103. struct ts_cat *ts_cat_copy(struct ts_cat *cat) {
  104. struct ts_cat *newcat = ts_cat_alloc();
  105. int i;
  106. for (i=0;i<cat->section_header->num_packets; i++) {
  107. newcat = ts_cat_push_packet(newcat, cat->section_header->packet_data + (i * TS_PACKET_SIZE));
  108. }
  109. if (newcat->initialized) {
  110. return newcat;
  111. } else {
  112. ts_LOGf("Error copying cat!\n");
  113. ts_cat_free(&newcat);
  114. return NULL;
  115. }
  116. }
  117. void ts_cat_check_generator(struct ts_cat *cat) {
  118. struct ts_cat *cat1 = ts_cat_copy(cat);
  119. if (cat1) {
  120. ts_compare_data("CAT (tspacket->struct)",
  121. cat1->section_header->packet_data,
  122. cat->section_header->packet_data,
  123. cat->section_header->num_packets * TS_PACKET_SIZE);
  124. ts_cat_free(&cat1);
  125. }
  126. uint8_t *ts_packets;
  127. int num_packets;
  128. ts_cat_generate(cat, &ts_packets, &num_packets);
  129. if (num_packets != cat->section_header->num_packets) {
  130. ts_LOGf("ERROR: num_packets:%d != sec->num_packets:%d\n", num_packets, cat->section_header->num_packets);
  131. }
  132. ts_compare_data("CAT (struct->tspacket)", cat->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
  133. free(ts_packets);
  134. }
  135. void ts_cat_dump(struct ts_cat *cat) {
  136. int i;
  137. ts_LOGf("CAT table\n");
  138. for(i=0;i<cat->section_header->num_packets;i++) {
  139. struct ts_header tshdr;
  140. ts_packet_header_parse(cat->section_header->packet_data + (i * TS_PACKET_SIZE), &tshdr);
  141. ts_packet_header_dump(&tshdr);
  142. }
  143. ts_section_header_dump(cat->section_header);
  144. if (cat->program_info_size > 0) {
  145. ts_LOGf(" * Descriptor dump:\n");
  146. ts_descriptor_dump(cat->program_info, cat->program_info_size);
  147. }
  148. ts_LOGf(" * CRC 0x%04x\n", cat->CRC);
  149. ts_cat_check_generator(cat);
  150. }
  151. int ts_cat_is_same(struct ts_cat *cat1, struct ts_cat *cat2) {
  152. if (cat1->CRC == cat2->CRC) // Same
  153. return 1;
  154. // If some version is not current, just claim the structures are the same
  155. if (!cat1->section_header->current_next_indicator || cat2->section_header->version_number)
  156. return 1;
  157. if (cat1->section_header->version_number != cat2->section_header->version_number) // Different
  158. return 0;
  159. return 1; // Same
  160. }
  161. enum CA_system ts_get_CA_sys(uint16_t CA_id) {
  162. if (CA_id >= 0x0600 && CA_id <= 0x06FF) return CA_IRDETO;
  163. if (CA_id >= 0x0B00 && CA_id <= 0x0BFF) return CA_CONNAX;
  164. if (CA_id >= 0x0D00 && CA_id <= 0x0DFF) return CA_CRYPTOWORKS;
  165. return CA_UNKNOWN;
  166. }
  167. char * ts_get_CA_sys_txt(enum CA_system CA_sys) {
  168. switch (CA_sys) {
  169. case CA_IRDETO: return "IRDETO CA";
  170. case CA_CONNAX: return "CONNAX CA";
  171. case CA_CRYPTOWORKS: return "CRYPTOWORKS CA";
  172. case CA_UNKNOWN:
  173. default: return "UNKNOWN CA";
  174. }
  175. }