In trying to find a workaround for this, I find that if I listen for the MediaErrorEvent that dispatches when the encoder stops (seems like this should be another event, along the lines of NetStream.Unpublish.Notify, but...), I can resupply a new VideoElement to the MediaPlayer instance and it restarts the stream correctly. I'm passing the same instance of RTMPDynamicStreamingNetLoader to the constructor of VideoElement. What I'm concerned about is if that is rebuilding the entire connection with FMS or if this is keeping the connection and just making another play() call on the NetStream. I suspect the former, but it's hard to tell from my FMS logs.
This would be a Bad Thing bootstrapper-wise: in a situation where a large number of participants have their window open as the encoder stops, they'll all bang on the FMS server for a reconnect when it stops.
I'd rather not work around the framework by listening to NetStatusEvent, but I may need to in order to prevent this situation? Does the OSMF team have any guidance on this?
We recently fixed a bug in this area (FM-603) where the Unpublish.Notify event was being ignored. Now, upon receiving this event we treat it as the completion of playback (e.g. so that if this is a VideoElement in a SerialElement, then the next child of the SerialElement will begin playback). But based on your example, I'm not sure if that's the right thing to do. When we get the Unpublish.Notify, either the live stream is done, or it's just a hiccup and will soon be republished. If we assume it's done (and signal "complete"), then we won't be able to resume if a Publish.Notify event follows.
In players you (or others) have built in the past, how have you dealt with the uncertainty around the Unpublish.Notify event? Assume that it might be followed by a Publish.Notify? Assume the worst? Specify a timeout value after which you assume it's unpublished for good?
We definitely assume for any Unpublish.Notify event that this may be followed by another Publish.Notify. In live streaming, we can't really judge 'over for good' from FMS responses. With previous players, we'd make a connection to NetConnection and NetStream, listen for the Publish.Notify and startup, respond to an Unpublish.Notify, but remain active, effectively ensuring we are able to restart playback any number of times. Being able to respond to these particular events is important also for us to convey that the stream has disconnected, rather than it just buffering.
This would seem to me a common use case for live streaming. That said, I think receiving a 'complete' signal is technically more accurate than a MediaEventError. As long as the framework had a way of remaining connected to FMS beyond this 'complete' signal then I'd be content. But I can see why you may want to destroy the player after such an event, particularly if you were using serial elements. But this wouldn't be a use case for live streaming.
As it stands, I don't currently see a workaround that doesn't behind the scenes require a reconnect to FMS.
Looking further into this, I may be ok with current functionality, since I am passing the same instance of RTMPDynamicStreamingNetLoader when I construct a new VideoElement. If I am reading the source correctly, its superclass, NetLoader, only ever constructs a new NetConnectionFactory in its constructor, when the parameter is null. Should one be specified, it will reuse it, which by default shares NetConnections, and will fire a NetConnectionFactoryEvent.CREATION_COMPLETE with the same NetConnection instance, one that's already connected. At this point, NetLoader handles this event and uses the existing (connected) NetConnection instance and subscribe to the new stream. Interesting also how if I were to pass a single instance of NetConnectionFactory to multiple instances of OSMF players, each playing VideoElements via RTMPDynamicStreamingNetLoader(myNetConnectionFactory), they'd all share and not open multiple connections to FMS.
This is my understanding looking through the code, and it does resolve my concern for a storm of connections happening when I create a new VideoElement on an unpublish event. Please let me know if I am incorrect.
So here's the current behavior that I see:
With 0.93, if you unpublish, then the player doesn't notice and it appears to keep playing (the current time doesn't change, but the player's state is PLAYING). If you subsequently republish the stream, the player will resume playback.
With public trunk, if you unpublish, then the player will assume playback is complete. It won't tear down the connection. If you subsequently republish, then nothing will happen. However, if you then call play(), playback will begin (again, using the same connection and stream).
So I think the current behavior is appropriate (and based on your latest response, sounds like you agree).
Your summary doesn't appear exactly correct.
On 0.93, my experience differs on 10.0 and 10.1 RC. Playback will resume fine on 10.1 RC (OS X) but will not resume playback on 10.0 unless I reconstruct a new VideoElement and pass it along to my MediaPlayer. I'm storing an instance of my RTMPDynamicStreamingNetLoader and passing it with each request to ensure that it uses the same NetConnection.
I have not had a chance to play with a nightly in a while, but if what you're describing will be the behavior in the next drop, that sounds more concerning. The problem is that I would need to store and manipulate the netStream object directly, which feels against the spirit of the framework. The RTMPDynamicStreamingNetLoader class does not override the creation of NetStreams so I don't have access to play2(). Depending on play() is also something I'm wary of, because I'd actually want to use the new play2() method and pass an object that gives me control over DVR, position in pre-recorded, etc., but perhaps that's already resolved in some of those new DVR related checkins I'm seeing fly by.
Thanks for your help, Brian.
I think I was unclear in my response. With the latest code, when you unpublish, the VideoElement (via its TimeTrait) will dispatch the TimeEvent.COMPLETE event. When the server subsequently republishes, the client can then invoke play (on the VideoElement's PlayTrait, or via MediaPlayer.play). There's no need to access the NetConnection or NetStream. If the client continues to use the same VideoElement, then everything should work. If the client creates a new VideoElement, then as long as you pass it the previously-used RTMPDynamicStreamingNetLoader, then it will reuse the existing NetConnection (but create a new NetStream). You shouldn't have to use NetStream's methods directly (or even know that there's a NetStream under the hood), you should be able to interact directly with the VideoElement or MediaPlayer APIs.
I will make this change to use MediaPlayer.play() when we move to the next sprint. Thanks again.