Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b84c19f719 | ||
|   | 7a563b07e3 | ||
|   | a743575ac9 | 
							
								
								
									
										25
									
								
								example/test/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								example/test/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/deepch/vdk/format/ts" | ||||
| 	"log" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	f, _ := os.Open("edb9708f29b24ba9b175808d6b9df9c6541e25766d4a40209a8f903948b72f3f.ts") | ||||
| 	m := ts.NewDemuxer(f) | ||||
| 	var i int | ||||
| 	for { | ||||
| 		p, err := m.ReadPacket() | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if p.IsKeyFrame { | ||||
| 			i = 0 | ||||
| 		} | ||||
| 		log.Println(i, p.Time, p.Data[4:10], len(p.Data)) | ||||
| 		i++ | ||||
|  | ||||
| 	} | ||||
| } | ||||
| @@ -3,23 +3,22 @@ package mp4 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/deepch/vdk/codec/h265parser" | ||||
|  | ||||
| 	"github.com/deepch/vdk/av" | ||||
| 	"github.com/deepch/vdk/codec/aacparser" | ||||
| 	"github.com/deepch/vdk/codec/h264parser" | ||||
| 	"github.com/deepch/vdk/codec/h265parser" | ||||
| 	"github.com/deepch/vdk/format/mp4/mp4io" | ||||
| 	"github.com/deepch/vdk/utils/bits/pio" | ||||
| 	"io" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type Muxer struct { | ||||
| 	w       io.WriteSeeker | ||||
| 	bufw    *bufio.Writer | ||||
| 	wpos    int64 | ||||
| 	streams []*Stream | ||||
| 	w                  io.WriteSeeker | ||||
| 	bufw               *bufio.Writer | ||||
| 	wpos               int64 | ||||
| 	streams            []*Stream | ||||
| 	NegativeTsMakeZero bool | ||||
| } | ||||
|  | ||||
| func NewMuxer(w io.WriteSeeker) *Muxer { | ||||
| @@ -206,8 +205,12 @@ func (self *Muxer) WritePacket(pkt av.Packet) (err error) { | ||||
|  | ||||
| func (self *Stream) writePacket(pkt av.Packet, rawdur time.Duration) (err error) { | ||||
| 	if rawdur < 0 { | ||||
| 		err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) | ||||
| 		return | ||||
| 		if self.muxer.NegativeTsMakeZero { | ||||
| 			rawdur = 0 | ||||
| 		} else { | ||||
| 			err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if _, err = self.muxer.bufw.Write(pkt.Data); err != nil { | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package mp4f | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"time" | ||||
|  | ||||
| @@ -238,14 +239,15 @@ func (self *Muxer) WriteTrailer() (err error) { | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (element *Muxer) WriteHeader(streams []av.CodecData) (err error) { | ||||
| func (element *Muxer) WriteHeader(streams []av.CodecData) error { | ||||
| 	element.streams = []*Stream{} | ||||
| 	for _, stream := range streams { | ||||
| 		if err = element.newStream(stream); err != nil { | ||||
| 			return | ||||
| 		if err := element.newStream(stream); err != nil { | ||||
| 			log.Println("WriteHeader", err) | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (element *Muxer) GetInit(streams []av.CodecData) (string, []byte) { | ||||
| @@ -285,6 +287,9 @@ func (element *Muxer) GetInit(streams []av.CodecData) (string, []byte) { | ||||
| } | ||||
|  | ||||
| func (element *Muxer) WritePacket(pkt av.Packet, GOP bool) (bool, []byte, error) { | ||||
| 	if pkt.Idx+1 > int8(len(element.streams)) { | ||||
| 		return false, nil, nil | ||||
| 	} | ||||
| 	stream := element.streams[pkt.Idx] | ||||
| 	if GOP { | ||||
| 		ts := time.Duration(0) | ||||
|   | ||||
| @@ -14,10 +14,11 @@ import ( | ||||
| ) | ||||
|  | ||||
| type Muxer struct { | ||||
| 	w       io.WriteSeeker | ||||
| 	bufw    *bufio.Writer | ||||
| 	wpos    int64 | ||||
| 	streams []*Stream | ||||
| 	w                  io.WriteSeeker | ||||
| 	bufw               *bufio.Writer | ||||
| 	wpos               int64 | ||||
| 	streams            []*Stream | ||||
| 	NegativeTsMakeZero bool | ||||
| } | ||||
|  | ||||
| func NewMuxer(w io.WriteSeeker) *Muxer { | ||||
| @@ -181,8 +182,12 @@ func (self *Muxer) WritePacket(pkt av.Packet) (err error) { | ||||
|  | ||||
| func (self *Stream) writePacket(pkt av.Packet, rawdur time.Duration) (err error) { | ||||
| 	if rawdur < 0 { | ||||
| 		err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) | ||||
| 		return | ||||
| 		if self.muxer.NegativeTsMakeZero { | ||||
| 			rawdur = 0 | ||||
| 		} else { | ||||
| 			err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if _, err = self.muxer.bufw.Write(pkt.Data); err != nil { | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	"github.com/deepch/vdk/codec/aacparser" | ||||
| 	"github.com/deepch/vdk/codec/h264parser" | ||||
| 	"github.com/deepch/vdk/format/mp4" | ||||
| 	"github.com/google/uuid" | ||||
| 	"github.com/moby/sys/mountinfo" | ||||
| 	"github.com/shirou/gopsutil/v3/disk" | ||||
| 	"os" | ||||
| @@ -19,7 +20,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| var MIME = []byte{11, 22, 111, 222, 11, 22, 111, 222} | ||||
| var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} | ||||
| var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_hour}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_hour}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} | ||||
|  | ||||
| const ( | ||||
| 	MP4 = "mp4" | ||||
| @@ -198,17 +199,18 @@ func (m *Muxer) OpenMP4() (err error) { | ||||
| 	m.WriteTrailer() | ||||
| 	m.start = time.Now().UTC() | ||||
|  | ||||
| 	p, err := m.filePatch() | ||||
| 	d, err := m.filePatch() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { | ||||
| 	if err = os.MkdirAll(filepath.Dir(d), 0755); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if m.d, err = os.Create(filepath.Dir(p) + "/tmp.mp4"); err != nil { | ||||
| 	if m.d, err = os.Create(filepath.Join(filepath.Dir(d), fmt.Sprintf("tmp_%s_%d.mp4", uuid.New(), time.Now().Unix()))); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	m.muxer = mp4.NewMuxer(m.d) | ||||
| 	m.muxer.NegativeTsMakeZero = true | ||||
| 	if err = m.muxer.WriteHeader(m.gof.Streams); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| @@ -264,6 +266,8 @@ func (m *Muxer) filePatch() (string, error) { | ||||
| 			ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%d", int(m.start.Month())), -1) | ||||
| 		case "{start_day}": | ||||
| 			ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%d", m.start.Day()), -1) | ||||
| 		case "{start_hour}": | ||||
| 			ts = strings.Replace(ts, "{start_hour}", fmt.Sprintf("%d", m.start.Hour()), -1) | ||||
| 		case "{start_minute}": | ||||
| 			ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%d", m.start.Minute()), -1) | ||||
| 		case "{start_second}": | ||||
| @@ -284,6 +288,8 @@ func (m *Muxer) filePatch() (string, error) { | ||||
| 			ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%d", int(m.end.Month())), -1) | ||||
| 		case "{end_day}": | ||||
| 			ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%d", m.end.Day()), -1) | ||||
| 		case "{end_hour}": | ||||
| 			ts = strings.Replace(ts, "{end_hour}", fmt.Sprintf("%d", m.end.Hour()), -1) | ||||
| 		case "{end_minute}": | ||||
| 			ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%d", m.end.Minute()), -1) | ||||
| 		case "{end_second}": | ||||
| @@ -321,10 +327,7 @@ func (m *Muxer) WriteTrailer() (err error) { | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			if err = os.Rename(m.d.Name(), p); err != nil { | ||||
| 			if err = os.Rename(m.d.Name(), filepath.Join(filepath.Dir(m.d.Name()), filepath.Base(p))); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -40,9 +40,10 @@ const ( | ||||
| ) | ||||
|  | ||||
| type Client struct { | ||||
| 	DebugRtsp bool | ||||
| 	DebugRtp  bool | ||||
| 	Headers   []string | ||||
| 	DebugRtsp    bool | ||||
| 	DebugRtp     bool | ||||
| 	DisableAudio bool | ||||
| 	Headers      []string | ||||
|  | ||||
| 	SkipErrRtpBlock bool | ||||
|  | ||||
| @@ -1076,12 +1077,44 @@ func (self *Stream) handleRtpPacket(packet []byte) (err error) { | ||||
| 		err = fmt.Errorf("rtp: packet too short") | ||||
| 		return | ||||
| 	} | ||||
| 	payloadOffset := 12 + int(packet[0]&0xf)*4 | ||||
|  | ||||
| 	timestamp := binary.BigEndian.Uint32(packet[4:8]) | ||||
|  | ||||
| 	/* | ||||
| 		Test offset | ||||
| 	*/ | ||||
| 	Padding := (packet[0]>>5)&1 == 1 | ||||
| 	Extension := (packet[0]>>4)&1 == 1 | ||||
| 	CSRCCnt := int(packet[0] & 0x0f) | ||||
|  | ||||
| 	RTPHeaderSize := 12 | ||||
|  | ||||
| 	payloadOffset := RTPHeaderSize | ||||
| 	end := len(packet) | ||||
| 	if end-payloadOffset >= 4*CSRCCnt { | ||||
| 		payloadOffset += 4 * CSRCCnt | ||||
| 	} | ||||
|  | ||||
| 	if Extension && end-payloadOffset >= 4 { | ||||
| 		extLen := 4 * int(binary.BigEndian.Uint16(packet[payloadOffset+2:])) | ||||
| 		payloadOffset += 4 | ||||
| 		if end-payloadOffset >= extLen { | ||||
| 			payloadOffset += extLen | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if Padding && end-payloadOffset > 0 { | ||||
| 		paddingLen := int(packet[end-1]) | ||||
| 		if end-payloadOffset >= paddingLen { | ||||
| 			end -= paddingLen | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if payloadOffset > len(packet) { | ||||
| 		err = fmt.Errorf("rtp: packet too short") | ||||
| 		return | ||||
| 	} | ||||
| 	timestamp := binary.BigEndian.Uint32(packet[4:8]) | ||||
|  | ||||
| 	payload := packet[payloadOffset:] | ||||
|  | ||||
| 	/* | ||||
|   | ||||
							
								
								
									
										1
									
								
								format/rtsp/server.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								format/rtsp/server.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| package rtsp | ||||
| @@ -284,7 +284,11 @@ func (self *Stream) payloadEnd() (n int, err error) { | ||||
| 						b := make([]byte, 4+len(nalu)) | ||||
| 						pio.PutU32BE(b[0:4], uint32(len(nalu))) | ||||
| 						copy(b[4:], nalu) | ||||
| 						self.addPacket(b, time.Duration(0), (1000*time.Millisecond)/time.Duration(self.fps)) | ||||
| 						fps := self.fps | ||||
| 						if self.fps == 0 { | ||||
| 							fps = 25 | ||||
| 						} | ||||
| 						self.addPacket(b, time.Duration(0), (1000*time.Millisecond)/time.Duration(fps)) | ||||
| 						n++ | ||||
| 					} | ||||
| 				} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user