Program.cs
Our brief is to connect to an RTMP server, and download a stream of content to our hard disk. The code for this application is available here Program.cs.
At the top of the Program.cs file are examples of connection parameters that connect to local servers running on your system as well as remote servers globally available on the Internet.
Here is a table showing the programmatic steps required to download a stream of RTMP data.
| A |
Open the target files. Two files will be needed - one for the audio data, and one for the video data. If an MP3 is being streamed, the video data will be empty.
|
| B |
Create an RtmpClient object. The RtmpClient constructor takes one parameters, a reference to the main window of your application. Since out application runs in a console, which is windowless, this parameter can be null.
|
| C |
Call an RtmpClient function to open an RtmpConnection object. The RtmpConnection encapsulates a connection to the RTMP server. Three parameters are required to create the connection - the host address, the host port (1935 for RTMP), and the protocol, which is RTMP.
There are several variants of RTMP, for example, RTMPT which is RTMP tunneled through HTTP, or RTMPE which is encrypted RTMP.
|
| D |
Set up the behavior parameters for our RtmpConnection.
Some RTMP servers combine messages into one large message to save on processing overhead. Enable the automatic chopping up of aggregate messages to break these messages up into their sub-messages.
During the connection handshake, the RTMP sends a SetPeerBW messages, and expects a WindowsAck message in return. Enable AutoRespondToSetPeerBW to ensure this done automatically.
Every so often the RTMP server sends out a Ping message to see if the client is still alive, and the server expects a Pong response within a timeframe. Enable AutoPingPong to automatically send the Pongs back.
During connection handshake, the server sends out a ReceiveAckWindow, which is the number of bytes the client can receive from the server after which the server expects an acknowledgement. This value is usually 250,000 bytes, but can be much less. If no acknowledgement is received, the server stops sending. Enable AutoAckReceivedData to automatically send these acknowledgments.
|
| E |
Call an RtmpConnection function to connect to the streaming application we are interested in. There are ten parameters for this function, defining the path of the stream, and the capabilities of the client. The AppName and the TcUrl are the most important. The audio and video capabilities can be set to ALL. The other parameters can often be left empty.
The RTMP connection parameters consist of application names, combined with relative locations.
Look at the sets of connection parameters at the top of the Program.cs file for examples of these values.
|
| F |
Call an RtmpConnection function to create a stream. This returns an RtmpStream object.
An RTMP connection can theoretically support multiple streams, but in reality only the more sophisticated RTMP servers can do this.
|
| G |
Enable the RtmpStream's collecting buffers for audio and video data.
By enabling the CollectAudioDataFlag and CollectVideoDataFlag, the audio and video data that is received by a stream is added to two internal thread-safe buffers.
The amount of data in these buffers can be tested at any time using the AvailableAudioDataSize and AvailableVideoDataSize variables.
When data has been collected into the buffers, an external application can grab the data and write it to a file. This is what our application is doing in the _WriteAudioAndVideoDataToFiles function.
|
| H |
Register for pre-processing on our RtmpStream.
The pre-processing callback allows us to look at RTMP messages as they arrive for our stream, before anything else is done with them. We can intercept meta-data messages and display them for the user.
Another method of storing our audio and video data would have been to intercept audio and video messages in a pre-processing callback function and write the message payload directly to the files. However in our application we use the RtmpStream's thread-safe buffers because they use less processor time.
Another use of pre-processing is to examine the messages sent from the RTMP server that indicate when the stream is paused, stopped, streaming and complete, and then update the application interface.
The pre-processor function is called from inside a thread. Any processing done in the pre-processing callback function should be minimal, and must not interact with any form controls. If you want to receive events from the RtmpClient, use the StatusChanged event of the RtmpClient, which is described below.
|
| I |
Play the stream.
Playing the stream initiates a flow of audio and video data from the RTMP server, and some meta-data.
|
| J |
Take the incoming audio and video data and write it to the target files. Keep doing this until the streaming stops.
|
| K |
Clean up the Rtmp session. Delete the stream, close the connection, and destruct the RtmpClient object.
|
| L |
Flush and close the target files.
|
| M |
There is a good change the audio data will consist of MP3 packets, so attempt to convert this data into a valid MP3 files by calling one of the static helper functions of the RtmpClient, RebuildMP3File.
|
Additional Functionality
The following is a chart of the public functions and properties of each of the main Rtmp classes.
| RtmpClient |
|
| |
RtmpClient |
Construct a new RtmpClient object.
|
| |
CreateConnection |
Create a new RtmpConnection object which encapsulates a connection to an RTMP server.
|
| |
StatusChanged |
An event to notify of changes to client, connection or stream. This event and its arguments are detailed below. |
| |
RebuildMP3File |
A static helper function that converts a file of MP3 frames downloaded from an RtmpStream into a valid MP3 file that can be played with an MP3 player. |
| |
|
|
| RtmpConnection |
|
| |
AutoRespondToSetPeerBW |
A boolean property for enabling automatic responses to the handshake message SetPeerBW. |
| |
AutoChopUpAggregateMessages |
A boolean property for enabling the chopping up of aggregate messages as soon as they are received. |
| |
AutoPingPong |
A boolean property for enabling automatic ping message handling. |
| |
AutoAckReceivedData |
A boolean property for enabling automatic data acknowledgment messages. |
| |
Timestamp |
A UInt32 property for getting the current client-side timestamp. Used when creating your own messages. |
| |
ChunkSize |
A UInt32 property for getting the current chunk size. Used when creating your own messages. |
| |
Close |
Close the current connection. Closes all streams for this connection. |
| |
IsValid |
Returns null if the stream is valid, otherwise returns a string description. |
| |
SendMessageAndWait |
Send a message and wait for a response. The response expected will have the same message target as the sent message, will have a string value for the first parameter (for example "_result" or "_onStatus"), and will be the same message type (for example, an Amf0 Command). |
| |
SendMessage |
Send a message and return immediately. |
| |
GetNextTransactionId |
Get the next transaction id, and increment the next transaction Id counter (2 - 0x7FFFFF). |
| |
GetNextAmfStreamId |
Get the next Amf Stream id. Amf stream ids are rotated on the client-side (3 - 28). |
| |
ConnectToApplication |
Connect to a streaming application on the server. |
| |
CreateStream |
Create a new RtmpStream object. |
| |
|
|
| RtmpStream |
|
| |
StreamId |
A UInt32 property for getting the stream id that was assigned to the stream by the RTMP server. |
| |
State |
An eState property for getting the current state. Values include Idle, Streaming, Reset, Paused, Stopped and Closed. Once a stream is closed, it cannot be re-opened. |
| |
AvailableAudioDataSize |
A UInt32 property for getting the amount of data collected in the audio data buffer. |
| |
AvailableVideoDataSize |
A UInt32 property for getting the amount of data collected in the video data buffer. |
| |
CollectAudioDataFlag |
A boolean property to enable the collecting of audio data in the audio data buffer. |
| |
CollectVideoDataFlag |
A boolean property to enable the collecting of video data in the video data buffer. |
| |
ForwardMetaDataFlag |
A boolean property which when enabled, sends a StatusChanged event when meta-data is received for this stream. |
| |
IsValid |
Returns null if the stream is valid, otherwise returns a string description. |
| |
Play |
Sends the play command for the stream. |
| |
Pause |
Pause or resume streaming. |
| |
Seek |
Seek to a time offset within the stream. |
| |
Close |
Close the stream using the RTMP function "deleteStream". |
| |
SetBufferSize |
Set the buffer size in milliseconds. |
| |
ClearAudioCollector |
Clear the buffer of collected audio data. |
| |
ClearVideoCollector |
Clear the buffer of collected video data. |
| |
GetCollectedAudioData |
Grab collected audio data into the buffer provided. |
| |
GetCollectedVideoData |
Grab collected video data into the buffer provided. |
| |
RegisterForPreProcessing |
Register a function as the pre-processing callback function for this stream. |
| |
StreamNameFormatter |
A static helper function to help format stream names. |
RTMP Messages
As message data is received it is translated into Rtmp messages.
Each RTMP message type has an associated class derived from RtmpMessage. Each message class has one or more properties for accessing the parameters of the message. Some of the message classes also have static helper functions to assist building commonly used messages.
| RtmpMessage |
This is an abstract top-level class. All of the message classes are based on this class. |
| |
AmfStreamId |
The Amf stream id for the message. |
| |
Timestamp |
The server-side timestamp. |
| |
MsgTarget |
The message target, which is either zero or a stream id. |
| |
MsgType |
An eMsgType property for getting the RTMP type of the message. |
| |
ToBuffer |
Creates a buffer out of the message that can be sent over a socket connection. |
| |
ToString |
Creates a string description of the message. |
| |
|
|
| RtmpMessage_AudioData |
The audio-data message. |
| |
Data |
A byte-array property containing the audio-data payload of the message. |
| |
SetData |
Set the audio-data payload. |
| |
|
|
| RtmpMessage_CommandAmf0 |
An AMF0 command message. |
| |
Parameters |
A ParameterList property for getting a reference to the list of parameters. |
| |
Build_NetConnection_Connect |
A static helper function for building a "connect" message. |
| |
Build_NetConnection_CreateStream |
A static helper function for building a "createStream" message. |
| |
Build_NetStream_Play |
A static helper function for building a "play" message. |
| |
Build_NetStream_Pause |
A static helper function for building a "pause" message. |
| |
Build_NetStream_Seek |
A static helper function for building a "seek" message. |
| |
Build_NetStream_DeleteStream |
A static helper function for building a "deleteStream" message. |
| |
|
|
| RtmpMessage_Control |
A control-code message. Control messages are used for a variety of functions, each with their own parameter set. |
| |
ControlCode |
Set or get the ControlCode for the message, including STREAM_BEGIN, STREAM_EOF, STREAM_DRY, SET_BUFFER_SIZE,
STREAM_IS_RECORDED,
PING_REQUEST,
PING_RESPONSE,
SWFV_REQUEST,
SWFV_RESPONSE,
UNKNOWN1 and
UNKNOWN2. |
| |
StreamId |
The stream-id parameter for the stream control code messages. |
| |
PingTime |
The ping-time data in a ping request and returned in a ping response (a pong). |
| |
SetBufferLength |
Get and set the SetBufferLength parameter in milliseconds. |
| |
ResponseBuffer |
The response buffer for the SWFV_REQUEST and SWFV_RESPONSE control messages. |
| |
Build_SetBufferSize |
A static helper function for building a SET_BUFFER_SIZE message. |
| |
Build_Pong |
A static helper function for building a PING_RESPONSE message. |
| |
|
|
| RtmpMessage_DataAck |
A acknowledgement of received data. |
| |
Value |
Get or set a UInt32 value representing the amount of bytes received since the last DataAck message was sent. |
| |
Build |
A static helper function for building a DataAck message. |
| |
|
|
| RtmpMessage_MetaDataAmf0 |
Meta-data that is streamed with the audio and video data. |
| |
Parameters |
A ParameterList property for getting a reference to the list of parameters. |
| |
|
|
| RtmpMessage_SetChunkSize |
A chunk-size value, sent from the RTMP server, specifying how message data will be chopped up. |
| |
Value |
A UInt32 property for getting and setting the new chunk size. |
| |
|
|
| RtmpMessage_SetPeerBW |
A SET_PEER_BW message. |
| |
eLimitType |
An eLimitValue property, including HARD, SOFT and DYNAMIC. |
| |
Value |
A UInt32 property for getting and setting the bandwidth value. |
| |
|
|
| RtmpMessage_VideoData |
The video-data message. |
| |
Data |
A byte array property containing the video-data payload of the message. |
| |
SetData |
Set the video-data payload. |
| |
|
|
| RtmpMessage_WindowAckSize |
A specification of the Ack data size. |
| |
Value |
A UInt32 property for getting and setting the acknowledgement widow size in bytes. |
| |
Build |
A static helper function for building a Window-Ack-Size message. |
There is one further message class, and this one does not correspond to an RTMP message type.
| RtmpMessage_Raw |
An Rtmp message with header and payload. |
| |
Payload |
A byte array property for accessing the payload buffer. |
| |
SetPayload |
Set the payload buffer. |
Messages that are not translated into one of the RTMP message type classes are encapsulated in as a raw message, RtmpMessage_Raw.
|