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.

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.

 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?

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 :-)

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.

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.

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.

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.

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.

As an aside, you could, if you wish, eliminate the ‘broken pipe’ signal by 
calling our
            ignoreSigPipeOnSocket()       (defined in 
“groupsock/include/GroupsockHelper.hh”)
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.

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.

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.

Thanks,
Tyson


Ross Finlayson
Live Networks, Inc.
http://www.live555.com/

_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

Reply via email to