nestegg

nim-nestegg - a portable, statically linked WebM format demuxer for Nim

wraps the popular and portable nestegg C library from mozilla in Nim goodness (expressiveness and memory safety)

Types

AudioCodec = enum
  acVorbis = (1, "vorbis"), acOpus = (3, "opus"), acUnknown = (127, "unkown")
Allowed codecs for WebM audio, or flag unknown
VideoCodec = enum
  vcVp8 = (0, "vp8"), vcVp9 = (2, "vp9"), vcAv1 = (4, "av1"), ## av1 is de-facto part of webm and assumed to become official
  vcUnknown = (127, "unkown")
Allowed codecs for WebM video, or flag unknown
TrackKind = enum
  tkVideo = (0, "video"), tkAudio = (1, "audio"), tkUnknown = (127, "unknown")
Track types, audio or video
InitError = object of IOError
  
An error that happens during setting up of the demuxer
DemuxError = object of IOError
  
An error that happens during the demuxing process itself
TrackObj = object
  case kind*: TrackKind
  of tkVideo:
      videoCodec*: VideoCodec
      videoParams*: video_params
      duration*: culonglong
      fps*: float

  of tkAudio:
      audioCodec*: AudioCodec
      audioParams*: audio_params

  of tkUnknown:
      nil

  num*: cuint
  codecData*: seq[Chunk]
Contains initialization data and metadata about one of the tracks multiplexed in the WebM file
Track = ref TrackObj
Chunk = object
  len*: int
  data*: ptr UncheckedArray[byte]
A chunk of data. Each multiplexed packet contains a series of these chunks that make up the actual encoded data to be sent to the decoder
PacketObj = object
  raw*: ptr cpacket
  length*: cuint
  timestamp*: culonglong
  track*: Track
  chunks*: seq[Chunk]
An individual data packet. A stream of these is sent over a file or a network, each track's packets interspersed with each other. That's what makes it a multiplexed stream. Each Packet contains one or more Chunks of raw data.
Packet = ref PacketObj
SourceObj = object
  io*: io
A data source interface that is mapped to a file by default, but other data sources such as network streams can be implemented.
Source = ref SourceObj
DemuxerObj = object
  file*: File
  context*: ptr nestegg
  duration*: uint64
  source*: Source
  tracks*: seq[Track]
  firstVideo*: Track
  firstAudio*: Track
The demuxer object that wraps the actual demux process. Can be iterated over to retrieve packets.
Demuxer = ref DemuxerObj

Procs

proc newTrack(context: ptr nestegg; trackNum: cuint): Track {...}{.
    raises: [InitError, ValueError], tags: [].}
proc newDemuxer(source: Source): Demuxer {...}{.raises: [InitError, ValueError],
    tags: [].}
Initialize a demuxer object from a data source. Reads all the initialization data and metadata and presents them in an object. Can be iterated over in order to retrieve data packets from the stream.
proc seek(demuxer: Demuxer; timestamp: uint64) {...}{.
    raises: [DemuxError, ValueError], tags: [].}
Seek to specified nestegg timestamp Note that some decoders require their own seek calls as well

Iterators

iterator items(demuxer: Demuxer): Packet {...}{.raises: [DemuxError, ValueError],
    tags: [].}
The iterater that retrieves packets from the demuxer. Note that a packet can be from various tracks, no guarantees are made in which order packets arrive in. Within the iterator, select codecs to handle the data and perform buffering as needed.
iterator items(packet: Packet): Chunk {...}{.raises: [], tags: [].}

Templates

template newDemuxer(file: File): Demuxer
Convenience template to create a demuxer from a file objcet If other sources are created, adding one of these keeps the interface friendly
template newDemuxer(filename: string): Demuxer
Convenience template to create a demuxer from a file name. The file is kept open and can be left open on termination. If the file needs to be closed within the program, it can be done manually like so: demuxer.file.close
template toOpenArray(chunk: Chunk; first, last: int): openArray[byte]
Allows passing a chunk of data to various collection functions that take an openArray for data analysis or processing. This is always a copy operation.