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.2KB

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