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

secdata.c 5.2KB

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