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.

eit_desc.c 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * EIT descriptor generator
  3. * Copyright (C) 2010-2011 Unix Solutions Ltd.
  4. *
  5. * Released under MIT license.
  6. * See LICENSE-MIT.txt for license terms.
  7. */
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <netdb.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "tsfuncs.h"
  14. static void ts_eit_regenerate_packet_data(struct ts_eit *eit) {
  15. uint8_t *ts_packets;
  16. int num_packets;
  17. ts_eit_generate(eit, &ts_packets, &num_packets);
  18. memcpy(eit->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
  19. eit->section_header->num_packets = num_packets;
  20. free(ts_packets);
  21. }
  22. struct ts_eit *ts_eit_init(struct ts_eit *eit, uint16_t service_id, uint16_t transport_stream_id, uint16_t org_network_id, uint8_t table_id, uint8_t sec_number, uint8_t last_sec_number) {
  23. eit->ts_header.pid = 0x12;
  24. eit->ts_header.pusi = 1;
  25. eit->ts_header.payload_field = 1;
  26. eit->ts_header.payload_offset = 4;
  27. eit->section_header->table_id = table_id;
  28. eit->section_header->version_number = 1;
  29. eit->section_header->current_next_indicator = 1;
  30. eit->section_header->section_syntax_indicator = 1;
  31. eit->section_header->private_indicator = 1;
  32. eit->section_header->section_length = 9 + 6; // Empty section, +6 (16+16+8+8 bits) for EIT table data
  33. eit->section_header->ts_id_number = service_id;
  34. eit->section_header->reserved1 = 3;
  35. eit->section_header->reserved2 = 3;
  36. eit->section_header->section_number = sec_number;
  37. eit->section_header->last_section_number = last_sec_number;
  38. eit->transport_stream_id = transport_stream_id; // 16 bits
  39. eit->original_network_id = org_network_id; // 16 bits
  40. eit->segment_last_section_number = 0; // 8 bits
  41. eit->last_table_id = table_id; // 8 bits
  42. eit->streams_num = 0;
  43. eit->initialized = 1;
  44. ts_eit_regenerate_packet_data(eit);
  45. return eit;
  46. }
  47. struct ts_eit *ts_eit_alloc_init(uint16_t service_id, uint16_t transport_stream_id, uint16_t org_network_id, uint8_t table_id, uint8_t sec_number, uint8_t last_sec_number) {
  48. struct ts_eit *eit = ts_eit_alloc();
  49. if (!eit)
  50. return NULL;
  51. return ts_eit_init(eit, service_id, transport_stream_id, org_network_id, table_id, sec_number, last_sec_number);
  52. }
  53. struct ts_eit *ts_eit_alloc_init_pf(uint16_t service_id, uint16_t transport_stream_id, uint16_t org_network_id, uint8_t sec_number, uint8_t last_sec_number) {
  54. return ts_eit_alloc_init(service_id, transport_stream_id, org_network_id, 0x4e, sec_number, last_sec_number);
  55. }
  56. struct ts_eit *ts_eit_alloc_init_schedule(uint16_t service_id, uint16_t transport_stream_id, uint16_t org_network_id, uint8_t sec_number, uint8_t last_sec_number) {
  57. return ts_eit_alloc_init(service_id, transport_stream_id, org_network_id, 0x50, sec_number, last_sec_number);
  58. }
  59. static int ts_eit_add_stream(struct ts_eit *eit, uint16_t event_id, uint8_t running, time_t start_time, int duration_sec, uint8_t *desc, uint16_t desc_size) {
  60. if (eit->streams_num == eit->streams_max - 1 || desc_size == 0) {
  61. FREE(desc);
  62. return 0;
  63. }
  64. uint16_t start_mjd;
  65. uint32_t start_bcd;
  66. uint32_t dur_bcd = ts_time_encode_bcd(duration_sec);
  67. ts_time_encode_mjd(&start_mjd, &start_bcd, &start_time, NULL);
  68. int stream_len = 12 + desc_size;
  69. if (stream_len + eit->section_header->section_length > 4093) {
  70. ts_LOGf("EIT no space left, max 4093, current %d will become %d!\n",
  71. eit->section_header->section_length,
  72. stream_len + eit->section_header->section_length);
  73. free(desc);
  74. return 0;
  75. }
  76. eit->section_header->section_length += stream_len;
  77. struct ts_eit_stream *sinfo = calloc(1, sizeof(struct ts_eit_stream));
  78. sinfo->event_id = event_id; // 2 bytes (16 bits)
  79. sinfo->start_time_mjd = start_mjd; // 5 bytes (40 bits)
  80. sinfo->start_time_bcd = start_bcd; //
  81. sinfo->duration_bcd = dur_bcd; // 3 bytes (24 bits)
  82. sinfo->running_status = running; // 2 bytes (3 bits), 1 == not running, 4 == running
  83. sinfo->free_CA_mode = 0; // (1 bit) , 0 == not scrambled
  84. sinfo->descriptor_size = desc_size; // (12 bits)
  85. sinfo->descriptor_data = desc; // desc_size bytes
  86. eit->streams[eit->streams_num] = sinfo;
  87. eit->streams_num++;
  88. ts_eit_regenerate_packet_data(eit);
  89. return 1;
  90. }
  91. int ts_eit_add_short_event_descriptor(struct ts_eit *eit, uint16_t event_id, uint8_t running, time_t start_time, int duration_sec, char *event_name, char *event_short_descr) {
  92. char *txt;
  93. uint8_t event_len = event_name ? strlen(event_name) : 0;
  94. uint8_t descr_len = event_short_descr ? strlen(event_short_descr) : 0;
  95. int desc_size = 2 + 3; // 2 bytes tag header, 3 bytes ISO lang code
  96. desc_size += 1 + event_len;
  97. desc_size += 1 + descr_len;
  98. if (desc_size > 255) {
  99. ts_LOGf("EIT short event descriptor size > 255 is not supported (%d)!\n", desc_size);
  100. return 0;
  101. }
  102. if (event_len == 0) {
  103. ts_LOGf("EIT event_len == 0!\n");
  104. return 0;
  105. }
  106. uint8_t *desc = calloc(1, desc_size);
  107. int dpos = 0;
  108. desc[dpos + 0] = 0x4d; // Short_event_descriptor
  109. desc[dpos + 1] = desc_size - 2; // -2 Because of two byte header
  110. desc[dpos + 2] = 'b';
  111. desc[dpos + 3] = 'u';
  112. desc[dpos + 4] = 'l';
  113. desc[dpos + 5] = event_len;
  114. dpos += 6;
  115. txt = event_name;
  116. while (txt[0]) {
  117. desc[dpos++] = txt[0];
  118. txt++;
  119. }
  120. desc[dpos++ ] = descr_len;
  121. if (descr_len) {
  122. txt = event_short_descr;
  123. while (txt[0]) {
  124. desc[dpos++] = txt[0];
  125. txt++;
  126. }
  127. }
  128. return ts_eit_add_stream(eit, event_id, running ? 4 : 1, start_time, duration_sec, desc, dpos);
  129. }
  130. int ts_eit_add_extended_event_descriptor(struct ts_eit *eit, uint16_t event_id, uint8_t running, time_t start_time, int duration_sec, char *text) {
  131. if (!text)
  132. return 0;
  133. char *txt;
  134. int desc_size = 2 + 3 + 1 + 1; // 2 bytes tag header
  135. // 3 bytes ISO lang code
  136. // 1 byte, desc_number, last_desc_number (4 bits + 4 bits)
  137. // 1 byte length of items (0 because items are unsupported)
  138. int text_len = strlen(text);
  139. desc_size += 1 + text_len;
  140. if (desc_size > 257) {
  141. ts_LOGf("EIT extended event descriptor size > 255 is not supported (%d)!\n", desc_size);
  142. return 0;
  143. }
  144. if (text_len == 0) {
  145. ts_LOGf("EIT text_len == 0!\n");
  146. return 0;
  147. }
  148. uint8_t *desc = calloc(1, desc_size);
  149. int dpos = 0;
  150. desc[dpos + 0] = 0x4e; // Extended_event_descriptor
  151. desc[dpos + 1] = desc_size - 2; // -2 Because of two byte header
  152. desc[dpos + 2] = (0 << 4) | (0 &~ 0xf0); // descriptor_number, last_descriptor_number;
  153. desc[dpos + 3] = 'b';
  154. desc[dpos + 4] = 'u';
  155. desc[dpos + 5] = 'l';
  156. desc[dpos + 6] = 0; // Length of items (items are not supported)
  157. desc[dpos + 7] = text_len;
  158. dpos += 8;
  159. txt = text;
  160. while (txt[0]) {
  161. desc[dpos++] = txt[0];
  162. txt++;
  163. }
  164. return ts_eit_add_stream(eit, event_id, running ? 4 : 1, start_time, duration_sec, desc, dpos);
  165. }