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.

tsfuncs_section_data.c 4.7KB

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