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

sdt_desc.c 4.0KB

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