I found this: MediaPlaybackSession.PositionChanged
and it works, but it triggers very rarely, on the order of 2-3 ticks per second for a regular 30fps video. The video itself plays fine, but I need an event to tick every frame so I can re-arrange an overlay in real-time.
I suppose I could use a threaded timer to tick for every frame based on its framerate, and update the internal frame count with the event above to account for any drift, but is there something that just triggers once every single frame?
So in the end I've found and tried three ways of getting per-frame ticks:
MediaPlaybackSession.PositionChanged
, as per my original question. This has the drawback of only triggering a couple of times per second.
MediaStreamSource.SampleRendered
, as per Simon's comment. This has the drawback of not triggering for forced position sets (seeks). It also seems to trigger before the playback session's position updates, so reading it in this event (even marshalled to the GUI thread) will get you an old position.
A plain threaded timer with the tick rate equal to the video's frame rate. This of course has a couple of drawbacks (out of sync with the video, may skip frames depending on thread scheduling), but the fact that it keeps ticking means that it will catch up on the next tick. Overall this has been very successful.