ONVIF for ZoneMinder – Streaming
The Media service
I wanted some quick wins therefore I focused on getting the camera to work. I decided the generic message parsing stuff would have to wait.
With the address I got previously I called the ONVIF Device Management web service method GetServices
.I received this response: (I removed all XML header information and information on all services but Media
.)
<tds:XAddr>http://192.168.0.20/onvif/Media</tds:XAddr> <tds:Capabilities> <trt:Capabilities SnapshotUri="true" Rotation="false"> <trt:ProfileCapabilities MaximumNumberOfProfiles="10"></trt:ProfileCapabilities> <trt:StreamingCapabilities RTPMulticast="true" RTP_TCP="true" RTP_RTSP_TCP="true" NonAggregateControl="false"> </trt:StreamingCapabilities> </trt:Capabilities> </tds:Capabilities> <tds:Version> <tt:Major>2</tt:Major> <tt:Minor>1</tt:Minor> </tds:Version> </tds:Service>
Among some capability information I got the address for the next service to call: http://192.168.0.20/onvif/Media.
I wanted to call these functions:
- GetProfiles () – returns a list of Media Profiles describing settings such as video resultion, audio quality
- GetStreamUri (Profile, StreamType) – returns a URI for the media feed
I would be able to enter the properties and URI of the video feed in ZoneMinder and get a first view of the camera.
Eventually this sequence of functions needed to be integrated into ZoneMinder. My goal was to automatically probe for ONVIF cameras and their settings. And then create a new monitor based on these settings.
Security
The first response I got was “The action requested requires authorization and the sender is not authorized.” Therefore I implemented a SecuritySerializer
module that enriches all outgoing messages with a WS-Security UsernameToken
header.
First view
For GetProfiles()
I got a response with two pre-configured profiles. One of which I pasted below.
By the way – ONVIF also defines messages to change these settings and create new profiles. However, it seems ZoneMinder has no UI for this functionality. You need to configure your camera with the program that comes with your camera and then enter its settings in the ZoneMinder monitor definition.
<trt:Profiles token="Profile_1" fixed="true"><tt:Name>mainStream</tt:Name> <tt:VideoSourceConfiguration token="VideoSourceToken"><tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:SourceToken>VideoSource_1</tt:SourceToken> <tt:Bounds x="0" y="0" width="2048" height="1536"></tt:Bounds> </tt:VideoSourceConfiguration> <tt:VideoEncoderConfiguration token="VideoEncoderToken_1"><tt:Name>VideoEncoder_1</tt:Name> <tt:UseCount>1</tt:UseCount> <tt:Encoding>H264</tt:Encoding> <tt:Resolution><tt:Width>1920</tt:Width> <tt:Height>1080</tt:Height> </tt:Resolution> <tt:Quality>3.000000</tt:Quality> <tt:RateControl><tt:FrameRateLimit>30</tt:FrameRateLimit> <tt:EncodingInterval>1</tt:EncodingInterval> <tt:BitrateLimit>4096</tt:BitrateLimit> </tt:RateControl> <tt:H264><tt:GovLength>60</tt:GovLength> <tt:H264Profile>Baseline</tt:H264Profile> </tt:H264> <tt:Multicast><tt:Address><tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>8600</tt:Port> <tt:TTL>1</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:SessionTimeout>PT5S</tt:SessionTimeout> </tt:VideoEncoderConfiguration> <tt:VideoAnalyticsConfiguration token="VideoAnalyticsToken"><tt:Name>VideoAnalyticsName</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:AnalyticsEngineConfiguration><tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="0"/> <tt:ElementItem Name="Layout"><tt:CellLayout Columns="22" Rows="15"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/> <tt:Scale x="0.001042" y="0.001852"/> </tt:Transformation> </tt:CellLayout> </tt:ElementItem> </tt:Parameters> </tt:AnalyticsModule> </tt:AnalyticsEngineConfiguration> <tt:RuleEngineConfiguration><tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"><tt:Parameters><tt:SimpleItem Name="MinCount" Value="5"/> <tt:SimpleItem Name="AlarmOnDelay" Value="100"/> <tt:SimpleItem Name="AlarmOffDelay" Value="100"/> <tt:SimpleItem Name="ActiveCells" Value="1wA="/> </tt:Parameters> </tt:Rule> </tt:RuleEngineConfiguration> </tt:VideoAnalyticsConfiguration> <tt:Extension></tt:Extension> </trt:Profiles>
This response gave me the resolution, framerate and encoding of the video feed. Finally I got this URI when I called GetStreamUri(Profile, StreamType)
:
rtsp://192.168.0.20:554/Streaming/Channels/1?transportmode=mcast&profile=Profile_1
I added username and password before the ip address and tested the feed with mplayer
and ffplay
— and finally with ZoneMinder. Success!
Nicest of all is: This procedure involved no network sniffer or guesswork. I just followed the ONVIF specifications. The procedure is deterministic and should be repeatable for any ONVIF camera.
This is a good basis for automating the manually performed steps. I am thinking of a “Probe ONVIF” button in the ZoneMinder “New Monitor” tab.
This post is part of The ONVIF series. See the other posts in the series here.
Recent Comments