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

pes_es.c 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * PES elementary stream 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 <netdb.h>
  9. #include <string.h>
  10. #include "tsfuncs.h"
  11. int ts_pes_es_mpeg_audio_header_parse(struct mpeg_audio_header *mpghdr, uint8_t *data, int datasz) {
  12. if (datasz < 4)
  13. return 0;
  14. uint8_t d1 = data[0];
  15. uint8_t d2 = data[1];
  16. uint8_t d3 = data[2];
  17. uint8_t d4 = data[3];
  18. mpghdr->syncword = (int)d1 << 4 | (d2 >> 4); // 12 bits
  19. mpghdr->ID = bit_on(d2, bit_4); // 1 bit
  20. mpghdr->layer = (d2 &~ 0xf9) >> 1; // 2 bits
  21. mpghdr->protection_bit = bit_on(d2, bit_1); // 1 bit
  22. mpghdr->bitrate_index = d3 >> 4; // 4 bits
  23. mpghdr->sampl_freq = (d3 &~ 0xf3) >> 2; // 2 bits
  24. mpghdr->padding_bit = bit_on(d3, bit_2); // 1 bit
  25. mpghdr->private_bit = bit_on(d3, bit_1); // 1 bit
  26. mpghdr->mode = d4 >> 6; // 2 bits
  27. mpghdr->mode_extension = (d4 &~ 0xcf) >> 4; // 2 bits
  28. mpghdr->copyright = bit_on(d4, bit_4); // 1 bit
  29. mpghdr->org_home = bit_on(d4, bit_3); // 1 bit
  30. mpghdr->emphasis = d4 &~ 0xfc; // 2 bits
  31. if (mpghdr->syncword != 0xfff) {
  32. ts_LOGf("!!! Error parsing mpeg audio header! Syncword should be 0xfff but it is 0x%03x!\n", mpghdr->syncword);
  33. return 0;
  34. } else {
  35. mpghdr->initialized = 1;
  36. return 1;
  37. }
  38. }
  39. void ts_pes_es_mpeg_audio_header_dump(struct mpeg_audio_header *mpghdr) {
  40. if (!mpghdr->initialized)
  41. return;
  42. // See ISO-11172-3 for more info
  43. ts_LOGf(" - ES analyze audio frame\n");
  44. ts_LOGf(" - Syncword : %x\n", mpghdr->syncword);
  45. if (mpghdr->syncword != 0xfff) {
  46. ts_LOGf("!!! ERROR: MPEG audo Syncword should be 0xfff!\n");
  47. return;
  48. }
  49. ts_LOGf(" - ID : %d (%s)\n", mpghdr->ID, mpghdr->ID ? "MPEG Audio" : "Other");
  50. ts_LOGf(" - layer : %d (%s)\n", mpghdr->layer,
  51. mpghdr->layer == 0 ? "reserved" :
  52. mpghdr->layer == 1 ? "Layer III" :
  53. mpghdr->layer == 2 ? "Layer II" :
  54. mpghdr->layer == 3 ? "Layer I" : "reserved"
  55. );
  56. ts_LOGf(" - protection_bit: %x\n", mpghdr->protection_bit);
  57. int br = 0;
  58. if (mpghdr->layer > 0 && mpghdr->layer < 4) {
  59. int bitrate_index_table[4][16] = {
  60. [3] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1}, // Layer 1
  61. [2] = { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1}, // Layer 2
  62. [1] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1} // Layer 3
  63. };
  64. br = bitrate_index_table[mpghdr->layer][mpghdr->bitrate_index];
  65. }
  66. ts_LOGf(" - bitrate_index : %d (%d kBit/s)\n", mpghdr->bitrate_index, br);
  67. ts_LOGf(" - sampl_freq : %d (%s)\n", mpghdr->sampl_freq,
  68. mpghdr->sampl_freq == 0 ? "44.1 kHz" :
  69. mpghdr->sampl_freq == 1 ? "48 kHz" :
  70. mpghdr->sampl_freq == 2 ? "32 kHz" : "reserved"
  71. );
  72. ts_LOGf(" - padding_bit : %d\n", mpghdr->padding_bit);
  73. ts_LOGf(" - private_bit : %d\n", mpghdr->private_bit);
  74. ts_LOGf(" - mode : %d (%s)\n", mpghdr->mode,
  75. mpghdr->mode == 0 ? "stereo" :
  76. mpghdr->mode == 1 ? "join_stereo" :
  77. mpghdr->mode == 2 ? "dual_channel" : "single_channel"
  78. );
  79. ts_LOGf(" - mode_extension: %x\n", mpghdr->mode_extension);
  80. ts_LOGf(" - copyright : %x\n", mpghdr->copyright);
  81. ts_LOGf(" - org_home : %x\n", mpghdr->org_home);
  82. ts_LOGf(" - emphasis : %d (%s)\n", mpghdr->emphasis,
  83. mpghdr->emphasis == 0 ? "none" :
  84. mpghdr->emphasis == 1 ? "50/15 microseconds" :
  85. mpghdr->emphasis == 2 ? "reserved" : "CCITT J.17"
  86. );
  87. }
  88. void ts_pes_es_parse(struct ts_pes *pes) {
  89. if (!pes->es_data)
  90. return;
  91. // Parse MPEG audio packet header
  92. if ((pes->is_audio_mpeg1 || pes->is_audio_mpeg2) && pes->es_data_size > 4) {
  93. struct mpeg_audio_header mpghdr;
  94. memset(&mpghdr, 0, sizeof(struct mpeg_audio_header));
  95. ts_pes_es_mpeg_audio_header_parse(&mpghdr, pes->es_data, pes->es_data_size);
  96. if (mpghdr.initialized) {
  97. pes->mpeg_audio_header = mpghdr;
  98. if (mpghdr.ID) {
  99. switch (mpghdr.layer) {
  100. case 3: pes->is_audio_mpeg1l1 = 1; break;
  101. case 2: pes->is_audio_mpeg1l2 = 1; break;
  102. case 1: pes->is_audio_mpeg1l3 = 1; break;
  103. }
  104. }
  105. }
  106. }
  107. // Look into elementary streams to detect AC3/DTS
  108. if (pes->is_audio_ac3) {
  109. if (pes->real_pes_packet_len >= 2 && (pes->es_data[0] == 0x0B && pes->es_data[1] == 0x77)) {
  110. pes->is_audio = 1;
  111. pes->is_audio_ac3 = 1;
  112. pes->is_audio_dts = 0;
  113. }
  114. if (pes->real_pes_packet_len >= 4 && (pes->es_data[0] == 0x7f && pes->es_data[1] == 0xfe && pes->es_data[2] == 0x80 && pes->es_data[3] == 0x01)) {
  115. pes->is_audio = 1;
  116. pes->is_audio_ac3 = 0;
  117. pes->is_audio_dts = 1;
  118. }
  119. }
  120. }
  121. void ts_pes_es_dump(struct ts_pes *pes) {
  122. if (pes->is_audio && pes->mpeg_audio_header.initialized) {
  123. ts_pes_es_mpeg_audio_header_dump(&pes->mpeg_audio_header);
  124. }
  125. }