<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div><blockquote type="cite">I've use Live555 for some prototypes for a while now and it's working quite well so far. My use cases<br>are to act as a cental video hub for a number of remote surveillance cameras as well as locally connected<br>USB cameras and serve H264/MJPEG streams using unicast and multicast. Those scenarios more or<br></blockquote><blockquote type="cite">less work ok. The code isn't too pretty but Live555 is quite hard to use.</blockquote><div><br></div><div>Yes, it's hard to use, but that's mainly because it's used to build complex systems. It's also intended for experienced systems programmers; not for the 'faint of heart' :-) Finally, everyone should remember that Live Networks, Inc. is not a charity, and I make no money by helping people with the software 'for free' on this mailing list; it's just something that I do as a public service.</div><div><br></div><br><blockquote type="cite">Now I need to save the streams to disk too. There is the handy StreamReplicator class that should allow</blockquote><blockquote type="cite">me to save the streams to disk as well as stream them to clients, but I've not really understood how to use<br>it correctly. From what I've understood I need to create one StreamReplicator for the source stream and<br>then replicator->createNewStreamReplica() for the streaming as well as the saving. Well, this does not work<br>at all so I'm doing something wrong.<br><br>The class that handles a local USB camera and unicasts MJPEG is basically:<br><br>class LocalMJpegUnicastServerMediaSubsession : public OnDemandServerMediaSubsession {<br></blockquote><div><br></div>First, because you're streaming from live sources (rather than prerecorded files), make sure that your "LocalMJpegUnicastServerMediaSubsession" constructor sets the "reuseFirstSource" parameter - in the "OnDemandServerMediaSubsession" constructor - to True.</div><div><br></div><div><br><blockquote type="cite">FramedSource* LocalMJpegUnicastServerMediaSubsession::createNewStreamSource (unsigned clientSessionID, unsigned& estBitRate) {<br> // create and initialize a source for the camera. This is a JPEGVideoSource subclass that captures, encodes and delivers JPEG frames<br> // it works fine as long as do not try to use StreamReplicator<br> MJpegFramedSource *source = MJpegFramedSource::createNew( envir() );<br> source->initialize( m_cameraParameters );<br><br> m_replicator = StreamReplicator::createNew( envir(), source, False );<br></blockquote><div><br></div>I would replace this line with:</div><div><span class="Apple-tab-span" style="white-space: pre;"> </span>if (m_replicator == NULL) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>m_replicator = StreamReplicator::createNew( envir(), source, False );</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>startSavingStream(yourFileName);</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div>and, of course, initialize "m_replicator" to NULL in your constructor.</div><div><br></div><div><br><blockquote type="cite"><br> return m_replicator->createStreamReplica();<br></blockquote><div><br></div>This is correct.</div><div><br></div><div><br><blockquote type="cite">RTPSink* LocalMJpegUnicastServerMediaSubsession::createNewRTPSink (Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource) {<br> return JPEGVideoRTPSink::createNew( envir(), rtpGroupsock );<br>} <br></blockquote><div><br></div>This is correct.</div><div><br></div><div><br><blockquote type="cite">When I use this ServerMediaSubsession and connect a client the call sequence I see is:<br><br>LocalMJpegUnicastServerMediaSubsession::createNewStreamSource() <br>LocalMJpegUnicastServerMediaSubsession::createNewRTPSink()<br></blockquote><div><br></div>FYI, at this point, you should also be seeing:</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>~JPEGVideoRTPSink()</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>~StreamReplica()</div><div><br><blockquote type="cite">LocalMJpegUnicastServerMediaSubsession::createNewStreamSource() <br>LocalMJpegUnicastServerMediaSubsession::createNewRTPSink()<br></blockquote><div><br></div>The reason for this is that the first "createNewStreamSource()"/"createNewRTPSink()" calls are to create 'dummy' objects that the RTSP server uses to get the stream's SDP description (for the RTSP 'DESCRIBE" command). These two objects are then deleted (thus the "FYI" above). Then, 'real' source and sink objects are created.</div><br><br><div apple-content-edited="true">
<span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px;"><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">Ross Finlayson<br>Live Networks, Inc.<br><a href="http://www.live555.com/">http://www.live555.com/</a></span></span>
</div>
<br></body></html>