From 37e53f373500896c61b7cb288e9e5152ec29569e Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 23 Nov 2013 11:25:58 +0800 Subject: [PATCH] add ts PCR analysis, the tool MPEG-2-ts-packet-analysis.2.4.5.0 decode PCR wrong --- trunk/doc/ts-PCR-analysis.txt | 105 ++++++++++++++++++++++++++++++++++ trunk/research/ts_info.cpp | 89 ++++++++++++++++------------ 2 files changed, 158 insertions(+), 36 deletions(-) create mode 100644 trunk/doc/ts-PCR-analysis.txt diff --git a/trunk/doc/ts-PCR-analysis.txt b/trunk/doc/ts-PCR-analysis.txt new file mode 100644 index 000000000..1b4468a25 --- /dev/null +++ b/trunk/doc/ts-PCR-analysis.txt @@ -0,0 +1,105 @@ +packet#7: +Adaptation fields + Adaptation_field_length: 7 + discontinuity_indicator: False + random_access_indicator: True + ES_priority_indicator: False + PCR_flag: True + OPCR_flag: False + splicing_point_flag: False + transport_private_data_flag: False + adaptation_field_extension_flag: False + PCR: 50572350000 +PES header + stream_id: E0 (video stream 224) + PES_packet_length: 35808 + PES_scrambling: 0 + PES_priority: False + data_alignment: False + copyright: False + original_or_copy: False + PTS_flag: True + DTS_flag: True + ESCR_flag: False + ES_rate_flag: False + DSM_trick_mode_flag: False + additional_copy_info_flag: False + PES_CRC_flag: False + PES_extension_flag: False + PES_header_data_length: 10 + PTS: 168704280 + DTS: 168700500 + + + +packet#665: +Adaptation fields + Adaptation_field_length: 7 + discontinuity_indicator: False + random_access_indicator: True + ES_priority_indicator: False + PCR_flag: True + OPCR_flag: False + splicing_point_flag: False + transport_private_data_flag: False + adaptation_field_extension_flag: False + PCR: 50616225000 +PES header + stream_id: E0 (video stream 224) + PES_packet_length: 29213 + PES_scrambling: 0 + PES_priority: False + data_alignment: False + copyright: False + original_or_copy: False + PTS_flag: True + DTS_flag: True + ESCR_flag: False + ES_rate_flag: False + DSM_trick_mode_flag: False + additional_copy_info_flag: False + PES_CRC_flag: False + PES_extension_flag: False + PES_header_data_length: 10 + PTS: 168850530 + DTS: 168846750 + +参考nginx-rtmp函数:ngx_rtmp_mpegts_write_frame +其中,nginx-rtmp写入PCR的逻辑如下: + if (f->key) { + packet[3] |= 0x20; /* adaptation */ + + *p++ = 7; /* size */ + *p++ = 0x50; /* random access + PCR */ + + p = ngx_rtmp_mpegts_write_pcr(p, f->dts - NGX_RTMP_HLS_DELAY); + } +只要碰到关键帧,就写入PCR。 +ngx_rtmp_mpegts_write_pcr(u_char *p, uint64_t pcr) +{ + *p++ = (u_char) (pcr >> 25); + *p++ = (u_char) (pcr >> 17); + *p++ = (u_char) (pcr >> 9); + *p++ = (u_char) (pcr >> 1); + *p++ = (u_char) (pcr << 7 | 0x7e); + *p++ = 0; + + return p; +} +即将高9位置0,6个reserverd置1,低33位输出(little-endian)。 + +nginx-rtmp写入dts的逻辑如下: + p = ngx_rtmp_mpegts_write_pts(p, 1, f->dts + NGX_RTMP_HLS_DELAY); +也就是说, + pcr = f->dts - NGX_RTMP_HLS_DELAY + f->dts = dts - NGX_RTMP_HLS_DELAY +计算出来的: + pcr = program_clock_reference_base = 168574500 + dts = 168700500 + 168574500 = 168700500 - 63000 - 63000 +可见,工具MPEG-2 TS packet analyser分析出来的pcr是不对的。 + +解码出来的结果: +demuxer+read packet 0006 0001128 0x47 0x41 0x00 0x35 ... 0xb6 0x9f 0x89 +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 +ts+pes stream_id: 224 size: 35808 pts: 168704280 dts: 168700500 total: 35808 header: 13 packet_size: 35795 parsed_size: 157 diff --git a/trunk/research/ts_info.cpp b/trunk/research/ts_info.cpp index 16ed15677..aebc713ca 100755 --- a/trunk/research/ts_info.cpp +++ b/trunk/research/ts_info.cpp @@ -228,6 +228,9 @@ public: // user defined total adaption field size. int __field_size; + // logic pcr/original_pcr + int64_t pcr; + int64_t original_pcr; TSAdaptionField(); virtual ~TSAdaptionField(); @@ -764,6 +767,8 @@ TSAdaptionField::TSAdaptionField() af_ext_reserved = NULL; af_reserved = NULL; __field_size = 0; + pcr = 0; + original_pcr = 0; } TSAdaptionField::~TSAdaptionField() @@ -802,10 +807,6 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int transport_private_data_flag = (value >> 1) & 0x01; adaptation_field_extension_flag = (value >> 0) & 0x01; - trace("ts+af af flags parsed, discontinuity: %d random: %d priority: %d PCR: %d OPCR: %d slicing: %d private: %d extension: %d", - discontinuity_indicator, random_access_indicator, elementary_stream_priority_indicator, PCR_flag, OPCR_flag, splicing_point_flag, - transport_private_data_flag, adaptation_field_extension_flag); - char* pp = NULL; if (PCR_flag) { pp = (char*)&program_clock_reference_base; @@ -816,8 +817,14 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int pp[1] = *p++; pp[0] = *p++; - program_clock_reference_extension = program_clock_reference_base & 0x1F; - program_clock_reference_base = (program_clock_reference_base >> 9) & 0x1FFFFFFFF; + program_clock_reference_extension = program_clock_reference_base & 0x1ff; + program_clock_reference_base = (program_clock_reference_base >> 15) & 0x1ffffffff; + + // high 9bits + pcr = program_clock_reference_extension; + pcr = (pcr << 33) & 0x3fe00000000; + // low 33bits + pcr |= program_clock_reference_base; } if (OPCR_flag) { pp = (char*)&original_program_clock_reference_base; @@ -828,8 +835,14 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int pp[1] = *p++; pp[0] = *p++; - original_program_clock_reference_extension = original_program_clock_reference_base & 0x1F; - original_program_clock_reference_base = (original_program_clock_reference_base >> 9) & 0x1FFFFFFFF; + original_program_clock_reference_extension = original_program_clock_reference_base & 0x1ff; + original_program_clock_reference_base = (original_program_clock_reference_base >> 15) & 0x1ffffffff; + + // high 9bits + original_pcr = program_clock_reference_extension; + original_pcr = (original_pcr << 33) & 0x3fe00000000; + // low 33bits + original_pcr |= program_clock_reference_base; } if (splicing_point_flag) { splice_countdown = *p++; @@ -909,6 +922,10 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int p += af_size; } + 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"", + discontinuity_indicator, random_access_indicator, elementary_stream_priority_indicator, PCR_flag, OPCR_flag, splicing_point_flag, + transport_private_data_flag, adaptation_field_extension_flag, pcr, original_pcr); + return ret; } @@ -1550,6 +1567,34 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l return pmt->demux(ctx, pkt, start, last, p, pmsg); } if (pid && (pid->type == TSPidTypeVideo || pid->type == TSPidTypeAudio)) { + TSMessage* msg = ctx->get_msg(pkt->header->pid); + + // flush previous PES_packet_length(0) packets. + if (msg->packet_start_code_prefix == 0x01 + && pkt->header->payload_unit_start_indicator == 1 + && msg->PES_packet_length == 0 + ) { + msg->detach(ctx, pmsg); + // reparse current message + p = start; + return ret; + } + + // parse continous packet. + if (!pkt->header->payload_unit_start_indicator) { + if (msg->packet_start_code_prefix != 0x01) { + trace("ts+pes decode continous packet error, msg is empty."); + return -1; + } + msg->append(p, last - p); + + // for PES_packet_length is 0, donot attach it. + if (msg->PES_packet_length > 0) { + msg->detach(ctx, pmsg); + } + return ret; + } + type = pid->type; pes = new TSPayloadPES(); 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*& payload->size = TS_PACKET_SIZE - header->get_size() - adaption_field->get_size(); if (header->adaption_field_control == TSAdaptionTypePayloadOnly || header->adaption_field_control == TSAdaptionTypeBoth) { - TSMessage* msg = ctx->get_msg(header->pid); - - // flush previous PES_packet_length(0) packets. - if (msg->packet_start_code_prefix == 0x01 - && header->payload_unit_start_indicator == 1 - && msg->PES_packet_length == 0 - ) { - msg->detach(ctx, pmsg); - // reparse current message - p = start; - return ret; - } - - // parse continous packet. - if (!header->payload_unit_start_indicator) { - if (msg->packet_start_code_prefix != 0x01) { - trace("ts+pes decode continous packet error, msg is empty."); - return -1; - } - msg->append(p, last - p); - - // for PES_packet_length is 0, donot attach it. - if (msg->PES_packet_length > 0) { - msg->detach(ctx, pmsg); - } - return ret; - } - // parse new packet. if ((ret = payload->demux(ctx, this, start, last, p, pmsg)) != 0) { trace("ts+header payload decode error. ret=%d", ret);