当传输流包有效载荷包含 PSI 数据时,payload_unit_start_indicator 具有以下意义: 若传输流包承载 PSI分段的首字节,则 payload_unit_start_indicator 值必为 1,指示此传输流包的有效载荷的首字节承载pointer_field. 若传输流包不承载 PSI 分段的首字节,则 payload_unit_start_indicator 值必为 0,指示在此有效载荷中不存在 pointer_field 只要是PSI就一定会有pointer_field
(r io.Reader, pt uint32)
| 35 | // 若传输流包不承载 PSI 分段的首字节,则 payload_unit_start_indicator 值必为 0,指示在此有效载荷中不存在 pointer_field |
| 36 | // 只要是PSI就一定会有pointer_field |
| 37 | func ReadPSI(r io.Reader, pt uint32) (lr *io.LimitedReader, psi MpegTsPSI, err error) { |
| 38 | // pointer field(8) |
| 39 | cr, ok := r.(*util.Crc32Reader) |
| 40 | if ok { |
| 41 | r = cr.R |
| 42 | } |
| 43 | pointer_field, err := util.ReadByteToUint8(r) |
| 44 | if err != nil { |
| 45 | return |
| 46 | } |
| 47 | |
| 48 | if pointer_field != 0 { |
| 49 | // 无论如何都应该确保能将pointer_field读取到,并且io.Reader指针向下移动 |
| 50 | // ioutil.Discard常用在,http中,如果Get请求,获取到了很大的Body,要丢弃Body,就用这个方法. |
| 51 | // 因为http默认重链接的时候,必须等body读取完成. |
| 52 | // 用于发送需要读取但不想存储的数据,目的是耗尽读取端的数据 |
| 53 | if _, err = io.CopyN(io.Discard, r, int64(pointer_field)); err != nil { |
| 54 | return |
| 55 | } |
| 56 | } |
| 57 | if ok { |
| 58 | r = cr |
| 59 | } |
| 60 | |
| 61 | // table id(8) |
| 62 | tableId, err := util.ReadByteToUint8(r) |
| 63 | if err != nil { |
| 64 | return |
| 65 | } |
| 66 | |
| 67 | // sectionSyntaxIndicator(1) + zero(1) + reserved1(2) + sectionLength(12) |
| 68 | // sectionLength 前两个字节固定为00 |
| 69 | sectionSyntaxIndicatorAndSectionLength, err := util.ReadByteToUint16(r, true) |
| 70 | if err != nil { |
| 71 | return |
| 72 | } |
| 73 | |
| 74 | // 指定该分段的字节数,紧随 section_length 字段开始,并包括 CRC |
| 75 | // 因此剩下最多只能在读sectionLength长度的字节 |
| 76 | lr = &io.LimitedReader{R: r, N: int64(sectionSyntaxIndicatorAndSectionLength & 0x3FF)} |
| 77 | |
| 78 | // PAT TransportStreamID(16) or PMT ProgramNumber(16) |
| 79 | transportStreamIdOrProgramNumber, err := util.ReadByteToUint16(lr, true) |
| 80 | if err != nil { |
| 81 | return |
| 82 | } |
| 83 | |
| 84 | // reserved2(2) + versionNumber(5) + currentNextIndicator(1) |
| 85 | versionNumberAndCurrentNextIndicator, err := util.ReadByteToUint8(lr) |
| 86 | if err != nil { |
| 87 | return |
| 88 | } |
| 89 | |
| 90 | // sectionNumber(8) |
| 91 | sectionNumber, err := util.ReadByteToUint8(lr) |
| 92 | if err != nil { |
| 93 | return |
| 94 | } |
no test coverage detected