Set position in mediaElement (ScrubbingEnabled alternative in WP8.1) - c#

I am trying to set position of video while video is paused.
In WPF it is simple with ScrubbingEnabled
property.
But there is nothing like this for windows phone.
So I use:
_mediaElement.Play();
_mediaElement.Position += new TimeSpan(0,0,0,0,50);//move video 50 milisecond forward
_mediaElement.Pause();
It is "working", but when I am trying to go (about)5 miliseconds back, it is moving forward and it is not clear solution...
How can I replace ScrubbingEnabled property on windows phone?
Edit
Code for 5ms back:
_mediaElement.Play();
_mediaElement.Position -= new TimeSpan(0,0,0,0,5);
_mediaElement.Pause();

Even assuming that your video is running at 60 frames per second, there's only one frame every 16.67 ms. So to move 5 ms should probably do nothing in many cases.
That would also explain why when you ask it to move 50 ms, it doesn't move by that exact amount, but rather goes to the time of the closest frame.
(if you move position by only a few frames, due to how digital video compression works it might not work as you expect either)

Ok. This is not exactly the answer, but today WP8.1 is obsolete and setting position with mediaElement on Windows 10 work pretty fine without Play-Pause hack.
So:
_mediaElement.Position -= new TimeSpan(0,0,0,0,33);
is moving video 1 frame back (30 FPS video), and
_mediaElement.Position -= new TimeSpan(0,0,0,0,5);
is not moving anywhere.
One interesting thing:
To move 1 frame you need to change position at least one half of frame time.
_mediaElement.Position -= new TimeSpan(0,0,0,0,16);//not moving
_mediaElement.Position -= new TimeSpan(0,0,0,0,17);//moving every 2nd "click"
Frame time for 30 FPS video is 1000/30 = 33.333 ms

Related

Unity colliders are moving as expected in the Editor but not in a Build

When in the game editor the game runs as intended and we can pick-up each object selected and move it from point A to point B. When building the game the game starts as intended but after a few moments, we noticed that the collider triggers for the object we want to be picked up are moving upwards indefinitely. There is an animation attached to the floor which will move the player and objects up when activated but the player has to complete a task for the animation to start.
We noticed this because we have an indicator which shows when the RayCast hovers over the collider to pick up the object, and it moves upwards after start.
This issue occurs on every object intended to be picked up in the scene that the player is currently in.
In editor the colliders don't move and the items can be picked up as intended but the issue came about ONLY when trying to build the game.
Tried:
Adding kinematics
Removing gravity
Removing every animation attached in the scene
Changing each part of the objects RigidBody
Changing the Awake() on pick-up script
Running in developer mode
Is this an issue where you're not accounting for the framerate? In other words, do you need to incorporate Time.deltaTime in your Update loop somewhere? This feels like that because I'm thinking the frame rates could differ drastically between the unoptimized editor environment, and a full build.
For example, if I'm moving an object 10 units each frame like this:
Update()
{
// Move to the right
transform.Position.x += 10;
}
Then that is frame rate dependent. On a device with a low framerate, the object will move slower than on a device with a high frame rate. On a 30 average fps device the object will move 300 units per second. On a 120 fps device the object will move 1,200 units!
That code should look something like this to account for frame rate changes:
Update()
{
// Move to the right
transform.Position.x += 10 * Time.deltaTime;
}
You may need to adjust the "10" value because now it's related to how fast the object is moving per second. Each Update will move the object a proportional amount of time for that frame.
(The above implementation probably isn't perfect, and introducing things like networking/multiplayer could require additional changes.)
See the docs for more information about Time.deltaTime

How do I GET the screen refresh Hz in C# UWP?

Does anyone know how to get the monitor Screen Refresh Rate (Hz) in a C# UWP app?
...that will be valid to publish to the Microsoft Store (ie, no HWNDs?).
The reason for the question is that when writing a game, it's good to base movement on elapsed time between updates. To get smooth frame timing it's useful to know how often we're drawing to the screen and so time our frame updates to be in sync with that.
For example, if you know the Refresh Rate is 120Hz then it's optimal to set a fixed game time:
TargetElapsedTime = TimeSpan.FromTicks((long)(TimeSpan.TicksPerSecond / 120L));
Which results in consistent frame timing and smooth motion.
Unbound the process timing using IsFixedTimeStep = false; in Game1.
The default of graphics.SynchronizeWithVerticalRetrace = true; should cap the FPS to match the refresh rate.
It should work according to the source code comments:
The first argument instructs DXGI to block until VSync, putting the application to sleep until the next VSync. This ensures we don't waste any cycles rendering frames that will never be displayed to the screen.
If you still need the actual refresh rate in Hz, calculate the average of (1000/gameTime.ElapsedTime.TotalMilliseconds) in update.

XNA performance on WP7

I'm trying to get the frame rate of my XNA game on WP7 up to 60 fps. It appears to be locked at around the 30fps mark. I've tried the change of but makes little difference.
PresentationParameters.PresentationInterval = PresentInterval.One
Any thoughts?
You can change the fixed time step that XNA defaults to:
// 166666 ticks is 16.6ms, which is 60hz
game.TargetElapsedTime = new TimeSpan(166666) // 'game' refers to your instance of XNA.Game
Here's documentation on the feature:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.targetelapsedtime.aspx
Or, if you just want to turn off the fixed timestep, try setting fixed time step to false:
game.IsFixedTimeStep = false // 'game' refers to your instance of XNA.Game
Here's documentation on the feature:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.isfixedtimestep.aspx
This is set to true by default in XNA, so you will see a fixed time-step until you set it otherwise.
Of course there is also the chance that performance problems are keeping you around 30 fps. You could be seeing V-sync holding up the frame to sync with the phone's display, either the display may be limited to 30 fps (not likely), or if your game is taking longer than 16.6ms per frame, the V-sync might be holding it to 30 fps to keep it in sync with the display. At 30 fps your game would render every other frame that the display refreshes. But if V-sync was disabled and your game was running at something like 50 fps, your game would only partially be done rendering by the time the display refreshed, and you'd end up with screen tearing.

Embedded Windows Media Player Set Position is slow

So, I have an AxWindowsMediaPlayer control on my form, and I'm looking to, while its playing, change the playback position to another point. I found:
mediaplayer.Ctlcontrols.currentPosition = <position in seconds>
But If I call that whilst its playing, it does jump to the right position and claims to keep playing, but in reality the video stops playing.
I've tried pausing/stopping before I change the position and playing afterwards, but no luck.
How can I get around this?
UPDATE
So, if I wait long enough, playback will resume again, but it will be a few seconds after the point I told it to jump to.
For example, if I tell it to jump to 15 seconds while its playing, it will jump to 15, Ctlcontrols.currentPosition will continue to increment, but the video won't actually start playing again until about five seconds later.
So... why isn't there a five second delay when I load the file? It plays instantaneously when I load it in... And how do I get rid of the delay after the jump?

How can I get rid of jerkiness in WinForms scrolling animation?

I'm writing a simple control in C# that works like a picture box, except the image is constantly scrolling upwards (and re-appearing from the bottom). The animation effect is driven by a timer (System.Threading.Timer) which copies from the cached image (in two parts) to a hidden buffer, which is then drawn to the control's surface in its Paint event.
The problem is that this scrolling animation effect is slightly jerky when run at a high frame rate of 20+ frames per second (at lower frame rates the effect is too small to be perceived). I suspect that this jerkiness is because the animation is not synchronized in any way with my monitor's refresh rate, which means that each frame stays on the screen for a variable length of time instead of for exactly 25 milliseconds.
Is there any way I can get this animation to scroll smoothly?
You can download a sample application here (run it and click "start"), and the source code is here. It doesn't look horribly jerky, but if you look at it closely you can see the hiccups.
WARNING: this animation produces a pretty weird optical illusion effect which might make you a little sick. If you watch it for awhile and then turn it off, it will look as if your screen is stretching itself vertically.
UPDATE: as an experiment, I tried creating an AVI file with my scrolling bitmaps. The result was less jerky than my WinForms animation, but still unacceptable (and it still made me sick to my stomach to watch it for too long). I think I'm running into a fundamental problem of not being synced with the refresh rate, so I may have to stick to making people sick with my looks and personality.
You would need to wait for a VSYNC before you draw the buffered image.
There is a CodeProject article that suggests using a multimedia timer and DirectX' method IDirectDraw::GetScanLine().
I'm quite sure you can use that method via Managed DirectX from C#.
EDIT:
After some more research and googling I come to the conclusion that drawing via GDI doesn't happen in realtime and even if you're drawing in the exact right moment it might actually happen too late and you will have tearing.
So, with GDI this seems not to be possible.
(http://www.vcskicks.com/animated-windows-form.html)
This link has an animation and they explain the way they accomplish it. There is also a sample project that you can download to see it in action.
Use double buffering. Here are two articles: 1 2.
Another factor to ponder is that using a timer doesn't guarantee you to be called at exactly the right time. The correct way to do this is to look at the time passed since the last draw and calculate the correct distance to move smoothly.
I had a similar problem a couple of months ago, and solved them by switching to WPF. The animated control ran a lot smoother than with a standard timer-based solution and I didn't have to take care of synchronization any more.
You might want to give it a try.
You need to stop relying on the timer event firing exactly when you ask it to, and work out the time difference instead, and then work out the distance to move. This is what games, and WPF do, which is why they can achieve smooth scrolling.
Let's say you know you need to move 100 pixels in 1 second (to sync with the music), then you calculate the time since your last timer event was fired (let's say it was 20ms) and work out the distance to move as a fraction of the total (20 ms / 1000 ms * 100 pixels = 2 pixels).
Rough sample code (not tested):
Image image = Image.LoadFromFile(...);
DateTime lastEvent = DateTime.Now;
float x = 0, y = 0;
float dy = -100f; // distance to move per second
void Update(TimeSpan elapsed) {
y += (elapsed.TotalMilliseconds * dy / 1000f);
if (y <= -image.Height) y += image.Height;
}
void OnTimer(object sender, EventArgs e) {
TimeSpan elapsed = DateTime.Now.Subtract(lastEvent);
lastEvent = DateTime.Now;
Update(elapsed);
this.Refresh();
}
void OnPaint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(image, x, y);
e.Graphics.DrawImage(image, x, y + image.Height);
}
Some ideas (not all good!):
When using a threading timer, check that your rendering time is considerably less than one frame interval (from the sound of your program, you should be fine). If rendering takes longer than 1 frame, you will get re-entrant calls and will start rendering a new frame before you've finished the last. One solution to this is to register for only a single callback at startup. Then in your callback, set up a new callback (rather than just asking to be called repeatedly every n milliseconds). That way you can guarantee that you only schedule a new frame when you've finished rendering the current one.
Instead of using a thread timer, which will call you back after an indeterminate amount of time (the only guarantee is that it is greater than or equal to the interval you specified), run your animation on a separate thread and simply wait (busy wait loop or spinwait) until it is time for the next frame. You can use Thread.Sleep to sleep for shorter periods to avoid using 100% CPU or Thread.Sleep(0) simply to yield and get another timeslice as soon as possible. This will help you to get much more consistent frame intervals.
As mentioned above, use the time between frames to calculate the distance to scroll, so that the scroll speed is independent of the frame rate. But note that you will get temporal sampling/aliasing effects if you try to scroll by a non-pixel rate (e.g. if you need to scroll by 1.4 pixels in a frame, the best you can do is 1 pixel, which will give a 40% speed error). A workaround for this would be to use a larger offscreen bitmap for scrolling and then scale it down when blitting to screen, so you can effectively scroll by sub-pixel amounts.
Use a higher thread priority. (really nasty, but may help!)
Use something a bit more controllable (DirectX) rather than GDI for rendering. This can be set up to swap the offscreen buffer on a vsync. (I'm not sure if Forms' double buffering bothers with syncing)
I had the same problem before and found it to be a video card issue.
Are you sure your video card can handle it?
I modified your example to use a multimedia timer that has a precision down to 1 ms, and most of the jerkiness went away. However, there is still some little tearing left, depending on where exactly you drag the window vertically. If you want a complete and perfect solution, GDI/GDI+ is probably not your way, because (AFAIK) it gives you no control over vertical sync.
Well, if you wanted to run the timer at a lower speed, you can always change the ammount the image is scrolled in the view. This gives better preformance, but makes the effect look kinda jerky.
Just change the _T += 1; line to add the new step...
Actually, you could even add a property to the control to adjust the step ammount.

Categories