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

tsfuncs_section_data.c 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <netdb.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include "tsfuncs.h"
  8. uint8_t *ts_section_data_alloc_section() {
  9. uint8_t *data = malloc(4096);
  10. memset(data, 0x30, 4096);
  11. return data;
  12. }
  13. uint8_t *ts_section_data_alloc_packet() {
  14. uint8_t *data = malloc(5120);
  15. memset(data, 0x31, 5120);
  16. return data;
  17. }
  18. struct ts_section_header *ts_section_data_alloc() {
  19. struct ts_section_header *section_data = calloc(1, sizeof(struct ts_section_header));
  20. section_data->section_data = ts_section_data_alloc_section();
  21. section_data->packet_data = ts_section_data_alloc_packet();
  22. return section_data;
  23. }
  24. void ts_section_data_clear(struct ts_section_header *sec) {
  25. if (!sec)
  26. return;
  27. // save
  28. uint8_t *section_data = sec->section_data;
  29. uint8_t *packet_data = sec->packet_data;
  30. // clear
  31. memset(section_data, 0x30, 4096);
  32. memset(packet_data , 0x31, 5120);
  33. memset(sec, 0, sizeof(struct ts_section_header));
  34. // restore
  35. sec->section_data = section_data;
  36. sec->packet_data = packet_data;
  37. }
  38. void ts_section_data_free(struct ts_section_header **psection_data) {
  39. struct ts_section_header *section_data = *psection_data;
  40. if (section_data) {
  41. FREE(section_data->section_data);
  42. FREE(section_data->packet_data);
  43. FREE(*psection_data);
  44. }
  45. }
  46. void ts_section_data_copy(struct ts_section_header *src, struct ts_section_header *dst) {
  47. if (!src || !dst)
  48. return;
  49. uint8_t *section_data = dst->section_data;
  50. uint8_t *packet_data = dst->packet_data;
  51. memcpy(section_data, src->section_data, 4096);
  52. memcpy(packet_data , src->packet_data, 5120);
  53. *dst = *src;
  54. dst->section_data = section_data;
  55. dst->packet_data = packet_data;
  56. ts_section_header_set_private_vars(dst);
  57. }
  58. // Fill CRC of the section data after secdata_size bytes
  59. uint32_t ts_section_data_calculate_crc(uint8_t *section_data, int secdata_size) {
  60. uint32_t check_crc = ts_crc32(section_data, secdata_size);
  61. section_data[secdata_size + 0] = ((check_crc &~ 0x00ffffff) >> 24);
  62. section_data[secdata_size + 1] = ((check_crc &~ 0xff00ffff) >> 16);
  63. section_data[secdata_size + 2] = ((check_crc &~ 0xffff00ff) >> 8);
  64. section_data[secdata_size + 3] = (check_crc &~ 0xffffff00);
  65. return check_crc;
  66. }
  67. #define min(a,b) ((a < b) ? a : b)
  68. // Returns alllocated and build ts packets in *packets "ts_header"
  69. // Returns number of packets in *num_packets
  70. void ts_section_data_gen_ts_packets(struct ts_header *ts_header, uint8_t *section_data, int section_data_sz, uint8_t pointer_field, uint8_t **packets, int *num_packets) {
  71. struct ts_header tshdr = *ts_header;
  72. *packets = ts_section_data_alloc_packet();
  73. int np = 1; // Minimum 1 TS packet
  74. int section_sz = section_data_sz; // Add 4 bytes CRC!
  75. int sect = section_sz - (TS_PACKET_SIZE - 5);
  76. while (sect > 0) {
  77. sect -= TS_PACKET_SIZE - 4;
  78. np++;
  79. }
  80. int i, sect_pos = 0, sect_dataleft = section_sz;
  81. *num_packets = np;
  82. int dataofs;
  83. for (i=0;i<np;i++) {
  84. uint8_t *curpacket = *packets + (i * TS_PACKET_SIZE); // Start of the current packet
  85. dataofs = 4; // Start after the TS header
  86. if (i == 0) { // First packet have pointer field
  87. if (ts_header->adapt_len)
  88. dataofs += ts_header->adapt_len + 1; // +1 for flags
  89. dataofs += pointer_field + 1;
  90. } else { // For the following packets after the first correct flags
  91. tshdr.pusi = 0;
  92. tshdr.continuity++;
  93. }
  94. ts_packet_header_generate(curpacket, &tshdr); // Do the header
  95. if (i == 0) { // Set pointer field in the first packet
  96. if (ts_header->adapt_len) {
  97. curpacket[4] = ts_header->adapt_len;
  98. curpacket[5] = 0; // Adaptation field flags, all off
  99. curpacket[5 + ts_header->adapt_len] = pointer_field;
  100. } else { // No adaptation field, just set pointer field
  101. curpacket[4] = pointer_field;
  102. }
  103. }
  104. uint8_t maxdatasize = TS_PACKET_SIZE - dataofs; // How much data can this packet carry
  105. int copied = min(maxdatasize, sect_dataleft);
  106. memcpy(curpacket + dataofs, section_data + sect_pos, copied); // Fill the data
  107. sect_pos += maxdatasize;
  108. sect_dataleft -= maxdatasize;
  109. if (sect_dataleft < 0)
  110. break;
  111. }
  112. }
  113. void ts_section_add_packet(struct ts_section_header *sec, struct ts_header *ts_header, uint8_t *ts_packet) {
  114. uint8_t payload_offset = ts_header->payload_offset;
  115. if (!sec->section_length)
  116. return;
  117. if (ts_header->pusi) {
  118. payload_offset += sec->pointer_field + 1; // Pointer field
  119. }
  120. int to_copy = TS_PACKET_SIZE - payload_offset;
  121. if (to_copy <= 0)
  122. return;
  123. if (sec->section_pos + to_copy >= 4092) {
  124. to_copy = sec->section_data_len - sec->section_pos;
  125. }
  126. memcpy(sec->section_data + sec->section_pos, ts_packet + payload_offset, to_copy);
  127. memcpy(sec->packet_data + (sec->num_packets * TS_PACKET_SIZE), ts_packet, TS_PACKET_SIZE);
  128. sec->section_pos += to_copy;
  129. sec->num_packets++;
  130. sec->initialized = (sec->section_pos+1) >= sec->section_data_len;
  131. if (sec->initialized) {
  132. // CRC is after sec->data[sec->data_len]
  133. sec->CRC = (sec->CRC << 8) | sec->data[sec->data_len + 3];
  134. sec->CRC = (sec->CRC << 8) | sec->data[sec->data_len + 2];
  135. sec->CRC = (sec->CRC << 8) | sec->data[sec->data_len + 1];
  136. sec->CRC = (sec->CRC << 8) | sec->data[sec->data_len + 0];
  137. }
  138. }