package util import ( "encoding/binary" "errors" "io" "net/url" "regexp" "strconv" "strings" "time" ) const ( StartKey = "start" EndKey = "end" RangeKey = "range" LoopKey = "loop" LocalTimeFormat = "2006-01-02T15:04:05" ) var ( UnixTimeReg = regexp.MustCompile(`^\d+$`) UnixTimeRangeReg = regexp.MustCompile(`^(\d+)(~|-)(\d+)$`) TimeStrRangeReg = regexp.MustCompile(`^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?)~(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?)$`) ) func TimeRangeQueryParse(query url.Values) (startTime, endTime time.Time, err error) { rangeStr := query.Get(RangeKey) if rangeStr == "" { startTimeStr := query.Get(StartKey) endTimeStr := query.Get(EndKey) if startTimeStr == "" { startTime = time.Time{} if endTimeStr == "" { endTime = time.Now() } else { if UnixTimeReg.MatchString(endTimeStr) { endTime, err = UnixTimeQueryParse(endTimeStr) } else { endTime, err = TimeQueryParse(endTimeStr) } } return } else if endTimeStr == "" { endTime = time.Now() if UnixTimeReg.MatchString(startTimeStr) { startTime, err = UnixTimeQueryParse(startTimeStr) } else { startTime, err = TimeQueryParse(startTimeStr) } return } rangeStr = startTimeStr + "~" + endTimeStr } if match := UnixTimeRangeReg.FindStringSubmatch(rangeStr); len(match) == 4 { startTime, err = UnixTimeQueryParse(match[1]) if err != nil { return } endTime, err = UnixTimeQueryParseRefer(match[3], startTime) } else if match := TimeStrRangeReg.FindStringSubmatch(rangeStr); len(match) == 3 { startTime, err = TimeQueryParse(match[1]) if err != nil { return } endTime, err = TimeQueryParseRefer(match[2], startTime) } else { err = errors.New("invalid time range") } return } func UnixTimeQueryParse(query string) (time.Time, error) { return UnixTimeQueryParseRefer(query, time.Now()) } func TimeQueryParse(query string) (time.Time, error) { return TimeQueryParseRefer(query, time.Now()) } func UnixTimeQueryParseRefer(query string, refer time.Time) (t time.Time, err error) { var unixTime int64 unixTime, err = strconv.ParseInt(query, 10, 64) if err != nil { return } switch len(query) { case 10: t = time.Unix(unixTime, 0) case 13: t = time.UnixMilli(unixTime) default: err = errors.New("invalid time") } return } func TimeQueryParseRefer(query string, refer time.Time) (time.Time, error) { if !strings.Contains(query, "T") { query = refer.Format("2006-01-02") + "T" + query } if strings.Contains(query, "Z") { return time.Parse(time.RFC3339, query) } return time.ParseInLocation("2006-01-02T15:04:05", query, time.Local) } /* func ReadByteToUintX(r io.Reader, l int) (data uint64, err error) { if l%8 != 0 || l > 64 { return 0, errors.New("disable convert") } bb := make([]byte, l) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } switch l / 8 { case 1: { return uint8(bb[0]), nil } case 2: { return BigEndian.Uint16(bb), nil } case 3: { return BigEndian.Uint24(bb), nil } case 4: { return BigEndian.Uint32(bb), nil } case 5: { //return BigEndian.Uint40(bb), nil return 0, errors.New("disable convert") } case 6: { return BigEndian.Uint48(bb), nil } case 7: { //return BigEndian.Uint56(bb), nil return 0, errors.New("disable convert") } case 8: { return BigEndian.Uint64(bb), nil } } return 0, errors.New("convert not exist") } */ // // 千万注意大小端,RTMP是大端 func ByteToUint32N(data []byte) (ret uint32, err error) { if len(data) > 4 { return 0, errors.New("ByteToUint32N error!") } for i := 0; i < len(data); i++ { ret <<= 8 ret |= uint32(data[i]) } return } // // 千万注意大小端,RTMP是大端 func ByteToUint64N(data []byte) (ret uint64, err error) { if len(data) > 8 { return 0, errors.New("ByteToUint64N error!") } for i := 0; i < len(data); i++ { ret <<= 8 ret |= uint64(data[i]) } return } // 千万注意大小端,RTMP是大端 func ByteToUint32(data []byte, bigEndian bool) (ret uint32, err error) { if bigEndian { return binary.BigEndian.Uint32(data), nil } else { return binary.LittleEndian.Uint32(data), nil } } func Uint32ToByte(data uint32, bigEndian bool) (ret []byte, err error) { if bigEndian { return BigEndian.ToUint32(data), nil } else { return LittleEndian.ToUint32(data), nil } } func ReadByteToUint8(r io.Reader) (data uint8, err error) { bb := make([]byte, 1) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } return uint8(bb[0]), nil } func ReadByteToUint16(r io.Reader, bigEndian bool) (data uint16, err error) { bb := make([]byte, 2) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } if bigEndian { return binary.BigEndian.Uint16(bb), nil } else { return binary.LittleEndian.Uint16(bb), nil } } func ReadByteToUint24(r io.Reader, bigEndian bool) (data uint32, err error) { bb := make([]byte, 3) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } if bigEndian { return BigEndian.Uint24(bb), nil } else { return LittleEndian.Uint24(bb), nil } } func ReadByteToUint32(r io.Reader, bigEndian bool) (data uint32, err error) { bb := make([]byte, 4) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } if bigEndian { return binary.BigEndian.Uint32(bb), nil } else { return binary.LittleEndian.Uint32(bb), nil } } func ReadByteToUint40(r io.Reader, bigEndian bool) (data uint64, err error) { bb := make([]byte, 5) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } if bigEndian { return BigEndian.Uint40(bb), nil } else { return LittleEndian.Uint40(bb), nil } } func ReadByteToUint48(r io.Reader, bigEndian bool) (data uint64, err error) { bb := make([]byte, 6) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } if bigEndian { return BigEndian.Uint48(bb), nil } else { return LittleEndian.Uint48(bb), nil } } /* func ReadByteToUint56(r io.Reader) (data uint64, err error) { bb := make([]byte, 7) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } return uint8(bb[0]), nil } */ func BigLittleSwap(v uint) uint { return (v >> 24) | ((v>>16)&0xff)<<8 | ((v>>8)&0xff)<<16 | (v&0xff)<<24 } func ReadByteToUint64(r io.Reader, bigEndian bool) (data uint64, err error) { bb := make([]byte, 8) if _, err := io.ReadFull(r, bb); err != nil { return 0, err } if bigEndian { return binary.BigEndian.Uint64(bb), nil } else { return binary.LittleEndian.Uint64(bb), nil } } func WriteUint8ToByte(w io.Writer, data uint8) error { bb := make([]byte, 8) bb[0] = byte(data) _, err := w.Write(bb[:1]) if err != nil { return err } return nil } func WriteUint16ToByte(w io.Writer, data uint16, bigEndian bool) error { var bb []byte if bigEndian { bb = BigEndian.ToUint16(data) } else { bb = LittleEndian.ToUint16(data) } _, err := w.Write(bb) if err != nil { return err } return nil } func WriteUint24ToByte(w io.Writer, data uint32, bigEndian bool) error { var bb []byte if bigEndian { bb = BigEndian.ToUint24(data) } else { bb = LittleEndian.ToUint24(data) } _, err := w.Write(bb) if err != nil { return err } return nil } func WriteUint32ToByte(w io.Writer, data uint32, bigEndian bool) error { var bb []byte if bigEndian { bb = BigEndian.ToUint32(data) } else { bb = LittleEndian.ToUint32(data) } _, err := w.Write(bb) if err != nil { return err } return nil } func WriteUint40ToByte(w io.Writer, data uint64, bigEndian bool) error { var bb []byte if bigEndian { bb = BigEndian.ToUint40(data) } else { bb = LittleEndian.ToUint40(data) } _, err := w.Write(bb) if err != nil { return err } return nil } func WriteUint48ToByte(w io.Writer, data uint64, bigEndian bool) error { var bb []byte if bigEndian { bb = BigEndian.ToUint48(data) } else { bb = LittleEndian.ToUint48(data) } _, err := w.Write(bb) if err != nil { return err } return nil } func WriteUint64ToByte(w io.Writer, data uint64, bigEndian bool) error { var bb []byte if bigEndian { bb = BigEndian.ToUint64(data) } else { bb = LittleEndian.ToUint64(data) } _, err := w.Write(bb) if err != nil { return err } return nil } func GetPtsDts(v uint64) uint64 { // 4 + 3 + 1 + 15 + 1 + 15 + 1 // 0011 // 0010 + PTS[30-32] + marker_bit + PTS[29-15] + marker_bit + PTS[14-0] + marker_bit pts1 := ((v >> 33) & 0x7) << 30 pts2 := ((v >> 17) & 0x7fff) << 15 pts3 := ((v >> 1) & 0x7fff) return pts1 | pts2 | pts3 } func PutPtsDts(v uint64) uint64 { // 4 + 3 + 1 + 15 + 1 + 15 + 1 // 0011 // 0010 + PTS[30-32] + marker_bit + PTS[29-15] + marker_bit + PTS[14-0] + marker_bit // 0x100010001 // 0001 0000 0000 0000 0001 0000 0000 0000 0001 // 3个 market_it pts1 := (v >> 30) & 0x7 << 33 pts2 := (v >> 15) & 0x7fff << 17 pts3 := (v & 0x7fff) << 1 return pts1 | pts2 | pts3 | 0x100010001 } func GetPCR(v uint64) uint64 { // program_clock_reference_base(33) + Reserved(6) + program_clock_reference_extension(9) base := v >> 15 ext := v & 0x1ff return base*300 + ext } func PutPCR(pcr uint64) uint64 { base := pcr / 300 ext := pcr % 300 return base<<15 | 0x3f<<9 | ext } func GetFillBytes(data byte, n int) []byte { b := make([]byte, n) for i := range b { b[i] = data } return b } func ToFloat64(num interface{}) float64 { switch v := num.(type) { case uint: return float64(v) case int: return float64(v) case uint8: return float64(v) case uint16: return float64(v) case uint32: return float64(v) case uint64: return float64(v) case int8: return float64(v) case int16: return float64(v) case int32: return float64(v) case int64: return float64(v) case float64: return v case float32: return float64(v) } return 0 } func Conf2Listener(conf string) (protocol string, ports []uint16) { var port string protocol, port, _ = strings.Cut(conf, ":") if r := strings.Split(port, "-"); len(r) == 2 { min, err := strconv.Atoi(r[0]) if err != nil { return } max, err := strconv.Atoi(r[1]) if err != nil { return } if min < max { ports = append(ports, uint16(min), uint16(max)) } } else if p, err := strconv.Atoi(port); err == nil { ports = append(ports, uint16(p)) } return } type littleEndian struct{} var LittleEndian littleEndian func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 } func (littleEndian) Uint24(b []byte) uint32 { return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 } func (littleEndian) Uint32(b []byte) uint32 { return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 } func (littleEndian) Uint40(b []byte) uint64 { return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 } func (littleEndian) Uint48(b []byte) uint64 { return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 } func (littleEndian) Uint64(b []byte) uint64 { return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 } func (littleEndian) ToUint16(v uint16) []byte { b := make([]byte, 2) b[0] = byte(v) b[1] = byte(v >> 8) return b } func (littleEndian) ToUint24(v uint32) []byte { b := make([]byte, 3) b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) return b } func (littleEndian) ToUint32(v uint32) []byte { b := make([]byte, 4) b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) return b } func (littleEndian) ToUint40(v uint64) []byte { b := make([]byte, 5) b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) b[4] = byte(v >> 32) return b } func (littleEndian) ToUint48(v uint64) []byte { b := make([]byte, 6) b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) b[4] = byte(v >> 32) b[5] = byte(v >> 40) return b } func (littleEndian) ToUint64(v uint64) []byte { b := make([]byte, 8) b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) b[4] = byte(v >> 32) b[5] = byte(v >> 40) b[6] = byte(v >> 48) b[7] = byte(v >> 56) return b } type bigEndian struct{} var BigEndian bigEndian func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 } func (bigEndian) Uint24(b []byte) uint32 { return uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16 } func (bigEndian) Uint32(b []byte) uint32 { return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 } func (bigEndian) Uint40(b []byte) uint64 { return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | uint64(b[1])<<24 | uint64(b[0])<<32 } func (bigEndian) Uint48(b []byte) uint64 { return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | uint64(b[2])<<24 | uint64(b[1])<<32 | uint64(b[0])<<40 } func (bigEndian) Uint64(b []byte) uint64 { return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 } func (bigEndian) ToUint16(v uint16) []byte { b := make([]byte, 2) b[0] = byte(v >> 8) b[1] = byte(v) return b } func (bigEndian) ToUint24(v uint32) []byte { b := make([]byte, 3) b[0] = byte(v >> 16) b[1] = byte(v >> 8) b[2] = byte(v) return b } func (bigEndian) ToUint32(v uint32) []byte { b := make([]byte, 4) b[0] = byte(v >> 24) b[1] = byte(v >> 16) b[2] = byte(v >> 8) b[3] = byte(v) return b } func (bigEndian) ToUint40(v uint64) []byte { b := make([]byte, 5) b[0] = byte(v >> 32) b[1] = byte(v >> 24) b[2] = byte(v >> 16) b[3] = byte(v >> 8) b[4] = byte(v) return b } func (bigEndian) ToUint48(v uint64) []byte { b := make([]byte, 6) b[0] = byte(v >> 40) b[1] = byte(v >> 32) b[2] = byte(v >> 24) b[3] = byte(v >> 16) b[4] = byte(v >> 8) b[5] = byte(v) return b } func (bigEndian) ToUint64(v uint64) []byte { b := make([]byte, 8) b[0] = byte(v >> 56) b[1] = byte(v >> 48) b[2] = byte(v >> 40) b[3] = byte(v >> 32) b[4] = byte(v >> 24) b[5] = byte(v >> 16) b[6] = byte(v >> 8) b[7] = byte(v) return b }