mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
add ts PCR analysis, the tool MPEG-2-ts-packet-analysis.2.4.5.0 decode PCR wrong
This commit is contained in:
parent
71015dc4a1
commit
37e53f3735
2 changed files with 158 additions and 36 deletions
105
trunk/doc/ts-PCR-analysis.txt
Normal file
105
trunk/doc/ts-PCR-analysis.txt
Normal file
|
@ -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
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue