finger out the ts audio/video package for AACADTS and H264NAL
正在显示
2 个修改的文件
包含
240 行增加
和
15 行删除
trunk/doc/ts-audio-video-analysis.txt
100644 → 100755
| 1 | +ts-audio-video-analysis.ts is generated by nginx-rtmp. | ||
| 2 | + | ||
| 1 | AUDIO 0x0F ISO/IEC 13818-7 Audio with ADTS transport syntax | 3 | AUDIO 0x0F ISO/IEC 13818-7 Audio with ADTS transport syntax |
| 2 | 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 | 4 | 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 |
| 3 | (gdb) p /x pkt.payload[0].pmt[0].at(1)[0] | 5 | (gdb) p /x pkt.payload[0].pmt[0].at(1)[0] |
| @@ -146,6 +148,28 @@ FLV header? | @@ -146,6 +148,28 @@ FLV header? | ||
| 146 | 0x60b340: 0xeb 0x07 0xb7 0xfc 0xc2 0x24 0x8d 0xfa | 148 | 0x60b340: 0xeb 0x07 0xb7 0xfc 0xc2 0x24 0x8d 0xfa |
| 147 | 0x60b348: 0xc0 0xaf 0x2a 0x76 0x53 0xc4 0x2d 0x80 | 149 | 0x60b348: 0xc0 0xaf 0x2a 0x76 0x53 0xc4 0x2d 0x80 |
| 148 | 0x60b350: 0x8f 0xc8 0xba 0x2e 0x2b 0xb7 0x18 0x9f | 150 | 0x60b350: 0x8f 0xc8 0xba 0x2e 0x2b 0xb7 0x18 0x9f |
| 151 | + | ||
| 152 | + | ||
| 153 | +TS的数据如下: | ||
| 154 | +(gdb) x /35795xb msg->packet_data | ||
| 155 | +0x00 0x00 0x00 0x01 | ||
| 156 | +0x09 0xf0 | ||
| 157 | + | ||
| 158 | +0x00 0x00 0x00 0x01 | ||
| 159 | +0x67 0x64 0x00 0x28 0xac 0xd1 | ||
| 160 | +0x60b310: 0xc0 0x50 0x05 0xbb 0xff 0x00 0x2d 0x00 | ||
| 161 | +0x60b318: 0x22 0x10 0x00 0x00 0x03 0x00 0x10 0x00 | ||
| 162 | +0x60b320: 0x00 0x03 0x03 0x08 0xf1 0x83 0x11 0xe0 | ||
| 163 | + | ||
| 164 | +0x00 0x00 0x00 0x01 | ||
| 165 | +0x68 0xe9 0xab 0x2c 0x8b | ||
| 166 | + | ||
| 167 | +0x00 0x00 0x01 | ||
| 168 | +0x65 0x88 0x84 0x00 | ||
| 169 | +0x60b338: 0x42 0xbf 0x4e 0x19 0x2a 0x00 0x0b 0xa7 | ||
| 170 | +0x60b340: 0xeb 0x07 0xb7 0xfc 0xc2 0x24 0x8d 0xfa | ||
| 171 | +0x60b348: 0xc0 0xaf 0x2a 0x76 0x53 0xc4 0x2d 0x80 | ||
| 172 | +0x60b350: 0x8f 0xc8 0xba 0x2e 0x2b 0xb7 0x18 0x9f | ||
| 149 | 0x60b358: 0xba 0x47 0x10 0x8b 0xc7 0x93 0x92 0x89 | 173 | 0x60b358: 0xba 0x47 0x10 0x8b 0xc7 0x93 0x92 0x89 |
| 150 | 0x60b360: 0x00 0x2d 0xdf 0x3b 0xcb 0x51 0xfe 0x27 | 174 | 0x60b360: 0x00 0x2d 0xdf 0x3b 0xcb 0x51 0xfe 0x27 |
| 151 | 0x60b368: 0x13 0xe3 0x29 0x48 0x71 0xf7 0x70 0x07 | 175 | 0x60b368: 0x13 0xe3 0x29 0x48 0x71 0xf7 0x70 0x07 |
| @@ -170,13 +194,34 @@ FLV header? | @@ -170,13 +194,34 @@ FLV header? | ||
| 170 | 0x60b400: 0x0a 0xea 0x86 0x93 0xce 0x90 0xe7 0x9b | 194 | 0x60b400: 0x0a 0xea 0x86 0x93 0xce 0x90 0xe7 0x9b |
| 171 | 0x60b408: 0x75 0x92 0x0d 0x6f 0xfa 0xa2 0xac 0x26 | 195 | 0x60b408: 0x75 0x92 0x0d 0x6f 0xfa 0xa2 0xac 0x26 |
| 172 | 0x60b410: 0xae 0xb1 0xc3 0x4c 0xab 0x92 0xc6 0xae | 196 | 0x60b410: 0xae 0xb1 0xc3 0x4c 0xab 0x92 0xc6 0xae |
| 173 | -0x60b418: 0x7a 0xcf 0xfa 0x0c 0xe7 0xc4 0x00 0x62 | ||
| 174 | -0x60b420: 0xc3 0xc8 0x49 0xbd 0x5e 0xb0 0xd3 0x4f | ||
| 175 | -0x60b428: 0xb2 0x60 0xf4 0x53 0xe8 0xba 0xa0 0xf3 | ||
| 176 | -0x60b430: 0xe5 0xb4 0xf4 0xb1 0x15 0x9d 0x28 0x4f | ||
| 177 | -0x60b438: 0x7f 0xc9 0x0a 0x50 0x90 0x4a 0xc3 0x19 | ||
| 178 | -0x60b440: 0xeb 0x50 0xee 0xde 0xe4 0x7d 0xed 0x69 | ||
| 179 | -0x60b448: 0x37 0x50 0x5d 0x0f 0x26 0x8b 0x96 0x57 | ||
| 180 | -0x60b450: 0x3e 0x5c 0x5f 0x68 0xbf 0xb8 0xb0 0xcb | ||
| 181 | -0x60b458: 0x90 0x9c 0xb2 0x18 0x23 0x1f 0x62 0xa5 | ||
| 182 | -0x60b460: 0x6f 0x37 0x9f 0x3a | ||
| 197 | + | ||
| 198 | +TS的第二个视频包数据如下: | ||
| 199 | +(gdb) x /4108xb 0x60b300 | ||
| 200 | +0x00 0x00 0x00 0x01 | ||
| 201 | +0x09 0xf0 | ||
| 202 | + | ||
| 203 | +0x00 0x00 0x01 | ||
| 204 | +0x41 0x9a 0x28 0xc8 0x4a 0xbf 0xe8 | ||
| 205 | +0x60b310: 0x06 0x44 0x30 0x05 0xea 0xd8 0x86 0xa5 | ||
| 206 | +0x60b318: 0xee 0x75 0xab 0x30 0xc8 0x7a 0x5c 0xe3 | ||
| 207 | +0x60b320: 0xc7 0x4a 0xdb 0xf6 0xe0 0x08 0xbe 0xc4 | ||
| 208 | +0x60b328: 0xb0 0xe4 0x5d 0xe7 0x95 0xf3 0x65 0x4e | ||
| 209 | +0x60b330: 0x00 0xed 0xdb 0xd1 0x5e 0xc3 0xb8 0x34 | ||
| 210 | +0x60b338: 0x3d 0xd3 0xfe 0x46 0x5b 0xfd 0xd9 0xf0 | ||
| 211 | +0x60b340: 0xa0 0x5d 0xa4 0xa8 0x3d 0x44 0x97 0x58 | ||
| 212 | +0x60b348: 0x20 0xd5 0x41 0xb2 0x49 0x72 0xd0 0x9b | ||
| 213 | +0x60b350: 0xa2 0xa7 0xbf 0xba 0x9c 0xa8 0x10 0x58 | ||
| 214 | +0x60b358: 0x07 0x47 0xf4 0xe5 0xe8 0x5d 0xf2 0x0d | ||
| 215 | +0x60b360: 0xfe 0x51 0x26 0x8a 0x6a 0x76 0xb8 0x35 | ||
| 216 | +0x60b368: 0x04 0xfe 0x01 0xb4 0xec 0x67 0xd5 0x1f | ||
| 217 | +0x60b370: 0xb0 0x66 0x0b 0x7e 0x52 0x58 0x38 0x1c | ||
| 218 | +0x60b378: 0xf3 0x4c 0x92 0xe8 0x38 0xc3 0x7e 0x5b | ||
| 219 | +0x60b380: 0xd6 0x17 0x47 0x49 0xba 0xae 0x6e 0xa0 | ||
| 220 | +0x60b388: 0xd8 0xfd 0x16 0xdb 0x85 0xd1 0x81 0x6e | ||
| 221 | +0x60b390: 0x43 0x17 0x82 0xb9 0x39 0xb0 0xa8 0xe8 | ||
| 222 | +0x60b398: 0x00 0x56 0x52 0x5e 0xfd 0xad 0x5a 0x43 | ||
| 223 | +0x60b3a0: 0x32 0x7a 0x4e 0xed 0xd7 0xb2 0x1b 0x4d | ||
| 224 | +0x60b3a8: 0x78 0x9e 0xad 0x4e 0x97 0x37 0x2c 0xbb | ||
| 225 | +0x60b3b0: 0xf3 0x99 0x45 0xee 0xce 0xc7 0x1f 0xeb | ||
| 226 | +0x60b3b8: 0x43 0x37 0xfd 0x67 0x34 0x97 0xcc 0x8c | ||
| 227 | +0x60b3c0: 0xc5 0xec 0x86 0xb0 0x57 0xb4 0x83 0xa9 |
| @@ -1636,11 +1636,171 @@ int TSHeader::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* la | @@ -1636,11 +1636,171 @@ int TSHeader::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* la | ||
| 1636 | } | 1636 | } |
| 1637 | 1637 | ||
| 1638 | /** | 1638 | /** |
| 1639 | -* Annex B Byte stream format | 1639 | +* Table 7-1 – NAL unit type codes, page 61. |
| 1640 | +*/ | ||
| 1641 | +enum TSH264NalUnitType | ||
| 1642 | +{ | ||
| 1643 | + TSH264NalUnitTypeUnspecified = 0, | ||
| 1644 | + TSH264NalUnitTypeCodedSlice = 1, | ||
| 1645 | + TSH264NalUnitTypeCodedSliceDataPartitionA = 2, | ||
| 1646 | + TSH264NalUnitTypeCodedSliceDataPartitionB = 3, | ||
| 1647 | + TSH264NalUnitTypeCodedSliceDataPartitionC = 4, | ||
| 1648 | + TSH264NalUnitTypeCodedSliceOfAnIDRPicture = 5, | ||
| 1649 | + TSH264NalUnitTypeSEI = 6, | ||
| 1650 | + /** | ||
| 1651 | + * 7.3.2.1 Sequence parameter set RBSP syntax | ||
| 1652 | + * seq_parameter_set_rbsp(), in page 45 | ||
| 1653 | + */ | ||
| 1654 | + TSH264NalUnitTypeSequenceParameterSet = 7, | ||
| 1655 | + /** | ||
| 1656 | + * 7.3.2.2 Picture parameter set RBSP syntax | ||
| 1657 | + * pic_parameter_set_rbsp(), in page 46 | ||
| 1658 | + */ | ||
| 1659 | + TSH264NalUnitTypePictureParameterSet = 8, | ||
| 1660 | + /** | ||
| 1661 | + * 7.3.2.4 Picture delimiter RBSP syntax | ||
| 1662 | + * pic_delimiter_rbsp(), in page 47 | ||
| 1663 | + */ | ||
| 1664 | + TSH264NalUnitTypePictureDelimiter = 9, | ||
| 1665 | + TSH264NalUnitTypeEndOfSequence = 10, | ||
| 1666 | + TSH264NalUnitTypeEndOfStream = 11, | ||
| 1667 | + TSH264NalUnitTypeFillerData = 12, | ||
| 1668 | + TSH264NalUnitTypeReservedStart = 13, | ||
| 1669 | + TSH264NalUnitTypeReservedEnd = 23, | ||
| 1670 | + TSH264NalUnitTypeUnspecifiedStart = 24, | ||
| 1671 | + TSH264NalUnitTypeUnspecifiedEnd = 31, | ||
| 1672 | +}; | ||
| 1673 | + | ||
| 1674 | +/** | ||
| 1675 | +* Table 7-2 – Meaning of pic_type, page 69. | ||
| 1676 | +*/ | ||
| 1677 | +enum TSH264PicType | ||
| 1678 | +{ | ||
| 1679 | + TSH264PicTypeI = 0, | ||
| 1680 | + TSH264PicTypeIP = 1, | ||
| 1681 | + TSH264PicTypeIPB = 2, | ||
| 1682 | + TSH264PicTypeSI = 3, | ||
| 1683 | + TSH264PicTypeSISP = 4, | ||
| 1684 | + TSH264PicTypeISI = 5, | ||
| 1685 | + TSH264PicTypeISIPSP = 6, | ||
| 1686 | + TSH264PicTypeISIPSPB = 7, | ||
| 1687 | +}; | ||
| 1688 | + | ||
| 1689 | +/** | ||
| 1690 | +* Annex B Byte stream format, in page 211. | ||
| 1640 | */ | 1691 | */ |
| 1641 | class TSH264Codec | 1692 | class TSH264Codec |
| 1642 | { | 1693 | { |
| 1643 | public: | 1694 | public: |
| 1695 | + int8_t forbidden_zero_bit; //1bit | ||
| 1696 | + int8_t nal_ref_idc; //2bits | ||
| 1697 | + TSH264NalUnitType nal_unit_type; //5bits | ||
| 1698 | + | ||
| 1699 | + // for nal_unit_type == TSH264NalUnitTypePictureDelimiter | ||
| 1700 | + TSH264PicType pic_type; //3bits | ||
| 1701 | + | ||
| 1702 | + u_int8_t* raw_data; | ||
| 1703 | + int size; | ||
| 1704 | + | ||
| 1705 | + TSH264Codec() | ||
| 1706 | + { | ||
| 1707 | + forbidden_zero_bit = 0; | ||
| 1708 | + nal_ref_idc = 0; | ||
| 1709 | + nal_unit_type = TSH264NalUnitTypeUnspecified; | ||
| 1710 | + pic_type = TSH264PicTypeI; | ||
| 1711 | + size = 0; | ||
| 1712 | + raw_data = NULL; | ||
| 1713 | + } | ||
| 1714 | + | ||
| 1715 | + u_int8_t at(int index) | ||
| 1716 | + { | ||
| 1717 | + if (index >= size) { | ||
| 1718 | + return 0; | ||
| 1719 | + } | ||
| 1720 | + return raw_data[index]; | ||
| 1721 | + } | ||
| 1722 | + | ||
| 1723 | + int parse(TSMessage* msg, char* last, char*& p) | ||
| 1724 | + { | ||
| 1725 | + int ret = 0; | ||
| 1726 | + | ||
| 1727 | + while (next_int(p, 3) != 0x000001) { | ||
| 1728 | + char ch = *p++; | ||
| 1729 | + if (ch != 0x00) { | ||
| 1730 | + trace("ts+h264 parse msg failed, " | ||
| 1731 | + "expect 0x00 before start-code. actual is: %#x", (u_int8_t)ch); | ||
| 1732 | + return -1; | ||
| 1733 | + } | ||
| 1734 | + } | ||
| 1735 | + | ||
| 1736 | + if (p >= last) { | ||
| 1737 | + trace("ts+h264 parse msg finished, no start-code."); | ||
| 1738 | + return ret; | ||
| 1739 | + } | ||
| 1740 | + | ||
| 1741 | + // start_code_prefix_one_3bytes /* equal to 0x000001 */ | ||
| 1742 | + p += 3; | ||
| 1743 | + | ||
| 1744 | + raw_data = (u_int8_t*)p; | ||
| 1745 | + while (p < last) { | ||
| 1746 | + if (match_start_code_prefix(p)) { | ||
| 1747 | + break; | ||
| 1748 | + } | ||
| 1749 | + p++; | ||
| 1750 | + } | ||
| 1751 | + size = (u_int8_t*)p - raw_data; | ||
| 1752 | + | ||
| 1753 | + trace("ts+h264 parse msg finished"); | ||
| 1754 | + return ret; | ||
| 1755 | + | ||
| 1756 | + // nal_unit( NumBytesInNALunit ) specified in page 44. | ||
| 1757 | + // where f(1) specified in page 43. | ||
| 1758 | + int8_t _nal_unit_type = *p++; | ||
| 1759 | + | ||
| 1760 | + forbidden_zero_bit = (_nal_unit_type >> 7) &0x01; | ||
| 1761 | + nal_ref_idc = (_nal_unit_type >> 5) &0x03; | ||
| 1762 | + _nal_unit_type &= 0x1f; | ||
| 1763 | + | ||
| 1764 | + nal_unit_type = (TSH264NalUnitType)_nal_unit_type; | ||
| 1765 | + | ||
| 1766 | + if (nal_unit_type == TSH264NalUnitTypePictureDelimiter) { | ||
| 1767 | + /** | ||
| 1768 | + * 7.3.2.4 Picture delimiter RBSP syntax | ||
| 1769 | + * pic_delimiter_rbsp(), in page 47 | ||
| 1770 | + */ | ||
| 1771 | + } else if (nal_unit_type == TSH264NalUnitTypeSequenceParameterSet) { | ||
| 1772 | + /** | ||
| 1773 | + * 7.3.2.1 Sequence parameter set RBSP syntax | ||
| 1774 | + * seq_parameter_set_rbsp(), in page 45 | ||
| 1775 | + */ | ||
| 1776 | + } else if (nal_unit_type == TSH264NalUnitTypePictureParameterSet) { | ||
| 1777 | + /** | ||
| 1778 | + * 7.3.2.2 Picture parameter set RBSP syntax | ||
| 1779 | + * pic_parameter_set_rbsp(), in page 46 | ||
| 1780 | + */ | ||
| 1781 | + } | ||
| 1782 | + | ||
| 1783 | + return ret; | ||
| 1784 | + } | ||
| 1785 | + | ||
| 1786 | + bool match_start_code_prefix(char*p) | ||
| 1787 | + { | ||
| 1788 | + return p[0] == 0x00 && p[1] == 0x00 && (p[2] == 0x00 || p[2] == 0x01); | ||
| 1789 | + } | ||
| 1790 | + | ||
| 1791 | + int32_t next_int(char* p, int bytes) | ||
| 1792 | + { | ||
| 1793 | + srs_assert(bytes <= sizeof(int32_t)); | ||
| 1794 | + | ||
| 1795 | + int32_t value = 0; | ||
| 1796 | + char* pp = (char*)&value; | ||
| 1797 | + | ||
| 1798 | + for (int i = 0; i < bytes; i++) { | ||
| 1799 | + *(pp + bytes - 1 - i) = *(p + i); | ||
| 1800 | + } | ||
| 1801 | + | ||
| 1802 | + return value; | ||
| 1803 | + } | ||
| 1644 | }; | 1804 | }; |
| 1645 | 1805 | ||
| 1646 | /** | 1806 | /** |
| @@ -1696,6 +1856,14 @@ public: | @@ -1696,6 +1856,14 @@ public: | ||
| 1696 | raw_data = NULL; | 1856 | raw_data = NULL; |
| 1697 | } | 1857 | } |
| 1698 | 1858 | ||
| 1859 | + u_int8_t at(int index) | ||
| 1860 | + { | ||
| 1861 | + if (index >= size) { | ||
| 1862 | + return 0; | ||
| 1863 | + } | ||
| 1864 | + return raw_data[index]; | ||
| 1865 | + } | ||
| 1866 | + | ||
| 1699 | int parse(TSMessage* msg, char*& p) | 1867 | int parse(TSMessage* msg, char*& p) |
| 1700 | { | 1868 | { |
| 1701 | int ret = 0; | 1869 | int ret = 0; |
| @@ -1775,21 +1943,33 @@ public: | @@ -1775,21 +1943,33 @@ public: | ||
| 1775 | 1943 | ||
| 1776 | int consume(TSMessage* msg) | 1944 | int consume(TSMessage* msg) |
| 1777 | { | 1945 | { |
| 1778 | - int ret = 0; | 1946 | + int ret = 0; |
| 1947 | + | ||
| 1948 | + char* p = msg->packet_data; | ||
| 1949 | + char* last = msg->packet_data + msg->packet_data_size; | ||
| 1779 | 1950 | ||
| 1780 | if (!msg->is_video()) { | 1951 | if (!msg->is_video()) { |
| 1781 | // parse AAC audio. | 1952 | // parse AAC audio. |
| 1782 | - char* p = msg->packet_data; | ||
| 1783 | - while (p < msg->packet_data + msg->packet_data_size) { | 1953 | + while (p < last) { |
| 1784 | TSAacAdts aac; | 1954 | TSAacAdts aac; |
| 1785 | if ((ret = aac.parse(msg, p)) != 0) { | 1955 | if ((ret = aac.parse(msg, p)) != 0) { |
| 1786 | return ret; | 1956 | return ret; |
| 1787 | } | 1957 | } |
| 1788 | trace("ts+aac audio raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x", | 1958 | trace("ts+aac audio raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x", |
| 1789 | - aac.size, aac.raw_data[0], aac.raw_data[1], aac.raw_data[2], aac.raw_data[3]); | 1959 | + aac.size, aac.at(0), aac.at(1), aac.at(2), aac.at(3)); |
| 1790 | // TODO: process audio. | 1960 | // TODO: process audio. |
| 1791 | } | 1961 | } |
| 1792 | } else { | 1962 | } else { |
| 1963 | + // parse H264 video. | ||
| 1964 | + while (p < last) { | ||
| 1965 | + TSH264Codec h264; | ||
| 1966 | + if ((ret = h264.parse(msg, last, p)) != 0) { | ||
| 1967 | + return ret; | ||
| 1968 | + } | ||
| 1969 | + trace("ts+h264 video raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x", | ||
| 1970 | + h264.size, h264.at(0), h264.at(1), h264.at(2), h264.at(3)); | ||
| 1971 | + // TODO: process video. | ||
| 1972 | + } | ||
| 1793 | } | 1973 | } |
| 1794 | 1974 | ||
| 1795 | return ret; | 1975 | return ret; |
-
请 注册 或 登录 后发表评论