<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 12 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Helvetica;
panose-1:2 11 6 4 2 2 2 2 2 4;}
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{mso-style-priority:34;
margin-top:0in;
margin-right:0in;
margin-bottom:0in;
margin-left:.5in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";}
span.apple-tab-span
{mso-style-name:apple-tab-span;}
span.apple-style-span
{mso-style-name:apple-style-span;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri","sans-serif";
color:#1F497D;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
@list l0
{mso-list-id:1149984344;
mso-list-type:hybrid;
mso-list-template-ids:-497785512 305826600 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
{mso-level-start-at:0;
mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;
mso-fareast-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
@list l1
{mso-list-id:1187911921;
mso-list-type:hybrid;
mso-list-template-ids:1766497990 -247033592 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l1:level1
{mso-level-start-at:0;
mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;
mso-fareast-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
@list l2
{mso-list-id:1300382581;
mso-list-type:hybrid;
mso-list-template-ids:694833046 1885770624 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l2:level1
{mso-level-start-at:0;
mso-level-number-format:bullet;
mso-level-text:-;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Calibri","sans-serif";
mso-fareast-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
ol
{margin-bottom:0in;}
ul
{margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<div>
<p class="MsoNormal" style="margin-left:.5in">I forget the specific motivation behind this API change (which occurred back in 2011), but I suspect it had to do with wanting to make sure that open files are never left lying around once the “ByteStreamFileSource”
object is closed.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">I can understand that, but that could have been achieved with the old API when deleteFidOnClose was true. If it was false instead, then the user was specifically
telling you that it was the user’s responsibility to make sure the fid was closed.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal" style="margin-left:.5in"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif""> I’m able to get around this by checking for a clientSessionId of 0 in my SubclassOnDemandServerMediaSubsession::createNewStreamSource() function.
In this case I don’t use the real file descriptor, but this seems like a hack to me. Is there a better way to prevent my file descriptor from getting closed before I want it to?<o:p></o:p></span></p>
</div>
</blockquote>
<div>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
</div>
<p class="MsoNormal" style="margin-left:.5in">Not that I can tell, because closing the “ByteStreamFileSource” object now always closes the fid. (Again, I’m not sure why the “deleteFidOnClose” parameter got removed, but there must have been a good reason for
this at the time :-)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">I’m sure there was a good reason. I’ve been on the list long enough to know that you always have good reasons for making your code changes.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="margin-left:.5in">An alternative would be for you to actually handle the ‘broken pipe’ signal in your other thread, by tearing down its end of the pipe. (And, then, you’d get to create the pipe a second time, for the ‘real’ (i.e.
“clientSessionId != 0”) stream.) In fact, you probably want to do this signal handling anyway, to handle the case when the ‘real’ stream gets closed - e.g., if your last RTSP client does a RTSP “TEARDOWN” on it. Since you need to do this anyway, you might
as well do it also for the “clientSessionId == 0” case, if it’s not too inefficient to do so.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">I agree that this sounds like a good solution in theory, but I don’t know that it can work in practice without resorting to what feels to me like hacks. Consider
the following.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">MyServer is a multithreaded class that manages the RTSP server as well as a thread that generates the H264 video. There is only a single source of live video
and the reuseFirstSource flag is always set to true. When MyServer starts up, it does its initialization, including creating the pipe used for communication between the RTSP and video production threads, starts the video production thread and then the main
thread becomes the RTSP thread. In the RTSP thread it sets up the task scheduler, usage environment, RTSP server, ServerMediaSession, ServerMediaSubsession, and then enters the scheduler’s event loop. As mentioned before, the ServerMediaSubsession object
is a sub-classed OnDemandServerMediaSubsession that passes the pipe fid to a ByteStreamFileSource.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">When a client connects to the RTSP server, it sends a DESCRIBE message, which triggers the creation of the temporary ByteStreamFileSource. As expected, the
deletion of this temporary object closes the pipe fid. The client then sends SETUP and PLAY messages. The SETUP message triggers the creation of the actual ByteStreamFileSource object using the (already closed) pipe fid. The PLAY message triggers the video
production thread to actually produce video (no point in doing useless work if no client is playing), so it tries to write to the pipe. Since I have never attempted to write to the pipe until this point, it is only now that I can notice (either through SIGPIPE
or EPIPE) that the read end of the pipe was closed, but it is now too late to give the ByteStreamFileSource object a new fid as that is set in the constructor (through the createNew() function). The only way I can see to change the fid when needed would be
to sub-class ByteStreamFileSource and expose methods to allow the protected fFid field to be changed, but that seems like a hack to me and I’m not sure what other implications that may have.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="margin-left:.5in">As an aside, you could, if you wish, eliminate the ‘broken pipe’ signal by calling our<o:p></o:p></p>
</div>
<div>
<div>
<p class="MsoNormal" style="margin-left:.5in"><span class="apple-tab-span">
</span>ignoreSigPipeOnSocket()<span class="apple-tab-span"> </span>(defined in “groupsock/include/GroupsockHelper.hh”)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="margin-left:.5in">function on the socket (i.e., at the LIVE555-thread end of the pipe). But in your case, you probably don’t want to do this, unless you have some other way of telling your non-LIVE555 thread that it needs to close
its end of the pipe.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Something somewhere is already ignoring SIGPIPE and I check for EPIPE on the write() call instead. Either way, both are only generated after a call to write().
As noted above, this is too late to be able to pass a new pipe fid to the ByteStreamFileSource instance, unless there is something that I am missing.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">I’m not necessarily asking for you to change the API back to how it was; as you said, there was probably a good reason for changing it in the first place.
I was hoping, however, that you or someone else on the list would have a clean an elegant solution. If not, I’ll stick with my hack of checking the clientSessionId (assuming this is guaranteed to be non-zero if there is an actual session). Alternatively,
if I have enough time (haha), I could change my code to have the OnDemandServerMediaSubsession sub-class create the pipe when a new stream source was created and then signal the other thread to close its old fid and start using the new one instead.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Thanks,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Tyson<o:p></o:p></span></p>
</div>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Helvetica","sans-serif";color:black"><br>
<br>
</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span class="apple-style-span"><span style="font-family:"Helvetica","sans-serif";color:black">Ross Finlayson</span></span><span style="font-family:"Helvetica","sans-serif";color:black"><br>
<span class="apple-style-span">Live Networks, Inc.</span><br>
<span class="apple-style-span"><a href="http://www.live555.com/">http://www.live555.com/</a></span></span>
<o:p></o:p></p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>