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

misc.c 6.6KB

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