Lesson 5 : Transmitting stream

Sending multicast

Download lesson [here]

In this lesson, we are receiving frames from an IP camera using LiveThread and recast those frames to a multicast address using another LiveThread. The filterchain looks like this:

(LiveThread:livethread) --> {InfoFrameFilter:info_filter) -->> (LiveThread:livethread2)

Let’s start by importing Valkka:

import time
from valkka.core import *

Live555’s default output packet buffer size might be too small, so let’s make it bigger before instantiating any LiveThreads:

setLiveOutPacketBuffermaxSize(95000)

Construct the filtergraph from end-to-beginning:

livethread2    =LiveThread("livethread2")
live_in_filter =livethread2.getFrameFilter()
info_filter    =InfoFrameFilter("info_filter",live_in_filter)
livethread     =LiveThread("livethread")

Start threads

livethread2.startCall()
livethread. startCall()

Define stream source: incoming frames from IP camera 192.168.1.41 are tagged with slot number “2” and they are written to “info_filter”:

ctx     =LiveConnectionContext(LiveConnectionType_rtsp, "rtsp://admin:nordic12345@192.168.1.41", 2, info_filter)

Define stream sink: all outgoing frames with slot number “2” are sent to port 50000:

out_ctx =LiveOutboundContext(LiveConnectionType_sdp, "224.1.168.91", 2, 50000)

Start playing:

livethread2.registerOutboundCall(out_ctx)
livethread. registerStreamCall(ctx)
livethread. playStreamCall(ctx)

Stream and recast to multicast for a while:

time.sleep(60)

livethread. stopStreamCall(ctx)
livethread. deregisterStreamCall(ctx)
livethread2.deregisterOutboundCall(out_ctx)

Stop threads in beginning-to-end order

livethread. stopCall();
livethread2.stopCall();

print("bye")

To receive the multicast stream, you need this file, save it as “multicast.sdp”:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 224.1.168.91
t=0 0
a=tool:libavformat 56.36.100
m=video 50000 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1
a=control:streamid=0

Then you can test that the stream is multicasted (while running the python script) with:

ffplay multicast.sdp

(feel free to launch this command several times simultaneously)

Note

Receiving and recasting the stream can also be done using a single LiveThread only. This is left as an excercise.

Using the RTSP server

Download lesson [here]

In this lesson, we establish an on-demand RTSP server at the localhost.

Stream is read from an IP camera and then re-streamed (shared) to a local RTSP server that serves at port 8554. While this snippet is running, you can test the RTSP server with:

ffplay rtsp://127.0.0.1:8554/stream1

Let’s start by importing Valkka:

import time
from valkka.core import *

Live555’s default output packet buffer size might be too small, so let’s make it bigger before instantiating any LiveThreads:

setLiveOutPacketBuffermaxSize(95000)

Construct the filtergraph from end-to-beginning:

livethread2    =LiveThread("livethread2")
live_in_filter =livethread2.getFrameFilter()
info_filter    =InfoFrameFilter("info_filter",live_in_filter)
livethread     =LiveThread("livethread")

Before starting the threads, establish an RTSP server on livethread2 at port 8554:

livethread2.setRTSPServer(8554);

Start threads

livethread2.startCall()
livethread. startCall()

Define stream source: incoming frames from IP camera 192.168.1.41 are tagged with slot number “2” and they are written to “info_filter”:

ctx     =LiveConnectionContext(LiveConnectionType_rtsp, "rtsp://admin:nordic12345@192.168.1.41", 2, info_filter)

Define stream sink: all outgoing frames with slot number “2” are sent to the RTSP server, with substream id “stream1”:

out_ctx =LiveOutboundContext(LiveConnectionType_rtsp, "stream1", 2, 0)

Start playing:

livethread2.registerOutboundCall(out_ctx)
livethread. registerStreamCall(ctx)
livethread. playStreamCall(ctx)

Stream and recast to the RTSP server for a while:

time.sleep(60)

livethread. stopStreamCall(ctx)
livethread. deregisterStreamCall(ctx)
livethread2.deregisterOutboundCall(out_ctx)

Stop threads in beginning-to-end order

livethread. stopCall();
livethread2.stopCall();

print("bye")