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.

sdt_desc.c 4.3KB

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