libtsfuncs is a library for mpeg PSI parsing and generation. https://georgi.unixsol.org/programs/libtsfuncs/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tsfuncs_sections.c 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <netdb.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include "tsfuncs.h"
  8. uint8_t *ts_section_header_parse(uint8_t *ts_packet, struct ts_header *ts_header, struct ts_section_header *ts_section_header) {
  9. if (ts_header->payload_offset + 8 > TS_PACKET_SIZE) {
  10. ts_packet_header_dump(ts_header);
  11. ts_LOGf("!!! Section start outside of TS packet %d!\n", ts_header->payload_offset + 8);
  12. return NULL;
  13. }
  14. uint8_t *data = ts_packet + ts_header->payload_offset;
  15. ts_section_header->pointer_field = data[0];
  16. data += ts_section_header->pointer_field + 1;
  17. ts_section_header->table_id = data[0];
  18. ts_section_header->section_syntax_indicator = data[1] >> 7; // x1111111
  19. ts_section_header->private_indicator = (data[1] &~ 0xBF) >> 6; // 1x111111
  20. ts_section_header->reserved1 = (data[1] &~ 0xCF) >> 4; // 11xx1111
  21. ts_section_header->section_length = ((data[1] &~ 0xF0) << 8) | data[2]; // 1111xxxx xxxxxxxx
  22. if (ts_section_header->section_length == 0)
  23. return NULL;
  24. // Stuffing table, ignore.
  25. if (ts_section_header->table_id == 0x72)
  26. return NULL;
  27. ts_section_header->ts_id_number = (data[3] << 8) | data[4]; // xxxxxxx xxxxxxx
  28. ts_section_header->reserved2 = data[5] >> 6; // xx111111
  29. ts_section_header->version_number = (data[5] &~ 0xC1) >> 1; // 11xxxxx1
  30. ts_section_header->current_next_indicator = data[5] &~ 0xFE; // 1111111x
  31. ts_section_header->section_number = data[6];
  32. ts_section_header->last_section_number = data[7];
  33. if (!ts_section_header->section_syntax_indicator) {
  34. ts_LOGf("!!! Table 0x%02x have no section_syntax_indicator set!\n",
  35. ts_section_header->table_id);
  36. ts_packet_header_dump(ts_header);
  37. ts_section_header_dump(ts_section_header);
  38. return NULL;
  39. }
  40. ts_section_header->data_size = ts_section_header->section_length + 3;
  41. ts_section_header->packet_section_len = ts_section_header->data_size - 8 - 4; // -8 for the section header, -4 for the CRC at the end
  42. return data + 8;
  43. }
  44. void ts_section_header_generate(uint8_t *ts_packet, struct ts_section_header *ts_section_header, uint8_t start) {
  45. ts_packet[start + 0] = ts_section_header->table_id;
  46. ts_packet[start + 1] = ts_section_header->section_syntax_indicator << 7; // x1111111
  47. ts_packet[start + 1] |= ts_section_header->private_indicator << 6; // 1x111111
  48. ts_packet[start + 1] |= ts_section_header->reserved1 << 4; // 11xx1111
  49. ts_packet[start + 1] |= ts_section_header->section_length >> 8; // 1111xxxx xxxxxxxx
  50. ts_packet[start + 2] = ts_section_header->section_length &~ 0xff00; // 1111xxxx xxxxxxxx
  51. ts_packet[start + 3] = ts_section_header->ts_id_number >> 8; // xxxxxxxx xxxxxxxx
  52. ts_packet[start + 4] = ts_section_header->ts_id_number &~ 0xff00;
  53. ts_packet[start + 5] = ts_section_header->reserved2 << 6; // xx111111
  54. ts_packet[start + 5] |= ts_section_header->version_number << 1; // 11xxxxx1
  55. ts_packet[start + 5] |= ts_section_header->current_next_indicator; // 1111111x
  56. ts_packet[start + 6] = ts_section_header->section_number;
  57. ts_packet[start + 7] = ts_section_header->last_section_number;
  58. }
  59. #define IN(x, a, b) \
  60. (x >= a && x <= b)
  61. void ts_section_header_dump(struct ts_section_header *t) {
  62. ts_LOGf("%s", " * Section header\n");
  63. if (t->pointer_field)
  64. ts_LOGf(" - Pointer field : %d\n", t->pointer_field);
  65. ts_LOGf(" - Table id : %03x (%d) %s\n", t->table_id, t->table_id,
  66. t->table_id == 0x00 ? "program_association_section" :
  67. t->table_id == 0x01 ? "conditional_access_section" :
  68. t->table_id == 0x02 ? "program_map_section" :
  69. t->table_id == 0x03 ? "transport_stream_description_section" :
  70. IN(t->table_id, 0x04, 0x3f) ? "reserved" :
  71. t->table_id == 0x40 ? "network_information_section - actual_network" :
  72. t->table_id == 0x41 ? "network_information_section - other_network" :
  73. t->table_id == 0x42 ? "service_description_section - actual_transport_stream" :
  74. IN(t->table_id, 0x43, 0x45) ? "reserved for future use" :
  75. t->table_id == 0x46 ? "service_description_section - other_transport_stream" :
  76. IN(t->table_id, 0x47, 0x49) ? "reserved for future use" :
  77. t->table_id == 0x4a ? "bouquet_association_section" :
  78. IN(t->table_id, 0x4b, 0x4d) ? "reserved for future use" :
  79. t->table_id == 0x4e ? "event_information_section - actual_transport_stream, present/following" :
  80. t->table_id == 0x4f ? "event_information_section - other_transport_stream, present/following" :
  81. IN(t->table_id, 0x50, 0x5f) ? "event_information_section - actual_transport_stream, schedule" :
  82. IN(t->table_id, 0x60, 0x6f) ? "event_information_section - other_transport_stream, schedule" :
  83. t->table_id == 0x70 ? "time_date_section" :
  84. t->table_id == 0x71 ? "running_status_section" :
  85. t->table_id == 0x72 ? "stuffing_section" :
  86. t->table_id == 0x73 ? "time_offset_section" :
  87. t->table_id == 0x74 ? "application information section (TS 102 812 [15])" :
  88. t->table_id == 0x75 ? "container section (TS 102 323 [13])" :
  89. t->table_id == 0x76 ? "related content section (TS 102 323 [13])" :
  90. t->table_id == 0x77 ? "content identifier section (TS 102 323 [13])" :
  91. t->table_id == 0x78 ? "MPE-FEC section (EN 301 192 [4])" :
  92. t->table_id == 0x79 ? "resolution notification section (TS 102 323 [13])" :
  93. IN(t->table_id, 0x79, 0x7d) ? "reserved for future use" :
  94. t->table_id == 0x7e ? "discontinuity_information_section" :
  95. t->table_id == 0x7f ? "section_information_section" :
  96. IN(t->table_id, 0x80, 0xfe) ? "user defined" :
  97. t->table_id == 0xff ? "reserved" : "Impossible!"
  98. );
  99. ts_LOGf(" - Section length : %03x (%d)\n", t->section_length, t->section_length);
  100. ts_LOGf(" - TS ID / Program No : %04x (%d)\n", t->ts_id_number, t->ts_id_number);
  101. ts_LOGf(" - Version number %d, current next %d, section number %d, last section number %d\n",
  102. t->version_number,
  103. t->current_next_indicator,
  104. t->section_number,
  105. t->last_section_number);
  106. ts_LOGf(" - Private vars : data_size:%d packet_section_len:%d num_packets:%d section_pos:%d\n",
  107. t->data_size,
  108. t->packet_section_len,
  109. t->num_packets,
  110. t->section_pos);
  111. }
  112. #undef IN