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

pes_data.c 4.4KB

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