123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package mpegps
- import (
- "encoding/binary"
- "errors"
- "io"
- "m7s.live/engine/v4/util"
- )
- const (
- StartCodePS = 0x000001ba
- StartCodeSYS = 0x000001bb
- StartCodeMAP = 0x000001bc
- StartCodeVideo = 0x000001e0
- StartCodeAudio = 0x000001c0
- PrivateStreamCode = 0x000001bd
- MEPGProgramEndCode = 0x000001b9
- )
- type EsHandler interface {
- ReceiveAudio(MpegPsEsStream)
- ReceiveVideo(MpegPsEsStream)
- ReceivePSM(util.Buffer, bool, bool)
- }
- type MpegPsEsStream struct {
- Type byte
- util.Buffer
- PTS uint32
- DTS uint32
- }
- type MpegPsStream struct {
- buffer util.Buffer
- EsHandler
- audio MpegPsEsStream
- video MpegPsEsStream
- }
- func (ps *MpegPsStream) Reset() {
- ps.buffer.Reset()
- ps.audio.Reset()
- if ps.video.Buffer.CanRead() {
- ps.ReceiveVideo(ps.video)
- ps.video.Buffer = make(util.Buffer, 0)
- } else {
- ps.video.Reset()
- }
- }
- func (ps *MpegPsStream) Feed(data util.Buffer) (err error) {
- reader := &data
- if ps.buffer.CanRead() {
- ps.buffer.Write(data)
- reader = &ps.buffer
- }
- var begin util.Buffer
- var payload []byte
- var frame MpegPsEsStream
- defer func() {
- if err != nil && begin.CanRead() {
- ps.buffer.Reset()
- ps.buffer.Write(begin)
- }
- }()
- for err == nil && reader.CanReadN(4) {
- begin = *reader
- code := reader.ReadUint32()
- switch code {
- case StartCodePS:
- if reader.CanReadN(9) {
- reader.ReadN(9)
- if reader.CanRead() {
- psl := reader.ReadByte() & 0x07
- if reader.CanReadN(int(psl)) {
- reader.ReadN(int(psl))
- continue
- }
- }
- }
- err = io.ErrShortBuffer
- case StartCodeSYS, PrivateStreamCode:
- _, err = ps.ReadPayload(reader)
- case StartCodeMAP:
- err = ps.decProgramStreamMap(reader)
- case StartCodeVideo:
- payload, err = ps.ReadPayload(reader)
- if err == nil {
- frame, err = ps.video.parsePESPacket(payload)
- if err == nil {
- ps.ReceiveVideo(frame)
- }
- }
- case StartCodeAudio:
- payload, err = ps.ReadPayload(reader)
- if err == nil {
- frame, err = ps.audio.parsePESPacket(payload)
- if err == nil {
- ps.ReceiveAudio(frame)
- }
- }
- case MEPGProgramEndCode:
- return
- default:
- err = errors.New("start code error")
- }
- }
- return
- }
- func (ps *MpegPsStream) ReadPayload(data *util.Buffer) (payload []byte, err error) {
- if !data.CanReadN(2) {
- return nil, io.ErrShortBuffer
- }
- payloadlen := data.ReadUint16()
- if data.CanReadN(int(payloadlen)) {
- payload = data.ReadN(int(payloadlen))
- } else {
- err = io.ErrShortBuffer
- }
- return
- }
- func (ps *MpegPsStream) decProgramStreamMap(data *util.Buffer) error {
- psm, err := ps.ReadPayload(data)
- if err != nil {
- return err
- }
- l := len(psm)
- index := 2
- programStreamInfoLen := binary.BigEndian.Uint16(psm[index:])
- index += 2
- index += int(programStreamInfoLen)
- programStreamMapLen := binary.BigEndian.Uint16(psm[index:])
- index += 2
- for programStreamMapLen > 0 {
- if l <= index+1 {
- break
- }
- streamType := psm[index]
- index++
- elementaryStreamID := psm[index]
- index++
- if elementaryStreamID >= 0xe0 && elementaryStreamID <= 0xef {
- ps.video.Type = streamType
- } else if elementaryStreamID >= 0xc0 && elementaryStreamID <= 0xdf {
- ps.audio.Type = streamType
- }
- if l <= index+1 {
- break
- }
- elementaryStreamInfoLength := binary.BigEndian.Uint16(psm[index:])
- index += 2
- index += int(elementaryStreamInfoLength)
- programStreamMapLen -= 4 + elementaryStreamInfoLength
- }
- return nil
- }
|