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.

pes_data.c 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "tsdata.h"
  4. #include "tsfuncs.h"
  5. #define START_ENTRIES 1
  6. #define ENTRIES_INCREMENT 1
  7. static struct pes_entry *pes_entry_alloc(uint16_t pid) {
  8. //ts_LOGf("Alloc pes_entry pid = %03x\n", pid);
  9. struct pes_entry *e = malloc(sizeof(struct pes_entry));
  10. e->pid = pid;
  11. e->pes = ts_pes_alloc();
  12. e->pes_next = NULL;
  13. return e;
  14. }
  15. static void pes_entry_free(struct pes_entry **pentry) {
  16. struct pes_entry *entry = *pentry;
  17. if (entry) {
  18. ts_pes_free(&entry->pes);
  19. ts_pes_free(&entry->pes_next);
  20. FREE(*pentry);
  21. }
  22. }
  23. static struct pes_entry *pes_entry_find(struct pes_array *pa, uint16_t pid) {
  24. int i;
  25. for (i=0;i<pa->max;i++) {
  26. struct pes_entry *e = pa->entries[i];
  27. if (e && e->pid == pid) {
  28. return e;
  29. }
  30. }
  31. return NULL;
  32. }
  33. struct pes_array *pes_array_alloc() {
  34. struct pes_array *pa = calloc(1, sizeof(struct pes_array));
  35. pa->max = START_ENTRIES;
  36. pa->entries = calloc(sizeof(struct pes_entry *), pa->max);
  37. return pa;
  38. }
  39. struct pes_array *pes_array_realloc(struct pes_array *pa) {
  40. pa->max += ENTRIES_INCREMENT;
  41. pa->entries = realloc(pa->entries, sizeof(struct pes_entry *) * pa->max);
  42. memset(&pa->entries[pa->cur], 0, sizeof(struct pes_entry *) * ((pa->max-1) - pa->cur));
  43. return pa;
  44. }
  45. void pes_array_dump(struct pes_array *pa) {
  46. int i;
  47. ts_LOGf("pa->max=%d\n", pa->max);
  48. ts_LOGf("pa->cur=%d\n", pa->cur);
  49. for (i=0;i<pa->max;i++) {
  50. ts_LOGf("pa->entry[%d]=0x%p\n", i, pa->entries[i]);
  51. if (pa->entries[i]) {
  52. ts_LOGf("pa->entry[%d]->pid=%03x\n", i, pa->entries[i]->pid);
  53. ts_LOGf("pa->entry[%d]->pes=%p\n", i, pa->entries[i]->pes);
  54. ts_pes_dump(pa->entries[i]->pes);
  55. }
  56. }
  57. }
  58. void pes_array_free(struct pes_array **ppa) {
  59. int i;
  60. struct pes_array *pa = *ppa;
  61. if (pa) {
  62. for (i=0;i<pa->max;i++) {
  63. pes_entry_free(&pa->entries[i]);
  64. }
  65. free(pa->entries);
  66. FREE(*ppa);
  67. }
  68. }
  69. struct pes_entry *pes_array_push_packet(struct pes_array *pa, uint16_t pid, struct ts_pat *pat, struct ts_pmt *pmt, uint8_t *ts_packet) {
  70. int i;
  71. if (ts_is_psi_pid(pid, pat))
  72. return NULL;
  73. struct pes_entry *p = pes_entry_find(pa, pid); // Find existing entry
  74. if (!p) { // New entry!
  75. int pes_carrying_pid = 0; // check if PID is mentioned in PMT
  76. for (i=0;i<pmt->streams_num;i++) {
  77. struct ts_pmt_stream *stream = pmt->streams[i];
  78. // Stream_type 0x80..0xff - user private
  79. // Stream_type 0x05 - private sections
  80. if (stream->pid == pid) {
  81. switch (stream->stream_type) {
  82. case 0x01: // return "11172-2 video (MPEG-1)";
  83. case 0x02: // return "H.262/13818-2 video (MPEG-2) or 11172-2 constrained video";
  84. case 0x03: // return "11172-3 audio (MPEG-1)";
  85. case 0x04: // return "13818-3 audio (MPEG-2)";
  86. case 0x06: // return "H.222.0/13818-1 PES private data";
  87. case 0x07: // return "13522 MHEG";
  88. case 0x08: // return "H.222.0/13818-1 Annex A - DSM CC";
  89. case 0x09: // return "H.222.1";
  90. case 0x0A: // return "13818-6 type A";
  91. case 0x0B: // return "13818-6 type B";
  92. case 0x0C: // return "13818-6 type C";
  93. case 0x0D: // return "13818-6 type D";
  94. case 0x0E: // return "H.222.0/13818-1 auxiliary";
  95. case 0x0F: // return "13818-7 Audio with ADTS transport syntax";
  96. case 0x10: // return "14496-2 Visual (MPEG-4 part 2 video)";
  97. case 0x11: // return "14496-3 Audio with LATM transport syntax (14496-3/AMD 1)";
  98. case 0x15: // return "Metadata in PES packets";
  99. case 0x1B: // return "H.264/14496-10 video (MPEG-4/AVC)";
  100. case 0x42: // return "AVS Video";
  101. pes_carrying_pid = 1;
  102. }
  103. break;
  104. }
  105. }
  106. if (!pes_carrying_pid) // We are not interrested
  107. return NULL;
  108. if (pa->cur >= pa->max) // Is there enough space in pes_array
  109. pa = pes_array_realloc(pa); // Try to get some more
  110. p = pes_entry_alloc(pid);
  111. pa->entries[pa->cur++] = p;
  112. }
  113. // Last packet finished video PES and we saved it here
  114. if (p->pes_next) {
  115. ts_pes_free(&p->pes);
  116. p->pes = p->pes_next;
  117. p->pes_next = NULL;
  118. }
  119. // Video PES packets have unknown size, so we need to look one packet in the
  120. // future to know when video PES is finished.
  121. if (ts_pes_is_finished(p->pes, ts_packet)) {
  122. p->pes_next = ts_pes_alloc();
  123. p->pes_next = ts_pes_push_packet(p->pes_next, ts_packet, pmt, pid);
  124. } else {
  125. p->pes = ts_pes_push_packet(p->pes, ts_packet, pmt, pid);
  126. }
  127. return p;
  128. }