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_misc.c 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. int dec2bcd(int dec) {
  9. return ((dec/10) << 4) + dec % 10;
  10. }
  11. int bcd2dec(int bcd) {
  12. return ((bcd>>4) * 10) + bcd % 16;
  13. }
  14. char *ts_hex_dump(uint8_t *d, int size, int col) {
  15. int i;
  16. char *buf = calloc(1, size * 6);
  17. if (!buf)
  18. return NULL;
  19. for (i=0;i<size;i++) {
  20. if (col && (i % col == col - 1))
  21. sprintf(buf+(i*3), "%02x\n", d[i]);
  22. else
  23. sprintf(buf+(i*3), "%02x ", d[i]);
  24. }
  25. return buf;
  26. }
  27. void ts_print_bytes(char *prefix, uint8_t *d, int size) {
  28. char *buf = ts_hex_dump(d, size, 0);
  29. ts_LOGf("%s -> %s\n", prefix, buf);
  30. free(buf);
  31. }
  32. void ts_compare_data(char *prefix, uint8_t *a, uint8_t *b, int size) {
  33. if (!a) {
  34. ts_LOGf("%s: !a\n", prefix);
  35. return;
  36. }
  37. if (!b) {
  38. ts_LOGf("%s: !b\n", prefix);
  39. return;
  40. }
  41. if (memcmp(a, b, size) == 0) {
  42. ts_LOGf(" **** %s generator is correct ****\n", prefix);
  43. } else {
  44. int i;
  45. for (i=0;i<size;i++) {
  46. ts_LOGf("%03d - %02x %02x | %s\n", i, a[i], b[i], a[i] == b[i] ? "ok" : "err");
  47. }
  48. }
  49. }
  50. char *init_dvb_string(uint8_t encoding, char *text) {
  51. if (!text)
  52. return NULL;
  53. int len = strlen(text);
  54. if (!len)
  55. return NULL;
  56. char *dvbtext = calloc(1, len + 2);
  57. memcpy(dvbtext + 1, text, len);
  58. dvbtext[0] = encoding; // See EN 300 469 table A.3
  59. return dvbtext;
  60. }
  61. char *init_dvb_string_utf8(char *text) {
  62. return init_dvb_string(0x10, text);
  63. }
  64. char *init_dvb_string_iso_8859_5(char *text) {
  65. return init_dvb_string(0x01, text);
  66. }
  67. int ts_is_psi_pid(uint16_t pid, struct ts_pat *pat) {
  68. // Skip PAT && reserved, SDT, EIT, RST, TDT/TOT. They are PSI packets
  69. if (pid < 0x10 || pid == 0x11 || pid == 0x12 || pid == 0x13 || pid == 0x14)
  70. return 1;
  71. int i;
  72. for (i=0;i<pat->programs_num;i++) {
  73. struct ts_pat_program *prg = pat->programs[i];
  74. if (prg->pid == pid) // PMT's are PSI
  75. return 1;
  76. }
  77. return 0;
  78. }
  79. int ts_is_stream_type_video(uint8_t stream_type) {
  80. return stream_type == STREAM_TYPE_MPEG1_VIDEO ||
  81. stream_type == STREAM_TYPE_MPEG2_VIDEO ||
  82. stream_type == STREAM_TYPE_AVC_VIDEO ||
  83. stream_type == STREAM_TYPE_AVS_VIDEO ||
  84. stream_type == STREAM_TYPE_MPEG4_PART2_VIDEO;
  85. }
  86. // This is not enough! Must look at stream descriptors to be sure!!!
  87. int ts_is_stream_type_ac3(uint8_t stream_type) {
  88. return stream_type == STREAM_TYPE_DOLBY_DVB_AUDIO ||
  89. stream_type == STREAM_TYPE_DOLBY_ATSC_AUDIO;
  90. }
  91. int ts_is_stream_type_audio(uint8_t stream_type) {
  92. return stream_type == STREAM_TYPE_MPEG1_AUDIO ||
  93. stream_type == STREAM_TYPE_MPEG2_AUDIO ||
  94. stream_type == STREAM_TYPE_ADTS_AUDIO ||
  95. ts_is_stream_type_ac3(stream_type);
  96. }
  97. // ISO/IEC 13818-1 : 2000 (E) | Table 2-29 - Stream type assignments, Page 66 (48)
  98. char *h222_stream_type_desc(uint8_t stream_type) {
  99. if (stream_type == 0 || (stream_type > 0x1c && stream_type < 0x7e))
  100. return "Reserved";
  101. switch (stream_type) {
  102. case 0x01: return "11172-2 video (MPEG-1)";
  103. case 0x02: return "H.262/13818-2 video (MPEG-2) or 11172-2 constrained video";
  104. case 0x03: return "11172-3 audio (MPEG-1)";
  105. case 0x04: return "13818-3 audio (MPEG-2)";
  106. case 0x05: return "H.222.0/13818-1 private sections";
  107. case 0x06: return "H.222.0/13818-1 PES private data";
  108. case 0x07: return "13522 MHEG";
  109. case 0x08: return "H.222.0/13818-1 Annex A - DSM CC";
  110. case 0x09: return "H.222.1";
  111. case 0x0A: return "13818-6 type A";
  112. case 0x0B: return "13818-6 type B";
  113. case 0x0C: return "13818-6 type C";
  114. case 0x0D: return "13818-6 type D";
  115. case 0x0E: return "H.222.0/13818-1 auxiliary";
  116. case 0x0F: return "13818-7 Audio with ADTS transport syntax";
  117. case 0x10: return "14496-2 Visual (MPEG-4 part 2 video)";
  118. case 0x11: return "14496-3 Audio with LATM transport syntax (14496-3/AMD 1)";
  119. case 0x12: return "14496-1 SL-packetized or FlexMux stream in PES packets";
  120. case 0x13: return "14496-1 SL-packetized or FlexMux stream in 14496 sections";
  121. case 0x14: return "ISO/IEC 13818-6 Synchronized Download Protocol";
  122. case 0x15: return "Metadata in PES packets";
  123. case 0x16: return "Metadata in metadata_sections";
  124. case 0x17: return "Metadata in 13818-6 Data Carousel";
  125. case 0x18: return "Metadata in 13818-6 Object Carousel";
  126. case 0x19: return "Metadata in 13818-6 Synchronized Download Protocol";
  127. case 0x1A: return "13818-11 MPEG-2 IPMP stream";
  128. case 0x1B: return "H.264/14496-10 video (MPEG-4/AVC)";
  129. case 0x42: return "AVS Video";
  130. case 0x7F: return "IPMP stream";
  131. default : return "Unknown";
  132. }
  133. }
  134. // System start codes, ISO 13818-1, Table 2-18
  135. // The function allocates memory which should be freed by the caller
  136. char *h222_stream_id_desc(uint8_t stream_id) {
  137. uint8_t stream_number;
  138. char *text = NULL;
  139. switch (stream_id) {
  140. case 0xbc: return strdup("Program stream map"); break;
  141. case 0xbd: return strdup("Private stream 1"); break;
  142. case 0xbe: return strdup("Padding stream"); break;
  143. case 0xbf: return strdup("Private stream 2"); break;
  144. case 0xf0: return strdup("ECM stream"); break;
  145. case 0xf1: return strdup("EMM stream"); break;
  146. case 0xf2: return strdup("DSMCC stream"); break;
  147. case 0xf3: return strdup("13522 stream"); break;
  148. case 0xf4: return strdup("H.222 A stream"); break;
  149. case 0xf5: return strdup("H.222 B stream"); break;
  150. case 0xf6: return strdup("H.222 C stream"); break;
  151. case 0xf7: return strdup("H.222 D stream"); break;
  152. case 0xf8: return strdup("H.222 E stream"); break;
  153. case 0xf9: return strdup("Ancillary stream"); break;
  154. case 0xff: return strdup("Program stream directory"); break;
  155. }
  156. if (stream_id >= 0xc0 && stream_id <= 0xdf) {
  157. stream_number = stream_id & 0x1f;
  158. asprintf(&text, "Audio stream %d", stream_number);
  159. } else if (stream_id >= 0xe0 && stream_id <= 0xef) {
  160. stream_number = stream_id & 0x0f;
  161. asprintf(&text, "Video stream %d", stream_number);
  162. } else if (stream_id >= 0xfc && stream_id <= 0xfe) {
  163. asprintf(&text, "Reserved data stream");
  164. } else {
  165. asprintf(&text, "Unrecognised stream id 0x%02x", stream_id);
  166. }
  167. return text;
  168. }