From a0ecc5a305ba9591e7e4662b59e80c294de94fb2 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 21 Nov 2013 22:33:32 +0800 Subject: [PATCH] finger out the PES_packet_length is 0 --- trunk/doc/ts-audio-video-analysis.txt | 160 +++++++++++----- trunk/research/ts_info.cpp | 263 ++++++++++++++++---------- 2 files changed, 276 insertions(+), 147 deletions(-) diff --git a/trunk/doc/ts-audio-video-analysis.txt b/trunk/doc/ts-audio-video-analysis.txt index 775f5f2f7..bb165de1e 100755 --- a/trunk/doc/ts-audio-video-analysis.txt +++ b/trunk/doc/ts-audio-video-analysis.txt @@ -228,52 +228,114 @@ TS -3031¸öts°üÊÇ¿Õ°ü£¬½âÎöÓÐÎÊÌ⣺ -47 41 00 38 07 50 05 09 5A A6 7E 00 00 00 01 E0 -00 00 80 C0 0A 31 28 53 60 81 11 28 53 42 F9 00 -00 00 01 09 F0 00 00 00 01 67 64 00 28 AC D1 C0 -50 05 BB FF 00 2D 00 22 10 00 00 03 00 10 00 00 -03 03 08 F1 83 11 E0 00 00 00 01 68 E9 AB 2C 8B -00 00 01 65 88 84 00 42 BF 08 EE 00 02 B2 75 8D -9F C4 24 E5 BD 27 87 F1 E4 09 A0 51 2D 12 FC F5 -6E 31 3D C4 0E 3F 51 47 07 BD D2 8C AB 72 1C 2D -D0 FA 2F 7D EF AA FB 17 C1 08 AD 36 8D F1 41 35 -E0 20 AE E8 75 66 39 15 78 88 01 E8 2E 4E 8A 8B -F8 04 68 BF EC 82 59 86 DE E1 66 32 37 FA 78 6D -01 EF C0 2C 6B A6 E9 36 44 4B C8 37 - -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: 50699466000 - -PES header - stream_id: E0 (video stream 224) - PES_packet_length: 0 (undefined) - 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: 169128000 - DTS: 169124220 - -Video sequence -Sequence header code not found in this packet -AFD not found in this packet \ No newline at end of file +µÚ3030¸ö°ü½âÎöÓеãÎÊÌ⣬ÉèÖÃÌõ¼þ¶Ïµã£º +condition 1 ctx->ts_packet_count == 3030 +·¢ÏÖÊý¾ÝÈçÏ£º +(gdb) x /188xb 0x7fffffffe2f0 +0x7fffffffe2f0: 0x47 0x41 0x00 0x38 0x07 0x50 0x05 0x09 +0x7fffffffe2f8: 0x5a 0xa6 0x7e 0x00 0x00 0x00 0x01 0xe0 +0x7fffffffe300: 0x00 0x00 0x80 0xc0 0x0a 0x31 0x28 0x53 +0x7fffffffe308: 0x60 0x81 0x11 0x28 0x53 0x42 0xf9 0x00 +0x7fffffffe310: 0x00 0x00 0x01 0x09 0xf0 0x00 0x00 0x00 +0x7fffffffe318: 0x01 0x67 0x64 0x00 0x28 0xac 0xd1 0xc0 +0x7fffffffe320: 0x50 0x05 0xbb 0xff 0x00 0x2d 0x00 0x22 +0x7fffffffe328: 0x10 0x00 0x00 0x03 0x00 0x10 0x00 0x00 +0x7fffffffe330: 0x03 0x03 0x08 0xf1 0x83 0x11 0xe0 0x00 +0x7fffffffe338: 0x00 0x00 0x01 0x68 0xe9 0xab 0x2c 0x8b +0x7fffffffe340: 0x00 0x00 0x01 0x65 0x88 0x84 0x00 0x42 +0x7fffffffe348: 0xbf 0x08 0xee 0x00 0x02 0xb2 0x75 0x8d +0x7fffffffe350: 0x9f 0xc4 0x24 0xe5 0xbd 0x27 0x87 0xf1 +0x7fffffffe358: 0xe4 0x09 0xa0 0x51 0x2d 0x12 0xfc 0xf5 +0x7fffffffe360: 0x6e 0x31 0x3d 0xc4 0x0e 0x3f 0x51 0x47 +0x7fffffffe368: 0x07 0xbd 0xd2 0x8c 0xab 0x72 0x1c 0x2d +0x7fffffffe370: 0xd0 0xfa 0x2f 0x7d 0xef 0xaa 0xfb 0x17 +0x7fffffffe378: 0xc1 0x08 0xad 0x36 0x8d 0xf1 0x41 0x35 +0x7fffffffe380: 0xe0 0x20 0xae 0xe8 0x75 0x66 0x39 0x15 +0x7fffffffe388: 0x78 0x88 0x01 0xe8 0x2e 0x4e 0x8a 0x8b +0x7fffffffe390: 0xf8 0x04 0x68 0xbf 0xec 0x82 0x59 0x86 +0x7fffffffe398: 0xde 0xe1 0x66 0x32 0x37 0xfa 0x78 0x6d +0x7fffffffe3a0: 0x01 0xef 0xc0 0x2c 0x6b 0xa6 0xe9 0x36 +0x7fffffffe3a8: 0x44 0x4b 0xc8 0x37 +header½âÎöÈçÏ£º +(gdb) p *this +$74 = {_vptr.TSHeader = 0x4080b0, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 1 '\001', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypeBoth, continuity_counter = 8 '\b'} +(gdb) p ctx->get(pid)[0] +$76 = {type = TSPidTypeVideo, stream_type = TSStreamTypeVideoH264, pid = 256, continuity_counter = 8 '\b'} +(gdb) p ctx->get_msg(256)[0] +$124 = {_vptr.TSMessage = 0x408290, pid = 256, type = TSPidTypeVideo, stream_type = TSStreamTypeVideoH264, + continuity_counter = 8 '\b', PES_packet_length = 0, stream_id = 224 '\340', packet_start_code_prefix = 1, + packet_header_size = 13, parsed_packet_size = 144, packet_data_size = 144, packet_data = 0x60b300 ""} +ÌØÊâµÄÊÇ£ºPES_packet_lengthΪ0£¬Ò²¾ÍÊÇδ֪³¤¶È¡£ +½âÎöÏÂÒ»¸ö°ü£¬headerΪ£º +(gdb) p header[0] +$123 = {_vptr.TSHeader = 0x408170, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 9 '\t'} +Õâ¸ö°üµÄ±êʶÊÇcontinuity_counterΪÉÏÒ»¸ö°üµÄÁ¬Ðø¡£Õâ¸ö°üÀïÃæÊÇ´¿´âµÄÊý¾Ý£º +(gdb) x /184xb 0x7fffffffe2f4 +0x7fffffffe2f4: 0x9c 0xfa 0x8c 0xc9 0x02 0x36 0xc2 0x46 +0x7fffffffe2fc: 0x97 0x01 0x31 0x3d 0xfa 0x83 0xc2 0x88 +0x7fffffffe304: 0x6b 0xb3 0x1c 0x63 0xcf 0xc6 0xc4 0xa6 +0x7fffffffe30c: 0xe2 0xa7 0xb3 0x26 0x62 0x7e 0xb4 0xf0 +0x7fffffffe314: 0x17 0x13 0x4c 0xd5 0x1b 0xee 0x80 0x37 +0x7fffffffe31c: 0x8f 0x6a 0xad 0x41 0x8f 0x43 0x39 0xbe +0x7fffffffe324: 0x2f 0x51 0xb4 0x0a 0x54 0x62 0xab 0xdc +0x7fffffffe32c: 0x11 0x92 0x92 0x85 0x18 0x92 0x29 0xd5 +0x7fffffffe334: 0xb5 0xbc 0x00 0x9e 0x26 0xc3 0xa4 0x04 +0x7fffffffe33c: 0xb6 0x97 0x62 0x9b 0x3b 0x3c 0x09 0x6b +0x7fffffffe344: 0x68 0x15 0xe7 0xcc 0x71 0xd9 0xb5 0x02 +0x7fffffffe34c: 0x19 0x8a 0x06 0x90 0x22 0xcd 0x3e 0x82 +0x7fffffffe354: 0xff 0x48 0x73 0x8b 0x00 0xdc 0xe5 0xdb +0x7fffffffe35c: 0x83 0x13 0x5e 0xe8 0x63 0xe9 0xb6 0xf0 +0x7fffffffe364: 0xc5 0x21 0x03 0x57 0xfb 0xb2 0xe1 0x9c +0x7fffffffe36c: 0x71 0x3e 0x36 0xe3 0x05 0xb7 0xf1 0x85 +0x7fffffffe374: 0x88 0x0e 0x51 0x52 0xd8 0x3c 0x80 0x1a +0x7fffffffe37c: 0x34 0xff 0xd9 0x5f 0x69 0xb4 0x9d 0xd7 +0x7fffffffe384: 0xc2 0x21 0xa8 0x85 0xc8 0xa2 0xdd 0xb8 +0x7fffffffe38c: 0xa3 0x43 0x2f 0x7e 0xc8 0xac 0x1b 0x67 +0x7fffffffe394: 0x17 0x6c 0x74 0xea 0x97 0xb8 0xa4 0xcf +0x7fffffffe39c: 0x43 0xf3 0x1c 0xad 0x89 0x91 0x28 0x49 +0x7fffffffe3a4: 0xf2 0xe8 0x0c 0xbf 0x75 0x8a 0x1c 0xac +ºóÐø»¹Óм¸¸ö°ü£º +$136 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 10 '\n'} +$137 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 11 '\v'} +$138 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 12 '\f'} +$141 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 13 '\r'} +$142 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 14 '\016'} +$143 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 15 '\017'} +È»ºó£¬Õâ¸ö°ü±äÁË£¬µ«ÊÇ»¹ÊǼÌÐøÇ°ÃæµÄ°ü£¬ÒòΪÊÇ0xFÒç³ö£º +$144 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 0 '\000'} +$148 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 0 '\000', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 1 '\001'} +Èç´ËÑ­»·£¬¿ÉÒÔÑ­»·ºÜ¶à´Î¡£Ò»Ö±µ½Õâ¸ö°ü£º +$556 = {_vptr.TSHeader = 0x408250, sync_byte = 71 'G', transport_error_indicator = 0 '\000', + payload_unit_start_indicator = 1 '\001', transport_priority = 0 '\000', pid = 256, + transport_scrambling_control = 0 '\000', adaption_field_control = TSAdaptionTypePayloadOnly, + continuity_counter = 4 '\004'} +ÆäÖеģºpayload_unit_start_indicatorΪ1¡£ \ No newline at end of file diff --git a/trunk/research/ts_info.cpp b/trunk/research/ts_info.cpp index 122a939b3..a89e8bd83 100755 --- a/trunk/research/ts_info.cpp +++ b/trunk/research/ts_info.cpp @@ -13,6 +13,7 @@ g++ -o ts_info ts_info.cpp -g -O0 -ansi #include #include #include +#include #include #include @@ -55,22 +56,33 @@ Annex A // Transport Stream packets are 188 bytes in length. #define TS_PACKET_SIZE 188 -// Program Association Table(see Table 2-25). -#define PID_PAT 0x00 -// Conditional Access Table (see Table 2-27). -#define PID_CAT 0x01 -// Transport Stream Description Table -#define PID_TSDT 0x02 -// null packets (see Table 2-3) -#define PID_NULL 0x01FFF +enum TSPidTable +{ + // Program Association Table(see Table 2-25). + TSPidTablePAT = 0x00, + // Conditional Access Table (see Table 2-27). + TSPidTableCAT = 0x01, + // Transport Stream Description Table + TSPidTableTSDT = 0x02, + // null packets (see Table 2-3) + TSPidTableNULL = 0x01FFF, +}; /*adaptation_field_control*/ -// No adaptation_field, payload only -#define AFC_PAYLOAD_ONLY 0x01 -// Adaptation_field only, no payload -#define AFC_ADAPTION_ONLY 0x02 -// Adaptation_field followed by payload -#define AFC_BOTH 0x03 +/** +* Table 2-5 – Adaptation field control values, page 38. +*/ +enum TSAdaptionType +{ + // Reserved for future use by ISO/IEC + TSAdaptionTypeReserved = 0x00, + // No adaptation_field, payload only + TSAdaptionTypePayloadOnly = 0x01, + // Adaptation_field only, no payload + TSAdaptionTypeAdaptionOnly = 0x02, + // Adaptation_field followed by payload + TSAdaptionTypeBoth = 0x03, +}; #endif // Table 2-29 – Stream type assignments. page 66. @@ -143,10 +155,10 @@ public: int8_t transport_error_indicator; //1bit int8_t payload_unit_start_indicator; //1bit int8_t transport_priority; //1bit - u_int16_t pid; //13bits + TSPidTable pid; //13bits // 1B int8_t transport_scrambling_control; //2bits - int8_t adaption_field_control; //2bits + TSAdaptionType adaption_field_control; //2bits u_int8_t continuity_counter; //4bits TSHeader(); @@ -214,8 +226,8 @@ public: // left bytes. char* af_reserved; - // user defined data size. - int __user_size; + // user defined total adaption field size. + int __field_size; TSAdaptionField(); virtual ~TSAdaptionField(); @@ -510,9 +522,13 @@ public: */ struct TSPid { - TSStreamType stream_type; TSPidType type; - int16_t pid; + // page 66. + TSStreamType stream_type; + // page 36 + TSPidTable pid; + // page 36 + u_int8_t continuity_counter; }; /** @@ -523,12 +539,14 @@ class TSMessage public: // 2.4.3.2 Transport Stream packet layer. page 36 // the pid of PES packet. - int16_t pid; + TSPidTable pid; // the type of pid. TSPidType type; // the type of stream, codec type. TSStreamType stream_type; + // page 36 + u_int8_t continuity_counter; // 2.4.3.7 Semantic definition of fields in PES packet. page 49 // PES packet header size plus data size. @@ -569,15 +587,15 @@ public: int pid_size; TSPid* pids; int64_t ts_packet_count; - std::map msgs; + std::map msgs; TSContext(); virtual ~TSContext(); - bool exists(int16_t pid); - TSPid* get(int16_t pid); - void push(TSStreamType stream_type, TSPidType type, int16_t pid); + bool exists(TSPidTable pid); + TSPid* get(TSPidTable pid); + void push(TSPidTable pid, TSStreamType stream_type, TSPidType type, u_int8_t continuity_counter); - TSMessage* get_msg(int16_t pid); + TSMessage* get_msg(TSPidTable pid); void detach(TSMessage* msg); }; @@ -592,7 +610,7 @@ TSContext::~TSContext() { srs_freepa(pids); - std::map::iterator it; + std::map::iterator it; for (it = msgs.begin(); it != msgs.end(); ++it) { TSMessage* msg = it->second; srs_freep(msg); @@ -600,7 +618,7 @@ TSContext::~TSContext() msgs.clear(); } -bool TSContext::exists(int16_t pid) +bool TSContext::exists(TSPidTable pid) { for (int i = 0; i < pid_size; i++) { if (pid == pids[i].pid) { @@ -611,7 +629,7 @@ bool TSContext::exists(int16_t pid) return false; } -TSPid* TSContext::get(int16_t pid) +TSPid* TSContext::get(TSPidTable pid) { for (int i = 0; i < pid_size; i++) { if (pid == pids[i].pid) { @@ -622,23 +640,25 @@ TSPid* TSContext::get(int16_t pid) return NULL; } -void TSContext::push(TSStreamType stream_type, TSPidType type, int16_t pid) +void TSContext::push(TSPidTable pid, TSStreamType stream_type, TSPidType type, u_int8_t continuity_counter) { - if (exists(pid)) { - return; + TSPid* p = get(pid); + + if (!p) { + p = new TSPid[pid_size + 1]; + memcpy(p, pids, sizeof(TSPid) * pid_size); + + p[pid_size] = (TSPid){type, stream_type, pid, continuity_counter}; + pid_size++; + + srs_freepa(pids); + pids = p; } - TSPid* p = new TSPid[pid_size + 1]; - memcpy(p, pids, sizeof(TSPid) * pid_size); - - p[pid_size] = (TSPid){stream_type, type, pid}; - pid_size++; - - srs_freepa(pids); - pids = p; + p->continuity_counter = continuity_counter; } -TSMessage* TSContext::get_msg(int16_t pid) +TSMessage* TSContext::get_msg(TSPidTable pid) { if (msgs[pid] == NULL) { TSMessage* msg = new TSMessage(); @@ -656,7 +676,7 @@ void TSContext::detach(TSMessage* msg) TSMessage::TSMessage() { - pid = 0; + pid = TSPidTablePAT; type = TSPidTypeReserved; stream_type = TSStreamTypeReserved; stream_id = 0; @@ -675,11 +695,21 @@ TSMessage::~TSMessage() void TSMessage::append(u_int8_t*& p, int size) { - if (size > 0) { - memcpy(packet_data + parsed_packet_size, p, size); - p += size; - parsed_packet_size += size; + if (size <= 0) { + return; } + + // for PES_packet_length is 0, the size is varient. + if (packet_data_size - parsed_packet_size < size) { + int realloc_size = size - (packet_data_size - parsed_packet_size); + packet_data = (char*)realloc(packet_data, packet_data_size + realloc_size); + + packet_data_size += realloc_size; + } + + memcpy(packet_data + parsed_packet_size, p, size); + p += size; + parsed_packet_size += size; } void TSMessage::detach(TSContext* ctx, TSMessage*& pmsg) @@ -729,7 +759,7 @@ TSAdaptionField::TSAdaptionField() marker_bit2 = 0; af_ext_reserved = NULL; af_reserved = NULL; - __user_size = 0; + __field_size = 0; } TSAdaptionField::~TSAdaptionField() @@ -741,7 +771,7 @@ TSAdaptionField::~TSAdaptionField() int TSAdaptionField::get_size() { - return __user_size; + return __field_size; } int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* last, u_int8_t*& p, TSMessage*& pmsg) @@ -750,7 +780,7 @@ int TSAdaptionField::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int adaption_field_length = *p++; u_int8_t* pos_af = p; - __user_size = 1 + adaption_field_length; + __field_size = 1 + adaption_field_length; if (adaption_field_length <= 0) { trace("ts+af empty af decoded."); @@ -965,7 +995,7 @@ int TSPayloadPAT::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t pp[0] = *p++; int16_t pid = programs[i] & 0x1FFF; - ctx->push(TSStreamTypeReserved, TSPidTypePMT, pid); + ctx->push((TSPidTable)pid, TSStreamTypeReserved, TSPidTypePMT, pkt->header->continuity_counter); } } @@ -1102,12 +1132,12 @@ int TSPayloadPMT::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t if (info->stream_type == TSStreamTypeVideoH264) { // TODO: support more video type. - ctx->push((TSStreamType)info->stream_type, TSPidTypeVideo, info->elementary_PID); + ctx->push((TSPidTable)info->elementary_PID, (TSStreamType)info->stream_type, TSPidTypeVideo, pkt->header->continuity_counter); trace("ts+pmt add pid: %d, type: H264 video", info->elementary_PID); } else if (info->stream_type == TSStreamTypeAudioAAC) { // TODO: support more audio type. // see aac: 6.2 Audio Data Transport Stream, ADTS - ctx->push((TSStreamType)info->stream_type, TSPidTypeAudio, info->elementary_PID); + ctx->push((TSPidTable)info->elementary_PID, (TSStreamType)info->stream_type, TSPidTypeAudio, pkt->header->continuity_counter); trace("ts+pmt add pid: %d, type: AAC audio", info->elementary_PID); } else { trace("ts+pmt ignore the stream type: %d", info->stream_type); @@ -1215,23 +1245,16 @@ int TSPayloadPES::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t { int ret = 0; - if (!pkt->header->payload_unit_start_indicator) { - TSMessage* msg = ctx->get_msg(pkt->header->pid); - if (msg->packet_start_code_prefix != 0x01) { - trace("ts+pes decode continous packet error, msg is empty."); - return -1; - } - msg->append(p, last - p); - msg->detach(ctx, pmsg); - return ret; - } - char* pp = (char*)&packet_start_code_prefix; pp[2] = *p++; pp[1] = *p++; pp[0] = *p++; packet_start_code_prefix &= 0xFFFFFF; + if (packet_start_code_prefix != 0x01) { + trace("ts+pes decode unit start packet error, msg is empty."); + return -1; + } stream_id = *p++; @@ -1413,6 +1436,7 @@ int TSPayloadPES::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t msg->type = pid->type; msg->stream_type = pid->stream_type; + msg->continuity_counter = pid->continuity_counter; msg->stream_id = stream_id; msg->packet_start_code_prefix = packet_start_code_prefix; @@ -1426,6 +1450,9 @@ int TSPayloadPES::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t msg->PES_packet_length = PES_packet_length; msg->packet_header_size = p - pos_packet; msg->packet_data_size = PES_packet_length - msg->packet_header_size; + if (PES_packet_length == 0) { + msg->packet_data_size = last - p - msg->packet_header_size; + } if (msg->packet_data_size > 0) { msg->packet_data = new char[msg->packet_data_size]; @@ -1433,12 +1460,16 @@ int TSPayloadPES::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t // PES_packet_data_byte int size = srs_min(msg->packet_data_size, last - p); - msg->append(p, size); + if (size > 0) { + msg->append(p, size); + } - msg->detach(ctx, pmsg); + if (PES_packet_length > 0) { + msg->detach(ctx, pmsg); + } - trace("ts+pes stream_id: %d size: %d pts: %"PRId64" dts: %"PRId64" packet_size: %d parsed_size: %d", - stream_id, PES_packet_length, pts, dts, msg->packet_data_size, msg->parsed_packet_size); + trace("ts+pes stream_id: %d size: %d pts: %"PRId64" dts: %"PRId64" total: %d header: %d packet_size: %d parsed_size: %d", + stream_id, PES_packet_length, pts, dts, msg->PES_packet_length, msg->packet_header_size, msg->packet_data_size, msg->parsed_packet_size); } else if (stream_id == PES_program_stream_map || stream_id == PES_private_stream_2 || stream_id == PES_ECM_stream @@ -1496,7 +1527,7 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l { int ret = 0; - if (pkt->header->pid == PID_PAT) { + if (pkt->header->pid == TSPidTablePAT) { read_pointer_field(pkt, p); type = TSPidTypePAT; @@ -1550,7 +1581,7 @@ int TSPacket::demux(TSContext* ctx, u_int8_t* start, u_int8_t* last, u_int8_t*& return ret; } - if (header->adaption_field_control == AFC_ADAPTION_ONLY || header->adaption_field_control == AFC_BOTH) { + if (header->adaption_field_control == TSAdaptionTypeAdaptionOnly || header->adaption_field_control == TSAdaptionTypeBoth) { if ((ret = adaption_field->demux(ctx, this, start, last, p, pmsg)) != 0) { trace("ts+header af(adaption field) decode error. ret=%d", ret); return ret; @@ -1561,7 +1592,36 @@ int TSPacket::demux(TSContext* ctx, u_int8_t* start, u_int8_t* last, u_int8_t*& // calc the user defined data size for payload. payload->size = TS_PACKET_SIZE - header->get_size() - adaption_field->get_size(); - if (header->adaption_field_control == AFC_PAYLOAD_ONLY || header->adaption_field_control == AFC_BOTH) { + 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); return ret; @@ -1588,9 +1648,9 @@ TSHeader::TSHeader() transport_error_indicator = 0; payload_unit_start_indicator = 0; transport_priority = 0; - pid = 0; + pid = TSPidTablePAT; transport_scrambling_control = 0; - adaption_field_control = 0; + adaption_field_control = TSAdaptionTypeReserved; continuity_counter = 0; } @@ -1614,23 +1674,27 @@ int TSHeader::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* la return -1; } - pid = 0; - ((char*)&pid)[1] = *p++; - ((char*)&pid)[0] = *p++; + int16_t _pid = 0; + char* pp = (char*)&_pid; + pp[1] = *p++; + pp[0] = *p++; - transport_error_indicator = (pid >> 15) & 0x01; - payload_unit_start_indicator = (pid >> 14) & 0x01; - transport_priority = (pid >> 13) & 0x01; - pid &= 0x1FFF; + transport_error_indicator = (_pid >> 15) & 0x01; + payload_unit_start_indicator = (_pid >> 14) & 0x01; + transport_priority = (_pid >> 13) & 0x01; + _pid &= 0x1FFF; - ctx->push(TSStreamTypeReserved, TSPidTypePAT, pid); + pid = (TSPidTable)_pid; continuity_counter = *p++; transport_scrambling_control = (continuity_counter >> 6) & 0x03; - adaption_field_control = (continuity_counter >> 4) & 0x03; + int8_t _adaption_field_control = (continuity_counter >> 4) & 0x03; + adaption_field_control = (TSAdaptionType)_adaption_field_control; continuity_counter &= 0x0F; + ctx->push(pid, TSStreamTypeReserved, TSPidTypePAT, continuity_counter); + trace("ts+header sync: %#x error: %d unit_start: %d priotiry: %d pid: %d scrambling: %d adaption: %d counter: %d", sync_byte, transport_error_indicator, payload_unit_start_indicator, transport_priority, pid, transport_scrambling_control, adaption_field_control, continuity_counter); @@ -1934,24 +1998,27 @@ int main(int /*argc*/, char** /*argv*/) u_int8_t* start = ts_packet; u_int8_t* last = ts_packet + TS_PACKET_SIZE; - TSPacket pkt; - TSMessage* msg = NULL; - if ((ret = pkt.demux(&ctx, start, last, p, msg)) != 0) { - trace("demuxer+read decode ts packet error. ret=%d", ret); - return ret; - } - - offset += nread; - if (!msg) { - continue; - } - - if ((ret = consume(msg)) != 0) { - trace("demuxer+consume parse and consume message failed. ret=%d", ret); - break; + // maybe need to parse multiple times for the PES_packet_length(0) packets. + while (p == start) { + TSPacket pkt; + TSMessage* msg = NULL; + if ((ret = pkt.demux(&ctx, start, last, p, msg)) != 0) { + trace("demuxer+read decode ts packet error. ret=%d", ret); + return ret; + } + + offset += nread; + if (!msg) { + continue; + } + + if ((ret = consume(msg)) != 0) { + trace("demuxer+consume parse and consume message failed. ret=%d", ret); + break; + } + + srs_freep(msg); } - - srs_freep(msg); } close(fd);