rtmp_core.bend checks
raw source on the hub · import 0x2355f41b6f5561f50104a75ccca27cf7/rtmp_core.bend as Rtmp_core
RTMP (Adobe's specification of 2012): the pure half of the client.
- the handshake's bytes; - the chunk stream: a message is cut into chunks, each after a header that says which chunk stream it is on and, in one of four sizes, what changed since that stream's last message; - the control messages and the commands (AMF0) a player sends; - what a message from the server means to a player; - FLV, the file the audio, video and data messages are written to as they are: a tag is a message with another header.
4 imports
import Base import ./bytes.bend as B import ./amf.bend as A import ./rtsp_core.bend as C
Types
type Shake source · line 31 · raw
Data
EarlyShake
Shake@c2:List<&2, U32> -> @rest:List<&2, U32> -> Shake
type Where source · line 129 · raw
Data
Where a URL's path sends us: the application to connect to, and the stream to play in it (the last part of the path, with the query).
Where@app:String -> @stream:String -> Where
type Lane source · line 204 · raw
Data
A chunk stream's last header: the timestamp, the 3-byte field it came in (a delta but in a type 0 header; FFFFFF says the real value is in 4 more bytes), the message's size, type and stream; and the message under way: the bytes it has, its pieces last first.
Lane@id:U32 -> @ts:U32 -> @field:U32 -> @len:U32 -> @typ:U32 -> @sid:U32 -> @got:U32 -> @parts:List<&2, List<&2, U32>> -> Lane
type Dec source · line 209 · raw
Data
The decoder: the size of the server's chunks, and its chunk streams.
Dec@size:U32 -> @chans:List<&2, Lane> -> Dec
type Step source · line 214 · raw
Data
A step of the decoder: nothing whole in the buffer; a chunk taken that ends no message; or a message.
MoreStep
Part@st:Dec -> @rest:List<&2, U32> -> Step
Msg@typ:U32 -> @ts:U32 -> @sid:U32 -> @payload:List<&2, U32> -> @st:Dec -> @rest:List<&2, U32> -> Step
type Ev source · line 366 · raw
Data
Idle: more bytes are needed. Skip: nothing to act on. Result and Error answer a command. Start, Over and Refused are the stream's status. Media is audio (8), video (9) or the metadata (18). Ping asks for a pong with the same bytes.
IdleEv
Skip@st:Dec -> @rest:List<&2, U32> -> Ev
Result@ts:List<&2, 0x2355f41b6f5561f50104a75ccca27cf7/amf.Tok> -> @st:Dec -> @rest:List<&2, U32> -> Ev
Error@msg:String -> @st:Dec -> @rest:List<&2, U32> -> Ev
Over@st:Dec -> @rest:List<&2, U32> -> Ev
Refused@msg:String -> @st:Dec -> @rest:List<&2, U32> -> Ev
Media@typ:U32 -> @ts:U32 -> @payload:List<&2, U32> -> @st:Dec -> @rest:List<&2, U32> -> Ev
Ping@data:List<&2, U32> -> @st:Dec -> @rest:List<&2, U32> -> Ev
type Tag source · line 475 · raw
Data
A media message as a session gives it: audio (8), video (9) or the metadata (18), its time in ms, and the data in the form an FLV tag holds (flv.bend takes frames out of it).
Tag@typ:U32 -> @ts:U32 -> @data:List<&2, U32> -> Tag
Definitions
def Rtmp.noise source · line 19 · raw
@n:Nat -> @+x:U32 -> @acc:List<&2, U32> -> List<&2, U32>
def Rtmp.hello source · line 28 · raw
@seed:U32 -> List<&2, U32>
C0 and C1: version 3, then 1536 bytes: a time, four zeros, and 1528 bytes of anything (here a sequence grown from the seed).
def Rtmp.shake.s2 source · line 35 · raw
@c:0x2355f41b6f5561f50104a75ccca27cf7/bytes.Cut -> @s1:List<&2, U32> -> Shake
def Rtmp.shake.s1 source · line 42 · raw
@c:0x2355f41b6f5561f50104a75ccca27cf7/bytes.Cut -> Shake
def Rtmp.shake source · line 52 · raw
@buf:List<&2, U32> -> Shake
The server's S0, S1 and S2 (1 + 1536 + 1536 bytes): C2 is S1 sent back, and what follows them is the chunk stream. Early when they are not all here yet.
def Rtmp.parts source · line 63 · raw
@fuel:Nat -> @c:0x2355f41b6f5561f50104a75ccca27cf7/bytes.Cut -> @+sep:List<&2, U32> -> @+size:Nat -> @acc:List<&2, U32> -> List<&2, U32>
The pieces of a payload, the separator between them.
def Rtmp.ext source · line 74 · raw
@big:Bool -> @ts:U32 -> List<&2, U32>
def Rtmp.message source · line 85 · raw
@+cs:U32 -> @typ:U32 -> @sid:U32 -> @+ts:U32 -> @+payload:List<&2, U32> -> @+size:U32 -> List<&2, U32>
A message as chunks of at most size bytes on chunk stream cs (2 to 63): the first after a full header (type 0), the others after a one-byte one (type 3). A timestamp that does not fit 3 bytes goes as FFFFFF there and in 4 bytes after each header.
def Rtmp.out source · line 97 · raw
U32
The chunk size this client announces and then writes with (the protocol starts at 128).
def Rtmp.control source · line 102 · raw
@typ:U32 -> @data:List<&2, U32> -> List<&2, U32>
Protocol control (on chunk stream 2, message stream 0; they are smaller than any chunk size).
def Rtmp.chunk_size source · line 106 · raw
@n:U32 -> List<&2, U32>
Set Chunk Size (1).
def Rtmp.ack source · line 110 · raw
@n:U32 -> List<&2, U32>
Acknowledgement (3): the bytes received so far.
def Rtmp.buffer source · line 114 · raw
@sid:U32 -> @ms:U32 -> List<&2, U32>
User control (4): event 3 is Set Buffer Length, 7 the answer to a ping.
def Rtmp.pong source · line 117 · raw
@data:List<&2, U32> -> List<&2, U32>
def Rtmp.command source · line 121 · raw
@cs:U32 -> @sid:U32 -> @ts:List<&2, 0x2355f41b6f5561f50104a75ccca27cf7/amf.Tok> -> List<&2, U32>
A command (20) of AMF0 values.
def Where.end source · line 132 · raw
@has:Bool -> @app:String -> @seg:String -> Where
def Where.slash source · line 139 · raw
@has:Bool -> @app:String -> @seg:String -> String
def Where.go source · line 147 · raw
@s:String -> @+has:Bool -> @+app:String -> @+seg:String -> @+query:Bool -> Where
app and seg are kept reversed; a "/" before the query ends a part.
def Where.of source · line 156 · raw
@path:String -> Where
def Where.app source · line 163 · raw
@w:Where -> String
def Where.stream source · line 167 · raw
@w:Where -> String
def Rtmp.connect source · line 174 · raw
@+app:String -> @host:String -> @port:U32 -> List<&2, U32>
connect, transaction 1: the application, its URL, and the codecs of enhanced RTMP this client reads (H.265), which a server sends only to a client that names them.
def Rtmp.create source · line 189 · raw
List<&2, U32>
createStream, transaction 2: its result carries the stream's id.
def Rtmp.play source · line 193 · raw
@+sid:U32 -> @stream:String -> List<&2, U32>
play on the stream, and how much the server may send ahead.
def Dec.new source · line 219 · raw
Dec
def Lane.find source · line 222 · raw
@cs:List<&2, Lane> -> @+id:U32 -> Lane
def Lane.drop source · line 230 · raw
@cs:List<&2, Lane> -> @+id:U32 -> List<&2, Lane>
def Rtmp.done source · line 240 · raw
@full:Bool -> @id:U32 -> @+ts:U32 -> @field:U32 -> @len:U32 -> @+typ:U32 -> @+sid:U32 -> @got:U32 -> @parts:List<&2, List<&2, U32>> -> @+size:U32 -> @others:List<&2, Lane> -> @rest:List<&2, U32> -> Step
The message is whole, or not yet.
def Rtmp.data source · line 252 · raw
@c:0x2355f41b6f5561f50104a75ccca27cf7/bytes.Cut -> @+n:U32 -> @ch:Lane -> @size:U32 -> @others:List<&2, Lane> -> Step
def Rtmp.body source · line 264 · raw
@+v:U32 -> @abs:Bool -> @fresh:Bool -> @ch:Lane -> @r:List<&2, U32> -> @+size:U32 -> @others:List<&2, Lane> -> Step
The chunk's data: up to the chunk size of what the message lacks. A chunk that starts a message moves the timestamp by v, or to v after a type 0 header.
def Rtmp.time source · line 272 · raw
@big:Bool -> @+field:U32 -> @abs:Bool -> @fresh:Bool -> @ch:Lane -> @r:List<&2, U32> -> @size:U32 -> @others:List<&2, Lane> -> Step
def Lane.field source · line 282 · raw
@ch:Lane -> U32
def Lane.fresh source · line 286 · raw
@ch:Lane -> Bool
def Lane.with source · line 292 · raw
@kind:Nat -> @ch:Lane -> @+h:List<&2, U32> -> Lane
The header a chunk brings: all of it (type 0), without the stream (1), the time only (2); a new header starts a message over.
def Rtmp.timed source · line 306 · raw
@+ch:Lane -> @abs:Bool -> @fresh:Bool -> @r:List<&2, U32> -> @size:U32 -> @others:List<&2, Lane> -> Step
def Rtmp.header source · line 311 · raw
@c:0x2355f41b6f5561f50104a75ccca27cf7/bytes.Cut -> @+kind:Nat -> @ch:Lane -> @size:U32 -> @others:List<&2, Lane> -> Step
def Rtmp.format source · line 320 · raw
@fmt:Nat -> @+ch:Lane -> @r:List<&2, U32> -> @size:U32 -> @others:List<&2, Lane> -> Step
def Rtmp.stream source · line 332 · raw
@fmt:U32 -> @+id:U32 -> @r:List<&2, U32> -> @st:Dec -> Step
def Rtmp.basic source · line 338 · raw
@zero:Bool -> @one:Bool -> @cs:U32 -> @fmt:U32 -> @t:List<&2, U32> -> @st:Dec -> Step
The chunk stream's number: 6 bits, or in 1 or 2 more bytes when they say 0 or 1.
def Rtmp.chunk source · line 351 · raw
@st:Dec -> @buf:List<&2, U32> -> Step
One chunk off the buffer.
def Ev.words source · line 376 · raw
@+code:String -> @+desc:String -> String
def Ev.status.of source · line 379 · raw
@bad:Bool -> @end:Bool -> @code:String -> @desc:String -> @st:Dec -> @rest:List<&2, U32> -> Ev
def Ev.status source · line 390 · raw
@+code:String -> @desc:String -> @st:Dec -> @rest:List<&2, U32> -> Ev
An onStatus: the stream ended, was refused, or goes on.
def Ev.named source · line 396 · raw
@res:Bool -> @err:Bool -> @status:Bool -> @+ts:List<&2, 0x2355f41b6f5561f50104a75ccca27cf7/amf.Tok> -> @st:Dec -> @rest:List<&2, U32> -> Ev
def Ev.command source · line 408 · raw
@+ts:List<&2, 0x2355f41b6f5561f50104a75ccca27cf7/amf.Tok> -> @st:Dec -> @rest:List<&2, U32> -> Ev
def Ev.user source · line 414 · raw
@p:List<&2, U32> -> @st:Dec -> @rest:List<&2, U32> -> Ev
A user control message: event 6 is a ping; the rest is news.
def Ev.data source · line 424 · raw
@yes:Bool -> @p:List<&2, U32> -> List<&2, U32>
A data message as a file wants it: servers pass on the publisher's "@setDataFrame" in front of "onMetaData", and a reader of FLV expects the name first.
def Ev.script source · line 434 · raw
@p:List<&2, U32> -> @ts:U32 -> @st:Dec -> @rest:List<&2, U32> -> Ev
Of the data messages only the metadata goes to the file: servers also send their own notes as data (a sample-access flag, a status), and a reader of FLV takes each for a stream of its own.
def Ev.typed source · line 441 · raw
@media:Bool -> @data:Bool -> @cmd:Bool -> @user:Bool -> @typ:U32 -> @ts:U32 -> @p:List<&2, U32> -> @st:Dec -> @rest:List<&2, U32> -> Ev
def Ev.of source · line 455 · raw
@s:Step -> Ev
def Rtmp.event source · line 466 · raw
@st:Dec -> @buf:List<&2, U32> -> Ev
The next event of a buffer.
def Flv.header source · line 480 · raw
List<&2, U32>
The file's header (audio and video both announced), and the size of the tag before the first, which is none.
def Flv.tag source · line 485 · raw
@typ:U32 -> @+ts:U32 -> @+data:List<&2, U32> -> List<&2, U32>
A tag: the type, the data's size, the timestamp (its top byte last), stream 0, the data, and the tag's whole size after it.
def Flv.of source · line 491 · raw
@t:Tag -> List<&2, U32>
A tag's bytes in a file.