Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 09/27/25 in all areas

  1. pyscripter

    UIAutomation in Delphi 13

    Indeed. See also my own translation: https://github.com/pyscripter/SynEdit/blob/27b5d713b4806ccbf38412cd138d8ee7d4ccc499/Source/SynAccessibility.pas#L220 The weird thing is that GetIt includes the "Windows API from WinMD" package that has correct translations of the Automation API and many others. Why Embarcadero did not use these translations escapes me. Please submit a bug report.
  2. MarceloHByte

    JSON benchmarks

    Hi, I've added mORMot version 2 and pasjson is on its way. https://github.com/hydrobyte/TestJSON Marcelo.
  3. dummzeuch

    for loop variable value after the loop

    A for loop is not a while loop with inc. the compiler might create code that counts down to zero rather than up, if the variable is not used inside the loop. Edit: Or it might even completely unroll the loop doing away with the variable altogether. But it does not matter: Relying on an undocumented implementation detail is a bad idea, regardless of whether it works or not. The next compiler version or a different compiler e.g. for a different platform might change that detail.
  4. You can do it in (at least) three ways: 1. Use AddRawOptions RegEx.AddRawOptions(PCRE_UNGREEDY); With older versions you can use this code (see [RSP-21733] Compile PCRE with JIT enabled - Embarcadero Technologies) {$IF (CompilerVersion <= 35) and not Declared(RTLVersion112)} type TPerlRegExHelper = class helper for TPerlRegEx procedure AddRawOptions(PCREOptions: Integer); end; procedure TPerlRegExHelper.AddRawOptions(PCREOptions: Integer); begin with Self do FPCREOptions := FPCREOptions or PCREOptions; end; type TRegExHelper = record helper for TRegEx public procedure AddRawOptions(PCREOptions: Integer); end; procedure TRegExHelper.AddRawOptions(PCREOptions: Integer); begin with Self do FRegEx.AddRawOptions(PCREOptions); end; {$ENDIF} 2. Another use of a class helper type TRegExHelper = record helper for TRegEx public procedure AddPCREOptions(PCREOptions: TPerlRegExOptions); end; procedure TRegExHelper.AddPCREOptions(PCREOptions: TPerlRegExOptions); begin with Self do FRegEx.FOptions := FRegEx.FOptions + PCREOptions; end; and use it (not tested): RegEx.AddPCREOptions([preUnGreedy]); 3. Use the ungreedy ? Instead, you can use the ungreedy ? in your regular expressions. See How can I write a regex which matches non greedy? - Stack Overflow.
  5. Kas Ob.

    Recover from call to dll that doesn't return

    I asked my free Claude with and the result was The code itself is unit PassthroughTransform; interface uses WinApi.Windows, WinApi.ComBaseApi, WinApi.MediaFoundationApi.MfApi, WinApi.MediaFoundationApi.MfObjects, WinApi.MediaFoundationApi.MfTransform, WinApi.MediaFoundationApi.MfIdl, System.Classes, System.SysUtils; type TPassthroughTransform = class(TInterfacedObject, IMFTransform) private FRefCount: Integer; FInputMediaType: IMFMediaType; FOutputMediaType: IMFMediaType; FInputSample: IMFSample; FAttributes: IMFAttributes; FStreamLimits: MFT_STREAM_LIMITS; FInputStreamInfo: MFT_INPUT_STREAM_INFO; FOutputStreamInfo: MFT_OUTPUT_STREAM_INFO; // Internal state FHasInput: Boolean; FDraining: Boolean; protected // Helper methods function IsValidInputStream(dwInputStreamID: DWORD): Boolean; function IsValidOutputStream(dwOutputStreamID: DWORD): Boolean; function OnCheckInputType(pmt: IMFMediaType): HResult; function OnSetInputType(pmt: IMFMediaType): HResult; function OnSetOutputType(pmt: IMFMediaType): HResult; public constructor Create; destructor Destroy; override; // IMFTransform methods function GetStreamLimits(out pdwInputMinimum: DWORD; out pdwInputMaximum: DWORD; out pdwOutputMinimum: DWORD; out pdwOutputMaximum: DWORD): HResult; stdcall; function GetStreamCount(out pcInputStreams: DWORD; out pcOutputStreams: DWORD): HResult; stdcall; function GetStreamIDs(dwInputIDArraySize: DWORD; var pdwInputIDs: DWORD; dwOutputIDArraySize: DWORD; var pdwOutputIDs: DWORD): HResult; stdcall; function GetInputStreamInfo(dwInputStreamID: DWORD; out pStreamInfo: MFT_INPUT_STREAM_INFO): HResult; stdcall; function GetOutputStreamInfo(dwOutputStreamID: DWORD; out pStreamInfo: MFT_OUTPUT_STREAM_INFO): HResult; stdcall; function GetAttributes(out pAttributes: IMFAttributes): HResult; stdcall; function GetInputStreamAttributes(dwInputStreamID: DWORD; out pAttributes: IMFAttributes): HResult; stdcall; function GetOutputStreamAttributes(dwOutputStreamID: DWORD; out pAttributes: IMFAttributes): HResult; stdcall; function DeleteInputStream(dwStreamID: DWORD): HResult; stdcall; function AddInputStreams(cStreams: DWORD; var adwStreamIDs: DWORD): HResult; stdcall; function GetInputAvailableType(dwInputStreamID: DWORD; dwTypeIndex: DWORD; out ppType: IMFMediaType): HResult; stdcall; function GetOutputAvailableType(dwOutputStreamID: DWORD; dwTypeIndex: DWORD; out ppType: IMFMediaType): HResult; stdcall; function SetInputType(dwInputStreamID: DWORD; pType: IMFMediaType; dwFlags: DWORD): HResult; stdcall; function SetOutputType(dwOutputStreamID: DWORD; pType: IMFMediaType; dwFlags: DWORD): HResult; stdcall; function GetInputCurrentType(dwInputStreamID: DWORD; out ppType: IMFMediaType): HResult; stdcall; function GetOutputCurrentType(dwOutputStreamID: DWORD; out ppType: IMFMediaType): HResult; stdcall; function GetInputStatus(dwInputStreamID: DWORD; out pdwFlags: DWORD): HResult; stdcall; function GetOutputStatus(out pdwFlags: DWORD): HResult; stdcall; function SetOutputBounds(hnsLowerBound: LONGLONG; hnsUpperBound: LONGLONG): HResult; stdcall; function ProcessEvent(dwInputStreamID: DWORD; pEvent: IMFMediaEvent): HResult; stdcall; function ProcessMessage(eMessage: MFT_MESSAGE_TYPE; ulParam: ULONG_PTR): HResult; stdcall; function ProcessInput(dwInputStreamID: DWORD; pSample: IMFSample; dwFlags: DWORD): HResult; stdcall; function ProcessOutput(dwFlags: DWORD; cOutputBufferCount: DWORD; var pOutputSamples: MFT_OUTPUT_DATA_BUFFER; out pdwStatus: DWORD): HResult; stdcall; end; implementation { TPassthroughTransform } constructor TPassthroughTransform.Create; begin inherited Create; FRefCount := 0; FHasInput := False; FDraining := False; // Initialize stream limits - single input, single output FStreamLimits.cbSize := SizeOf(MFT_STREAM_LIMITS); FStreamLimits.dwInputMaximum := 1; FStreamLimits.dwInputMinimum := 1; FStreamLimits.dwOutputMaximum := 1; FStreamLimits.dwOutputMinimum := 1; // Initialize stream info FInputStreamInfo.cbSize := SizeOf(MFT_INPUT_STREAM_INFO); FInputStreamInfo.hnsMaxLatency := 0; FInputStreamInfo.dwFlags := 0; // No special requirements FInputStreamInfo.cbMaxLookahead := 0; FInputStreamInfo.cbAlignment := 0; FOutputStreamInfo.cbSize := SizeOf(MFT_OUTPUT_STREAM_INFO); FOutputStreamInfo.dwFlags := MFT_OUTPUT_STREAM_PROVIDES_SAMPLES or MFT_OUTPUT_STREAM_WHOLE_SAMPLES; FOutputStreamInfo.cbAlignment := 0; FOutputStreamInfo.cbSize := 0; // Create attributes store MFCreateAttributes(FAttributes, 0); end; destructor TPassthroughTransform.Destroy; begin FInputMediaType := nil; FOutputMediaType := nil; FInputSample := nil; FAttributes := nil; inherited Destroy; end; function TPassthroughTransform.IsValidInputStream(dwInputStreamID: DWORD): Boolean; begin Result := (dwInputStreamID = 0); end; function TPassthroughTransform.IsValidOutputStream(dwOutputStreamID: DWORD): Boolean; begin Result := (dwOutputStreamID = 0); end; function TPassthroughTransform.OnCheckInputType(pmt: IMFMediaType): HResult; var majorType: TGUID; begin if not Assigned(pmt) then begin Result := E_POINTER; Exit; end; // Get the major type Result := pmt.GetMajorType(majorType); if FAILED(Result) then Exit; // For a passthrough, we accept most media types // You can add specific validation here based on your needs Result := S_OK; end; function TPassthroughTransform.OnSetInputType(pmt: IMFMediaType): HResult; begin FInputMediaType := pmt; Result := S_OK; end; function TPassthroughTransform.OnSetOutputType(pmt: IMFMediaType): HResult; begin FOutputMediaType := pmt; Result := S_OK; end; function TPassthroughTransform.GetStreamLimits(out pdwInputMinimum, pdwInputMaximum, pdwOutputMinimum, pdwOutputMaximum: DWORD): HResult; begin pdwInputMinimum := FStreamLimits.dwInputMinimum; pdwInputMaximum := FStreamLimits.dwInputMaximum; pdwOutputMinimum := FStreamLimits.dwOutputMinimum; pdwOutputMaximum := FStreamLimits.dwOutputMaximum; Result := S_OK; end; function TPassthroughTransform.GetStreamCount(out pcInputStreams, pcOutputStreams: DWORD): HResult; begin pcInputStreams := 1; pcOutputStreams := 1; Result := S_OK; end; function TPassthroughTransform.GetStreamIDs(dwInputIDArraySize: DWORD; var pdwInputIDs: DWORD; dwOutputIDArraySize: DWORD; var pdwOutputIDs: DWORD): HResult; begin // Fixed stream IDs, so this is not needed Result := E_NOTIMPL; end; function TPassthroughTransform.GetInputStreamInfo(dwInputStreamID: DWORD; out pStreamInfo: MFT_INPUT_STREAM_INFO): HResult; begin if not IsValidInputStream(dwInputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; pStreamInfo := FInputStreamInfo; Result := S_OK; end; function TPassthroughTransform.GetOutputStreamInfo(dwOutputStreamID: DWORD; out pStreamInfo: MFT_OUTPUT_STREAM_INFO): HResult; begin if not IsValidOutputStream(dwOutputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; pStreamInfo := FOutputStreamInfo; Result := S_OK; end; function TPassthroughTransform.GetAttributes(out pAttributes: IMFAttributes): HResult; begin pAttributes := FAttributes; if Assigned(pAttributes) then pAttributes._AddRef; Result := S_OK; end; function TPassthroughTransform.GetInputStreamAttributes(dwInputStreamID: DWORD; out pAttributes: IMFAttributes): HResult; begin // No per-stream attributes pAttributes := nil; Result := E_NOTIMPL; end; function TPassthroughTransform.GetOutputStreamAttributes(dwOutputStreamID: DWORD; out pAttributes: IMFAttributes): HResult; begin // No per-stream attributes pAttributes := nil; Result := E_NOTIMPL; end; function TPassthroughTransform.DeleteInputStream(dwStreamID: DWORD): HResult; begin // Cannot delete streams - we have fixed streams Result := E_NOTIMPL; end; function TPassthroughTransform.AddInputStreams(cStreams: DWORD; var adwStreamIDs: DWORD): HResult; begin // Cannot add streams - we have fixed streams Result := E_NOTIMPL; end; function TPassthroughTransform.GetInputAvailableType(dwInputStreamID, dwTypeIndex: DWORD; out ppType: IMFMediaType): HResult; begin // Passthrough accepts any type, so we don't enumerate types ppType := nil; Result := MF_E_NO_MORE_TYPES; end; function TPassthroughTransform.GetOutputAvailableType(dwOutputStreamID, dwTypeIndex: DWORD; out ppType: IMFMediaType): HResult; begin if not IsValidOutputStream(dwOutputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if not Assigned(FInputMediaType) then begin Result := MF_E_TRANSFORM_TYPE_NOT_SET; Exit; end; if dwTypeIndex > 0 then begin Result := MF_E_NO_MORE_TYPES; Exit; end; // Output type is the same as input type for passthrough Result := MFCreateMediaType(ppType); if SUCCEEDED(Result) then Result := FInputMediaType.CopyAllItems(ppType); end; function TPassthroughTransform.SetInputType(dwInputStreamID: DWORD; pType: IMFMediaType; dwFlags: DWORD): HResult; begin if not IsValidInputStream(dwInputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if (dwFlags and MFT_SET_TYPE_TEST_ONLY) <> 0 then begin // Just test if we can accept this type Result := OnCheckInputType(pType); Exit; end; // Actually set the type Result := OnCheckInputType(pType); if SUCCEEDED(Result) then Result := OnSetInputType(pType); end; function TPassthroughTransform.SetOutputType(dwOutputStreamID: DWORD; pType: IMFMediaType; dwFlags: DWORD): HResult; begin if not IsValidOutputStream(dwOutputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if not Assigned(FInputMediaType) then begin Result := MF_E_TRANSFORM_TYPE_NOT_SET; Exit; end; // For passthrough, output type must match input type if not Assigned(pType) then begin FOutputMediaType := nil; Result := S_OK; Exit; end; // Compare types - they should be identical for passthrough Result := pType.IsEqual(FInputMediaType, pdwFlags); if (Result <> S_OK) then begin Result := MF_E_INVALIDMEDIATYPE; Exit; end; if (dwFlags and MFT_SET_TYPE_TEST_ONLY) = 0 then Result := OnSetOutputType(pType) else Result := S_OK; end; function TPassthroughTransform.GetInputCurrentType(dwInputStreamID: DWORD; out ppType: IMFMediaType): HResult; begin if not IsValidInputStream(dwInputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if not Assigned(FInputMediaType) then begin ppType := nil; Result := MF_E_TRANSFORM_TYPE_NOT_SET; Exit; end; ppType := FInputMediaType; ppType._AddRef; Result := S_OK; end; function TPassthroughTransform.GetOutputCurrentType(dwOutputStreamID: DWORD; out ppType: IMFMediaType): HResult; begin if not IsValidOutputStream(dwOutputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if not Assigned(FOutputMediaType) then begin ppType := nil; Result := MF_E_TRANSFORM_TYPE_NOT_SET; Exit; end; ppType := FOutputMediaType; ppType._AddRef; Result := S_OK; end; function TPassthroughTransform.GetInputStatus(dwInputStreamID: DWORD; out pdwFlags: DWORD): HResult; begin if not IsValidInputStream(dwInputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if FHasInput then pdwFlags := 0 // Cannot accept input else pdwFlags := MFT_INPUT_STATUS_ACCEPT_DATA; Result := S_OK; end; function TPassthroughTransform.GetOutputStatus(out pdwFlags: DWORD): HResult; begin if FHasInput then pdwFlags := MFT_OUTPUT_STATUS_SAMPLE_READY else pdwFlags := 0; Result := S_OK; end; function TPassthroughTransform.SetOutputBounds(hnsLowerBound, hnsUpperBound: LONGLONG): HResult; begin // Not implemented for passthrough Result := E_NOTIMPL; end; function TPassthroughTransform.ProcessEvent(dwInputStreamID: DWORD; pEvent: IMFMediaEvent): HResult; begin // Events are not processed in basic passthrough Result := E_NOTIMPL; end; function TPassthroughTransform.ProcessMessage(eMessage: MFT_MESSAGE_TYPE; ulParam: ULONG_PTR): HResult; begin case eMessage of MFT_MESSAGE_COMMAND_FLUSH: begin FInputSample := nil; FHasInput := False; FDraining := False; Result := S_OK; end; MFT_MESSAGE_COMMAND_DRAIN: begin FDraining := True; Result := S_OK; end; MFT_MESSAGE_NOTIFY_BEGIN_STREAMING: Result := S_OK; MFT_MESSAGE_NOTIFY_END_STREAMING: begin FInputSample := nil; FHasInput := False; FDraining := False; Result := S_OK; end; MFT_MESSAGE_SET_D3D_MANAGER: Result := S_OK; // Ignore for passthrough else Result := E_NOTIMPL; end; end; function TPassthroughTransform.ProcessInput(dwInputStreamID: DWORD; pSample: IMFSample; dwFlags: DWORD): HResult; begin if not IsValidInputStream(dwInputStreamID) then begin Result := MF_E_INVALIDSTREAMNUMBER; Exit; end; if not Assigned(pSample) then begin Result := E_POINTER; Exit; end; if not Assigned(FInputMediaType) then begin Result := MF_E_NOTACCEPTING; Exit; end; if FHasInput then begin Result := MF_E_NOTACCEPTING; Exit; end; // Store the input sample FInputSample := pSample; FHasInput := True; Result := S_OK; end; function TPassthroughTransform.ProcessOutput(dwFlags: DWORD; cOutputBufferCount: DWORD; var pOutputSamples: MFT_OUTPUT_DATA_BUFFER; out pdwStatus: DWORD): HResult; var pBuffer: IMFMediaBuffer; pInputBuffer: IMFMediaBuffer; pData, pInputData: PByte; cbData, cbInputData: DWORD; cbMaxLength, cbInputMaxLength: DWORD; begin pdwStatus := 0; if cOutputBufferCount < 1 then begin Result := E_INVALIDARG; Exit; end; if not FHasInput then begin Result := MF_E_TRANSFORM_NEED_MORE_INPUT; Exit; end; if not Assigned(pOutputSamples.pSample) then begin Result := E_INVALIDARG; Exit; end; try // Get the output buffer Result := pOutputSamples.pSample.GetBufferByIndex(0, pBuffer); if FAILED(Result) then Exit; // Get the input buffer Result := FInputSample.GetBufferByIndex(0, pInputBuffer); if FAILED(Result) then Exit; // Lock both buffers Result := pInputBuffer.Lock(pInputData, cbInputMaxLength, cbInputData); if FAILED(Result) then Exit; try Result := pBuffer.Lock(pData, cbMaxLength, cbData); if FAILED(Result) then Exit; try // Ensure output buffer is large enough if cbMaxLength < cbInputData then begin Result := MF_E_BUFFERTOOSMALL; Exit; end; // Copy data (passthrough) if cbInputData > 0 then Move(pInputData^, pData^, cbInputData); // Set the data length Result := pBuffer.SetCurrentLength(cbInputData); if FAILED(Result) then Exit; finally pBuffer.Unlock; end; finally pInputBuffer.Unlock; end; // Copy sample attributes Result := FInputSample.CopyAllItems(pOutputSamples.pSample); if FAILED(Result) then Exit; // Clear input FInputSample := nil; FHasInput := False; pOutputSamples.dwStatus := 0; Result := S_OK; except Result := E_UNEXPECTED; end; end; end. And that is way time saving from going after researching each and every method, this is really nice, anyway, i am sure there is bugs and as always many tweaking is needed but the skeleton is right, also you can ask an AI to go and show how to register as Local instead of global and how to use it. And good luck !
  6. aehimself

    for loop variable value after the loop

    They grow up so fast :)
  7. Kas Ob.

    Recover from call to dll that doesn't return

    Nice find, and it will allow deeper diagnose of the problem. So try different path, in other words try to pinpoint the failure cause with using MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, from https://learn.microsoft.com/en-us/windows/win32/medfound/mf-source-reader-enable-advanced-video-processing This arbitrary "looks for video processors" is most likely the culprit, assuming the MF_READWRITE_DISABLE_CONVERTERS is disabled, so try to use see what the difference between the two OSs in selecting the transformer, so, Use MFTEnumEx https://learn.microsoft.com/en-us/windows/win32/api/mfapi/nf-mfapi-mftenumex with MFT_CATEGORY_VIDEO_PROCESSOR also compare how disabling hardware acceleration impacting this enumeration, and MFTGetInfo https://learn.microsoft.com/en-us/windows/win32/api/mfapi/nf-mfapi-mftgetinfo to get more in depth view of the failing or freezing cause, which seems wrong transformer or un-configured (more advanced that need extra settings) transformer. Also you can build your own IMFTransform which is declared in WinApi.MediaFoundationApi.MfTransform and use MFTRegisterLocal to use it with registering the COM itself (as dll), this what got to mind when i asked if there is extra codecs installed and they might be registered them selves as transformers in this case. In other words you are on the correct path now, and highly recommend to continue tweaking and fixing MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING instead of MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, if the problem is selecting different transformer then you need to fix that, the one that was/is working for both OSs, the one with high compatibility across WMF in Windows, see it could be as simple as HDR thingy (transformer) which got higher priority in Windows 11 ps; writing IMFTransform might be not an easy job but will greatly enhance you debugging and tweaking. ps2; searching the Internet for something helps in tracing and i found this gem, never used it, but it looks brilliant and what doctor should recommend https://learn.microsoft.com/en-us/windows/win32/medfound/mftrace https://learn.microsoft.com/en-us/windows/win32/medfound/using-mftrace
  8. Renate Schaaf

    Recover from call to dll that doesn't return

    I think I found the setting with the potential for errors and hangs: It's the source-reader attribute MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING. It allows the source-reader to decode to a new size, change pixel-aspect and framerate. If I change it to MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, all the videos that worked under Win10 can be processed under Win11 too. And the encoder does framerate-conversion automagically! Problem is, now I have to resize the output myself, which is causing a slowdown. I solved it for the time being by having a slow but safe procedure AddVideo and one which is fast but might fail. I'll also implement the test based on Remy's idea. And then I hope that the next Win-Update will fix the problems.
  9. The fix was for a different problem but it also fixed this particular one. We sent new builds to Embarcadero ahead of time, during the beta period, that was before this fix. We will publish a patch soon at steema.com, with this fix and other fixes if new bugs appear, hopefully not.
  10. Lars Fosdal

    New Delphi features in Delphi 13

    Possible ways to do that, include Have a step-in/step-out monthly subscription model - with a price comparable to streaming services such as Apple, HBO Max, Prime, Disney+, SkyShowtime, Netflix... Improve the capabilities of the lowest tier of Delphi by having full Linux and database support - or even simply have one single tier Keep writing good software, readworthy articles and contribute to open source where you can
  11. ŁukaszDe

    Does anyone know if MadExcept is dead ?

    New version is now available: madExcept 5.2.0 comes with the following changes: · added support for Delphi 13 · added support for 64 bit IDE
  12. Stefan Glienke

    JSON benchmarks

    FWIW, such benchmarks should also run in parallel because especially string-related parsing is usually full of heap allocations that can suffer highly in multithreading. I am also sure that @Arnaud Bouchez could join the game and stomp all these libraries into the ground performancewise with mormot
  13. Lars Fosdal

    JSON benchmarks

    IMO, if you need multiple values for a field, you should use a list element. Duplicate key/value pairs in JSON just doesn't make sense. https://JsonLint.com does not like them either.
  14. Stefan Glienke

    JSON benchmarks

    No, but according to RFC 8259, they *should* be unique. I just pointed out that by supporting that feature, there needs to be done more than simply adding pairs without any lookup. In fact, it looks like some implementations don't even allow adding duplicate names.
  15. Lachlan Gemmell

    for loop variable value after the loop

    Delphi 2 baby and still there in Delphi 13.
×