Documentation ¶
Index ¶
- Variables
- func DoTimeRangesOverlap(start1, end1, start2, end2 time.Time) bool
- func VideoFileHasVideoTrack(vf VideoFile, trackName string, width, height int) bool
- func VideoFileMaxTrackEndTime(vf VideoFile) time.Time
- type Archive
- func (a *Archive) AutoStatsToLog()
- func (a *Archive) Close()
- func (a *Archive) GetDynamicSettings() DynamicSettings
- func (a *Archive) ListStreams() []*StreamInfo
- func (a *Archive) MaxVideoFileDuration() time.Duration
- func (a *Archive) Read(streamName string, trackNames []string, startTime, endTime time.Time, ...) (map[string]*TrackReadResult, error)
- func (a *Archive) SetDynamicSettings(settings DynamicSettings)
- func (a *Archive) StreamInfo(streamName string) *StreamInfo
- func (a *Archive) StreamSizes() map[string]int64
- func (a *Archive) TotalSize() int64
- func (a *Archive) Write(streamName string, payload map[string]TrackPayload) error
- type DynamicSettings
- type ErrCodecSwitch
- type NALU
- type NALUFlags
- type ReadFlags
- type StaticSettings
- type StreamInfo
- type Track
- type TrackPayload
- type TrackReadResult
- type VideoFile
- type VideoFileRF1
- func (v *VideoFileRF1) Close() error
- func (v *VideoFileRF1) CreateVideoTrack(trackName string, timeBase time.Time, codec string, width, height int) error
- func (v *VideoFileRF1) HasCapacity(trackName string, nNALU int, maxPTS time.Time, combinedPayloadBytes int) bool
- func (v *VideoFileRF1) ListTracks() map[string]Track
- func (v *VideoFileRF1) Read(trackName string, startTime, endTime time.Time, flags ReadFlags) ([]NALU, error)
- func (v *VideoFileRF1) Size() (int64, error)
- func (v *VideoFileRF1) Write(trackName string, packets []NALU) error
- type VideoFormat
- type VideoFormatRF1
Constants ¶
This section is empty.
Variables ¶
var ErrTrackNotFound = errors.New("Track not found")
Functions ¶
func DoTimeRangesOverlap ¶
func VideoFileHasVideoTrack ¶
Returns true if the file has a video track with the given name, width and height
func VideoFileMaxTrackEndTime ¶
Find the time of the last packet in the video file, from any track
Types ¶
type Archive ¶
type Archive struct {
// contains filtered or unexported fields
}
Archive is a collection of zero or more video streams, rooted at the same base directory. Every sub-directory from the base holds the videos of one stream. The stream name is the directory name. Archive is not safe for use from multiple threads.
func Open ¶
func Open(logger logs.Log, baseDir string, formats []VideoFormat, initSettings StaticSettings, settings DynamicSettings) (*Archive, error)
Open a directory of video files for reading and/or writing. The directory baseDir must exist, but it may be empty. When creating new streams, formats[0] is used, so the ordering of formats is important.
func (*Archive) AutoStatsToLog ¶
func (a *Archive) AutoStatsToLog()
func (*Archive) Close ¶
func (a *Archive) Close()
Close the archive. It is important to close the archive, because doing so will finalize the writing of any archive files. For example, rf1 files are oversized initially to avoid fragmentation, and closing them will shrink them back down to their final size, and update their headers with appropriate information. However, the archive is designed to withstand a hard reset, and to be able to recover as much data as possible in that event. It's just not the most efficient thing to do.
func (*Archive) GetDynamicSettings ¶
func (a *Archive) GetDynamicSettings() DynamicSettings
func (*Archive) ListStreams ¶
func (a *Archive) ListStreams() []*StreamInfo
Get a list of all streams in the archive, and some metadata about each stream.
func (*Archive) MaxVideoFileDuration ¶
func (*Archive) Read ¶
func (a *Archive) Read(streamName string, trackNames []string, startTime, endTime time.Time, flags ReadFlags) (map[string]*TrackReadResult, error)
Read packets from the archive. The map that is returned contains the tracks that were requested. If no packets are found, we return an empty map and a nil error.
func (*Archive) SetDynamicSettings ¶
func (a *Archive) SetDynamicSettings(settings DynamicSettings)
func (*Archive) StreamInfo ¶
func (a *Archive) StreamInfo(streamName string) *StreamInfo
Returns metadata about the stream, or nil if the stream is not found
func (*Archive) StreamSizes ¶
Return the size of each stream
func (*Archive) Write ¶
func (a *Archive) Write(streamName string, payload map[string]TrackPayload) error
Write a payload to the archive. payload keys are track names. The payload must always include the exact same set of tracks, even if some of them have no new content to write. We use the set of tracks and their properties (eg width, height) to figure out when we need to close a file and open a new one. For example, if the user decides to enable HD recording, then the track composition would change. Such a change requires a new video file.
type DynamicSettings ¶
type DynamicSettings struct {
MaxArchiveSize int64 // Maximum size of all files in the archive. We will eat into old files when we need to recycle space. Zero = no limit.
}
Dynamic Settings (can be changed while running). These are settings that a user is likely to change while the system is running, so we make it possible to do so.
func DefaultDynamicSettings ¶
func DefaultDynamicSettings() DynamicSettings
type ErrCodecSwitch ¶
func (ErrCodecSwitch) Error ¶
func (e ErrCodecSwitch) Error() string
type NALU ¶
type NALU struct { PTS time.Time Flags NALUFlags Payload []byte Length int32 // Length is only valid if Payload is nil }
Network Abstraction Layer Unit (NALU)
func (*NALU) IsKeyFrame ¶
type NALUFlags ¶
type NALUFlags uint32
NALU flags
const ( NALUFlagKeyFrame NALUFlags = 1 // Key frame NALUFlagEssentialMeta NALUFlags = 2 // Essential metadata, required to initialize the decoder (eg SPS/PPS NALUs in h264/h265) NALUFlagAnnexB NALUFlags = 4 // Packet has Annex-B "emulation prevention bytes" and start codes )
We have 12 bits for flags, so maximum flag value is 1 << 11 = 2048
type StaticSettings ¶
type StaticSettings struct { MaxBytesPerRead int // Maximum number of bytes that we will return from a single Read() SweepInterval time.Duration // How often we check if we need to recycle space // Write buffer settings MaxWriteBufferSize int // Maximum amount of memory per stream in our write buffer before we flush MaxWriteBufferDiscardMultiple int // MaxWriteBufferSize * MaxWriteBufferDiscardMultiple is max buffer memory before we discard incoming writes MaxWriteBufferTime time.Duration // Maximum amount of time that we'll buffer data in memory before writing it to disk }
Static Settings (cannot be changed while archive is open). These settings cannot be changed while the archive is being used. If you want to change these, you must close and re-open the archive.
func DefaultStaticSettings ¶
func DefaultStaticSettings() StaticSettings
func (*StaticSettings) MaxWriteBufferDiscardLimit ¶
func (s *StaticSettings) MaxWriteBufferDiscardLimit() int
type StreamInfo ¶
Information about a stream
type Track ¶
type Track struct { Name string StartTime time.Time Duration time.Duration Codec string Width int // Only applicable to video tracks Height int // Only applicable to video tracks }
Metadata about a track
type TrackPayload ¶
type TrackPayload struct { TrackType rf1.TrackType Codec string // For audio/video tracks VideoWidth int // For video tracks VideoHeight int // For video tracks NALUs []NALU }
Track payload used when writing packets. Every write call has enough information to create a new track, if necessary. This allows us to have a stateless Write API.
func MakeVideoPayload ¶
func MakeVideoPayload(codec string, width, height int, nalus []NALU) TrackPayload
func (*TrackPayload) EqualStructure ¶
func (t *TrackPayload) EqualStructure(b *TrackPayload) bool
Returns true if all parameters except the payload is identical (eg same codec,width,height,etc)
type TrackReadResult ¶
type VideoFile ¶
type VideoFile interface { Close() error // ListTracks returns a map of track names to track metadata ListTracks() map[string]Track // Return true if the video file can still grow larger to accept the given packets. // Note that even if your video file is capable of storing terabytes of data in a single file, // you should arbitrarily cap the size at something smaller, because the sweeper deletes whole // video files. If your entire video history is stored in one or two files, then the rolling // recorder would need to delete massive chunks of history whenever it needs more space. HasCapacity(trackName string, nNALU int, maxPTS time.Time, combinedPayloadBytes int) bool // Create a new video track in the file. // You must do this before writing packets to the track. CreateVideoTrack(trackName string, timeBase time.Time, codec string, width, height int) error Write(trackName string, packets []NALU) error Read(trackName string, startTime, endTime time.Time, flags ReadFlags) ([]NALU, error) // Total size of the video file(s) Size() (int64, error) }
VideoFile is the analog of VideoFormat, but this is an embodied handle that can be read from and written to
type VideoFileRF1 ¶
func (*VideoFileRF1) Close ¶
func (v *VideoFileRF1) Close() error
func (*VideoFileRF1) CreateVideoTrack ¶
func (*VideoFileRF1) HasCapacity ¶
func (*VideoFileRF1) ListTracks ¶
func (v *VideoFileRF1) ListTracks() map[string]Track
func (*VideoFileRF1) Size ¶
func (v *VideoFileRF1) Size() (int64, error)
type VideoFormat ¶
type VideoFormat interface { IsVideoFile(filename string) bool Open(filename string) (VideoFile, error) Create(filename string) (VideoFile, error) Delete(filename string, tracks []string) error }
A video file type must support the VideoFormat interface in order to be used by fsv.
type VideoFormatRF1 ¶
type VideoFormatRF1 struct { }
func (*VideoFormatRF1) Delete ¶
func (f *VideoFormatRF1) Delete(filename string, tracks []string) error
func (*VideoFormatRF1) IsVideoFile ¶
func (f *VideoFormatRF1) IsVideoFile(filename string) bool