Ross,<div><br></div><div>Thanks for the advice. </div><div><br></div><div>I found MF_H264_DeviceSource::deliverFrame() as well as an old trace statement I put in it back on my successful cobble. This is in fact the "deep inside" I was looking for, albeit having been called back from deep inside and now back in my code. The trace is coming out, which proves that this is connected. I also made the H264VideoStreamDiscreteFramer change and removed the 'start code', but it didn't help. My new cobble is still not working.</div>
<div><br></div><div>Perhaps I should tell you the actual problem! When I go back to using ByteStreamFileSource as the FramedSource, VLC successfully opens the announced rtsp://<a href="http://192.168.123.5:8554/h264ESVideoTest">192.168.123.5:8554/h264ESVideoTest</a> and plays it great. This proves the VLC side is working. However, when I use MF_H264_DeviceSource as the FramedSource, VLC says it can't even open it. Nevertheless, when VLC does try to open it, I do see a trace for my MF_H264_DeviceSource being created and passed back as FramedSource, and I see my trace in MF_H264_DeviceSource::deliverFrame() start happening. For some reason, however, there's a difference such that VLC can no longer open the stream.</div>
<div><br></div><div>Here's my intercept. Just for the easiest method and testing, I trap the filename in H264VideoFileServerMediaSubsession:: createNewStreamSource. This function normally creates a ByteStreamFileSource. But if the filename is "<device>", I cause it to instead create a MF_H264_DeviceSource. You can also see the H264VideoStreamDiscreteFramer change I just made.</div>
<div><br></div><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>FramedSource* H264VideoFileServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>// HgF: Add this DEBUG stuff</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>#ifdef _DEBUG</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>//#define TRACE(msg)<span class="Apple-tab-span" style="white-space:pre"> </span>OutputDebugString(TEXT(msg))<span class="Apple-tab-span" style="white-space:pre"> </span>/* HgF */</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>#define TRACE TRACEX</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>void CDECL TRACEX(PCSTR pszFormat, ...);</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>#else</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>#define TRACE(...)<span class="Apple-tab-span" style="white-space:pre"> </span>/* OMIT IF NOT DEBUGGING */</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>#endif</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>FramedSource* returnFramedSource;</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>FramedSource* videoES;<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF: Add this var as common place for source pointer. Note it's type better matches what H264VideoStreamFramer::createNew() wants anyway</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>estBitrate = 500; // kbps, estimate</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>// Create the video source:</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>if (0==strcmp(fFileName,"<device>")) {<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF: Add this hook for using MF_H264_DeviceSource instead of ByteStreamFileSource</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>TRACE("BEFORE HOOK - H264VideoFileServerMediaSubsession::createNewStreamSource() using MF_H264_DeviceSource to receive live SPIIR-Capture H.264 stream\n"); </div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>MF_H264_DeviceSource* theSource</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>= MF_H264_DeviceSource::createNew(</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>*SPIIROnDemandRTSPServer::env /* UsageEnvironment& */, </div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>&SPIIROnDemandRTSPServer::H264VideoDeviceStreamer_params /* MF_H264_DeviceParameters */);</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>videoES = theSource;</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>TRACE("AFTER HOOK - H264VideoFileServerMediaSubsession::createNewStreamSource() using MF_H264_DeviceSource to receive live SPIIR-Capture H.264 stream\n"); </div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>// Create a framer for the Video Elementary Stream:</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>returnFramedSource = H264VideoStreamDiscreteFramer::createNew(envir(), videoES);<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF-20130215 per advice from Ross Finlayson, must use H264VideoStreamDiscreteFramer, not H264VideoStreamFramer</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>} else {<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF: The ByteStreamFileSource code in this clause is unchanged, aside from copying fileSource into videoES and TRACE statements</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>TRACE("NOT HOOKED - H264VideoFileServerMediaSubsession::createNewStreamSource() using ByteStreamFileSource to play file %s\n", fFileName); </div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName);</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>if (fileSource == NULL) {</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>TRACE("NOT HOOKED - H264VideoFileServerMediaSubsession::createNewStreamSource() ERROR OPENING FILE %s\n", fFileName); </div><div><span class="Apple-tab-span" style="white-space:pre"> </span>return NULL;</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>fFileSize = fileSource->fileSize();</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>videoES = fileSource;<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF: Add this copy to common place for source pointer</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>TRACE("NOT HOOKED - H264VideoFileServerMediaSubsession::createNewStreamSource() ready to play %s\n", fFileName); </div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>// Create a framer for the Video Elementary Stream:</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>returnFramedSource = H264VideoStreamFramer::createNew(envir(), videoES);<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF-20130215 per advice from Ross Finlayson, must use H264VideoStreamDiscreteFramer, not H264VideoStreamFramer</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>return(returnFramedSource);<span class="Apple-tab-span" style="white-space:pre"> </span>// HgF-20130215 per advice from Ross Finlayson, must use H264VideoStreamDiscreteFramer, not H264VideoStreamFramer</div>
<div>}</div></div></blockquote></div><div><br><div>ADDITIONAL CONFUSION... I thought tracking this down might help me find my problem, but it appears not.</div><div><br></div><div>Please don't let the question below subtract from focus on the more important question above, about VLC not being able to open the stream in the MF_H264_DeviceSource case when it can in the ByteStreamFileSource case. I know VLC isn't yours. The question is about how Live555 is reacting to my code, not about VLC.</div>
<div><br></div><div>It appears that BasicTaskScheduler0::doEventLoop is being called recursively. SPIIROnDemandRTSPServer (derived from testOnDemandRTSPServer calls it. Then, when an incoming request event occurs, it ends up being called again. This causes the location of the watchVariable to be changed for this recursive instance. When using ByteStreamFileSource, it seems to set this new watchVariable, and the recursive instance stops, returning to the original instance. But in my MF_H264_DeviceSource where VLC causes an incoming request event yet can't connector for some reason, no such set of the watchVariable occurs, so the recursive instance won't stop, and when my mainline sets the watchVariable of the first instance of doEventLoop, it does nothing because the recursive instance is still running.</div>
<div><br></div><div>Below is the call stack when the recursive doEventLoop() first begins.</div><div><br></div><div><div>><span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!BasicTaskScheduler0::doEventLoop(char * watchVariable) Line 85<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!H264VideoFileServerMediaSubsession::getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource) Line 99<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!OnDemandServerMediaSubsession::setSDPLinesFromRTPSink(RTPSink * rtpSink, FramedSource * inputSource, unsigned int estBitrate) Line 325<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!OnDemandServerMediaSubsession::sdpLines() Line 68<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!ServerMediaSession::generateSDPDescription() Line 233<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!RTSPServer::RTSPClientConnection::handleCmd_DESCRIBE(const char * urlPreSuffix, const char * urlSuffix, const char * fullRequestStr) Line 398<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!RTSPServer::RTSPClientConnection::handleRequestBytes(int newBytesRead) Line 759<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!RTSPServer::RTSPClientConnection::incomingRequestHandler1() Line 623<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div><div>
<span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!RTSPServer::RTSPClientConnection::incomingRequestHandler(void * instance, int __formal) Line 616<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!BasicTaskScheduler::SingleStep(unsigned int maxDelayTime) Line 164<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!BasicTaskScheduler0::doEventLoop(char * watchVariable) Line 88<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!SPIIROnDemandRTSPServer::doEventLoop(char * watchVariable) Line 125<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div><div>
<span class="Apple-tab-span" style="white-space:pre"> </span>Capture.exe!OutputThreadFunction(void * lpParam) Line 113<span class="Apple-tab-span" style="white-space:pre"> </span>C++</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>kernel32.dll!BaseThreadInitThunk()<span class="Apple-tab-span" style="white-space:pre"> </span>Unknown</div>
<div> <span class="Apple-tab-span" style="white-space:pre"> </span>ntdll.dll!RtlUserThreadStart()<span class="Apple-tab-span" style="white-space:pre"> </span>Unknown</div></div><div><br></div><div>On further analysis, it's watchVariable is fDoneFlag member of H264VideoFileSerrverMdiaSubsession. I see this var initialized to zero, but can find nowhere it's ever set. So I don't know how it's ever set in the ByteStreamFileSource case.</div>
<div><br></div><div><br><div class="gmail_quote">On Fri, Feb 15, 2013 at 6:43 PM, Ross Finlayson <span dir="ltr"><<a href="mailto:finlayson@live555.com" target="_blank">finlayson@live555.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div><div class="im"><blockquote type="cite"><div>Now I'm trying to reproduce my cobble, but for unicast and derived from SPIIROnDemandRTSPServer.cpp instead. Exactly as before, my frames get created and I call signalNewFrameData(), but then no frames are coming out IP. With all this cobbling, I'm not sure I have all the lose ends reconnected. Therefore, I'm interested in setting a breakpoint deep inside Live555 somewhere. </div>
</blockquote><div><br></div></div>No, you shouldn't be setting breakpoints 'deep inside LIVE555', because that code is working just fine, and it's code that you're unfamiliar with. Instead, you should be setting breakpoints in *your own* code. Specifically, you should be setting a breakpoint in your "deliverFrame0()" function - i.e., in the function that you passed as a parameter to the "createEventTrigger()" call. That function is the function that should be getting called after each event is triggered.</div>
<div><br></div><div>Don't forget, of course, that all of this happens within the LIVE555 event loop, so don't forget to call "doEventLoop()" in your application to start the event loop running.</div><div>
<div class="im"><br><br><blockquote type="cite"><div>One other thing, both H264VideoDeviceStreamer.cpp and SPIIROnDemandRTSPServer.cpp use a ByteStreamFileSource. In both cases I've replaced that with my MF_H264_DeviceSource.</div>
</blockquote><div><br></div></div>OK, but don't forget that - because your "MF_H264_DeviceSource" code (presumably) delivers discrete H.264 NAL units - you must feed this into a "H264VideoStreamDiscreteFramer", *not* a "H264VideoStreamFramer" (as was used when the input was a byte stream). Also, the H.264 NAL units that come out of your "MF_H264_DeviceSource" code *must not* include a preceding 'start code' (i.e., must not start with 0x00 0x00 0x00 0x01).</div>
<span class="HOEnZb"><font color="#888888"><br><br><div>
<span style="text-indent:0px;letter-spacing:normal;font-variant:normal;text-align:-webkit-auto;font-style:normal;font-weight:normal;line-height:normal;border-collapse:separate;text-transform:none;font-size:medium;white-space:normal;font-family:Helvetica;word-spacing:0px"><span style="text-indent:0px;letter-spacing:normal;font-variant:normal;text-align:-webkit-auto;font-style:normal;font-weight:normal;line-height:normal;border-collapse:separate;text-transform:none;font-size:medium;white-space:normal;font-family:Helvetica;word-spacing:0px">Ross Finlayson<br>
Live Networks, Inc.<br><a href="http://www.live555.com/" target="_blank">http://www.live555.com/</a></span></span>
</div>
<br></font></span></div><br>_______________________________________________<br>
live-devel mailing list<br>
<a href="mailto:live-devel@lists.live555.com">live-devel@lists.live555.com</a><br>
<a href="http://lists.live555.com/mailman/listinfo/live-devel" target="_blank">http://lists.live555.com/mailman/listinfo/live-devel</a><br>
<br></blockquote></div><br></div></div>