MediaCtrl Seek() and Tell()

I’m working with Windows 10 and several macOS versions trying to get my software upgraded to wxPython 4.1 and running on Catalina. I’m using Python 3.7.7 and mostly the latest daily build (currently 4.1.1a1.dev4845 because of drag-and-drop issues with the official 4.1.0 release).

I am seeing a problem with the MediaCtrl specifically with positioning media files using Seek().

On macOS 10.10.5 Yosemite if I use wxPython 4.0.6, Seek()s seem to work, with Tell() coming up with the same value as provided to Seek(), indicating the video was positioned correctly. I get the same result on Windows 10 with wxPython 4.1.1a1.dev4845.

However, on macOS Yosemite with wxPython 4.1.1a1.dev4845, that doesn’t work. Here’s what happens when I write a loop to seek every frame from 5.0 seconds to 7.0 seconds in an *.mp4 video.

A first Seek() within a given whole second does not change the media position So Seek(5033) does not take me to the frame AFTER the 5.0 second mark (5000, with a frame being 33 milliseconds long), but leaves the media Tell() unchanged, whereever it was before the Seek().

A second Seek() within a given second will reposition the media position at the whole second mark. So Seek(5033) fails to change position, but following it with Seek(5066) sets the video position to 5000 milliseconds (as reported by Tell()) rather than 2 frames later at 5066. All subsequent calls within that second leave the media position at 5000. When I call Seek(6023), the first call in a new whole second, the Tell() returns 5000, but the next Seek(6056) shifts the Tell() value (that is, the media position) to 6000.

On macOS 10.15.5 Catalina, wxPython 4.0.6 doesn’t support the MediaCtrl correctly, if I recall right. wxPython 4.1.1a1.dev4845 works the same as on Yosemite, but with the added bonus of an error message for the first 10 Seek() calls that says some variation of:

Python[704:7574] CMTimeMakeWithSeconds(5.033 seconds, timescale 1): warning: error of -0.033 introduced due to very low timescale

My users need frame accuracy in seeking and playing their video files. They are working with precise video selections from within larger video files. They also sometimes play multiple videos simultaneously (following a synchronization process). A frame or two off is one thing, but differences of up to a second make this feature unusable. Frame accuracy is really central to my program.

Is this problem from wxPython or is it a wxWidgets issue? Is there anything that can be done about it to make MediaCtrl.Seek() work correctly on macOS? I know that this frame accuracy was supported for at least a decade prior to the 4.1 release.

I’ll attach a simple sample. In the code, you’ll need to point to a media file (one that’s at least 31 seconds long) and run it. It will load your media file and Seek() a position a bit more than 30 seconds in. Press the “Test” button and look at your command line output. You’ll see a list of positions sent to Seek(), positions returned by Tell(), and the difference between the two.

Thanks in advance for looking into this.

David

Here’s the promised sample app.

David

Video_wx_410.py (3.8 KB)

You might want to try 4.0.7post2 and see how it behaves there. There was a change to use AVFoundation instead of QTKit there, as QTKit isn’t available on 10.15. The problem might be with the AVFoundation implementation or with AVFoundation itself, so you might have to troubleshoot in wxWidgets to see.

You are correct, Scott. I see the same problem in wxPython
4.0.7-post2 on macOS Yosemite.

David

And not in wxPython 4.0.7-post 1.

I also suspect the QTKit --> AVFoundation change.

Since I was still using an older compiler and SDK until recently then the builds continued using QTKit even after the default in wxWidgets switched to AVFoundation, because only QTKit was available in the SDK. With OSX 10.15 removing it entirely from the platform then I had to update to newer versions, and now it will just build with AVFoundation. IIRC, QTKit was actually deprecated way back in Yosemite, so it’s been a long time coming.

Unfortunately, I don’t know much about the guts of the media ctrl and its backends. Just enough to wrap the C++ classes for Python. So yes, it’s probably going to take some discussions with wxWidgets folks to make any progress here.

Yeah, I think this is the relevant code:

However, I don’t know what is going on there and agree with Robin. I would suggest opening a Trac ticket or writing to wx mailing list.

I’ve never had much luck approaching the wxWidgets community. I
have posted a few issues to Trac over the years and there they
sit. Any suggestions what I can do to engage the wxWidgets
community more effectively?

David

You could try writing to the wx-users or wx-dev mailing list(s). The first thing they will probably ask you is if you can reproduce the problem in one of the samples. So it might take a bit of work to compile wxWidgets and then try the media sample to see if you can reproduce the problem there. The person that you probably want to try to engage with is Stefan Csomor. He’s the one that maintains most of the macOS stuff.

In fact, I’m pretty sure this is wrong:

[m_player seekToTime:CMTimeMakeWithSeconds(where.GetValue() / 1000.0, 1)
         toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

I believe that is actually causing it to round the seek time to the nearest second.

I was wondering about that too. This looks relevant: https://stackoverflow.com/questions/22666190/using-seconds-in-avplayer-seektotime

I think I’ve got a fix for you. I’ll send a pull request to wxWidgets shortly. One thing: I had to add a wx.Yield() between Seek() and Tell() to get your test case to pass. Otherwise, the Seek() hadn’t completed before the Tell() operation.

Thanks Scott. That’s really awesome to see.

David

The change will be included in the next snapshot build.

Wow! That’s fantastic. Thank you very much, Scott and Robin.

David

I downloaded and installed the newest daily build today. Video
is working perfectly on macOS Catalina now. I was able to
synchronize 3 video files so they play as a single unit, which is
what I needed to be able to do.

  Again, thank you both. I really appreciate you taking the time to

sort this out and solve the problem.

David

You’re quite welcome. Thanks for providing a good reproducer!