mirror of
				https://github.com/Monibuca/engine.git
				synced 2025-11-01 04:12:49 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package engine
 | |
| 
 | |
| import (
 | |
| 	"io"
 | |
| 
 | |
| 	"go.uber.org/zap"
 | |
| 	"m7s.live/engine/v4/codec/mpegts"
 | |
| 	"m7s.live/engine/v4/track"
 | |
| )
 | |
| 
 | |
| type TSPublisher struct {
 | |
| 	Publisher
 | |
| 	*mpegts.MpegTsStream
 | |
| 	adts []byte
 | |
| }
 | |
| 
 | |
| func (t *TSPublisher) Feed(r io.Reader) error {
 | |
| 	return t.MpegTsStream.Feed(r, t.OnPmtStream, t.OnPES)
 | |
| }
 | |
| 
 | |
| func (t *TSPublisher) OnEvent(event any) {
 | |
| 	switch v := event.(type) {
 | |
| 	case IPublisher:
 | |
| 		t.MpegTsStream = mpegts.NewMpegTsStream()
 | |
| 		if !t.Equal(v) {
 | |
| 			t.AudioTrack = v.getAudioTrack()
 | |
| 			t.VideoTrack = v.getVideoTrack()
 | |
| 		}
 | |
| 	default:
 | |
| 		t.Publisher.OnEvent(event)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (t *TSPublisher) OnPmtStream(s mpegts.MpegTsPmtStream) {
 | |
| 	switch s.StreamType {
 | |
| 	case mpegts.STREAM_TYPE_H264:
 | |
| 		if t.VideoTrack == nil {
 | |
| 			t.VideoTrack = track.NewH264(t.Publisher.Stream)
 | |
| 		}
 | |
| 	case mpegts.STREAM_TYPE_H265:
 | |
| 		if t.VideoTrack == nil {
 | |
| 			t.VideoTrack = track.NewH265(t.Publisher.Stream)
 | |
| 		}
 | |
| 	case mpegts.STREAM_TYPE_AAC:
 | |
| 		if t.AudioTrack == nil {
 | |
| 			t.AudioTrack = track.NewAAC(t.Publisher.Stream)
 | |
| 		}
 | |
| 	case mpegts.STREAM_TYPE_G711A:
 | |
| 		if t.AudioTrack == nil {
 | |
| 			t.AudioTrack = track.NewG711(t.Publisher.Stream, true)
 | |
| 		}
 | |
| 	case mpegts.STREAM_TYPE_G711U:
 | |
| 		if t.AudioTrack == nil {
 | |
| 			t.AudioTrack = track.NewG711(t.Publisher.Stream, false)
 | |
| 		}
 | |
| 	default:
 | |
| 		t.Warn("unsupport stream type:", zap.Uint8("type", s.StreamType))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (t *TSPublisher) OnPES(pes mpegts.MpegTsPESPacket) {
 | |
| 	if pes.Header.Dts == 0 {
 | |
| 		pes.Header.Dts = pes.Header.Pts
 | |
| 	}
 | |
| 	switch pes.Header.StreamID & 0xF0 {
 | |
| 	case mpegts.STREAM_ID_AUDIO:
 | |
| 		if t.AudioTrack != nil {
 | |
| 			switch t.AudioTrack.(type) {
 | |
| 			case *track.AAC:
 | |
| 				if t.adts == nil {
 | |
| 					t.adts = append(t.adts, pes.Payload[:7]...)
 | |
| 					t.AudioTrack.WriteADTS(t.adts)
 | |
| 				}
 | |
| 				current := t.AudioTrack.CurrentFrame()
 | |
| 				current.PTS = uint32(pes.Header.Pts)
 | |
| 				current.DTS = uint32(pes.Header.Dts)
 | |
| 				remainLen := len(pes.Payload)
 | |
| 				current.BytesIn += remainLen
 | |
| 				for remainLen > 0 {
 | |
| 					// AACFrameLength(13)
 | |
| 					// xx xxxxxxxx xxx
 | |
| 					frameLen := (int(pes.Payload[3]&3) << 11) | (int(pes.Payload[4]) << 3) | (int(pes.Payload[5]) >> 5)
 | |
| 					if frameLen > remainLen {
 | |
| 						break
 | |
| 					}
 | |
| 
 | |
| 					t.AudioTrack.WriteSlice(pes.Payload[7:frameLen])
 | |
| 					pes.Payload = pes.Payload[frameLen:remainLen]
 | |
| 					remainLen -= frameLen
 | |
| 					t.AudioTrack.Flush()
 | |
| 				}
 | |
| 			case *track.G711:
 | |
| 				t.AudioTrack.WriteRaw(uint32(pes.Header.Pts), pes.Payload)
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 	case mpegts.STREAM_ID_VIDEO:
 | |
| 		if t.VideoTrack != nil {
 | |
| 			t.VideoTrack.WriteAnnexB(uint32(pes.Header.Pts), uint32(pes.Header.Dts), pes.Payload)
 | |
| 		}
 | |
| 	}
 | |
| }
 | 
