Panel | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
Expand | ||||||||||||
| ||||||||||||
|
The media streamer is controlled by setting a pipeline configuration. The stream-source component and stream-destination component are specified by passing a string to the roMediaStreamer.SetPipeline() method. This string contains both the source and destination components concatenated together; the different stages of the pipeline are delimited by commas.
The pipeline is started by calling the start()
method (without extra arguments). The stop()
method can be used to stop the pipeline. However, some of the pipeline stages (described in the Media Streamer State Machine section below) will continue running internally, so the reset()
method may be preferable for terminating the stream.
Simple File Streaming
The following example shows how to stream from a file source to a single client:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("file:///data/clip.ts, udp://239.192.0.0:1234/")
m.Start() |
To stop the stream, call m.reset()
.
The file
source and udp/rtp
destinations do not function the same as in 4.7 firmware. However, the 4.7 method of file streaming is still available using the filesimple
, udpsimple
and rtpsimple
components. The following example works exactly the same as media streaming in 4.7:
Code Block |
---|
m.SetPipeline("filesimple:///data/clip.ts, udpsimple://239.192.0.0:1234/") |
Note that the filesimple
component only works with udpsimple/rtpsimple
, and vice versa.
...
The media streamer, represented by the SetPipeline()
method, has four states:
- RESET: The media streamer has been created, but nothing is allocated or running.
- INITIALISED: Some allocation may have happened and some resources may be reserved, but nothing is running.
- CONNECTED: All structures have been created and all the pipeline components are connected together. Though the pipeline is producing no output, some internal parts of it may already be running.
- RUNNING: The pipeline is running.
When a media streamer is created, it starts in the RESET state. After calling SetPipeline()
, the states can be progressed through using the following roMediaStreamer methods: Initialise()
, Connect()
, and Start()
. Moving to a later state causes any intervening states to be traversed automatically, which is why a pipeline can be started by simply calling Start()
.
When a media streamer is in the RUNNING state, it can be moved backwards through the states by calling, respectively, Stop()
, Disconnect()
, and Reset()
. As before, intermediate states can be omitted, so it is possible to stop the media streamer and de-allocate all its resources simply by calling Reset()
. While Stop()
does stop any output from emerging from the pipeline, there may still be some internal activity.
Calling SetPipeline()
always causes the media streamer to return to the RESET state. All of the above interface functions, aside from SetPipeline()
, take no arguments.
Source Components
This section lists the currently available source components for a streaming pipeline. Note that some source components (i.e. mem:/
and memsimple:/
) cannot be called until they are first created using destination components, which are described in the next section.
filesimple:///filename
...
Code Block |
---|
m.SetPipeline("filesimple:///file.ts?loop, udpsimple://239.192.0.0:1234/") |
file:///filename
This component can act as either a source or a destination. As a source, it reads from an MPEG-2 transport stream file and can be connected more generally to other components. This non-simple component must be used when connected to hls:
destination components (because it uses an indexed stream). Because it uses fewer resources, we recommend using the filesimple:
component instead of the file:
component whenever it is sufficient.
This component accepts the optional key
and iv
parameters for file encryption/decryption.
The optional loop parameter can be appended to cause the input file to loop:
Code Block |
---|
m.SetPipeline("file:///file.ts?loop, hls:///file?duration=3") |
hdmi:[///]
This component receives audio and video from the HDMI Input. It can then be fed through an 6545413 component and streamed or written to a file.
display:[///]
This component receives the audio and video of the current presentation, allowing the player to encode and stream its current display output. See the Display Encoding page for more information about using this component.
udp://IP_address:port/
This component receives a stream using the UDP protocol.
rtp://IP_address:port/
This component receives a stream using the RTP protocol.
rtsp://IP_address:port/path
This component receives a stream using the RTSP protocol. An optional dtcp.port
parameter can be included to specify a DTCP-IP encrypted session:
Code Block | ||
---|---|---|
| ||
rtsp://10.1.243:554/stream1?dtcp.port=8888 |
http://IP_address:port/path
This component receives a stream using the HTTP protocol.
https://IP_address:port/path
This component receives a stream using the HTTPS protocol.
gst://IP_address:port/path
This component receives a GStreamer pipeline and generates a non-simple stream using it.
gstsimple://IP_address:port/path
This component receives a GStreamer pipeline and generates a simple stream using it.
memsimple:/name/stream.ts
This component reads from a previously created (destination) memory stream component with the given name, and forwards the results to other simple components. Note that /stream.ts
is appended to denote "the entire memory buffer". The following example will multicast a memory stream:
Code Block |
---|
m.SetPipeline("memsimple:/livestream/stream.ts, rtpsimple://239.192.0.0:5004/") |
A memsimple:
source component can originate from either a simple memory stream (using the memsimple:
destination component) or a non-simple, "indexed" memory stream (using the mem:
destination component).
See the Memory Streaming page for more details.
mem:/name/stream.ts
This component reads from a previously created destination memory stream with the given name
; it can then forward the results to other non-simple components. Note that /stream.ts
is appended to denote "the entire memory buffer". Assuming sufficient resources, the following example will transcode and stream a memory stream:
Code Block |
---|
m.SetPipeline("mem:/livestream/stream.ts, decoder:, encoder:, rtp://239.192.0.0:5004/") |
Destination Components
This section lists the currently available destination components.
udpsimple://IP_address:port/
This component streams its input over UDP to the given IP address and port. This destination only works with the filesimple:
or memsimple:
source component as input.
rtpsimple://IP_address:port/
This component streams its input over RTP to the given IP address and port. This destination only works with the filesimple:
or memsimple:
source component as input.
httpsimple:///socket=num
This component streams its input over an HTTP connection. This destination only works with the filesimple:
or memsimple:
source component as input. It is intended for use as an HTTP media server and cannot be used to stream directly to a client.
udp://IP_address:port/
This component streams its input over UDP to the given IP address and port.
rtp://IP_address:port/
This component streams its input over RTP to the given IP address and port.
http:///socket=num
This component streams its input over an HTTP connection. This component is intended for use as an HTTP media server and cannot be used to stream directly to a client.
file:///filename
This component writes its input to the named file, which will be saved as an MPEG-2 transport stream file. This component accepts the optional key
and iv
parameters for file encryption.
display:[///]
This component allows you to see what's in a stream (often in conjunction with the decoder component) and is provided for debugging only: BrightScript primarily utilizes the roVideoPlayer and roAudioPlayer objects to play back streaming content.
memsimple:/name
This component works only with the filesimple:
component. It writes its input to a memory stream named /name
. This constitutes a simple memory stream, meaning that it is not indexed and cannot be input to a mem:
source, only another memsimple:
source. This component takes an optional size parameter that specifies the size of the memory buffer in megabytes. The default memory buffer size is 5MB.
Code Block |
---|
m.SetPipeline("filesimple:///file.ts, memsimple:/file?size=2") |
mem:/name
This component creates a memory stream with the specified /name
. This component can receive input from general components and writes to an indexed (rather than simple) memory stream, which can be re-read by the mem:
source component. It can therefore be used to support HLS streaming.
Code Block |
---|
m.SetPipeline("file:///file.ts, mem:/file?duration=3&size=25") |
The mem:
destination component accepts two optional parameters:
size
: The size of the memory buffer in MB (megabytes). For HLS streaming, this needs to be a large buffer.duration
: The target duration of the index points (which become HLS segments).
hls:///path
This component segments the incoming stream and writes it to the given path. The written segments will have the name "path_000000.ts", "path_0000001.ts", etc., and the index file will be named "path_index.m3u8".
The HLS destination component accepts the parameter duration
, which specifies the approximate target length, in seconds, of the HLS segments. The default value is 5, so to segment a file into 3 second durations you could use code similar to the following:
Code Block |
---|
m.SetPipeline("file:///file.ts, hls:///file?duration=3") |
The above function would split the file.ts file into segments of approximately 3 seconds each, named "file_000000.ts", "file_000001.ts", "file_000002.ts", etc.
Destination Component Options
The following options apply to the udpsimple
, rtpsimple
, udp
, and rtp
destination components.
maxbitrate
The maxbitrate
parameter throttles the maximum instantaneous bitrate (in Kbps) of a stream. For example, the following component would never stream at a rate greater than approximately 2Mbps:
Code Block | ||
---|---|---|
| ||
rtp://IP_address:port/?maxbitrate=2000 |
This number needs tuning both for the content being streamed and the network over which they are being sent. Note that it can be challenging to configure bitrates for some wireless networks.
ttl
The ttl
parameter specifies how many times multicast packets can be forwarded across switches and other network infrastructure. The default value for this parameter is 1.
Code Block | ||||
---|---|---|---|---|
| ||||
rtp://IP_address:port/?ttl=64 |
Other Components
...
This component receives an un-encoded input and outputs audio/video data encoded as an MPEG-2 transport stream. The following are valid parameters:
audiodelay=[delay_in_ms]
: The audio synchronization offset in milliseconds. The default value is 0. A positive value will delay the audio with respect to the video, while a negative value will delay the video with respect to the audio.delay=[delay_in_ms]
: The A2P delay in milliseconds. If this parameter is set to 0 (the default value), the encoder determines the delay.pframes=[frames]
: The number of P-slices between I-slices in the GOPbframes=[frames]
: The number of B-slices between P-slices in the GOPvbitrate=[bitrate]
: The video bitrate specified in Kbpsvformat=[format]
: The resolution and frame rate of the video output. Theformat
can be specified as any of the following:- 480i50
- 480p25
- 720p24
- 720p25
- 720p30
- 720p50
- 720p60
- 1080i50
- 1080i60
- 1080p24
- 1080p25
- 1080p30
- 1080p50
- 1080p60
This component utilizes H.264 for video and AAC for audio. The default video format is 720p30, and the default bitrate is 6Mbps.
Note | ||
---|---|---|
| ||
With firmware versions 6.2.63 and later, the H.264 video is encoded at High profile with B-frames. With earlier versions of firmware, video is encoded at level 4.1 without B-frames. |
The following example encodes video from the HDMI Input and writes it to the local storage as a .ts file:
Code Block |
---|
m.SetPipeline("hdmi:, encoder:vformat=480p25&vbitrate=1000, file:///hdmi.ts") |
esencoder:[///][param=value]
This component receives an un-encoded input and outputs video data as an elementary H.264 stream (as opposed to the standard encoder:
component, which outputs an MPEG-2 transport stream). The H.264 stream has no audio data. This component accepts the same audiodelay
, vformat
, and vbitrate
parameters as the encoder: component.
Since non-simple components expect an MPEG-2 transport stream, this component only works with the following: rtpsimple:
, udpsimple:
, httpsimple:
, and memsimple:
.
decoder:[///]
This component receives an encoded input and decodes it. The primary uses of this component are to pass a video stream to the display:
destination for playback or to pass a video file to an encoder:
component for transcoding.
HDCP
The roMediaStreamer object will honor the copy-protection status of its inputs by assigning the same status to its outputs. Each stream can have one of the following levels of copy protection:
- None: No copy protection is enabled. These streams can be saved to files or streamed over the network without restriction.
- HDCP: The input is protected with HDCP. It can be neither saved nor streamed, but it can be output to an HDCP-authenticated display.
HDCP Workflow
The roMediaStreamer object will handle HDCP authentication and de-authentication as follows:
...
HDCP Overview
High-bandwidth Digital Content Protection (HDCP), which protects content from duplication, can affect customers using the HDMI® input on XD1230, XD1132, 4K1142, XT1143, and XT1144 BrightSign players. BrightSign hardware can not violate HDCP key rules, so users can be affected if they try to use content that is protected, or use a box that strips HDCP from HDMI signals.
There are two versions of HDCP. HDCP 1.x is content encryption for standard, high-def, 1080K content and is supported on BrightSign players. HDCP 2.x is content encryption for 4K (high-resolution) content. HDCP 2.2 may work but is not yet officially supported by BrightSign players.
HDCP Compliance
Any HDCP-protected signal must remain HDCP-protected through the entire HDMI chain. This applies to all BrightSign players with HDMI inputs (the XD1230, XD1132, 4K1142, XT1143, and XT1144). If If the HDMI input signal is protected by HDCP:
BrightSign players cannot encode the HDMI input for streaming or saving to file.
BrightSign players cannot display the HDMI input if any device in the HDMI chain is not HDCP-compliant or refuses a HDCP-protected handshake/connection.
ThisThis includes HDMI splitters/DAs, media converters/transceivers (HDMI-over-Cat5, etc), A/V receivers, TVs/displays, analog output (on XD1230 and XD1132), and display encoding
(stream the player output screen). In. In this case, BrightSign players will still play the audio (barring bugs or incompatibility) from the HDMI input, but the area where the HDMI input video should be will be empty/gray.
...
For more details on how streaming and HDCP work in the BrightSign system, see HDCP.
Forcing HDCP On
BrightSign offersroVideoMode, a BrightScript function that will force HDCP on all the time. This prevents issues of compatibility because in at least some versions of the OS, HDCP won't be applied on the output until the HDCP content is displayed.
Here is an example of how to use this function:
Code Block | ||
---|---|---|
| ||
mode = createobject("roVideomode")
mode.ConfigureHdmiInput({MaxHdcpVersion:1, EdidFilename:0}) |
Additional Notes
The player only enables HDCP on the HDMI output if HDCP is detected on the HDMI input
, save for Aaron's comment above?????Chromecast, Apple TV, Amazon Fire Stick, and Roku boxes.
Set top cable, satellite boxes, and streaming devices enable HDCP on their output
for obvious reasons.
Most game consoles enable HDCP on their HDMI output, though
in some casesit
dependsmay depend on the output mode or software being used.
SomeMacBookswill enable HDCP on the output if the destination device reports it supports HDCP, regardless of whether protected content is being displayed or not.
Some computer DVI graphics cards can support HDCP over DVI, as can some DVI AV devices like certain projectors and DVD players with DVI output, however, most DVI-HDMI conversion will lose HDCP
and a lot of.
Many early displays don't support HDCP over DVI
.Someand some early HDMI displays don't support HDCP over HDMI either. If it's not specifically mentioned, it probably isn't supported on the device.
There
wasis an allowance in the DMCA for a HDCP-protected source device to allow SD (Standard Definition) analog output, but in practice this
wasis rarely seen/used.
There are some instances where an HDCP-protected source can end up being output via analog on devices with both HDMI and analog outputs
(on BrightSign players and the original OLED TiVo Series 3 set-top boxes), but these should not be relied upon. This doesn't apply to current models without analog outputs. See Will-HDCP-content-display-over-an-analog-video-output?
HDCP 1.x and HDCP 2.x (available in HDMI 2.x)
are separate entitiesare separate entities. While HDMI 2.x devices are generally supposed to fall back to work with HDCP 1.x devices, it isn't always a smooth
process, hence devices like HDfury Integral and similar in-line conversion/translation devices.
Encryption Flags
The encryption level can be forced by flagging it on the source component. For example, the following source component will force any connected display receiving HDMI input to be HDCP authenticated:
Code Block | ||
---|---|---|
| ||
hdmi:encryption=hdcp |
Warning | ||
---|---|---|
| ||
The HDCP encryption status of a stream cannot be removed by setting the encryption parameter to none. |
...
The file:///
source and destination components accept the optional key
and iv parameters, which can be used to encrypt or decrypt a file using the AES CTR algorithm. The key
and iv values must be specified as 16-byte hex strings.
Note that this file encryption process is distinct from HDCP authentication. There are no restrictions on how encrypted files may be used in a pipeline, but you cannot use this form of encryption on a stream that was originally HDCP protected.
The following example saves an HLS stream as an encrypted file. Once the file is written, it can be decrypted from a file:///
source component using the same key
and iv values:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("http://<ip-address>/playlist.m3u8,file:///file.ts?key= 30313233343536373839616263646566&iv=30313233343536373839616263646566")
m.Start() |
Streaming Examples
The following code snippets provide examples for common types of media streaming.
Streaming an MPEG-2 TS File over UDP
To initialize the roMediaStreamer instance and begin the stream, use the following:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("file:///data/clip.ts, udp://239.192.0.0:1234/")
m.Start() |
To stop the stream, use the following:
Code Block |
---|
m.reset() |
You can also use the simple form of components for most common streaming tasks. The following would operate identically to the above stream, while using fewer resources:
Code Block |
---|
m.SetPipeline("filesimple:///data/clip.ts, udpsimple://239.192.0.0:1234/") |
Streaming an Encoded HDMI Input over RTP
The resolution and bitrate of the streamed video can be changed by adding parameters to the encoder:
component. Use the following code to stream the input using the native resolution and default bitrate:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("hdmi:, encoder:, rtp://239.192.0.0:1234/")
m.Start() |
To stop the stream, use the following:
Code Block |
---|
m.reset() |
Recording a File
The following code will record an HDMI Input and save it as a file named hdmi.ts:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("hdmi:, encoder:, file:///hdmi.ts")
m.Start() |
...
process
...
Code Block |
---|
m.reset() |
Transcoding and Streaming a File
The output of a decoder:
component can be connected to the input of an encoder:
component to transcode the data. This is useful if you want to modify the bitrate of the video before streaming it over the network. The following code will transcode the file.ts video before streaming it over RTP:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("file:///file.ts, decoder:, encoder:vbitrate=1000, rtp://239.192.0.0:5004/")
m.Start() |
To stop the transcoding process, use the following:
Code Block |
---|
m.reset() |
Re-streaming
The player can be used to output a streaming input using a different protocol by connecting an IP client component to an IP server component. The following code will receive an HTTP stream and then stream it using RTP:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("http://172.30.1.37/file.ts, rtp://239.192.0.0:5004/")
m.Start() |
To stop the stream, use the following:
Code Block |
---|
m.reset() |
Segmenting a File Using HLS
An existing .ts file can be segmented for streaming using the HLS protocol. The resulting file segments can then be streamed directly by making HTTP requests to an HTTP Media Server. The following code will use the file.ts video to generate segments that are approximately 10 seconds in duration:
Code Block |
---|
m = CreateObject("roMediaStreamer")
m.SetPipeline("file:///file.ts, hls:///media_segment?duration=10")
m.Start() |
In this case, the files will begin with media_segment_000000.ts, and the counter will increment once for each segment. The index file will be written as "media_segment_index.m3u8".
Simple and Non-Simple Components
To conserve system resources, we recommend using the simple versions of components whenever possible. Use the following guidelines to determine whether simple or non-simple components should be used:
- Use simple components when streaming a file from local storage using UDP, RTP, or HTTP protocols (without any encoding or transcoding involved in the pipeline).
- Use non-simple components whenever the pipeline includes encoding, transcoding, or HLS streaming.
- When ingesting a stream from a remote source and re-streaming it, use the
udpsimple:
,rtpsimple:
, andhttpsimple:
destination components. If you need to modulate the stream (or re-stream using HLS), use non-simple components. - Since a
memsimple:
source component can read from amem:
destination component, use thememsimple:
source component in conjunction withudpsimple:
,rtpsimple:
, orhttpsimple:
when memory streaming. Themem:
source component should only be used with thehls:
destination component ( orfile:
if debugging).