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

sdt_desc.c 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. static void ts_sdt_regenerate_packet_data(struct ts_sdt *sdt) {
  8. uint8_t *ts_packets;
  9. int num_packets;
  10. ts_sdt_generate(sdt, &ts_packets, &num_packets);
  11. memcpy(sdt->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
  12. sdt->section_header->num_packets = num_packets;
  13. free(ts_packets);
  14. }
  15. struct ts_sdt *ts_sdt_alloc_init(uint16_t org_network_id, uint16_t transport_stream_id) {
  16. struct ts_sdt *sdt = ts_sdt_alloc();
  17. sdt->ts_header.pid = 0x11;
  18. sdt->ts_header.pusi = 1;
  19. sdt->ts_header.payload_field = 1;
  20. sdt->ts_header.payload_offset = 4;
  21. sdt->section_header->table_id = 0x42;
  22. sdt->section_header->version_number = 1;
  23. sdt->section_header->current_next_indicator = 1;
  24. sdt->section_header->section_syntax_indicator = 1;
  25. sdt->section_header->private_indicator = 1;
  26. sdt->section_header->section_length = 9 + 3; // Empty section (9) + 3 (16+8) for SDT table data
  27. sdt->section_header->ts_id_number = transport_stream_id;
  28. sdt->section_header->reserved1 = 3;
  29. sdt->section_header->reserved2 = 3;
  30. sdt->original_network_id = org_network_id; // 16 bits
  31. sdt->reserved = 0xff; // 8 bits
  32. sdt->initialized = 1;
  33. ts_sdt_regenerate_packet_data(sdt);
  34. return sdt;
  35. }
  36. static int ts_sdt_add_stream(struct ts_sdt *sdt, uint16_t service_id, uint8_t *desc, uint8_t desc_size) {
  37. if (sdt->streams_num == sdt->streams_max - 1 || desc_size == 0) {
  38. FREE(desc);
  39. return 0;
  40. }
  41. int stream_len = 2 + 1 + 2 + desc_size;
  42. if (stream_len + sdt->section_header->section_length > 4093) {
  43. ts_LOGf("SDT no space left, max 4093, current %d will become %d!\n",
  44. sdt->section_header->section_length,
  45. stream_len + sdt->section_header->section_length);
  46. free(desc);
  47. return 0;
  48. }
  49. sdt->section_header->section_length += stream_len;
  50. struct ts_sdt_stream *sinfo = calloc(1, sizeof(struct ts_sdt_stream));
  51. sinfo->service_id = service_id; // 16 bits (2 bytes)
  52. sinfo->reserved1 = 63; // 6 bits are up
  53. sinfo->EIT_schedule_flag = 0; // 1 bit
  54. sinfo->EIT_present_following_flag = 1; // 1 bit (1 byte) We have EIT
  55. sinfo->running_status = 4; // 3 bits
  56. sinfo->free_CA_mode = 1; // 1 bit
  57. sinfo->descriptor_size = desc_size; // 12 bits (2 bytes)
  58. sinfo->descriptor_data = desc; // desc_size bytes
  59. sdt->streams[sdt->streams_num] = sinfo;
  60. sdt->streams_num++;
  61. ts_sdt_regenerate_packet_data(sdt);
  62. return 1;
  63. }
  64. int ts_sdt_add_service_descriptor(struct ts_sdt *sdt, uint16_t service_id, uint8_t video, char *provider_name, char *service_name) {
  65. char *name;
  66. if (!service_name && !provider_name)
  67. return 0;
  68. int desc_size = 2 + 1; // 2 tag, size; 1 service_type
  69. desc_size += 1 + (provider_name ? strlen(provider_name) : 0);
  70. desc_size += 1 + (service_name ? strlen(service_name) : 0);
  71. if (desc_size > 257) {
  72. ts_LOGf("SDT service_descriptor size > 255 is not supported (%d)!\n", desc_size);
  73. return 0;
  74. }
  75. int dpos = 0;
  76. uint8_t *desc = calloc(1, desc_size);
  77. desc[dpos + 0] = 0x48; // Service descriptor
  78. desc[dpos + 1] = desc_size - 2; // -2 Because of two byte header
  79. desc[dpos + 2] = video ? 0x01 : 0x02; // DVB Table 75: Service type coding: 0x01 - digital tv, 0x02 - digital radio
  80. desc[dpos + 3] = (provider_name ? strlen(provider_name) : 0);
  81. dpos += 4;
  82. if (!provider_name || strlen(provider_name) == 0) {
  83. dpos++;
  84. } else {
  85. name = provider_name;
  86. while (name[0]) {
  87. desc[dpos++] = name[0];
  88. name++;
  89. }
  90. }
  91. if (!service_name || strlen(service_name) == 0) {
  92. dpos++;
  93. } else {
  94. desc[dpos++] = (service_name ? strlen(service_name) : 0);
  95. name = service_name;
  96. while (name[0]) {
  97. desc[dpos++] = name[0];
  98. name++;
  99. }
  100. }
  101. return ts_sdt_add_stream(sdt, service_id, desc, desc_size);
  102. }