diff --git a/trunk/doc/ts-audio-video-analysis.txt b/trunk/doc/ts-audio-video-analysis.txt old mode 100644 new mode 100755 index a63fabe56..55b8fb73c --- a/trunk/doc/ts-audio-video-analysis.txt +++ b/trunk/doc/ts-audio-video-analysis.txt @@ -1,3 +1,5 @@ +ts-audio-video-analysis.ts is generated by nginx-rtmp. + AUDIO 0x0F ISO/IEC 13818-7 Audio with ADTS transport syntax 110x xxxx ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC 14496-3 audio stream number x xxxx (gdb) p /x pkt.payload[0].pmt[0].at(1)[0] @@ -146,6 +148,28 @@ FLV header? 0x60b340: 0xeb 0x07 0xb7 0xfc 0xc2 0x24 0x8d 0xfa 0x60b348: 0xc0 0xaf 0x2a 0x76 0x53 0xc4 0x2d 0x80 0x60b350: 0x8f 0xc8 0xba 0x2e 0x2b 0xb7 0x18 0x9f + + +TSµÄÊý¾ÝÈçÏ£º +(gdb) x /35795xb msg->packet_data +0x00 0x00 0x00 0x01 +0x09 0xf0 + +0x00 0x00 0x00 0x01 +0x67 0x64 0x00 0x28 0xac 0xd1 +0x60b310: 0xc0 0x50 0x05 0xbb 0xff 0x00 0x2d 0x00 +0x60b318: 0x22 0x10 0x00 0x00 0x03 0x00 0x10 0x00 +0x60b320: 0x00 0x03 0x03 0x08 0xf1 0x83 0x11 0xe0 + +0x00 0x00 0x00 0x01 +0x68 0xe9 0xab 0x2c 0x8b + +0x00 0x00 0x01 +0x65 0x88 0x84 0x00 +0x60b338: 0x42 0xbf 0x4e 0x19 0x2a 0x00 0x0b 0xa7 +0x60b340: 0xeb 0x07 0xb7 0xfc 0xc2 0x24 0x8d 0xfa +0x60b348: 0xc0 0xaf 0x2a 0x76 0x53 0xc4 0x2d 0x80 +0x60b350: 0x8f 0xc8 0xba 0x2e 0x2b 0xb7 0x18 0x9f 0x60b358: 0xba 0x47 0x10 0x8b 0xc7 0x93 0x92 0x89 0x60b360: 0x00 0x2d 0xdf 0x3b 0xcb 0x51 0xfe 0x27 0x60b368: 0x13 0xe3 0x29 0x48 0x71 0xf7 0x70 0x07 @@ -170,13 +194,34 @@ FLV header? 0x60b400: 0x0a 0xea 0x86 0x93 0xce 0x90 0xe7 0x9b 0x60b408: 0x75 0x92 0x0d 0x6f 0xfa 0xa2 0xac 0x26 0x60b410: 0xae 0xb1 0xc3 0x4c 0xab 0x92 0xc6 0xae -0x60b418: 0x7a 0xcf 0xfa 0x0c 0xe7 0xc4 0x00 0x62 -0x60b420: 0xc3 0xc8 0x49 0xbd 0x5e 0xb0 0xd3 0x4f -0x60b428: 0xb2 0x60 0xf4 0x53 0xe8 0xba 0xa0 0xf3 -0x60b430: 0xe5 0xb4 0xf4 0xb1 0x15 0x9d 0x28 0x4f -0x60b438: 0x7f 0xc9 0x0a 0x50 0x90 0x4a 0xc3 0x19 -0x60b440: 0xeb 0x50 0xee 0xde 0xe4 0x7d 0xed 0x69 -0x60b448: 0x37 0x50 0x5d 0x0f 0x26 0x8b 0x96 0x57 -0x60b450: 0x3e 0x5c 0x5f 0x68 0xbf 0xb8 0xb0 0xcb -0x60b458: 0x90 0x9c 0xb2 0x18 0x23 0x1f 0x62 0xa5 -0x60b460: 0x6f 0x37 0x9f 0x3a \ No newline at end of file + +TSµÄµÚ¶þ¸öÊÓƵ°üÊý¾ÝÈçÏ£º +(gdb) x /4108xb 0x60b300 +0x00 0x00 0x00 0x01 +0x09 0xf0 + +0x00 0x00 0x01 +0x41 0x9a 0x28 0xc8 0x4a 0xbf 0xe8 +0x60b310: 0x06 0x44 0x30 0x05 0xea 0xd8 0x86 0xa5 +0x60b318: 0xee 0x75 0xab 0x30 0xc8 0x7a 0x5c 0xe3 +0x60b320: 0xc7 0x4a 0xdb 0xf6 0xe0 0x08 0xbe 0xc4 +0x60b328: 0xb0 0xe4 0x5d 0xe7 0x95 0xf3 0x65 0x4e +0x60b330: 0x00 0xed 0xdb 0xd1 0x5e 0xc3 0xb8 0x34 +0x60b338: 0x3d 0xd3 0xfe 0x46 0x5b 0xfd 0xd9 0xf0 +0x60b340: 0xa0 0x5d 0xa4 0xa8 0x3d 0x44 0x97 0x58 +0x60b348: 0x20 0xd5 0x41 0xb2 0x49 0x72 0xd0 0x9b +0x60b350: 0xa2 0xa7 0xbf 0xba 0x9c 0xa8 0x10 0x58 +0x60b358: 0x07 0x47 0xf4 0xe5 0xe8 0x5d 0xf2 0x0d +0x60b360: 0xfe 0x51 0x26 0x8a 0x6a 0x76 0xb8 0x35 +0x60b368: 0x04 0xfe 0x01 0xb4 0xec 0x67 0xd5 0x1f +0x60b370: 0xb0 0x66 0x0b 0x7e 0x52 0x58 0x38 0x1c +0x60b378: 0xf3 0x4c 0x92 0xe8 0x38 0xc3 0x7e 0x5b +0x60b380: 0xd6 0x17 0x47 0x49 0xba 0xae 0x6e 0xa0 +0x60b388: 0xd8 0xfd 0x16 0xdb 0x85 0xd1 0x81 0x6e +0x60b390: 0x43 0x17 0x82 0xb9 0x39 0xb0 0xa8 0xe8 +0x60b398: 0x00 0x56 0x52 0x5e 0xfd 0xad 0x5a 0x43 +0x60b3a0: 0x32 0x7a 0x4e 0xed 0xd7 0xb2 0x1b 0x4d +0x60b3a8: 0x78 0x9e 0xad 0x4e 0x97 0x37 0x2c 0xbb +0x60b3b0: 0xf3 0x99 0x45 0xee 0xce 0xc7 0x1f 0xeb +0x60b3b8: 0x43 0x37 0xfd 0x67 0x34 0x97 0xcc 0x8c +0x60b3c0: 0xc5 0xec 0x86 0xb0 0x57 0xb4 0x83 0xa9 diff --git a/trunk/research/ts_info.cpp b/trunk/research/ts_info.cpp index 662fa352a..24bc51897 100755 --- a/trunk/research/ts_info.cpp +++ b/trunk/research/ts_info.cpp @@ -1636,11 +1636,171 @@ int TSHeader::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* la } /** -* Annex B Byte stream format +* Table 7-1 – NAL unit type codes, page 61. +*/ +enum TSH264NalUnitType +{ + TSH264NalUnitTypeUnspecified = 0, + TSH264NalUnitTypeCodedSlice = 1, + TSH264NalUnitTypeCodedSliceDataPartitionA = 2, + TSH264NalUnitTypeCodedSliceDataPartitionB = 3, + TSH264NalUnitTypeCodedSliceDataPartitionC = 4, + TSH264NalUnitTypeCodedSliceOfAnIDRPicture = 5, + TSH264NalUnitTypeSEI = 6, + /** + * 7.3.2.1 Sequence parameter set RBSP syntax + * seq_parameter_set_rbsp(), in page 45 + */ + TSH264NalUnitTypeSequenceParameterSet = 7, + /** + * 7.3.2.2 Picture parameter set RBSP syntax + * pic_parameter_set_rbsp(), in page 46 + */ + TSH264NalUnitTypePictureParameterSet = 8, + /** + * 7.3.2.4 Picture delimiter RBSP syntax + * pic_delimiter_rbsp(), in page 47 + */ + TSH264NalUnitTypePictureDelimiter = 9, + TSH264NalUnitTypeEndOfSequence = 10, + TSH264NalUnitTypeEndOfStream = 11, + TSH264NalUnitTypeFillerData = 12, + TSH264NalUnitTypeReservedStart = 13, + TSH264NalUnitTypeReservedEnd = 23, + TSH264NalUnitTypeUnspecifiedStart = 24, + TSH264NalUnitTypeUnspecifiedEnd = 31, +}; + +/** +* Table 7-2 – Meaning of pic_type, page 69. +*/ +enum TSH264PicType +{ + TSH264PicTypeI = 0, + TSH264PicTypeIP = 1, + TSH264PicTypeIPB = 2, + TSH264PicTypeSI = 3, + TSH264PicTypeSISP = 4, + TSH264PicTypeISI = 5, + TSH264PicTypeISIPSP = 6, + TSH264PicTypeISIPSPB = 7, +}; + +/** +* Annex B Byte stream format, in page 211. */ class TSH264Codec { public: + int8_t forbidden_zero_bit; //1bit + int8_t nal_ref_idc; //2bits + TSH264NalUnitType nal_unit_type; //5bits + + // for nal_unit_type == TSH264NalUnitTypePictureDelimiter + TSH264PicType pic_type; //3bits + + u_int8_t* raw_data; + int size; + + TSH264Codec() + { + forbidden_zero_bit = 0; + nal_ref_idc = 0; + nal_unit_type = TSH264NalUnitTypeUnspecified; + pic_type = TSH264PicTypeI; + size = 0; + raw_data = NULL; + } + + u_int8_t at(int index) + { + if (index >= size) { + return 0; + } + return raw_data[index]; + } + + int parse(TSMessage* msg, char* last, char*& p) + { + int ret = 0; + + while (next_int(p, 3) != 0x000001) { + char ch = *p++; + if (ch != 0x00) { + trace("ts+h264 parse msg failed, " + "expect 0x00 before start-code. actual is: %#x", (u_int8_t)ch); + return -1; + } + } + + if (p >= last) { + trace("ts+h264 parse msg finished, no start-code."); + return ret; + } + + // start_code_prefix_one_3bytes /* equal to 0x000001 */ + p += 3; + + raw_data = (u_int8_t*)p; + while (p < last) { + if (match_start_code_prefix(p)) { + break; + } + p++; + } + size = (u_int8_t*)p - raw_data; + + trace("ts+h264 parse msg finished"); + return ret; + + // nal_unit( NumBytesInNALunit ) specified in page 44. + // where f(1) specified in page 43. + int8_t _nal_unit_type = *p++; + + forbidden_zero_bit = (_nal_unit_type >> 7) &0x01; + nal_ref_idc = (_nal_unit_type >> 5) &0x03; + _nal_unit_type &= 0x1f; + + nal_unit_type = (TSH264NalUnitType)_nal_unit_type; + + if (nal_unit_type == TSH264NalUnitTypePictureDelimiter) { + /** + * 7.3.2.4 Picture delimiter RBSP syntax + * pic_delimiter_rbsp(), in page 47 + */ + } else if (nal_unit_type == TSH264NalUnitTypeSequenceParameterSet) { + /** + * 7.3.2.1 Sequence parameter set RBSP syntax + * seq_parameter_set_rbsp(), in page 45 + */ + } else if (nal_unit_type == TSH264NalUnitTypePictureParameterSet) { + /** + * 7.3.2.2 Picture parameter set RBSP syntax + * pic_parameter_set_rbsp(), in page 46 + */ + } + + return ret; + } + + bool match_start_code_prefix(char*p) + { + return p[0] == 0x00 && p[1] == 0x00 && (p[2] == 0x00 || p[2] == 0x01); + } + + int32_t next_int(char* p, int bytes) + { + srs_assert(bytes <= sizeof(int32_t)); + + int32_t value = 0; + char* pp = (char*)&value; + + for (int i = 0; i < bytes; i++) { + *(pp + bytes - 1 - i) = *(p + i); + } + + return value; + } }; /** @@ -1696,6 +1856,14 @@ public: raw_data = NULL; } + u_int8_t at(int index) + { + if (index >= size) { + return 0; + } + return raw_data[index]; + } + int parse(TSMessage* msg, char*& p) { int ret = 0; @@ -1775,21 +1943,33 @@ public: int consume(TSMessage* msg) { - int ret = 0; + int ret = 0; + + char* p = msg->packet_data; + char* last = msg->packet_data + msg->packet_data_size; if (!msg->is_video()) { // parse AAC audio. - char* p = msg->packet_data; - while (p < msg->packet_data + msg->packet_data_size) { + while (p < last) { TSAacAdts aac; if ((ret = aac.parse(msg, p)) != 0) { return ret; } trace("ts+aac audio raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x", - aac.size, aac.raw_data[0], aac.raw_data[1], aac.raw_data[2], aac.raw_data[3]); + aac.size, aac.at(0), aac.at(1), aac.at(2), aac.at(3)); // TODO: process audio. } } else { + // parse H264 video. + while (p < last) { + TSH264Codec h264; + if ((ret = h264.parse(msg, last, p)) != 0) { + return ret; + } + trace("ts+h264 video raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x", + h264.size, h264.at(0), h264.at(1), h264.at(2), h264.at(3)); + // TODO: process video. + } } return ret;