add ts PCR analysis, the tool MPEG-2-ts-packet-analysis.2.4.5.0 decode PCR wrong
正在显示
2 个修改的文件
包含
158 行增加
和
36 行删除
trunk/doc/ts-PCR-analysis.txt
0 → 100644
| 1 | +packet#7: | ||
| 2 | +Adaptation fields | ||
| 3 | + Adaptation_field_length: 7 | ||
| 4 | + discontinuity_indicator: False | ||
| 5 | + random_access_indicator: True | ||
| 6 | + ES_priority_indicator: False | ||
| 7 | + PCR_flag: True | ||
| 8 | + OPCR_flag: False | ||
| 9 | + splicing_point_flag: False | ||
| 10 | + transport_private_data_flag: False | ||
| 11 | + adaptation_field_extension_flag: False | ||
| 12 | + PCR: 50572350000 | ||
| 13 | +PES header | ||
| 14 | + stream_id: E0 (video stream 224) | ||
| 15 | + PES_packet_length: 35808 | ||
| 16 | + PES_scrambling: 0 | ||
| 17 | + PES_priority: False | ||
| 18 | + data_alignment: False | ||
| 19 | + copyright: False | ||
| 20 | + original_or_copy: False | ||
| 21 | + PTS_flag: True | ||
| 22 | + DTS_flag: True | ||
| 23 | + ESCR_flag: False | ||
| 24 | + ES_rate_flag: False | ||
| 25 | + DSM_trick_mode_flag: False | ||
| 26 | + additional_copy_info_flag: False | ||
| 27 | + PES_CRC_flag: False | ||
| 28 | + PES_extension_flag: False | ||
| 29 | + PES_header_data_length: 10 | ||
| 30 | + PTS: 168704280 | ||
| 31 | + DTS: 168700500 | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | +packet#665: | ||
| 36 | +Adaptation fields | ||
| 37 | + Adaptation_field_length: 7 | ||
| 38 | + discontinuity_indicator: False | ||
| 39 | + random_access_indicator: True | ||
| 40 | + ES_priority_indicator: False | ||
| 41 | + PCR_flag: True | ||
| 42 | + OPCR_flag: False | ||
| 43 | + splicing_point_flag: False | ||
| 44 | + transport_private_data_flag: False | ||
| 45 | + adaptation_field_extension_flag: False | ||
| 46 | + PCR: 50616225000 | ||
| 47 | +PES header | ||
| 48 | + stream_id: E0 (video stream 224) | ||
| 49 | + PES_packet_length: 29213 | ||
| 50 | + PES_scrambling: 0 | ||
| 51 | + PES_priority: False | ||
| 52 | + data_alignment: False | ||
| 53 | + copyright: False | ||
| 54 | + original_or_copy: False | ||
| 55 | + PTS_flag: True | ||
| 56 | + DTS_flag: True | ||
| 57 | + ESCR_flag: False | ||
| 58 | + ES_rate_flag: False | ||
| 59 | + DSM_trick_mode_flag: False | ||
| 60 | + additional_copy_info_flag: False | ||
| 61 | + PES_CRC_flag: False | ||
| 62 | + PES_extension_flag: False | ||
| 63 | + PES_header_data_length: 10 | ||
| 64 | + PTS: 168850530 | ||
| 65 | + DTS: 168846750 | ||
| 66 | + | ||
| 67 | +参考nginx-rtmp函数:ngx_rtmp_mpegts_write_frame | ||
| 68 | +其中,nginx-rtmp写入PCR的逻辑如下: | ||
| 69 | + if (f->key) { | ||
| 70 | + packet[3] |= 0x20; /* adaptation */ | ||
| 71 | + | ||
| 72 | + *p++ = 7; /* size */ | ||
| 73 | + *p++ = 0x50; /* random access + PCR */ | ||
| 74 | + | ||
| 75 | + p = ngx_rtmp_mpegts_write_pcr(p, f->dts - NGX_RTMP_HLS_DELAY); | ||
| 76 | + } | ||
| 77 | +只要碰到关键帧,就写入PCR。 | ||
| 78 | +ngx_rtmp_mpegts_write_pcr(u_char *p, uint64_t pcr) | ||
| 79 | +{ | ||
| 80 | + *p++ = (u_char) (pcr >> 25); | ||
| 81 | + *p++ = (u_char) (pcr >> 17); | ||
| 82 | + *p++ = (u_char) (pcr >> 9); | ||
| 83 | + *p++ = (u_char) (pcr >> 1); | ||
| 84 | + *p++ = (u_char) (pcr << 7 | 0x7e); | ||
| 85 | + *p++ = 0; | ||
| 86 | + | ||
| 87 | + return p; | ||
| 88 | +} | ||
| 89 | +即将高9位置0,6个reserverd置1,低33位输出(little-endian)。 | ||
| 90 | + | ||
| 91 | +nginx-rtmp写入dts的逻辑如下: | ||
| 92 | + p = ngx_rtmp_mpegts_write_pts(p, 1, f->dts + NGX_RTMP_HLS_DELAY); | ||
| 93 | +也就是说, | ||
| 94 | + pcr = f->dts - NGX_RTMP_HLS_DELAY | ||
| 95 | + f->dts = dts - NGX_RTMP_HLS_DELAY | ||
| 96 | +计算出来的: | ||
| 97 | + pcr = program_clock_reference_base = 168574500 | ||
| 98 | + dts = 168700500 | ||
| 99 | + 168574500 = 168700500 - 63000 - 63000 | ||
| 100 | +可见,工具MPEG-2 TS packet analyser分析出来的pcr是不对的。 | ||
| 101 | + | ||
| 102 | +解码出来的结果: | ||
| 103 | +demuxer+read packet 0006 0001128 0x47 0x41 0x00 0x35 ... 0xb6 0x9f 0x89 | ||
| 104 | +ts+af af flags parsed, discontinuity: 0 random: 1 priority: 0 PCR: 1 OPCR: 0 slicing: 0 private: 0 extension: 0 pcr: 168574500 opcr: 0 | ||
| 105 | +ts+pes stream_id: 224 size: 35808 pts: 168704280 dts: 168700500 total: 35808 header: 13 packet_size: 35795 parsed_size: 157 |
| @@ -228,6 +228,9 @@ public: | @@ -228,6 +228,9 @@ public: | ||
| 228 | 228 | ||
| 229 | // user defined total adaption field size. | 229 | // user defined total adaption field size. |
| 230 | int __field_size; | 230 | int __field_size; |
| 231 | + // logic pcr/original_pcr | ||
| 232 | + int64_t pcr; | ||
| 233 | + int64_t original_pcr; | ||
| 231 | 234 | ||
| 232 | TSAdaptionField(); | 235 | TSAdaptionField(); |
| 233 | virtual ~TSAdaptionField(); | 236 | virtual ~TSAdaptionField(); |
| @@ -764,6 +767,8 @@ TSAdaptionField::TSAdaptionField() | @@ -764,6 +767,8 @@ TSAdaptionField::TSAdaptionField() | ||
| 764 | af_ext_reserved = NULL; | 767 | af_ext_reserved = NULL; |
| 765 | af_reserved = NULL; | 768 | af_reserved = NULL; |
| 766 | __field_size = 0; | 769 | __field_size = 0; |
| 770 | + pcr = 0; | ||
| 771 | + original_pcr = 0; | ||
| 767 | } | 772 | } |
| 768 | 773 | ||
| 769 | TSAdaptionField::~TSAdaptionField() | 774 | TSAdaptionField::~TSAdaptionField() |
| @@ -802,10 +807,6 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | @@ -802,10 +807,6 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | ||
| 802 | transport_private_data_flag = (value >> 1) & 0x01; | 807 | transport_private_data_flag = (value >> 1) & 0x01; |
| 803 | adaptation_field_extension_flag = (value >> 0) & 0x01; | 808 | adaptation_field_extension_flag = (value >> 0) & 0x01; |
| 804 | 809 | ||
| 805 | - trace("ts+af af flags parsed, discontinuity: %d random: %d priority: %d PCR: %d OPCR: %d slicing: %d private: %d extension: %d", | ||
| 806 | - discontinuity_indicator, random_access_indicator, elementary_stream_priority_indicator, PCR_flag, OPCR_flag, splicing_point_flag, | ||
| 807 | - transport_private_data_flag, adaptation_field_extension_flag); | ||
| 808 | - | ||
| 809 | char* pp = NULL; | 810 | char* pp = NULL; |
| 810 | if (PCR_flag) { | 811 | if (PCR_flag) { |
| 811 | pp = (char*)&program_clock_reference_base; | 812 | pp = (char*)&program_clock_reference_base; |
| @@ -816,8 +817,14 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | @@ -816,8 +817,14 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | ||
| 816 | pp[1] = *p++; | 817 | pp[1] = *p++; |
| 817 | pp[0] = *p++; | 818 | pp[0] = *p++; |
| 818 | 819 | ||
| 819 | - program_clock_reference_extension = program_clock_reference_base & 0x1F; | ||
| 820 | - program_clock_reference_base = (program_clock_reference_base >> 9) & 0x1FFFFFFFF; | 820 | + program_clock_reference_extension = program_clock_reference_base & 0x1ff; |
| 821 | + program_clock_reference_base = (program_clock_reference_base >> 15) & 0x1ffffffff; | ||
| 822 | + | ||
| 823 | + // high 9bits | ||
| 824 | + pcr = program_clock_reference_extension; | ||
| 825 | + pcr = (pcr << 33) & 0x3fe00000000; | ||
| 826 | + // low 33bits | ||
| 827 | + pcr |= program_clock_reference_base; | ||
| 821 | } | 828 | } |
| 822 | if (OPCR_flag) { | 829 | if (OPCR_flag) { |
| 823 | pp = (char*)&original_program_clock_reference_base; | 830 | pp = (char*)&original_program_clock_reference_base; |
| @@ -828,8 +835,14 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | @@ -828,8 +835,14 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | ||
| 828 | pp[1] = *p++; | 835 | pp[1] = *p++; |
| 829 | pp[0] = *p++; | 836 | pp[0] = *p++; |
| 830 | 837 | ||
| 831 | - original_program_clock_reference_extension = original_program_clock_reference_base & 0x1F; | ||
| 832 | - original_program_clock_reference_base = (original_program_clock_reference_base >> 9) & 0x1FFFFFFFF; | 838 | + original_program_clock_reference_extension = original_program_clock_reference_base & 0x1ff; |
| 839 | + original_program_clock_reference_base = (original_program_clock_reference_base >> 15) & 0x1ffffffff; | ||
| 840 | + | ||
| 841 | + // high 9bits | ||
| 842 | + original_pcr = program_clock_reference_extension; | ||
| 843 | + original_pcr = (original_pcr << 33) & 0x3fe00000000; | ||
| 844 | + // low 33bits | ||
| 845 | + original_pcr |= program_clock_reference_base; | ||
| 833 | } | 846 | } |
| 834 | if (splicing_point_flag) { | 847 | if (splicing_point_flag) { |
| 835 | splice_countdown = *p++; | 848 | splice_countdown = *p++; |
| @@ -909,6 +922,10 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | @@ -909,6 +922,10 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int | ||
| 909 | p += af_size; | 922 | p += af_size; |
| 910 | } | 923 | } |
| 911 | 924 | ||
| 925 | + trace("ts+af af flags parsed, discontinuity: %d random: %d priority: %d PCR: %d OPCR: %d slicing: %d private: %d extension: %d pcr: %"PRId64" opcr: %"PRId64"", | ||
| 926 | + discontinuity_indicator, random_access_indicator, elementary_stream_priority_indicator, PCR_flag, OPCR_flag, splicing_point_flag, | ||
| 927 | + transport_private_data_flag, adaptation_field_extension_flag, pcr, original_pcr); | ||
| 928 | + | ||
| 912 | return ret; | 929 | return ret; |
| 913 | } | 930 | } |
| 914 | 931 | ||
| @@ -1550,6 +1567,34 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l | @@ -1550,6 +1567,34 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l | ||
| 1550 | return pmt->demux(ctx, pkt, start, last, p, pmsg); | 1567 | return pmt->demux(ctx, pkt, start, last, p, pmsg); |
| 1551 | } | 1568 | } |
| 1552 | if (pid && (pid->type == TSPidTypeVideo || pid->type == TSPidTypeAudio)) { | 1569 | if (pid && (pid->type == TSPidTypeVideo || pid->type == TSPidTypeAudio)) { |
| 1570 | + TSMessage* msg = ctx->get_msg(pkt->header->pid); | ||
| 1571 | + | ||
| 1572 | + // flush previous PES_packet_length(0) packets. | ||
| 1573 | + if (msg->packet_start_code_prefix == 0x01 | ||
| 1574 | + && pkt->header->payload_unit_start_indicator == 1 | ||
| 1575 | + && msg->PES_packet_length == 0 | ||
| 1576 | + ) { | ||
| 1577 | + msg->detach(ctx, pmsg); | ||
| 1578 | + // reparse current message | ||
| 1579 | + p = start; | ||
| 1580 | + return ret; | ||
| 1581 | + } | ||
| 1582 | + | ||
| 1583 | + // parse continous packet. | ||
| 1584 | + if (!pkt->header->payload_unit_start_indicator) { | ||
| 1585 | + if (msg->packet_start_code_prefix != 0x01) { | ||
| 1586 | + trace("ts+pes decode continous packet error, msg is empty."); | ||
| 1587 | + return -1; | ||
| 1588 | + } | ||
| 1589 | + msg->append(p, last - p); | ||
| 1590 | + | ||
| 1591 | + // for PES_packet_length is 0, donot attach it. | ||
| 1592 | + if (msg->PES_packet_length > 0) { | ||
| 1593 | + msg->detach(ctx, pmsg); | ||
| 1594 | + } | ||
| 1595 | + return ret; | ||
| 1596 | + } | ||
| 1597 | + | ||
| 1553 | type = pid->type; | 1598 | type = pid->type; |
| 1554 | pes = new TSPayloadPES(); | 1599 | pes = new TSPayloadPES(); |
| 1555 | return pes->demux(ctx, pkt, start, last, p, pmsg); | 1600 | return pes->demux(ctx, pkt, start, last, p, pmsg); |
| @@ -1599,34 +1644,6 @@ int TSPacket::demux(TSContext* ctx, u_int8_t* start, u_int8_t* last, u_int8_t*& | @@ -1599,34 +1644,6 @@ int TSPacket::demux(TSContext* ctx, u_int8_t* start, u_int8_t* last, u_int8_t*& | ||
| 1599 | payload->size = TS_PACKET_SIZE - header->get_size() - adaption_field->get_size(); | 1644 | payload->size = TS_PACKET_SIZE - header->get_size() - adaption_field->get_size(); |
| 1600 | 1645 | ||
| 1601 | if (header->adaption_field_control == TSAdaptionTypePayloadOnly || header->adaption_field_control == TSAdaptionTypeBoth) { | 1646 | if (header->adaption_field_control == TSAdaptionTypePayloadOnly || header->adaption_field_control == TSAdaptionTypeBoth) { |
| 1602 | - TSMessage* msg = ctx->get_msg(header->pid); | ||
| 1603 | - | ||
| 1604 | - // flush previous PES_packet_length(0) packets. | ||
| 1605 | - if (msg->packet_start_code_prefix == 0x01 | ||
| 1606 | - && header->payload_unit_start_indicator == 1 | ||
| 1607 | - && msg->PES_packet_length == 0 | ||
| 1608 | - ) { | ||
| 1609 | - msg->detach(ctx, pmsg); | ||
| 1610 | - // reparse current message | ||
| 1611 | - p = start; | ||
| 1612 | - return ret; | ||
| 1613 | - } | ||
| 1614 | - | ||
| 1615 | - // parse continous packet. | ||
| 1616 | - if (!header->payload_unit_start_indicator) { | ||
| 1617 | - if (msg->packet_start_code_prefix != 0x01) { | ||
| 1618 | - trace("ts+pes decode continous packet error, msg is empty."); | ||
| 1619 | - return -1; | ||
| 1620 | - } | ||
| 1621 | - msg->append(p, last - p); | ||
| 1622 | - | ||
| 1623 | - // for PES_packet_length is 0, donot attach it. | ||
| 1624 | - if (msg->PES_packet_length > 0) { | ||
| 1625 | - msg->detach(ctx, pmsg); | ||
| 1626 | - } | ||
| 1627 | - return ret; | ||
| 1628 | - } | ||
| 1629 | - | ||
| 1630 | // parse new packet. | 1647 | // parse new packet. |
| 1631 | if ((ret = payload->demux(ctx, this, start, last, p, pmsg)) != 0) { | 1648 | if ((ret = payload->demux(ctx, this, start, last, p, pmsg)) != 0) { |
| 1632 | trace("ts+header payload decode error. ret=%d", ret); | 1649 | trace("ts+header payload decode error. ret=%d", ret); |
-
请 注册 或 登录 后发表评论