ps文件解析(纯c解析代码)
程序员文章站
2022-06-27 21:49:07
参考链接:1. PS流的格式和解析总结 http://www.cnblogs.com/lihaiping/p/4181607.html 2. TS科普5 PES包解析 https://blog.csdn.net/cabbage2008/article/details/49612011 PES包的解析 ......
参考链接:1. ps流的格式和解析总结 http://www.cnblogs.com/lihaiping/p/4181607.html
2. ts科普5 pes包解析 https://blog.csdn.net/cabbage2008/article/details/49612011
pes包的解析(本代码主要解析了pts和dts, 需结合下图和代码中的pes包的伪代码看):
startcode(24) + streamid(8) + pes_len(16) + {header: flag1(8) + flag2(8, pts标识在这儿) + header_len(8)} + {header_data(header_len, 若前面的flag有数据, 数据就在这儿)} + pes_data(pes_len-3-header_len)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <arpa/inet.h> 5 6 #define tab44 " " 7 #define printf_debug 8 9 #define max_ps_startcode_len 4 10 #define max_pdts_len 5 11 #define max_es_nums 6 12 #define max_pdts_string_len 12 13 #define mmin_ps_header_len 14 14 15 16 #define scode_ps_end 0x000001b9 17 #define scode_ps_header 0x000001ba 18 #define scode_ps_system_header 0x000001bb 19 #define scode_ps_system_map_header 0x000001bc 20 21 /********************************************************************************************************** 22 pack_header() { 23 pack_start_code 32 bits 24 '01' 2 bits 25 system_clock_reference_base[32..30] 3 bits 26 marker_bit 1 bit 27 system_clock_reference_base[29..15] 15 bits 28 marker_bit 1 bit 29 system_clock_reference_base[14..0] 15 bits 30 marker_bit 1 bit 31 system_clock_reference_extension 9 bits 32 marker_bit 1 bit 33 program_mux_rate 22 bits 34 marker_bit 1 bit 35 marker_bit 1 bit 36 reserved 5 bit 37 pack_stuffing_length 3 bits 38 39 for (i=0; i<pack_stuffing_length; i++){ 40 stuffing_byte 8 bits 41 } 42 43 if (nextbits() == system_header_start_code) { 44 system_header() 45 } 46 } 47 **********************************************************************************************************/ 48 49 50 /********************************************************************************************************** 51 system_header() { 52 system_header_start_code 32 bits 53 header_length 16 bits 54 marker_bit 1 bit 55 rate_bound 22 bits 56 marker_bit 1 bit 57 audio_bound 6 bits 58 fixed_flag 1 bit 59 csps_flag 1 bit 60 system_audio_lock_flag 1 bit 61 system_video_lock_flag 1 bit 62 marker_bit 1 bit 63 vedio_bound 5 bits 64 packet_rate_restriction_flag 1 bit 65 reserved_bits 7 bits 66 67 while (nextbits() == '1') { 68 stream_id 8 bits 69 '11' 2 bits 70 p-std_buffer_bound_scale 1 bit 71 p-std_buffer_size_bound 13 bits 72 } 73 } 74 **********************************************************************************************************/ 75 76 77 /********************************************************************************************************** 78 program_stream_map() { 79 packet_start_code_prefix 24 bits 80 map_stream_id 8 bits 81 program_stream_map_length 16 bits 82 current_next_indicator 1 bit 83 reserved 2 bits 84 program_stream_map_version 5 bits 85 reserved 7 bits 86 marker_bit 1 bit 87 program_stream_info_length 16 bits 88 89 for (i=0;i<n;i++) { 90 descriptor() 91 } 92 93 elementary_stream_map_length 16 bits 94 95 for (i=0;i<n1;i++) { 96 stream_type 8 bits 97 elementary_stream_id 8 bits 98 99 elementary_stream_info_length 16 bits 100 101 for (i=0;i<n2;i++) { 102 descriptor() 103 } 104 } 105 106 crc_32 32 bits 107 } 108 109 ** current_next_indicator: 当前下一个指示符字段, 1位字段. 置'1'时表示传送的节目流映射当前是可用的. 110 置'0'时表示传送的节目流映射还不可用, 但它将是下一个生效的表. 111 ** program_stream_map_version: 5位字段, 表示整个节目流映射的版本号. 一旦节目流映射的定义发生变化, 112 该字段将递增1, 并对32取模. 在current_next_indicator为'1'时, 该字段应该是当前适用的节目流映射的版本号; 113 在current_next_indicator为'0'时, 该字段应该是下一个适用的节目流映射的版本号. 114 ** stream_type: 流类型字段, 该字段只能标志包含在pes分组中的基本流且取值不能为0x05. 115 1. mpeg-4视频流: 0x10; 116 2. h.264视频流: 0x1b; 117 3. svac视频流: 0x80; 118 4. g.711音频流: 0x90; 119 5. g.722.1音频流: 0x92; 120 6. g.723.1音频流: 0x93; 121 7. g.729音频流: 0x99; 122 8. svac音频流: 0x9b. 123 因为节目映射流字段只有在关键帧打包的时候, 才会存在, 所以如果要判断ps打包的流编码类型, 就根据这个字段来判断. 124 ** elementary_stream_map_length: 基本流映射长度字段. 指出在该节目流映射中的所有基本流信息的字节长度. 125 它只包括stream_type、elementary_stream_id和elementary_stream_info_length字段. 126 ** elementary_stream_id: 基本流标识字段, 8位字段, 指出该基本流所在pes分组的pes分组标题中stream_id字段的值. 127 这个字段的定义, 其中0x(c0~df)指音频, 0x(e0~ef)为视频. 128 **********************************************************************************************************/ 129 typedef struct t_es_map 130 { 131 unsigned char streamtype; 132 unsigned char esid; 133 unsigned short esinfolen; 134 } t_es_map; 135 136 typedef struct t_ps_map 137 { 138 unsigned char curnextind:1, :2, version:5; 139 140 unsigned short psinfolen; 141 unsigned short esstreammaplen; 142 143 unsigned int esmapnum; 144 145 t_es_map esmaps[max_es_nums]; 146 } t_ps_map; 147 148 /********************************************************************************************************** 149 pes_packet() { 150 packet_start_code_prefix 24 bits 151 stream_id 8 bits 152 pes_packet_length 16 bits 153 154 if (stream_id != program_stream_map 155 && stream_id != padding_stream 156 && stream_id != private_stream_2 157 && stream_id != ecm 158 && stream_id != emm 159 && stream_id != program_stream_directory 160 && stream_id != dsmcc_stream 161 && stream_id != itu-t rec.h.222.1 type e stream) { 162 '10' 2 bits 163 pes_scrambling_control 2 bits 164 pes_priority 1 bit 165 data_alignment_indicator 1 bit 166 copyright 1 bit 167 original_or_copy 1 bit 168 169 pts_dts_flags 2 bits 170 escr_flag 1 bit 171 es_rate_flag 1 bit 172 dsm_trick_mode_flag 1 bit 173 additional_copy_info_flag 1 bit 174 pes_crc_flag 1 bit 175 pes_extension_flag 1 bit 176 177 pes_header_data_length 8 bits 178 179 if (pts_dts_flags == '10') { 180 '0010' 4 bits 181 pts[32..30] 3 bits 182 marker_bit 1 bit 183 pts[29..15] 15 bits 184 marker_bit 1 bit 185 pts[14..0] 15 bits 186 marker_bit 1 bit 187 } 188 189 if (pts_dts_flags == '11') { 190 '0011' 4 bits 191 pts[32..30] 3 bits 192 marker_bit 1 bit 193 pts[29..15] 15 bits 194 marker_bit 1 bit 195 pts[14..0] 15 bits 196 marker_bit 1 bit 197 '0001' 4 bits 198 pts[32..30] 3 bits 199 marker_bit 1 bit 200 pts[29..15] 15 bits 201 marker_bit 1 bits 202 pts[14..0] 15 bits 203 marker_bit 1 bit 204 } 205 206 if (escr_flag == '1') { 207 reserved 2 bits 208 escr_base[32..30] 3 bits 209 marker_bit 1 bit 210 escr_base[29..15] 15 bits 211 marker_bit 1 bit 212 escr_base[14..0] 15 bits 213 marker_bit 1 bit 214 escr_extension 9 bits 215 marker_bit 1 bit 216 } 217 218 if (es_rate_flag == '1') { 219 marker_bit 1 bit 220 es_rate 22 bits 221 marker_bit 1 bit 222 } 223 224 if (dsm_trick_mode_flag == '1') { 225 trick_mode_control 3 bits 226 227 if (trick_mode_control == fast_forward) { 228 field_id 2 bits 229 intra_slice_refresh 1 bits 230 frequency_truncation 2 bits 231 } else if (trick_mode_control == slow_motion) { 232 rep_cntrl 5 bits 233 } else if (trick_mode _control == freeze_frame) { 234 field_id 2 bits 235 reserved 3 bits 236 } else if (trick_mode _control == fast_reverse) { 237 field_id 2 bits 238 intra_slice_refresh 1 bit 239 frequency_truncation 2 bits 240 } else if (trick_mode_control == slow_reverse) { 241 rep_cntrl 5 bits 242 } else { 243 reserved 5 bits 244 } 245 } 246 247 if (additional_copy_info_flag =='1') { 248 marker_bit 1 bit 249 additional_copy_info 7 bits 250 } 251 252 if (pes_crc_flag == ‘1’) { 253 previous_pes_packet_crc 16 bits 254 } 255 256 if (pes_extension_flag == '1') { 257 pes_private_data_flag 1 bit 258 pack_header_field_flag 1 bit 259 program_packet_sequence_counter_flag 1 bit 260 p-std_buffer_flag 1 bit 261 reserved 3 bits 262 pes_extension_flag_2 1 bit 263 264 if (pes_private_data_flag == '1') { 265 pes_private_data 128 bits 266 } 267 268 if (pack_header_field_flag == '1') { 269 pack_field_length 8 bits 270 pack_header() 271 } 272 273 if (program_packet_sequence_counter_flag == '1') { 274 marker_bit 1 bit 275 program_packet_sequence_counter 7 bits 276 marker-bit 1 bit 277 mpeg1_mpeg2_indentifier 1 bit 278 original_stuff_length 6 bits 279 } 280 281 if (p-std_buffer_flag == '1') { 282 '01' 2 bits 283 p-std_buffer_scale 1 bit 284 p-std_buffer_size 13 bits 285 } 286 287 if (pes_extension_flag_2 == '1') { 288 marker_bit 1 bit 289 pes_extension_field_length 7 bits 290 291 for (i=0; i<pes_extension_field_length; i++) { 292 reserved 8 bits 293 } 294 } 295 } 296 297 for (i=0; i<n1; i++) { 298 stuffing_byte 8 bits 299 } 300 301 for (i=0; i<n2; i++) { 302 pes_packet_data_byte 8 bits 303 } 304 } else if (stream_id == program_stream_map 305 || stream_id == private_stream_2 306 || stream_id == ecm 307 || stream_id == emm 308 || stream_id == program_stream_directory 309 || stream_id == dsmcc_stream 310 || stream_id == itu-t rec. h.222.1 type e stream ) { 311 for (i=0; i<pes_packet_length; i++) { 312 pes_packet_data_byte 8 bits 313 } 314 } else if (steam_id == padding_stream) { 315 for (i=0; i<pes_packet_length; i++) { 316 padding_byte 8 bits 317 } 318 } 319 } 320 321 ** stream_id: 322 1011 1100 program_stream_map(0xbc) 323 1011 1101 private_stream_1(0xbd) 324 1011 1110 padding_stream(0xbe) 325 1011 1111 private_stream-2(0xbf) 326 110x xxxx gb/t xxxx.3或gb/t aaaa.3音频流编号xxxx(0xc0~0xdf) 327 1110 xxxx gb/t xxxx.2或gb/t aaaa.2视频流编号xxxx(0xe0~0xef) 328 1111 0000 ecm_stream(0xf0) 329 1111 0001 emm_stream(0xf1) 330 1111 0010 gb/t xxxx.1附录b或gb/t xxxx.6_dsmcc_stream(0xf2) 331 1111 0011 iso/iec_13522_stream(0xf3) 332 1111 0100 itu-t rec. h.222.1类型a 333 1111 0101 itu-t rec. h.222.1类型b 334 1111 0110 itu-t rec. h.222.1类型c 335 1111 0111 itu-t rec. h.222.1类型d 336 1111 1000 itu-t rec. h.222.1类型e 337 1111 1001 ancillary_stream(0xf9) 338 1111 1010…1111 1110 保留数据流 339 1111 1111 program_stream_directory(0xff) 340 符号x表示值'0'或'1'均被允许且可产生相同的流类型. 流号码由x的取值决定. 341 **********************************************************************************************************/ 342 typedef struct t_ps_pes 343 { 344 unsigned char streamid; 345 346 long long pts; 347 long long dts; 348 349 unsigned char ptsstr[max_pdts_string_len+1]; 350 unsigned char dtsstr[max_pdts_string_len+1]; 351 352 unsigned char pesheaderlen; 353 } t_ps_pes; 354 355 static void parsepsheader(unsigned char* const psheaderdata) 356 { 357 358 } 359 360 static void parsepssystemheader(unsigned char* const pssysheaderdata) 361 { 362 363 } 364 365 static void parsepssystemmapheader(unsigned char* const psmapheaderdata) 366 { 367 int i = 0; 368 369 t_ps_map psmap = {0}; 370 371 unsigned char *data = null; 372 373 data = psmapheaderdata; 374 375 memset(&psmap, 0, sizeof(psmap)); 376 377 psmap.curnextind = (data[0]>>7) & 0x1; 378 psmap.version = data[0] & 0x1f; 379 380 data += 2; 381 382 psmap.psinfolen = (data[0] << 8) | data[1]; 383 384 data += psmap.psinfolen; 385 386 psmap.esstreammaplen = (data[0] << 8) | data[1]; 387 388 psmap.esmapnum = psmap.esstreammaplen / 4; 389 390 for (i=0; i<psmap.esmapnum; i++) 391 { 392 if (i == max_es_nums) 393 { 394 printf("now just save %d es info!\n", max_es_nums); 395 396 break; 397 } 398 399 psmap.esmaps[i].streamtype = data[0]; 400 psmap.esmaps[i].esid = data[1]; 401 psmap.esmaps[i].esinfolen = (data[2] << 8) | data[3]; 402 403 data += (4+psmap.esmaps[i].esinfolen); 404 } 405 406 #ifdef printf_debug 407 int mnum = 0; 408 409 if (psmap.esmapnum > max_es_nums) 410 { 411 mnum = max_es_nums; 412 } 413 414 for (i=0; i<mnum; i++) 415 { 416 printf("%s%sstreamnum: %d, streamtype: %d, esid: %d\n", tab44, tab44, i, psmap.esmaps[i].streamtype, psmap.esmaps[i].esid); 417 } 418 #endif 419 } 420 421 static void getpdts(unsigned char *pdtsdata, long long *pdts, unsigned char *pdtsstring) 422 { 423 int hour = 0; 424 int minute = 0; 425 int second = 0; 426 int msecond = 0; 427 428 long long pts = 0; 429 long long pts2ms = 0; 430 431 unsigned char ptsstr[max_pdts_string_len+1] = {0}; 432 433 /* 5个字节转33位的值 */ 434 pts = (((pdtsdata[0]>>1) & 0x7) << 30) | (pdtsdata[1] << 22) | (((pdtsdata[2]>>1) & 0x7f) << 15) | (pdtsdata[3] << 7) | (pdtsdata[4]>>1 & 0x7f); 435 436 /* 90khz, 1000ms/90 */ 437 pts2ms = pts/90; 438 439 hour = pts2ms/(60*60*1000); 440 minute = (pts2ms - hour * (60*60*1000)) / (60*1000); 441 second = (pts2ms - hour * (60*60*1000) - minute * (60*1000)) / 1000; 442 msecond = pts2ms - hour * (60*60*1000) - minute * (60*1000) - second * 1000; 443 444 sprintf(ptsstr, "%02d:%02d:%02d:%03d", hour, minute, second, msecond); 445 446 ptsstr[max_pdts_string_len] = '\0'; 447 448 memcpy(pdtsstring, ptsstr, max_pdts_string_len); 449 450 *pdts = pts; 451 } 452 453 /********************************************************************************* 454 startcode(24) + streamid(8) + pes_len(16) + {header: flag1(8) + flag2(8, pts标识在这儿) + header_len(8)} + {header_data(header_len, 若前面的flag有数据, 数据就在这儿)} + pes_data(pes_len-3-header_len) 455 **********************************************************************************/ 456 static void parsepes(const unsigned char streamid, unsigned char* const pesdata, const unsigned short peslen) 457 { 458 unsigned char pts_dts_flag; 459 460 static int audionum = 0; 461 static int videonum = 0; 462 static int privatenum = 0; 463 static int paddingnum = 0; 464 465 unsigned char *data = null; 466 467 unsigned char pts[max_pdts_len+1] = {0}; 468 unsigned char dts[max_pdts_len+1] = {0}; 469 470 t_ps_pes pspes = {0}; 471 472 data = pesdata; 473 474 memset(&pspes, 0x0, sizeof(pspes)); 475 476 pspes.streamid = streamid; 477 478 if (((streamid>=0xc0) && (streamid<=0xdf)) || ((streamid>=0xe0) && (streamid<=0xef))) 479 { 480 pts_dts_flag = data[1]>>6 & 0x3; 481 482 pspes.pesheaderlen = data[2]; 483 484 data += 3; 485 486 switch (pts_dts_flag) 487 { 488 case 0: /* 00, no pts, dts */ 489 break; 490 491 case 2: /* 10, only pts*/ 492 memset(pts, 0x0, sizeof(pts)); 493 494 memcpy(pts, data, max_pdts_len); 495 496 getpdts(pts, &pspes.pts, pspes.ptsstr); 497 498 break; 499 500 case 3: /* 11 pts & dts*/ 501 memset(pts, 0x0, sizeof(pts)); 502 memset(dts, 0x0, sizeof(dts)); 503 504 memcpy(pts, data, max_pdts_len); 505 memcpy(dts, data+max_pdts_len, max_pdts_len); 506 507 getpdts(pts, &pspes.pts, pspes.ptsstr); 508 getpdts(dts, &pspes.dts, pspes.dtsstr); 509 510 break; 511 512 default: 513 break; 514 } 515 } 516 517 518 #ifdef printf_debug 519 if ((streamid>=0xc0) && (streamid<=0xdf)) 520 { 521 audionum++; 522 523 printf("%s%spes, audio[%d], streamid: 0x%02x(%d), peslength: %d, pesheaderlen: %d", tab44, tab44, audionum, streamid, streamid, peslen, pspes.pesheaderlen); 524 525 if (2 == pts_dts_flag) 526 { 527 printf(", pts: %s(%lld)", pspes.ptsstr, pspes.pts); 528 } 529 530 if (3 == pts_dts_flag) 531 { 532 printf(", pts: %s(%lld), dts: %s(%lld)", pspes.ptsstr, pspes.pts, pspes.dtsstr, pspes.dts); 533 } 534 535 printf("\n"); 536 } 537 else if ((streamid>=0xe0) && (streamid<=0xef)) 538 { 539 videonum++; 540 541 printf("%s%spes, video[%d], streamid: 0x%02x(%d), peslength: %d, pesheaderlen: %d", tab44, tab44, videonum, streamid, streamid, peslen, pspes.pesheaderlen); 542 543 if (2 == pts_dts_flag) 544 { 545 printf(", pts: %s(%lld)", pspes.ptsstr, pspes.pts); 546 } 547 548 if (3 == pts_dts_flag) 549 { 550 printf(", pts: %s(%lld), dts: %s(%lld)", pspes.ptsstr, pspes.pts, pspes.dtsstr, pspes.dts); 551 } 552 553 printf("\n"); 554 } 555 else if ((streamid==0xbd) || (streamid==0xbf)) 556 { 557 privatenum++; 558 559 printf("%s%spes, private[%d], streamid: 0x%02x(%d), peslength: %d\n", tab44, tab44, privatenum, streamid, streamid, peslen); 560 } 561 else if (streamid==0xbe) 562 { 563 paddingnum++; 564 565 printf("%s%spes, padding[%d], streamid: 0x%02x(%d), peslength: %d\n", tab44, tab44, privatenum, streamid, streamid, peslen); 566 } 567 else 568 { 569 printf("%s%spes, streamid: 0x%02x(%d), peslength: %d\n", tab44, tab44, streamid, streamid, peslen); 570 } 571 #endif 572 } 573 574 int main(int argc, char *argv[]) 575 { 576 int readlen = 0; 577 int pack_stuffing_length = 0; 578 579 unsigned int startcode = 0; 580 581 unsigned short pespacketlen = 0; 582 unsigned short pssystemheaderlen = 0; 583 unsigned short pssystemmapheaderlen = 0; 584 585 unsigned char pesstreamid = 0; 586 587 unsigned char scodedata[max_ps_startcode_len+1] = {0}; 588 unsigned char psdata[mmin_ps_header_len-3] = {0}; 589 590 unsigned char *pesdata = null; 591 592 file *fp = null; 593 594 if (2 != argc) 595 { 596 printf("usage: flvparse **.mpg\n"); 597 598 return -1; 599 } 600 601 fp = fopen(argv[1], "rb"); 602 if (!fp) 603 { 604 printf("open file[%s] error!\n", argv[1]); 605 606 return -1; 607 } 608 609 while (1) 610 { 611 readlen = fread(&startcode, max_ps_startcode_len, 1, fp); 612 if (1 != readlen) 613 { 614 break; 615 } 616 617 startcode = ntohl(startcode); 618 619 #ifdef printf_debug 620 if (scode_ps_header == startcode) 621 { 622 printf("+startcode: 0x%08x\n", startcode); 623 } 624 else 625 { 626 printf("%s+startcode: 0x%08x\n", tab44, startcode); 627 } 628 #endif 629 630 if ((0 != (startcode>>24 & 0xff)) && (0 != (startcode>>16 & 0xff)) && (1 != (startcode>>8 & 0xff))) 631 { 632 return -1; 633 } 634 635 switch (startcode) 636 { 637 case scode_ps_header: 638 memset(psdata, 0x0, sizeof(psdata)); 639 640 readlen = fread(psdata, 1, mmin_ps_header_len-4, fp); 641 if ((mmin_ps_header_len-4) != readlen) 642 { 643 fclose(fp); 644 645 return 0; 646 } 647 648 pack_stuffing_length = psdata[mmin_ps_header_len-5] & 0x7; 649 650 fseek(fp, pack_stuffing_length, seek_cur); 651 652 break; 653 654 case scode_ps_system_header: 655 if (1 != fread(&pssystemheaderlen, 2, 1, fp)) 656 { 657 fclose(fp); 658 659 return 0; 660 } 661 662 pssystemheaderlen = ntohs(pssystemheaderlen); 663 664 fseek(fp, pssystemheaderlen, seek_cur); 665 666 break; 667 668 case scode_ps_system_map_header: 669 if (1 != fread(&pssystemmapheaderlen, 2, 1, fp)) 670 { 671 fclose(fp); 672 673 return 0; 674 } 675 676 pssystemmapheaderlen = ntohs(pssystemmapheaderlen); 677 678 pesdata = (unsigned char*)malloc(pssystemmapheaderlen); 679 if (pesdata) 680 { 681 memset(pesdata, 0x0, pespacketlen); 682 683 if (pssystemmapheaderlen != fread(pesdata, 1, pssystemmapheaderlen, fp)) 684 { 685 fclose(fp); 686 687 return 0; 688 } 689 690 parsepssystemmapheader(pesdata); 691 692 free(pesdata); 693 694 pesdata = null; 695 } 696 697 break; 698 699 case scode_ps_end: 700 #ifdef printf_debug 701 printf("ps is end!\n"); 702 #endif 703 704 return 0; 705 706 break; 707 708 /* pes pcaket */ 709 default: 710 pesstreamid = startcode & 0xff; 711 712 if (1 != fread(&pespacketlen, 2, 1, fp)) 713 { 714 fclose(fp); 715 716 return 0; 717 } 718 719 pespacketlen = ntohs(pespacketlen); 720 721 pesdata = (unsigned char*)malloc(pespacketlen); 722 if (pesdata) 723 { 724 memset(pesdata, 0x0, pespacketlen); 725 726 if (pespacketlen != fread(pesdata, 1, pespacketlen, fp)) 727 { 728 fclose(fp); 729 730 return 0; 731 } 732 733 parsepes(pesstreamid, pesdata, pespacketlen); 734 735 free(pesdata); 736 737 pesdata = null; 738 } 739 740 break; 741 } 742 } 743 744 fclose(fp); 745 746 return 0; 747 }