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

eit_desc.c 6.4KB

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