Skip to main content

DTSC Specification (V2 rev2, 2023-10-16)

Packet types

DTSC Packets can currently be these types:

  • DTSC_HEAD packets are 4 bytes DTSC , followed by 4 bytes length and packed content.
  • DTSC_COMMS packets are 4 bytes DTCM, followed by 4 bytes length and packed content.
  • DTSC_V1 packets are 4 bytes DTPD, followed by 4 bytes length and packed content.
  • DTSC_V2 packets are 4 bytes DTP2, followed by 4 bytes length, 4 bytes trackID, 8 bytes time, and packed content.

Note: The length is always without the first 8 bytes counted (i.e. only count everything after the length itself).

Packet content

All packed content is stored in a compact format similar to binary JSON. It is encoded as follows: 1 byte data type, followed by some number of bytes of content:

  • 0x01 (signed 64 bits integer): 8 bytes of integer contents, in network byte order (MSB first)
  • 0x02 (string): 4 bytes of string length (MSB first) followed by length-bytes string contents
  • 0xE0 (object): an arbitrary amount of [2 bytes (MSB) keysize, keysize bytes string key, a single packed DTSC datatype], followed by the 3-byte sequence 0x0000EE
  • 0x0A (array): an arbitrary amount of [a single packed DTSC datatype], followed by the 3-byte sequence 0x0000EE

Note that there is no float or boolean data type. Both are currently represented by integers. Also note that objects are inherently unsorted/unordered. The default implementation sorts alphabetically by key, but this behaviour should not be depended on or expected.

DTSC_HEAD

The DTSC_HEAD packet contains stream metadata, in the following format:

  • Optional flag "vod": integer 1 if VoD (may appear together with "live" flag if both apply)
  • Optional flag "live": integer 1 if live (may appear together with "vod" flag if both apply)
  • Optional deprecated flag "merged": integer 1 if data is guaranteed to be ordered between tracks
  • Optional integer "bufferwindow": time in ms that is buffered in current live stream
  • Optional integer "moreheader": byte offset in current file where a header that overrides this header can be found
  • Optional integer "unixzero": Unix time in ms that corresponds with the zero point in the timeline of the stream. Automatically calculated from the greatest-value "lastms" field if missing.
  • Object "tracks", containing 0 or more of the following object, keyed by human-readable track name (bold entries only required for VoD streams):
    • Integer "trackid": 1-indexed unique track ID
    • String "fragments": byte-packed binary string with fragment data (content is version-dependant)
    • String "keys": byte-packed binary string with key data (content is version-dependant)
    • String "parts": byte-packed binary string with fragment data (content is version-dependant)
    • Optional string "ivecs": byte-packed binary string with ivec data for encryption (content is version-dependant)
    • Integer "firstms": ms position of first available (i.e. requestable) data packet in track
    • Integer "lastms": ms position of last available (i.e. requestable) data packet in track
    • Integer "bps": estimate of average bytes per second for data in this track (i.e. byterate, not bitrate)
    • Optional integer "missed_frags": count of fragments that have been deleted from the buffer since stream start.
    • String "codec": name of data codec for this track (e.g. "AAC", "H264", "HEVC", "Opus", "MP3", etc)
    • String "type": human-readable type of track (e.g.: "audio", "video", "meta")
    • Optional string "init": binary string with codec initialization data
    • Optional string "keysizes": byte-packed binary string with key size data (content is version-dependant)
    • In case type == "audio":
      • Integer "rate": sampling rate in Hz
      • Integer "size": sample size in bytes
      • Integer "channels": channel count (e.g. 1 for mono, 2 for stereo, etc)
    • In case type == "video":
      • Integer "width": width in pixels of video
      • Integer "height": height in pixels of video
      • Integer "fpks": frames per kilo-second (e.g. 29.97 FPS = 29970 fpks)

DTSC_V1 and DTSC_V2

DTSC_V1 and DTSC_V2 packets are both data packet types. V1 is deprecated, V2 is the new style. They contain the same data, but V2 has the time and trackid fields exposed near the beginning of the packet as opposed to these being in a variable location. This allows for very fast (re)indexing of these files.

All timestamps are DTS (decoding time stamp / time of arrival for packets) in milliseconds from any arbitrary starting point. The timestamp must not wrap mid-stream, which (since it’s unsigned 64 bits) means the max duration for a stream is just under 600 million years. That should be sufficient for any practical purpose.

V2’s "packed data" is an object containing the fields: data (string): raw codec data for this packet keyframe (int): only present if the current packet is a video keyframe, and then set to 1 offset (int): only present if DTS and PTS (presentation time stamp / display time) differ, and contains PTS-DTS. This means it must always be positive, as a packet could never be displayed before it is decoded.

V1 in addition contains the fields: time (int): the packet timestamp (in V2 this field is part of the header) trackid (int): the packet’s track ID (in V2 this field is part of the header)

Any additional (non-standardized) fields may or may not be ignored, and may or may not be preserved. Custom field names that are not intended to be made part of this specification in the future should be prefixed by a company or project name to prevent namespace collisions.

Signalling

The DTSC_COMMS packet contains a list of DTSC protocol commands, each an object of:

  • String cmd: command identifier string
  • Optional variable data types: command arguments

command: play

argument stream: (string) name of stream to play

Requests playback start for the given stream.

command: error

argument msg: (string) error message

Pass through an error message.

command: ok

argument msg: (string) non-error message

Pass through an acceptance/status message.

command: push

argument stream: (string) name of stream to receive argument password (optional string) password, plaintext

Requests storage for the given stream.

command: hi

argument: salt: (optional string) semi-random string for salting communications this connection argument: version: (optional string) System/server/whatever version, human-readable argument: pack_method: (integer) Version of packed data parts in headers (0 = error, 1 = old pre-bigmeta style, 2 = bigmeta style)

Welcome message sent by server to client, indicating protocol version and salt for future passwords. Must await at least 1 hi message with valid salt before a push with password is sent (no waiting is necessary for password-less pushing).

command: reset

Requests a reset of the internal metadata of the other side. Should be followed by a DTSC_HEAD packet.

command: ping

Requests a response from the other side. Any response will do, but pong is a good default.