Windows Media video playback grows slow after several topology switches - winapi

Win64, Windows Media Foundation app in C++. I have a handful of topologies and a single media session. The app switches between topologies:
TheSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, NextTopology);
PROPVARIANT v;
InitPropVariantFromInt64(0, &v);
TheSession->Start(&GUID_NULL, &v);
It generally works. But I've noticed after some time of this, video playback becomes slow, it skips frames. The machine has CPU aplenty. Frame skipping lasted for at least a minute, wasn't a momentary fluke. After a while, frame skipping is observed on all videos. I have a semi-reliable repro on this condition. When you switch topologies in that state, it goes fine for a short while (~30sec), then slows down. The CPU utilization during the slowdown doesn't spike - it's not CPU. There is some resource exhaustion, but not CPU.
When I switch topologies like that, the previous topology is not explicitly stopped. Could it be that some processing for the evicted topology is still running, even though it's not in the session anymore? If so, how does one stop the processing on a disconnected topology? The only idea that comes to mind is calling Stop on the media source of the evicted topology.
Stopping and starting the session seems to clear up the condition.
Also, can I somehow confirm that my hunch about extraneous processing is correct to begin with? There is no state on the topology object that I can see.
I'm feeding the same audio and video renderer to all topologies, not sure if it matters.
As a workaround, I've implemented the logic where on video switch, the session is stopped, the code waits for the stopped event, then the topology is loaded and started. On testing I can't reproduce the frame skipping any longer. For now, I'll take the good news.
UPD: I've created a minimal example, sans the sample video files: https://gist.github.com/sevaa/88754eafffd68d8671ec593dc310faec
It relies on two video files, c:\Temp\SlowPlayer\a.m4v and c:\Temp\SlowPlayer\b.m4v (feel free to change the paths). If you try to reproduce, you could even use two copies of the same video there, as long as you can observe the video switching. Compile with Visual Studio 2022 as a Windows desktop project.
The frame skipping in my testing starts being visible around switch #10, gets really bad around #15.

Related

Packet Corruption: Why sometimes ffmpeg .bat batch video editing makes my computer unstable unable to restart?

I'm doing very time consuming ffmpeg video editing. That's why I put my commands into a .bat batch file and run them over night. Usually that works fine, but from time to time when I look the next moring I see an error message of this kind:
From that state on, I didn't find any good way to close the console. When I press the [x] button in the top right corner, it freezes. When I try to kill the application using the task manager nothing happens. Even explorer.exe cannot be closed using the task manager. A shutdown won't do anything. During the last month I had this problem about three times and the only way I could close it was to long press the power button of the computer until it was turned off "the bad way".
Any ideas what to in such situations?
Or even better: How to prevent those situations?
What can the reason(s) be for the error?
Do you understand the message?
When the computer is started again the next morining and I run the same .bat file again everything works fine. So the same error does not repeat and the video is edited nicely!
Edit: Now, about one week after posting this question the problem occurred many more times! It is very annoying. I guess it has to do with the external hard drive connected by USB. Sometimes it randomly interrupts the connection! That might be the reason for the behavior. Whatever its causing the error, I want to learn a solution how to deal with this in future. I don't want to always push the reset button of my computer. I want a proper way to be able to shut it down.
To narrow down the cause, what is causing this error, and what is not, here is a list of seven seven seemingly isolated solutions that each alone or all together should fix your problem:
The .bat Batch File
Apparently there is nothing wrong with your coded .bat batch files.
If that was the case, then none of your past videos would have rendered.
But just to be sure, try to run your .bat in a different laptop or computer on the heaviest and most demanding video editing project files just to make sure that the .bat files in fact and without a doubt flawless.
The Computer CPU
Make sure that your CPU runs flawlessly not just for 30 minutes but for the hours long burn tests that are the video
projects at night you mention. Poor contact between a concave or convex heatsink and cpu or lack of or too much of thermal paste can make cpu too hot and unstable during prolonged cpu intensive burn tests. A software like OCCT or Intel
Burn Test should be able to run for hours in your case without a
single fault.
The Computer RAM
To test your memory you can use MemTest86 or my favourite the open source MemTest86+ which should run for hours without a single memory error.
The OS Integrity
Run CMD as admin, and type chkdsk c: /f or chkdsk c: /f /r /x and press Y to check and repair (after a reboot) the local hard drive c: or any other partitions that are the source or destination of your rendering projects. When your computer encounters a sudden shutdown or detects a corrupted file system, sometimes this is the cause of a corrupted OS file. This checks for the integrity of the most important system files. Also sfc /scannow is another way to check System Files which scans and repairs system files.
The Harddrive
Connect your external drive locally, and run both a short and deep long test to make sure the harddrive has zero cluster faults. A SMART test from Crystical Disk Info famout for their Crystal Disk Test, can be a good way to see all the past errors on a Harddrive. Also, try to run the nightly batch files on the HDD connected internally. That way you can rule out the next item:
The Cable Quality
Cat rated UTP networking and USB cables are notoriously known for their poor manufacturing quality and low reliability. Not just over time, but new out of the box they can be the cause of disconnects, bad connections and low throughput. There is not something like they work 100% or they work 0%. Sometimes they sit right in between and "work, but to a degree" enough to be sold, with the absolute bare minimum and sometimes under minimum quality strands that are anything but cupper. So check your cables, replace the cables with other cables that you have laying around. CCA (Copper Cladded Aluminium) is the garbage to stay away from. Get proper Cupper only cables.
USB to SATA (HDD) or M.2 NVMe (SSD) Adapter Chip
Some USB-to-SATA adapters are notorious for their low stamina, stopping working when the adapter chips become exhausted in professional usage over prolonged continous workloads, resulting in disconnects even if they would be connected via a cupper USB 3.2 cable to the computer! The internet is full of forums with people having problems with older generation cheaper JMicron chips causing interruptions causing failures in copying files from or to the PC. Realtek chips are somewhat better, but often the solutions on the last page shows all problems went away when they bought an expensive adapter that uses an ASMedia chip.

SC_MONITORPOWER starts background tasks

Summary
When putting the monitor in sleep mode in Windows 10, Windows seems to execute some tasks that don't get executed with the screen on.
This is interfering with our software, and we need to get rid of it.
Ful story
For a hardware device with a touch screen, I need to be able to turn off the touch screen when it's not in use, for durability reasons. Windows has a message that you can send to turn it off, SC_MONITORPOWER. More specifically:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
This works fine, but when the screen is off, Windows is apparently sometimes performing some tasks that it doesn't do when the screen is on. We are careful to never write anything to the screen in this situation (that causes huge problems when the screen is off, in fact just having a blinking cursor in a DOS box is using up half a core when the screen is off).
Our software requires a callback to be executed every 0.25 ms. We have turned nearly every task, service and several other things in Windows off, and with the screen on, I can run our software for days without ever missing a callback. But with the screen off I get hiccups. The callback already runs at the highest possible priority.
So there is apparently something that we missed when we turned all services and tasks off. There appear to be 2 causes of hiccups:
One happens once every 10-30 hours or so (not sure of the exact time, it seems to vary). But it always happens 5 times, with EXACTLY 5 minutes (at most a few milliseconds off) in between (so in total it happens 5 times in a 25 minute period).
Beside this, we get a single hiccup typically every 4-10 hours, but the time between occurrences doesn't seem to be very constant so there could also be multiple causes.
I'm a bit at a loss here, and running analysis software can easily interfere with our own software, making it harder to detect when these hiccups really occur and when they are caused by running the analysis software.
Interestingly, I have seen this 5-times-every-5-minutes thing also on a completely different system (different hardware, different OS version), when recording audio in Adobe Audition. Audition misses pieces of audio every 5 minutes in this case, and I think it also only happens when the monitor is in sleep mode and you're not logged in remotely.
We have already tried to turn the touch screen off using direct monitor commands like Nircmd does, and it doesn't support those. My guess is that the SC_MONITORPOWER message is triggering more things in Windows, and if we can turn them off, that would fix our problem. Any ideas?
System
Intel i5-8700 with 6 cores, Windows LTSB, no extra software installed except our own.
Never mind, problem solved. It was not an extra task that was being started, it was one of the existing Windows processes that for some reason only causes issues when the display is off. Since killing them is not an option (Windows will just restart them), I've suspended the following processes, and the culprit is one of these (I don't know which one yet):
sihost.exe
igfxEM.exe (I very much suspect this one)
RuntimeBroker.exe
dllhost.exe
taskhostw.exe
explorer.exe
I have to continue testing a bit longer to be absolutely certain, but so far with these tasks all suspended I've not seen a missed callback in the last 38 hours. I don't know yet if there are any drawbacks to suspending all these things, so I'll try to find the cause(s) and suspend only that/those.

Allow computer to sleep while playing audio from a Windows application

I am working on a Windows 10 application that plays audio in the background. What I would like to be able to do is allow the computer to still go in to Sleep Mode while the audio is playing (as in, Power & Sleep Settings, Sleep after XX minutes). And by this, I mean stop playing the audio and go to Sleep (not continue playing while in Sleep). Is this even possible? Searching online hasn't been fruitful, as I can pretty much only find information on how to prevent Sleep, not enable it.
Running powercfg.exe /requests shows the audio playback is indeed preventing sleep:
SYSTEM:
[DRIVER] Realtek High Definition Audio (...)
An audio stream is currently in use.
I am currently using the IAudioClient and IAudioRenderClient interfaces for playback, via client->Start(), renderClient->GetBuffer(). I could switch to a different API if necessary. However, whatever I use needs to allow other applications (VLC, YouTube, Windows sounds, etc.) to play audio as normal at the same time.
My application is always running on the system I'm using it on, and I simply want the system to be able to go to Sleep at the set system timeout. I also need to apply this exception to my application only - if other applications are playing audio that would prevent Sleep, the system should not Sleep.
Are there any Windows API calls that can make Windows ignore my application playing audio and still let the system go into Sleep Mode?
What you are asking for is not possible today. When the system goes to sleep, it essentially means that the processors in your system stops executing any instructions and powers down. Although this is not like shutting down the system, it is very close to it. All the devices connected to the processors are also powered down to save the battery/power consumption.

Windows 8/10 API Detect suspended process

UWP (or "Metro") apps in Windows 8/10 are frequently suspended when they are not in the foreground. Apps in this state continue to exist but no longer consume CPU time. This change seems to have been introduced to improve performance on low-power/storage devices like tablets and phones.
Please can I ask, what is the most elegant and simple method to detect an app in this state?
I can see 2 possible solutions at the moment:
Call NtQuerySystemInformation() and the enumerate each process and each thread. A process is "suspended" if all threads are in the suspended state. This approach will require a lot of code and critically NtQuerySystemInformation() is only semi-documented and could be removed in a future OS. NtQueryInformationProcess() may also offer a solution with the same problem.
Call GetProcessTimes() and record the counters for each process. Wait some time (minutes) and check these again. If the process counters haven't changed then assume the process is suspended. This is a hack and I may get shot down for even thinking of it.
Jim
The second one (GetProcessTimes() … wait … and check these again. 
If the process counters haven’t changed then assume the process is suspended)
is less reliable. 
If a process is waiting for input (e.g., keyboard, mouse, or network)
and not getting any, it will use very little CPU time
and will appear to be suspended by this approach.

Windows 7: poor GUI response in my program while downloading data; is there some way to improve this?

I've written a program that (among other things) downloads multiple large files from a server on the LAN, using TCP. This program runs fine under Linux, MacOS/X, and generally under Windows as well (it uses Qt for the GUI and straight sockets calls for networking), but on certain Windows machines the download appears to be too much for the machine to handle, and I'm wondering if anyone has any ideas as to why that is and what can be done about it.
When downloading files, my program spawns a separate I/O thread that basically just sits in a loop, downloading data over TCP and writing it to a file, writing 128KB per call to QFile:write(). Each file is typically several hundred megabytes long, and a typical download session writes out several dozen of these files. Note that the I/O thread runs independently of the GUI thread, so I wouldn't expect it to affect GUI's performance much if at all -- especially not when running on a multicore PC.
The PC in question is a Core-2Duo Quad Q6600 running at 2.40GHz, with 4GB of RAM. It's running Windows 7 Ultimate SP1, 32-bit. It is receiving data over a Gigabit Ethernet connection and writing it to files on the NTFS-formatted boot partition of the 232GB internal Hitachi ATA drive.
The symptom is that sometimes during a download (seemingly at random) the program's GUI will become non-responsive for 10 to 30 seconds at a time, and often the title bar of the window will have "(not responding)" appended to it. The symptom will then clear up again and the download will proceed normally again. Another symptom is that the desktop is extremely sluggish during the download... for example, if I click on the "Start" button, the Start menu will take ~30 seconds to populate, instead of being populated near-instantaneously as I would expect.
Note that Task Manager shows plenty of free memory, but it does show short spikes of CPU usage to 100% one one of the 4 cores, at the same time the problems are seen.
The data is arriving over Gigabit Ethernet, and if I have my program just receive the data and throw it away (without writing it to the hard drive), the machine can maintain a constant download rate of about 96MB/sec without breaking a sweat. If I write the received data to a file, however, the download rate decreases to about 37MB/sec, and the symptoms described above start to appear.
The interesting thing is that just for curiosity's sake I added this call to my I/O thread's entry function, just before the beginning of its event loop:
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
When I did that, the "(not responding)" symptoms cleared, but then download speed was reduced to only ~25MB/sec.
So my questions are:
Does anyone know what might be causing the sporadic hangups of the GUI when the hard drive is under a heavy write-load?
Why does lowering the I/O thread's priority cause the download rate to drop so much, given that there are three idle cores on the machine? I would think that even a lower-priority thread would have plenty of CPU available in this situation.
Is there any way to get a maximum download rate without causing Windows' desktop responsiveness and/or my app's GUI responsiveness to suffer problems?
Without seeing any code is hard to answer but this seems to be something related to processors and the fact that your download thread is not leaving any space for other threads to performs other operations.
It seems it never waits and that the driver of the network card is not well written.
Are you sure your thread is entering in an idle state when there is no data incoming?
In OS with a single processor a for (;;) {} will consume 100% cpu and if it talks continuously with the kernel it may stops other processes or other threads for doing that, especially if there is a bug or a very bad behaviour in some network card driver in your case.
Probably putting the thread priority below normal you are asking the OS to use your thread less often, this gives by a magical combination of things that allow things to not hang too much.
Check the code, maybe you are forgetting something?
Check if adding a sleep(0) to force the OS to yield to another thread sometime will make things better, but this is a temporary fix, you should find why your thread is consuming 100% cpu, if it is.

Resources