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

pes.c 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. * MPEGTS PES 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 <inttypes.h>
  14. #include "tsfuncs.h"
  15. #define pes_data_size_buffer (1024)
  16. #define pes_max_data_size (1024*1024)
  17. struct ts_pes *ts_pes_alloc() {
  18. struct ts_pes *pes = calloc(1, sizeof(struct ts_pes));
  19. pes->pes_data_size = pes_data_size_buffer;
  20. pes->pes_data = malloc(pes->pes_data_size);
  21. memset(pes->pes_data, 0x33, pes->pes_data_size);
  22. return pes;
  23. }
  24. void ts_pes_free(struct ts_pes **ppes) {
  25. struct ts_pes *pes = *ppes;
  26. if (pes) {
  27. FREE(pes->pes_data);
  28. FREE(*ppes);
  29. }
  30. }
  31. void ts_pes_clear(struct ts_pes *pes) {
  32. if (!pes)
  33. return;
  34. // save
  35. uint8_t *pes_data = pes->pes_data;
  36. uint32_t pes_data_size = pes->pes_data_size;
  37. // clear
  38. memset(pes_data, 0x33, pes_data_size);
  39. memset(pes, 0, sizeof(struct ts_pes));
  40. // restore
  41. pes->pes_data = pes_data;
  42. pes->pes_data_size = pes_data_size;
  43. }
  44. static void ts_pes_add_payload_to_pes_data(struct ts_pes *pes, uint8_t *payload, uint8_t payload_size) {
  45. uint32_t new_data_pos = pes->pes_data_pos + payload_size;
  46. // Check if there is enough space in pes->pes_data
  47. if (new_data_pos > pes->pes_data_size) {
  48. int old_data_size = pes->pes_data_size;
  49. pes->pes_data_size *= 2;
  50. // ts_LOGf("realloc to %d from %d\n", old_data_size, pes->pes_data_size);
  51. pes->pes_data = realloc(pes->pes_data, pes->pes_data_size);
  52. // Poison
  53. memset(pes->pes_data + pes->pes_data_pos, 0x34, pes->pes_data_size - old_data_size);
  54. }
  55. memcpy(pes->pes_data + pes->pes_data_pos, payload, payload_size);
  56. pes->pes_data_pos += payload_size;
  57. if (pes->pes_packet_len) {
  58. // If packet size is known, mark the packet as initialized
  59. if (pes->pes_data_pos >= pes->pes_packet_len) {
  60. pes->pes_data_initialized = 1;
  61. }
  62. }
  63. }
  64. // This function is used to determine the last PES was finished before current ts_packet
  65. int ts_pes_is_finished(struct ts_pes *pes, uint8_t *ts_packet) {
  66. if (pes->pes_data_initialized)
  67. return 1;
  68. // Time to mark PES as initialized since current packet has PUSI
  69. if (ts_packet_is_pusi(ts_packet) && pes->real_pes_packet_len == -1) {
  70. pes->real_pes_packet_len = pes->pes_data_pos;
  71. pes->pes_data_initialized = 1;
  72. // ts_LOGf("packet finished, len:%d\n", pes->real_pes_packet_len);
  73. if (!ts_pes_parse(pes)) {
  74. ts_LOGf("error parsing!\n");
  75. ts_pes_clear(pes);
  76. return 0;
  77. }
  78. // ts_LOGf("parsed OK!\n");
  79. return 1;
  80. }
  81. return 0;
  82. }
  83. // Fill is_video, is_audio, is_ac3, etc..flags in PES packet
  84. void ts_pes_fill_type(struct ts_pes *pes, struct ts_pmt *pmt, uint16_t pid) {
  85. int i;
  86. pes->is_audio = IS_AUDIO_STREAM_ID(pes->stream_id);
  87. pes->is_video = IS_VIDEO_STREAM_ID(pes->stream_id);
  88. if (pmt && pmt->initialized) {
  89. for (i=0;i<pmt->streams_num;i++) {
  90. struct ts_pmt_stream *stream = pmt->streams[i];
  91. if (stream->pid != pid)
  92. continue;
  93. pes->is_audio = pes->is_audio && ts_is_stream_type_audio(stream->stream_type);
  94. pes->is_audio_mpeg1 = pes->is_audio && stream->stream_type == STREAM_TYPE_MPEG1_AUDIO;
  95. pes->is_audio_mpeg2 = pes->is_audio && stream->stream_type == STREAM_TYPE_MPEG2_AUDIO;
  96. // To determine if type is AC3 we need to check descriptors
  97. //pes->is_audio_ac3 = ts_is_stream_type_ac3(stream->stream_type); // We need to also check descriptors because this is not ENOUGH!
  98. pes->is_audio_aac = pes->is_audio && stream->stream_type == STREAM_TYPE_ADTS_AUDIO;
  99. pes->is_video = pes->is_video && ts_is_stream_type_video(stream->stream_type);
  100. pes->is_video_mpeg1 = pes->is_video && stream->stream_type == STREAM_TYPE_MPEG1_VIDEO;
  101. pes->is_video_mpeg2 = pes->is_video && stream->stream_type == STREAM_TYPE_MPEG2_VIDEO;
  102. pes->is_video_mpeg4 = pes->is_video && stream->stream_type == STREAM_TYPE_MPEG4_PART2_VIDEO;
  103. pes->is_video_h264 = pes->is_video && stream->stream_type == STREAM_TYPE_AVC_VIDEO;
  104. pes->is_video_avs = pes->is_video && stream->stream_type == STREAM_TYPE_AVS_VIDEO;
  105. if (!stream->ES_info)
  106. break;
  107. // Parse stream descriptors to gather more information
  108. uint8_t tag, this_length;
  109. uint8_t *data = stream->ES_info;
  110. int data_len = stream->ES_info_size;
  111. while (data_len >= 2) {
  112. tag = data[0];
  113. this_length = data[1];
  114. data += 2;
  115. data_len -= 2;
  116. if (this_length > data_len) {
  117. // Not much we can do! Give up.
  118. ts_LOGf("!!! Descriptor 0x%02x says length %d, but only %d bytes left\n", tag, this_length, data_len);
  119. break;
  120. }
  121. switch (tag) {
  122. case 3: { // Audio stream descriptor
  123. struct {
  124. uint8_t free_format_flag : 1,
  125. ID : 1,
  126. layer : 2,
  127. vbr_flag : 1,
  128. reserved : 3;
  129. } as;
  130. if (this_length >= 1) {
  131. as.free_format_flag = bit_on(data[0], bit_8);
  132. as.ID = bit_on(data[0], bit_7);
  133. as.layer = (data[0] &~ 0xcf) >> 4; // 11xx1111
  134. as.vbr_flag = bit_on(data[0], bit_4);
  135. as.reserved = data[0] &~ 0xf0; // 1111xxxx
  136. if (as.ID) {
  137. pes->is_audio = 1;
  138. pes->is_audio_mpeg1l1 = as.layer == 3;
  139. pes->is_audio_mpeg1l2 = as.layer == 2;
  140. pes->is_audio_mpeg1l3 = as.layer == 1;
  141. }
  142. }
  143. break;
  144. }
  145. case 5: { // Registration descriptor
  146. if (this_length == 4) {
  147. uint32_t reg_ident = data[0] << 24;
  148. reg_ident |= data[1] << 16;
  149. reg_ident |= data[2] << 8;
  150. reg_ident |= data[3];
  151. // See http://smpte-ra.org/mpegreg/mpegreg.html
  152. if (reg_ident == 0x41432D33) { // AC-3
  153. pes->is_audio = 1;
  154. pes->is_audio_ac3 = 1;
  155. //ts_LOGf("reg_desc says AC-3\n");
  156. }
  157. if (reg_ident == 0x44545331 || reg_ident == 0x44545332 || reg_ident == 0x44545333) { // DTS1, DTS2, DTS2
  158. pes->is_audio = 1;
  159. pes->is_audio_dts = 1;
  160. //ts_LOGf("reg_desc says DTSx\n");
  161. }
  162. }
  163. break;
  164. }
  165. case 0x6a: { // AC-3 descriptor
  166. //ts_LOGf("ac3_desc found\n");
  167. pes->is_audio = 1;
  168. pes->is_audio_ac3 = 1;
  169. break;
  170. }
  171. case 0x7b: { // DTS descriptor
  172. //ts_LOGf("ac3_desc found\n");
  173. pes->is_audio = 1;
  174. pes->is_audio_dts = 1;
  175. break;
  176. }
  177. case 0x56: { // teletext
  178. //ts_LOGf("teletext_desc found\n");
  179. pes->is_teletext = 1;
  180. break;
  181. }
  182. case 0x59: { // Subtitling descriptor
  183. //ts_LOGf("subtitle_desc found\n");
  184. pes->is_subtitle = 1;
  185. break;
  186. }
  187. } // switch
  188. data_len -= this_length;
  189. data += this_length;
  190. } // while
  191. }
  192. }
  193. }
  194. struct ts_pes *ts_pes_push_packet(struct ts_pes *pes, uint8_t *ts_packet, struct ts_pmt *pmt, uint16_t pid) {
  195. struct ts_header ts_header;
  196. memset(&ts_header, 0, sizeof(struct ts_header));
  197. uint8_t *payload = ts_packet_header_parse(ts_packet, &ts_header);
  198. uint8_t payload_size = ts_header.payload_size;
  199. if (!payload || !payload_size)
  200. goto OUT;
  201. if (ts_header.pusi) {
  202. // Received PUSI packet before PES END, clear the table to start gathering new one
  203. if (pes->ts_header.pusi)
  204. ts_pes_clear(pes);
  205. uint8_t stream_id = 0;
  206. int pes_packet_len = 0;
  207. if (payload[0] == 0x00 && payload[1] == 0x00 && payload[2] == 0x01) { // pes_start_code_prefix
  208. pes->ts_header = ts_header;
  209. stream_id = payload[3];
  210. pes_packet_len = (payload[4] << 8) | payload[5];
  211. // ts_LOGf("NEW PES. Stream_id=%02x pes_length=%d\n", stream_id, pes_packet_len);
  212. if (pes_packet_len == 0 && pes->real_pes_packet_len == -1) {
  213. ts_LOGf("!!! ERROR: New pes with pes_packed_len == 0, started before the old was finished\n");
  214. goto ERROR;
  215. }
  216. if (pes_packet_len > 0) {
  217. pes->real_pes_packet_len = pes_packet_len;
  218. } else {
  219. pes->real_pes_packet_len = -1;
  220. }
  221. pes->stream_id = stream_id;
  222. pes->pes_packet_len = pes_packet_len;
  223. ts_pes_fill_type(pes, pmt, pid);
  224. } else {
  225. ts_LOGf("!!! PES_start_code_prefix not found. Expected 0x00 0x00 0x01 but get 0x%02x 0x%02x 0x%02x! PID %03x\n",
  226. payload[0], payload[1], payload[2], ts_header.pid);
  227. goto ERROR;
  228. }
  229. }
  230. if (pes->stream_id) {
  231. ts_pes_add_payload_to_pes_data(pes, payload, payload_size);
  232. // ts_LOGf("Payload %d added, tot_size: %d\n", payload_size, pes->pes_data_pos);
  233. if (pes->pes_data_pos > pes_max_data_size) {
  234. ts_LOGf("PES Payload size %d exceeded pes_data_max_size: %d pid: %03x\n",
  235. pes->pes_data_pos, pes_max_data_size, pes->ts_header.pid);
  236. goto ERROR;
  237. }
  238. }
  239. if (pes->pes_data_initialized) {
  240. if (!ts_pes_parse(pes))
  241. goto ERROR;
  242. }
  243. OUT:
  244. return pes;
  245. ERROR:
  246. ts_pes_clear(pes);
  247. return pes;
  248. }
  249. int ts_pes_parse(struct ts_pes *pes) {
  250. uint8_t *data = pes->pes_data;
  251. if (!pes->pes_data_initialized) {
  252. ts_LOGf("!!! pes_data_initialized not true\n");
  253. return 0;
  254. }
  255. if (pes->real_pes_packet_len == -1) {
  256. ts_LOGf("!!! real_pes_data_len is == -1\n");
  257. return 0;
  258. }
  259. if (pes->pes_data_size < 6) {
  260. ts_LOGf("!!! PES data_size < 6\n");
  261. return 0;
  262. }
  263. if (!(data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01)) { // pes_start_code_prefix
  264. ts_LOGf("!!! PES_start_code_prefix error! Expected 0x00 0x00 0x01 but get 0x%02x 0x%02x 0x%02x! PID %03x\n",
  265. data[0], data[1], data[2], pes->ts_header.pid);
  266. return 0;
  267. }
  268. pes->stream_id = data[3]; // 8 bits
  269. pes->pes_packet_len = (data[4] << 8) | data[5]; // 16 bits
  270. int dpos = 6;
  271. if (!IS_PES_STREAM_SUPPORTED(pes->stream_id)) {
  272. // We do not handle this streams...
  273. ts_LOGf("!!! Unsupported stream, ignore! (%02x) PID %03x\n", pes->stream_id, pes->ts_header.pid);
  274. return 0;
  275. }
  276. dpos = 6;
  277. if ((data[dpos] &~ 0x3f) != 0x80) { // 10xxxxxx (first two bits must be 10 eq 0x80
  278. ts_LOGf("!!! No 10 bits at PES start, expected 0x80 get 0x%02x, org: %02x! PID %03x\n",
  279. data[dpos] &~ 0x3f, data[dpos], pes->ts_header.pid);
  280. return 0;
  281. }
  282. // data[dpos] = 0xff;
  283. pes->flags_1 = data[dpos];
  284. pes->scrambling = (data[dpos] &~ 0xCF) >> 4;
  285. pes->priority = bit_on(data[dpos], bit_4);
  286. pes->data_alignment = bit_on(data[dpos], bit_3);
  287. pes->copyright = bit_on(data[dpos], bit_2);
  288. pes->original_or_copy = bit_on(data[dpos], bit_1);
  289. dpos = 7;
  290. // data[dpos] = 0xff;
  291. pes->flags_2 = data[dpos];
  292. pes->PTS_flag = bit_on(data[dpos], bit_8);
  293. pes->DTS_flag = bit_on(data[dpos], bit_7);
  294. pes->ESCR_flag = bit_on(data[dpos], bit_6);
  295. pes->ES_rate_flag = bit_on(data[dpos], bit_5);
  296. pes->trick_mode_flag = bit_on(data[dpos], bit_4);
  297. pes->add_copy_info_flag = bit_on(data[dpos], bit_3);
  298. pes->pes_crc_flag = bit_on(data[dpos], bit_2);
  299. pes->pes_extension_flag = bit_on(data[dpos], bit_1);
  300. dpos = 8;
  301. pes->pes_header_len = data[dpos];
  302. dpos = 9;
  303. if (!pes->PTS_flag && pes->DTS_flag) // Invalid, can't have only DTS flag
  304. return 0;
  305. if (pes->PTS_flag && !pes->DTS_flag) {
  306. ts_decode_pts_dts(&data[dpos], &pes->PTS);
  307. dpos += 5;
  308. pes->have_pts = 1;
  309. }
  310. if (pes->PTS_flag && pes->DTS_flag) {
  311. ts_decode_pts_dts(&data[dpos], &pes->PTS);
  312. pes->have_pts = 1;
  313. dpos += 5;
  314. ts_decode_pts_dts(&data[dpos], &pes->DTS);
  315. pes->have_dts = 1;
  316. dpos += 5;
  317. }
  318. if (pes->ESCR_flag) {
  319. uint64_t ESCR_base;
  320. uint32_t ESCR_extn;
  321. ESCR_base = (data[dpos+4] >> 3) |
  322. (data[dpos+3] << 5) |
  323. (data[dpos+2] << 13) |
  324. (data[dpos+1] << 20) |
  325. ((((uint64_t)data[dpos]) & 0x03) << 28) |
  326. ((((uint64_t)data[dpos]) & 0x38) << 27);
  327. ESCR_extn = (data[dpos+5] >> 1) | (data[dpos+4] << 7);
  328. pes->ESCR = ESCR_base * 300 + ESCR_extn;
  329. dpos += 6;
  330. }
  331. if (pes->ES_rate_flag) {
  332. // Not decoded...
  333. dpos += 3;
  334. }
  335. if (pes->trick_mode_flag) {
  336. // Not decoded...
  337. dpos += 1;
  338. }
  339. if (pes->add_copy_info_flag) {
  340. // Not decoded...
  341. dpos += 1;
  342. }
  343. if (pes->pes_crc_flag) {
  344. // Not decoded...
  345. dpos += 2;
  346. }
  347. if (pes->pes_extension_flag) {
  348. // data[dpos] = 0xff;
  349. pes->flags_3 = data[dpos];
  350. pes->pes_private_data_flag = bit_on(data[dpos], bit_8); // 1xxxxxxx
  351. pes->pack_header_field_flag = bit_on(data[dpos], bit_7); // x1xxxxxx
  352. pes->program_packet_seq_counter_flag = bit_on(data[dpos], bit_6); // xx1xxxxx
  353. pes->p_std_buffer_flag = bit_on(data[dpos], bit_5); // xxx1xxxx
  354. pes->reserved2 = (data[dpos] &~ 0x0e) >> 1; // xxxx111x
  355. pes->pes_extension2_flag = bit_on(data[dpos], bit_1); // xxxxxxx1
  356. if (pes->pes_private_data_flag) {
  357. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+7];
  358. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+6];
  359. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+5];
  360. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+4];
  361. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+3];
  362. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+2];
  363. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+1];
  364. pes->pes_private_data_1 = (pes->pes_private_data_1 << 8) | data[dpos+0];
  365. dpos += 8;
  366. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+7];
  367. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+6];
  368. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+5];
  369. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+4];
  370. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+3];
  371. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+2];
  372. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+1];
  373. pes->pes_private_data_2 = (pes->pes_private_data_2 << 8) | data[dpos+0];
  374. dpos += 8;
  375. }
  376. if (pes->pack_header_field_flag) {
  377. pes->pack_header_len = data[dpos];
  378. pes->pack_header = pes->pes_data + 1 + dpos; // Pointer into *pes_data
  379. dpos += 1 + pes->pack_header_len;
  380. }
  381. if (pes->program_packet_seq_counter_flag) {
  382. // Not decoded
  383. dpos += 2;
  384. }
  385. if (pes->p_std_buffer_flag) {
  386. if ((data[dpos] &~ 0x3f) != 0x40) { // 01xxxxxx (first two bits must be 01 eq 0x40
  387. return 0;
  388. }
  389. // Not decoded...
  390. dpos += 2;
  391. }
  392. if (pes->pes_extension2_flag) {
  393. pes->pes_extension_field_len = data[dpos] &~ 0x80; // x1111111
  394. pes->pes_extension2 = pes->pes_data + 1 + dpos; // Pointer into *pes_data
  395. dpos += 1 + pes->pes_extension_field_len;
  396. }
  397. }
  398. int maxstuffing = 32; // Maximum 32 stuffing bytes
  399. // Skip stuffing bytes (8 is minimum PES header len)
  400. while ((--maxstuffing > 0) && (dpos-8 <= pes->pes_header_len) && (data[dpos] == 0xff)) {
  401. dpos++;
  402. }
  403. pes->es_data = pes->pes_data + dpos;
  404. pes->es_data_size = pes->real_pes_packet_len - dpos;
  405. pes->initialized = 1;
  406. if (pes->data_alignment)
  407. ts_pes_es_parse(pes);
  408. return 1;
  409. }
  410. #define min(a,b) ((a < b) ? a : b)
  411. void ts_pes_dump(struct ts_pes *pes) {
  412. if (!pes->initialized)
  413. return;
  414. ts_LOGf("PES packet\n");
  415. ts_packet_header_dump(&pes->ts_header);
  416. ts_LOGf(" * Content : %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
  417. pes->is_audio ? "Audio " : "",
  418. pes->is_audio_mpeg1 ? "MP1 " : "",
  419. pes->is_audio_mpeg1l1 ? "Layer1 " : "",
  420. pes->is_audio_mpeg1l2 ? "Layer2 " : "",
  421. pes->is_audio_mpeg1l3 ? "Layer3 " : "",
  422. pes->is_audio_mpeg2 ? "MP2 " : "",
  423. pes->is_audio_aac ? "AAC " : "",
  424. pes->is_audio_ac3 ? "AC3 " : "",
  425. pes->is_audio_dts ? "DTS " : "",
  426. pes->is_video ? "Video " : "",
  427. pes->is_video_mpeg1 ? "MPEG1 " : "",
  428. pes->is_video_mpeg2 ? "MPEG2 " : "",
  429. pes->is_video_mpeg4 ? "MPEG4p2 " : "",
  430. pes->is_video_h264 ? "H.264 " : "",
  431. pes->is_video_avs ? "AVS " : "",
  432. pes->is_teletext ? "Teletext " : "",
  433. pes->is_subtitle ? "Subtitles " : ""
  434. );
  435. char *stream_id_text = h222_stream_id_desc(pes->stream_id);
  436. ts_LOGf(" * Stream_id : 0x%02x (%d) %s\n", pes->stream_id, pes->stream_id, stream_id_text);
  437. FREE(stream_id_text);
  438. ts_LOGf(" * Packet len : 0x%04x (%d) real_len: %d %s\n",
  439. pes->pes_packet_len, pes->pes_packet_len, pes->real_pes_packet_len-pes->pes_header_len-6, pes->is_video ? "VIDEO" : (pes->is_audio ? "AUDIO" : "OTHER"));
  440. ts_LOGf(" * Header len : %d\n", pes->pes_header_len);
  441. ts_LOGf(" * Flags 1 : 0x%02x | scrambling=%d priority=%d data_align=%d copyright=%d org_or_copy=%d\n",
  442. pes->flags_1,
  443. pes->scrambling,
  444. pes->priority,
  445. pes->data_alignment,
  446. pes->copyright,
  447. pes->original_or_copy
  448. );
  449. ts_LOGf(" * Flags 2 : 0x%02x | %s%s%s%s%s%s%s%s\n",
  450. pes->flags_2,
  451. pes->PTS_flag ? "PTS " : "",
  452. pes->DTS_flag ? "DTS " : "",
  453. pes->ESCR_flag ? "ESCR " : "",
  454. pes->ES_rate_flag ? "ES_rate " : "",
  455. pes->trick_mode_flag ? "Trick_mode " : "",
  456. pes->add_copy_info_flag ? "Add_copy " : "",
  457. pes->pes_crc_flag ? "PES_CRC " : "",
  458. pes->pes_extension_flag ? "PES_Ext " : ""
  459. );
  460. if (pes->PTS_flag && pes->have_pts)
  461. ts_LOGf(" * PTS : %"PRIu64" (%"PRIu64" ms) (%"PRIu64".%04"PRIu64" sec)\n",
  462. pes->PTS,
  463. pes->PTS / 90,
  464. pes->PTS / 90000, (pes->PTS % 90000) / 9
  465. );
  466. if (pes->DTS_flag && pes->have_dts)
  467. ts_LOGf(" * DTS : %"PRIu64" (%"PRIu64" ms) (%"PRIu64".%04"PRIu64" sec)\n",
  468. pes->DTS,
  469. pes->DTS / 90,
  470. pes->DTS / 90000, (pes->DTS % 90000) / 9
  471. );
  472. if (pes->ESCR_flag)
  473. ts_LOGf(" * ESCR : %"PRIu64"\n", pes->ESCR);
  474. if (pes->ES_rate_flag)
  475. ts_LOGf(" * ES_rate : %lu\n" , (unsigned long)pes->ES_rate * 50); // In units of 50 bytes
  476. if (pes->pes_extension_flag) {
  477. ts_LOGf(" * Ext flags : 0x%02x | %s%s%s%s%s\n",
  478. pes->flags_3,
  479. pes->pes_private_data_flag ? "Private_data_flag " : "",
  480. pes->pack_header_field_flag ? "Pack_header_flag " : "",
  481. pes->program_packet_seq_counter_flag ? "Prg_pack_seq_flag " : "",
  482. pes->p_std_buffer_flag ? "P-STD_buf_flag " : "",
  483. pes->pes_extension2_flag ? "Ext2_flag " : ""
  484. );
  485. }
  486. if (pes->pes_private_data_flag) {
  487. ts_LOGf(" * PES priv_data : 0x%08llx%08llx\n",
  488. (unsigned long long)pes->pes_private_data_1,
  489. (unsigned long long)pes->pes_private_data_2);
  490. }
  491. if (pes->pack_header_field_flag) {
  492. ts_LOGf(" * Pack_header ... \n");
  493. }
  494. if (pes->program_packet_seq_counter_flag) {
  495. ts_LOGf(" * Prg_seq_cnt : %d\n", pes->program_packet_seq_counter);
  496. }
  497. ts_LOGf(" - Private : pes_data_pos:%u es_data_size:%u\n",
  498. pes->pes_data_pos,
  499. pes->es_data_size
  500. );
  501. char *phex = ts_hex_dump(pes->pes_data, min(32, pes->pes_data_pos), 0);
  502. ts_LOGf(" - PES dump : %s...\n", phex);
  503. free(phex);
  504. if (pes->es_data) {
  505. char *hex = ts_hex_dump(pes->es_data, min(32, pes->es_data_size), 0);
  506. ts_LOGf(" - ES dump : %s...\n", hex);
  507. free(hex);
  508. }
  509. }