shaka-project / shaka-player-embedded

Shaka Player in a C++ Framework
Apache License 2.0
238 stars 63 forks source link

Add a client callback interface for Video events #52

Closed bnge closed 5 years ago

bnge commented 5 years ago

I'm trying to figure out when the player enters a playing state, I'd prefer doing it via an event or callback rather than polling video->Playing().

I'm not that familiar with Shaka Player, but it seems like the onstatechange event might be what I'm looking for. I tried implementing support for the event, but either I missed something, or it's never fired. I'd appreciate it if you could point me in the right direction.

Here's the code I added to AttachListeners() in shaka::Player, I also added a new function shaka::Player::Client::OnStateChange.

const auto on_state_change = [=](Handle<JsObject> event) {
    LocalVar<JsValue> state = GetMemberRaw(event, "state");
    client->OnStateChange(ConvertToString(state));
};
ATTACH("onstatechange", on_state_change);
TheModMaker commented 5 years ago

That event is for transitions between load states in the Player. For example, changing from loaded to attached. This is mainly for testing and isn't that useful for apps.

There isn't a Player event for playing/paused, etc. What you'd need to do is add a client interface to the Video object and listen for those events there. Since the video is an HTMLVideoElement object, it is a bit easier since we don't need to go back and forth with JavaScript. There is a SetCppEventListener method on it you could use to register a C++ listener to call the client callback.

Or we'll add this feature once we have time.

TheModMaker commented 5 years ago

I should also mention that, except for buffering events and ending the video, we never change playing/paused state unless you call it. So you could use the buffering callback for this. Otherwise we will keep playing what you called last on the Video object.

bnge commented 5 years ago

Thanks for replying and for clarifying the onstatechange event to me.

Specifically what I want to do is to notice when media first is presented to the user, e.g. after the manifest was loaded, the first segments are downloaded and media is/can be presented.

To make sure I understand you correctly: would the point in time where media can be presented to the user be at the same point in time I get the first buffering event that has buffer=false? Also, would that be same point in time as the first playing event from the Video object?

TheModMaker commented 5 years ago

Correct. Once you get a OnBuffering callback with is_buffering=false, the content will be available. There will also be a playing event around the same time. It looks like we get frame available first (from Draw), then a playing event, then an OnBuffering callback; so just trying Draw would be the most accurate method.

If you are using the C++ API, you can look at the result from Draw; it will return nullptr until a frame is available to draw.

https://github.com/google/shaka-player-embedded/blob/d393adc8279edacf8686d5c32f20745bad75c349/shaka/demo/main.cc#L172

bnge commented 5 years ago

Thank you!

I'm also interested in knowing when the last piece of media is presented. I guess if I created a client callback interface for Video, I could register a callback for the ended event?

TheModMaker commented 5 years ago

Yep, that would be the best option. The only options currently would be to either poll Ended() or to check Duration() and CurrentTime() and make some educated guesses to get close.