Jump to content

Kas Ob.

Members
  • Content Count

    561
  • Joined

  • Last visited

  • Days Won

    10

Kas Ob. last won the day on July 5

Kas Ob. had the most liked content!

Community Reputation

145 Excellent

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Here a suggestion and highly important; Make sure all call backs from the system 100% safe against exception, you can't raise an exception or allow the RTL to raise one, make sure to encapsulate the code with try..except and no re-raise.
  2. I very well familiar with the alertable wait and APC, i simply have different point view of them, they are fast and nice but also dangerous namely where there is a chance for an exception to raise, See, Delphi RTL can raise exception in so many places starting form the Memory Manager to most functionality, one exception raise and things can go very wrong, and most dangerously if any parameter passed or utilized where stack allocated. Here a very nice article about something very similar, and remember this happen with Unity and that code was shipped with millions if not billions within applications and games running by end users; https://unity.com/blog/engine-platform/debugging-memory-debugging-memory-corruption-who-wrote-2-into-my-stack-who-the-hell
  3. I didn't say mine faster, all what i pointed to is centralizing the 3 important handles in one loop, one thread, short and direct code, and that is it, although it is very strange it is performing slower, as there is no locking at all. Anyway, glad you had the look and thank you !
  4. Well the forum is not allowing me to send more text in private, but here the one last important thing to use when " FProcess.SyncEvents := True;" Hope you are OK with suggestion of such style !
  5. In case i don't remember my Github password and don't use it ?! Well, if you are OK with suggestion here then please take what you see fit, if not just ignore. Thoughts on the implementation; 1) Overlapped is well, we all know, but they do exist to provide specific usage, they allow converting simple IO operation from right-now synchronous or asynchronous to something fire now and poll later, if you need to block and wait on one operation then you lost the need for using overlapped in the first place, as example you can issue Read over socket or file, either synchronous or asynchronous, but with overlapped you can issue 10 or 100 read file then poll the status later, or even block on 64 of them with one thread and get notified when such slow operation finished, also one great advantage is you can unify multiple and different operation with one thread, now to the point, if you are using overlapped IO operation then block with WaitForSingleObject or WaitForSingleObjectEx then you are missing the advantage of overlapped operation, you could use block read and it will behave the same, suggestion; Don't use ReadCompletionRoutine, not here, it is overkill. Issue ReadFile once not any more the whole unit could have one read inside a loop, read then use WaitForMultipleObjects or WaitForMultipleObjectsEx if you wish, because here we can monitor not just the read operation but an event to signal thread exit and the handle if the child process, all in one loop simple, short, efficient and straight to the point. 2) Terminating the child and its spawns, TerminateProcessTree will do most of the time unless one of the child had tweaked its security and privilege's, now it will stay there, there is better solution than terminating the child tree or sending signals, it is https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects Using Job objects is way easy than it look, and because i have many versions of using Pipes named or unnamed, i picked one and DM you, will not paste it here, it is vetted and used but not in your thread and your code, it is for you look and cherry pick what you like form it. ps; I use this command to measure time for console command PipeIPC.SendData('cmd /v:on /c "set start=!time! && dir j:\android /s && set end=!time! && echo Start time: !start! && echo End time: !end!"'#13#10); the unit i sent is fully bidirectional, and this command will show the time that a command like "dir j:\android /s" takes, one problem here is for this to work we need to spawn another console with /v:on as i couldn't make "setlocal enabledelayedexpansion" work, anyway , that command will spawn another console and execute the dir command, and what is interesting is that the time reported is different from the real console ran from Windows Explorer, your TProcess and my unit execute that command From standalone console the result of that dir on my fastest drive j: and using my unit which was almost the same as yours, (your last changes refuse to compile as AttachConsole is not declared in older Delphinos) And that is due the flush the console that executing the command had to flush, Delphi console application generally are slower due the excessive flush, but in this case and because the child is sending so many data, Delphi is flushing once per 4k, and that is really nice effect.
  6. @pyscripter Hi, Are you up for suggestions ? even if they are not so small touching the core approach with overlapped operation (on Windows) ?
  7. Debugging and tracking the OnChecked event, the behavior has nothing to do with Delphi and its VCL, it is triggered by Windows message, so you have to use a workaround about that, something like what Remy suggested.
  8. You are right the the behavior is wrong and buggy, Using similar approach of create then add, doesn't show caption, but no memory leak on XE8.
  9. But, it is already created, initialized (with default) and added with ListView1.Items.Add Your next Item.Checked := SomeLinkedObject.Enabled; Is triggering the event as designed, nothing wrong here, If you don't want that behavior, then try to create the item as local var, not by calling Items.Add then set (Initialize) properties and only then add it to the items, though i am not sure if this will trigger the event or not, it shouldn't, but who knows you need to test it, this will change the narrative of the expected behaviour and might, i say might, be discussed as bug or short in design, if just adding an item triggers an event.
  10. This is one those that really bite. I don't have a concrete answer but lets handle this step by step, The stack trace (calls) is short, so i would suggest to increase it, there is 20 calls and it is not enough to go back, only the last 5 belong to your application, even the last two belong to FastMM5, and the named and relevant 3 are in the RTL not even your code, these 3 say very little as they are just converting or extracting string, they are doing the allocating, before that there is 15 calls Of these 15 call we see that the calls with addresses start with 77 and 74 are definitely comes form OS dlls, but these recorded two are a concern to me 750A9F4B [Unknown function at ] 750A9F4B [Unknown function at ] this looks like recursive ! also the whole LdrLoadAlternateResourceModuleEx calling the above then leading to another loop just the same then landing at Delphi string handling code is strange the least. Suggestions; 1) Increase the default stack call entries in FastMM5 ffrom 20 to may be 64 see, if that help in showing more information, we need source of this recursive calls, i don't use FastMM5 but looking at the repository the adjustment should be here https://github.com/pleriche/FastMM5/blob/master/FastMM5.pas#L1166-L1168 2) The whole thing is loading resources, namely form already loaded module (binary file being EXE or DLL..), so it is highly possible the problem sits in wrong handling WideString, WideString is not Delphi string it is different beast from UnicodeString, RTL should handling this behind the scene unless you are invoking something in wrong way or forcing resource loading by directly calling some API with wrong declaration between WideString and string. 3) the Enigma for me is this address "750A9F4B" , use what ever you can within the debugger, alas Delphi debugger is half useless and short in many places like this exact case, it might skip these OS calls in its stack trace window, rendering the use of break points and step into in the CPU window harder than usual, anyway try to find out who own that address, from what i see most likely it is a BPL and you are using it, also it doesn't have debug info, so you must pinpoint it. step 3 is crucial to understand how this happen and what went wrong, this is the one that tried to load/extract some null-terminated string from resource within a module then recursively called for the conversion into Delphi string. And good luck !
  11. @pyscripter , nice ! Removing "([])" from https://github.com/pyscripter/pascal-process/blob/main/Source/PascalProcess.pas#L454-L455 will make it compile and run on XE8
  12. Kas Ob.

    Bitmaps to Video for Mediafoundation

    Great, just pay attention to the samples i provided above and download stuff from the internet, use LOTR video as role of thumb... One thing though, double check why is the difference which is very visible from the downloaded video in my last post in the pts (Presentation Time Stamp), in that video it is 200 for video and 1024 for audio, while transcoded video and the one built from slideshow shows 1000 for video pts and the while still 1024 for audio, while 1024 for audio is correct for 48khz, i can't understand how 1000 is there for both 30fps and 60fps (even after transcoding into 60fps from 30 still the same)
  13. Kas Ob.

    Bitmaps to Video for Mediafoundation

    Great, and you are on the right way, make use of real video for testing. You are right and i am right here, but you are ignoring one essential fact, that your daily player as mine are good, they are so good that they fix this stuff at runtime to their best effort, i provided earlier a link to ffmpeg and how it does its magic to fix these to its best effort. As for proof, i will provide one, but let me make it clear here, your player not showing the problem is solemnly based on their advanced algorithm for corrections, BUT and it is huge but, if you are you use similar code with basic algorithms and APIs just like yours the problem will manifest badly. now to the proof; 1) i went to this page https://archive.org/details/4-k-hdr-60-fps-dolby-vision-demo-2160p-60fps-vp-9-128kbit-aac and didn't download the video with highest quality, i used the "H.264" on the right side under "Download Options" it is 16.6mb , that is enough. 2) I have ffprobe (the link to download is in earlier post) and extracted the frames and their timing for debugging the video its self and see how original with quality encoder have interleaved the frames and their duration. 3) i transcoded the video without changing the default setting and repeated the process with output video and restoring the FPS to 60 instead of 30, the downloaded/original video is 59.94 fps 4) used the ffprobe on these 3 video files 5) made small parser for the ffprobe output, here is its parsing loop, it is easier to see and follow than using Notepad++ procedure TForm10.ProcessFile(const FileN: string); var StrList: TStringList; Line: string; i, p: Integer; begin StrList := TStringList.Create; try StrList.LineBreak := '[/FRAME]'#13#10; StrList.LoadFromFile(FileN); if StrList.Count = 0 then Exit; Memo1.Lines.BeginUpdate; try for i := 0 to StrList.Count - 1 do begin Line := StrList[i]; p := PosEx('pkt_pos', Line); if p > 0 then Line := LeftStr(Line, p - 1); if Length(Line) > Length('[FRAME] media_type=') then Line := RightStr(Line, Length(Line) - Length('[FRAME] media_type=') - 1); Line := ReplaceStr(Line, #13#10, ' '); Memo1.Lines.Add(Line); end; finally Memo1.Lines.EndUpdate; end; finally StrList.Free; end; end; Now i went to compare and check for the timestamps 1) the original (downloaded) some of the begging and middle and end of that original video, how commercial (or may be even not commercial) and high end encoder interleaved the frames and their durations What we see, smooth interleave with fixed frames length, but it compensate with extra video when it is short, and extra audio frame when it is short, notice the audio and video end at the same, the green box show at the end the difference is small, yet after that it will push both streams to the end but the difference through out all video didn't go above this 10-13 ms, 2) Lets see the transcoded version at 30 fps (default setting) and from the middle We see a desyncing in the middle the last video frame in the video sequence is 99.133333 while the following audio sections of frames, the last one corresponding to that video frame is 99.118271 the difference is 15ms at the end the difference is 33ms, so we correct and synced video now is desynced and audio is drifting by something 10-11ms per minutes, not much , i agree and in fact it is almost within the allowed standard for 10ms drift, but again this small drifting is for this combination for this video. 3) lets see the one i transcoded further from the generated 60 fps into 60fps and the result , taking only the first frames and the last Now it is more synced at the end than the first transcoded one, the drift is only 6ms ! How this happen ? Just look at how the first frames and their time stamps, the audio start at "pts=2229 pts_time=0.046437" meaning the audio is drifted forward 46ms since the the start and lost 40ms till the end. Dear Renate, in no way i am saying it is bad or wrong, pointing to anything, and pretty please don't take my posts here in the wrong way, you did awesome job and pretty neat usage MF, i merely want to show you a better way, make it commercial worth and avoid these hidden bugs, my points here are for anyone who love to know, or care. Now, is it huge adjustment, no you are overthinking it, it is the small details, like when the audio frames should be pushed and interleaved?, how many of these streams and frames of sort before switching to another? do we need to make sure of the duration in dynamic way instead of simple loops? All of these questions are very simple and the change in your code should be minimum, again not asking you to change it, just to point when it fail if it failed beyond acceptable video quality, the culprit was the fixed frames count and duration, and that is it. Debugging (in this case dissecting) the video itself to its frames while keeping an eye on how best practice is being utilized is way better then watching video as player play their roles, and not being sure of using best practice or accurate timing. To summarize what could be better; 1) push less frames before switching between streams like shown above, like you LOTR video, 1or 2 then switch instead of pushing over 8, 2) make sure the the audio frames start form 0 time 3) if you don't like adjusting video duration, it is ok, we have many ways to skin a cat, don't know what the cat did but follow best practice and the cat will be skinned, adjust audio frames, even this is not really necessary, and both can be skipped, and not touched 4) third way to fix 3, we use the most naive way, and make sure there is no drifting skipping (3) , just make audio frames try to hit the video duration or more, if it did hit more even with 1ms then the next chunk of audio push less frames and skip an audio frame, because we are pushing at 1 video frame then 1 audio frame, then it is easy as skip this time. and we fixed synced video. Anyway, that is all and good luck, it is your code and it is your call.
  14. Kas Ob.

    Bitmaps to Video for Mediafoundation

    Yes, my mistake i saw it as inside the loop, stupid hasty looking. It was meant as an extra safety check, since the code already checks for EndOfStream, and that hasn't failed so far. But I've put it back in If you are going to adjust the audio frame duration then it will be used but you must save/remember the difference for the next frame to subtract/reduce, so in its current usage now it is redundant. Switching to dynamic audio frames will be way better and more accurate, and will prevent desyncing.
  15. Kas Ob.

    Bitmaps to Video for Mediafoundation

    Well i am bad writer, i said strange as this is exactly how it is used https://github.com/rmesch/Bitmaps2Video-for-Media-Foundation/blob/main/Utilities/uDirectoryTree.pas#L313-L314 And how it didn't raise AV on Renate debugger, that is strange thing.
×