package storage import ( "bytes" "encoding/binary" "fmt" "io" ) // Constants for detection video and audio types. const ( PacketTypeAV1 = 1 PacketTypeH264 = 2 PacketTypeH265 = 3 PacketTypeMJPEG = 4 PacketTypeVP8 = 5 PacketTypeVP9 = 6 PacketTypeG711 = 21 PacketTypeAAC = 22 PacketTypeLPCM = 23 PacketTypeOPUS = 24 ) // InterleavedPacket is the structure of each inner packet. type InterleavedPacket struct { Type byte Pts int64 H264AUs [][]byte LPCMSamples []byte } // Segment is overall structure according to each period. type Segment struct { Date string Duration string Packet InterleavedPacket Packets []InterleavedPacket } // writeString записывает строку: сначала int32 длина, затем данные. func writeString(w io.Writer, s string) error { if err := binary.Write(w, binary.LittleEndian, int32(len(s))); err != nil { return err } _, err := w.Write([]byte(s)) return err } // WritePacket записывает один interleaved пакет. func WritePacket(w io.Writer, pkt InterleavedPacket) error { // Записываем тип пакета (1 байт) if err := binary.Write(w, binary.LittleEndian, pkt.Type); err != nil { return err } // Записываем pts (int64) if err := binary.Write(w, binary.LittleEndian, pkt.Pts); err != nil { return err } if pkt.Type == PacketTypeH264 { // Для H264 – AU как [][]byte. numAUs := int32(len(pkt.H264AUs)) if err := binary.Write(w, binary.LittleEndian, numAUs); err != nil { return err } for _, au := range pkt.H264AUs { if err := binary.Write(w, binary.LittleEndian, int32(len(au))); err != nil { return err } if _, err := w.Write(au); err != nil { return err } } } else if pkt.Type == PacketTypeLPCM { // Для LPCM – просто длина и данные. if err := binary.Write(w, binary.LittleEndian, int32(len(pkt.LPCMSamples))); err != nil { return err } if _, err := w.Write(pkt.LPCMSamples); err != nil { return err } } else { return fmt.Errorf("неизвестный тип пакета: %d", pkt.Type) } return nil } // WriteHeader записывает заголовок сегмента (Start и Duration). func WriteHeader(w io.Writer, seg Segment) error { var buf bytes.Buffer if err := writeString(&buf, seg.Date); err != nil { return err } if err := writeString(&buf, seg.Duration); err != nil { return err } segData := buf.Bytes() if err := binary.Write(w, binary.LittleEndian, int32(len(segData))); err != nil { return err } _, err := w.Write(segData) return err } // WriteInterleavedPacket записывает сегмент с пакетами. // Теперь количество пакетов определяется динамически. func WriteInterleavedPacket(w io.Writer, seg Segment) error { var buf bytes.Buffer if err := binary.Write(&buf, binary.LittleEndian, int32(1)); err != nil { return err } // Записываем каждый пакет. if err := WritePacket(&buf, seg.Packet); err != nil { return err } segData := buf.Bytes() if err := binary.Write(w, binary.LittleEndian, int32(len(segData))); err != nil { return err } _, err := w.Write(segData) return err }