Jump to content

Yaron

Members
  • Content Count

    275
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Yaron


  1. I know Delphi 7 is old, but I have projects that I maintain and once I upgraded to Windows 10, compilation/running is a lot slower compared to Win 7 (on the same machine).

     

    I believe it may has something to do with the real-time virus protection (which I disabled in Win7 and is very hard to disable in Win10), but there may be other factors I'm not aware of.

     

    Does anyone have any tips to speed things up?


  2. If anyone is interested, here's the relevant section of the manifest file after I tested it works correctly:
     

            <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                    android:label="ZP Remote"
                    android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                    android:launchMode="singleTask">
                <!-- Tell NativeActivity the name of our .so -->
                <meta-data android:name="android.app.lib_name"
                    android:value="ZP_Remote" />
                <intent-filter>  
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter> 
                <intent-filter android:label="Play in ZP">  
                    <action android:name="android.intent.action.SEND" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:mimeType="text/plain" />
                </intent-filter> 
            </activity>
            <activity-alias
                    android:targetActivity="com.embarcadero.firemonkey.FMXNativeActivity"
                    android:name="com.embarcadero.firemonkey.FMXNativeActivity.Queue">
                <!-- Put second SEND action inside activity-alias tag -->
                <intent-filter android:label="Queue in ZP">
                    <action android:name="android.intent.action.SEND" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:mimeType="text/plain" />
                </intent-filter>
            </activity-alias>

     

    • Like 1

  3. I got a DM with a request on how I added Android AdMob interstitial ads, here's the code:

     

    First the definition:

    
      {$IF DEFINED(ANDROID) and DEFINED(ADMOB_FULLPAGE)}
      TInterStitialAdViewListener = class(TJavaLocal, JIAdListener)
        private
          FAD: JInterstitialAd;
        public
          constructor Create(AAD: JInterstitialAd);
          procedure onAdClosed; cdecl;
          procedure onAdFailedToLoad(errorCode: Integer); cdecl;
          procedure onAdLeftApplication; cdecl;
          procedure onAdOpened; cdecl;
          procedure onAdLoaded; cdecl;
      end;
      {$ENDIF}
    
    [code]
    
     
    
    Then in the private section of the main form:
    
    [code]
    
        {$IF DEFINED(ANDROID) and DEFINED(ADMOB_FULLPAGE)}
        LAdViewListener : TInterStitialAdViewListener;
        FInterStitial   : JInterstitialAd;
        {$ENDIF}
    
    

     

    In the form's onCreate:

    
        {$IFDEF ADMOB_FULLPAGE}
          FInterStitial := TJInterstitialAd.JavaClass.init(MainActivity);
          {$IFDEF TRACEDEBUG}
          FInterStitial.setAdUnitId(StringToJString('ca-app-pub-3940256099942544/1033173712')); // google test ad
          {$ELSE}
          FInterStitial.setAdUnitId(StringToJString('ca-app-pub-xxxxxxxxxxxxxxxxxxx/xxxxxxxxxxx')); // real ad code
          {$ENDIF}
        {$ENDIF}
    
    

     

    And finally:

    
    {$IF DEFINED(ANDROID) and DEFINED(ADMOB_FULLPAGE)}
    constructor TInterStitialAdViewListener.Create(AAD: JInterstitialAd);
    begin
      inherited Create;
      FAD := AAD;
      {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener created');{$ENDIF}
    end;
    
     
    
    procedure TInterStitialAdViewListener.onAdClosed;
    begin
      {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdClosed event');{$ENDIF}
      //MainForm.ShowModal;
    end;
    
     
    
    procedure TInterStitialAdViewListener.onAdFailedToLoad(errorCode: Integer);
    begin
      {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdFailedToLoad code #'+errorCode.toString);{$ENDIF}
      {$IFDEF TRACEDEBUG}ShowMessage('AdFailedToLoad code #'+errorCode.toString);{$ENDIF}
    end;
    
     
    
    procedure TInterStitialAdViewListener.onAdLeftApplication;
    begin
      {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdLeftApplication');{$ENDIF}
    end;
    
     
    
    procedure TInterStitialAdViewListener.onAdLoaded;
    begin
      {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdLoaded');{$ENDIF}
      FAD.show;
    end;
    
     
    
    procedure TInterStitialAdViewListener.onAdOpened;
    begin
      {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdOpened');{$ENDIF}
    end;
    
     
    
    procedure TMainForm.ShowInterStitialAd;
    var
      LADRequestBuilder: JAdRequest_Builder;
      LadRequest: JAdRequest;
    begin
      LADRequestBuilder := TJAdRequest_Builder.Create;
      {$IFDEF TRACEDEBUG}LADRequestBuilder.addTestDevice(MainActivity.getDeviceID);{$ENDIF}
      LadRequest := LADRequestBuilder.build();
      LAdViewListener := TInterStitialAdViewListener.Create(FInterStitial);
      CallInUIThread(
      procedure
      begin
        FInterStitial.setAdListener(TJAdListenerAdapter.JavaClass.init
          (LAdViewListener));
        FInterStitial.loadAd(LadRequest);
      end);
    end;
    {$ENDIF}
    
    

     


  4. @Dave Nottage

    Yes, I am working with the same "SEND" action.

     

    I read the article you linked to, but didn't see any mention regarding the same action used more than once.

     

    I did get an answer on stackoverflow that I should use an Activity Alias, but haven't had time to test it yet and I haven't figured out yet (mainly due to lack of time) how to do this in delphi :

    if (intent.component.className.endsWith(".Queue"){
        // putting data in the queue...
    } else {
        // playing requested data...
    }


     


  5. I tried modifying the manifest file to include two entries with different labels:

                <intent-filter android:label="Play in XX">  
                    <action android:name="android.intent.action.SEND" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:mimeType="text/plain" />
                </intent-filter> 
                <intent-filter android:label="Queue in XX">  
                    <action android:name="android.intent.action.SEND" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:mimeType="text/plain" />
                </intent-filter>

    However, only the first entry shows up in YouTube and on top of that I'm not even sure how to read the label value from my Delphi code so I can distinguish between the two call even if YouTube did list them.


  6. 5 hours ago, Dave Nottage said:

    Does calling registerIntentAction with another action not work?

    I don't see the mechanism that would allow me to distinguish between multiple intents.

    I don't understand how calling "MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_SEND);" again would help.

     


  7. I am trying to write Android intent code so when a user chooses to share text with another application, my app will appear twice as an option, each with a different label and a mechanism I can distinguish between the two intents.

     

    Basically, I'm trying to have  "Play" and "Queue"  options for URLs shared from the YouTube app.

     

    I have no issues with just one intent, defining in  "AndroidManifest.template.xml"

                <intent-filter>  
                    <action android:name="android.intent.action.SEND" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:mimeType="text/plain" />
                </intent-filter>

    And in code:

      // Register the type of intent action that we want to be able to receive.
      // Note: A corresponding <action> tag must also exist in the <intent-filter> section of AndroidManifest.template.xml.
      MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_SEND);
      TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage);
    procedure TMainForm.HandleActivityMessage(const Sender: TObject; const M: TMessage);
    begin
      if M is TMessageReceivedNotification then
        HandleIntentAction(TMessageReceivedNotification(M).Value);
    end;
    function TMainForm.HandleIntentAction(const Data: JIntent): Boolean;
    var
      Extras   : JBundle;
      sURL     : String;
    begin
      Result := False;
      if Data <> nil then
      begin
        Extras := Data.getExtras;
        if Extras <> nil then
        Begin
          sURL := JStringToString(Extras.getString(TJIntent.JavaClass.EXTRA_TEXT));
          {$IFDEF TRACEDEBUG}AddDebugEntry('Intent string "'+sURL+'"');{$ENDIF}
          Extras := nil;
        End
      end
    end;

     

    How can I add a second intent?


  8. I'm using AJAX forms with javascript's "history.pushState" to preserve the browser's "back" button functionality.

     

    So if my entry point is "https://myserver.com/v/site/", clicking on a link would look like "https://myserver.com/v/site/page1/" without any actual page being loaded (only part of the page).

     

    My problem is that when the user tries to refresh the page, MARS won't recognize the "https://myserver.com/v/site/page1/" path.  In reality, I would like to redirect such URLs back to "https://myserver.com/v/site/".

     

    I tried registering the InvokeError procedure like this:

        TMARSActivation.RegisterInvokeError(
          procedure (const AActivation: IMARSActivation; const AException: Exception; var AHandled: Boolean)
          begin
            ShowMessage(AActivation.Request.URL);
            AHandled := True;
          end
        );

    Which is triggered, but "AActivation.Request.URL" returns an empty string and I'm not sure how to perform the redirect...  can you help?


  9. I need to temporarily disable HDR to display a menu system when an HDR video is playing.

    It's been a bit of a chase finding out this is done, so I thought I'll share.

     

    There's documentation of how to do it with C++ here:
    https://stackoverflow.com/questions/53517128/query-if-hdr-is-active-on-windows

     

    But even Delphi 10.3.3 is missing "Winapi.DXGI1_6.pas".

    However,  Searching for this file led me to MfPack (https://sourceforge.net/projects/mfpack/), which does carry up to date header conversions.


  10. @eivindbakkestuen:

    I have a 4 Core/8 Thread GPU and the CPU is not really tasked, I believe it's mostly disk I/O.

     

    @Fr0sT.Brutal:

    You missed the bit where I wrote that the mediainfo data is synched with a central scrape-coordination thread, so the main UI is only disturbed when all the data has been scraped. And yes, it can be analyzing 100's (even 1000's) of files, trying to do so for about 4 concurrently.

     


  11. @Remy Lebeau Debugging multiple threads is very difficult (at least in D7) as the run-point seems to jump between the threads each time you advance one line (unless there's something I'm missing?)

    This is why I use a lot of debug log entries.

     

    I believe the code I pasted above doesn't synchronize anything with the main thread, it's passing data to another (scraping) thread which works (synchronizes) just fine when doing other heavy work unrelated to mediainfo.

     


  12. Here are more details (it's somewhat big, but may help others in the future):

     

    1. I have an Idle priority information-scraping thread so the UI won't be affected by the scraping process.
    2. The scraping thread pre-creates & uses an idle priority TMediaInfoThread thread (see below).
    3. The scraping activates the mediainfo thread.
    4. This is the mediainfo's DLL pascal header file : https://github.com/MediaArea/MediaInfoLib/blob/master/Source/MediaInfoDLL/MediaInfoDLL.pas
    5. And you can download the DLL here https://mediaarea.net/en/MediaInfo/Download/Windows

     

    Code used to activate MediaInfo data gathering thread:

       MediaInfoThread.MediaName  := MediaName;
       MediaInfoThread.ScrapeType := niVideo;
       MediaInfoThread.ResumeThread;
    
       // do other scraping related meta-data gathering (e.g. online DB lookup) while mediainfo is processing to maximize concurrently/performance.
    
       While MediaInfoThread.IsSuspended = False do Sleep(1);
       If MediaInfoThread.miResult = True then
    


    The MediaInfo thread code:

    Type
      TMediaInfoThread = Class(TThread)
        procedure execute; override;
      private
        FEvent             : THandle;
      public
        ScraperThreadIndex : Integer;
        IsSuspended        : Boolean;
        ScrapeType         : Integer;
        MediaName          : WideString;
        miResult           : Boolean;
        miWidth            : Integer;
        miHeight           : Integer;
        miDuration         : Double;
        miIcons            : WideString;
        miMediaTAGs        : TZPTAGRec;
        Closed             : PBoolean;
        procedure ResumeThread;
      end;
    
    
    procedure TMediaInfoThread.Execute;
    begin
      {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','Thread Created, ID #'+IntToStr(ThreadID));{$ENDIF}
      FEvent := CreateEvent(nil,
                            False,    // auto reset
                            False,    // initial state = not signaled
                            nil);
    
      ResetTagData(miMediaTAGs);                      
      ScrapeType  := niVideo;
      IsSuspended := True;
      {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','Thread Initially Suspended');{$ENDIF}
      WaitForSingleObject(FEvent, INFINITE);  // Wait to start processing
      {$IFDEF LOC1ALTRACE}
      DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','Thread Initially Resumed'+CRLF);
      {$ENDIF}
      While (Terminated = False) do
      Begin
        {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','MediaInfo on "'+MediaName+'" (before)');{$ENDIF}
        miResult := MediaInfo_GetMediaInfoCache(MediaName,ScrapeType,miIcons,miWidth,miHeight,miDuration,@miMediaTAGs,ScraperThreadIndex);
        {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','MediaInfo on "'+MediaName+'" (after)');{$ENDIF}
        If Terminated = False then
        Begin
          IsSuspended := True;
          {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','MediaInfo complete, Thread Suspended'+CRLF);{$ENDIF}
          WaitForSingleObject(FEvent, INFINITE);  // No more Work
          {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','Thread Resumed');{$ENDIF}
          If Terminated = False then ResetTagData(miMediaTAGs);
        End;
      End;
      {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','Close event handle');{$ENDIF}
      CloseHandle(fEvent);
    
      If @Closed <> nil then Closed^ := True;
    
      {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(ScraperThreadIndex)+'.txt','Thread Terminated');{$ENDIF}
    end;
    
    
    procedure TMediaInfoThread.ResumeThread;
    begin
      SetEvent(FEvent);
      IsSuspended := False;
    end;
    
    function MediaInfo_GetMediaInfo(FileName : WideString; ScrapeType : Integer; miData : PMediaInfoDataRecord; grabThreadID : Integer) : Boolean;
    var
      miHandle       : Cardinal;
      sFormat        : WideString;
      sFormatVersion : WideString;
      sFormatString  : WideString;
      sProfile       : WideString;
      sCodecID       : WideString;
      sScanType      : WideString;
      sDuration      : WideString;
      aCount         : Integer;
      vCount         : Integer;
      I              : Integer;
      mWidth         : Integer;
      mHeight        : Integer;
      mChannels      : Integer;
      iWidth         : Integer;
      iHeight        : Integer;
      iChannels      : Integer;
      iCodec         : Integer;
      S              : String;
    begin
      {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','MediaInfo_GetMediaInfo (before)');{$ENDIF}
      Result := False;
      With miData^ do
      Begin
        iconFormat     := niNone;
        iconResolution := niNone;
        iconVideo      := niNone;
        iconAudio      := niNone;
        iconChannels   := niNone;
        ResetTagData(TAGs);
    
        If MediaInfoLoaded = True then
        Begin
          {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','MediaInfoLoaded = True');{$ENDIF}
          miHandle        := MediaInfo_New;
          {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','MediaInfo Handle : '+IntToHex(miHandle,8));{$ENDIF}
          If MediaInfo_Open(miHandle, PWideChar(FileName)) = 1 then
          Begin
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Open successful');{$ENDIF}
            Result := True;
    
            // Duration
            sDuration      := MediaInfo_Get(miHandle, Stream_General, 0, 'Duration'      , Info_Text, Info_Name);
            mediaDuration  := StrToFloatDef(sDuration,0) / 1000;
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Duration : '+sDuration);{$ENDIF}
    
            // File format
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','*** File Format ');{$ENDIF}
            sFormat        := MediaInfo_Get(miHandle, Stream_General, 0, 'Format'        , Info_Text, Info_Name);
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Format : '+sFormat);{$ENDIF}
            sFormatVersion := MediaInfo_Get(miHandle, Stream_General, 0, 'Format_Version', Info_Text, Info_Name);
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','FormatVersion : '+sFormatVersion);{$ENDIF}
            sProfile       := MediaInfo_Get(miHandle, Stream_General, 0, 'Format_Profile', Info_Text, Info_Name);
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Profile : '+sProfile);{$ENDIF}
            iconFormat     := MediaInfo_FormatToNavIcon(sFormat,sFormatVersion,sProfile);
    
            If ScrapeType = niVideo then
            Begin
              // Video Codec & Resolution
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','*** Video Codec & Resolution');{$ENDIF}
              mWidth  := -1;
              mHeight := -1;
              vCount := MediaInfo_Count_Get(miHandle, Stream_Video, -1);
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Video Streams : '+IntToStr(vCount));{$ENDIF}
              For I := 0 to vCount-1 do
              Begin
                iWidth         := StrToIntDef(MediaInfo_Get(miHandle, Stream_Video, I, 'Width' , Info_Text, Info_Name),-1);
                iHeight        := StrToIntDef(MediaInfo_Get(miHandle, Stream_Video, I, 'Height', Info_Text, Info_Name),-1);
    
                If (iWidth > mWidth) or (iHeight > mHeight) then
                Begin
                  {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Video Resolution : '+IntToStr(iWidth)+'x'+IntToStr(iHeight));{$ENDIF}
                  mWidth         := iWidth;
                  mHeight        := iHeight;
                  sFormat        := MediaInfo_Get(miHandle, Stream_Video, I, 'Format'        , Info_Text, Info_Name);
                  {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Format : '+sFormat);{$ENDIF}
                  sFormatVersion := MediaInfo_Get(miHandle, Stream_Video, I, 'Format_Version', Info_Text, Info_Name);
                  {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. FormatVersion : '+sFormatVersion);{$ENDIF}
                  sProfile       := MediaInfo_Get(miHandle, Stream_Video, I, 'Format_Profile', Info_Text, Info_Name);
                  {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Profile : '+sProfile);{$ENDIF}
                  sScanType      := TNT_WideLowercase(MediaInfo_Get(miHandle, Stream_Video, I, 'ScanType', Info_Text, Info_Name));
                  {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. ScanType : '+sScanType);{$ENDIF}
                  sCodecID       := MediaInfo_Get(miHandle, Stream_Video, I, 'CodecID'       , Info_Text, Info_Name);
                  {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. CodecID : '+sCodecID);{$ENDIF}
    
                  iconResolution := MediaInfo_ResolutionToNavIcon(mWidth,mHeight,sScanType);
                  iconVideo      := MediaInfo_VideoCodecToNavIcon(sFormat,sFormatVersion,sCodecID,sProfile);
                  mediaWidth     := mWidth;
                  mediaHeight    := mHeight;
                End;
              End;
            End
              else
            Begin
              // Audio TAGs
              TAGs.tgTitle     := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Track'              , Info_Text, Info_Name));
              TAGs.tgGenre     := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Genre'              , Info_Text, Info_Name));
              TAGs.tgTrack     := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Track/Position'     , Info_Text, Info_Name));
              TAGs.tgArtist    := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Performer'          , Info_Text, Info_Name));
              TAGs.tgAlbum     := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Album'              , Info_Text, Info_Name));
              TAGs.tgYear      := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Recorded_Date'      , Info_Text, Info_Name));
              TAGs.tgAuthor    := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'WrittenBy'          , Info_Text, Info_Name));
              TAGs.tgComment   := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Comment'            , Info_Text, Info_Name));
              TAGs.tgURL       := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Track/Url'          , Info_Text, Info_Name));
              TAGs.tgCopyright := UTF8Decode(MediaInfo_Get(miHandle, Stream_General, 0, 'Copyright'          , Info_Text, Info_Name));
              S                     :=            MediaInfo_Get(miHandle, Stream_General, 0, 'Encoded_Application', Info_Text, Info_Name);
              If S = '' then S      :=            MediaInfo_Get(miHandle, Stream_General, 0, 'Encoded_Library'    , Info_Text, Info_Name);
              TAGs.tgAuthor    := UTF8Decode(S);
            End;
    
            // Audio Codec & Channels
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','*** Audio Codec & Channels');{$ENDIF}
            mChannels := -1;
            aCount    := MediaInfo_Count_Get(miHandle, Stream_Audio, -1);
            {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Audio Streams : '+IntToStr(aCount));{$ENDIF}
            For I := 0 to aCount-1 do
            Begin
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Audio Stream');{$ENDIF}
              iCodec    := -1;
              //sCommercialName := MediaInfo_Get(miHandle, Stream_Audio, I, 'Format_Commercial_IfAny', Info_Text, Info_Name);
              sFormatString := MediaInfo_Get(miHandle, Stream_Audio, I, 'Format/String' , Info_Text, Info_Name);
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Format String : '+sFormatString);{$ENDIF}
              sFormat       := MediaInfo_Get(miHandle, Stream_Audio, I, 'Format'        , Info_Text, Info_Name);
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Format : '+sFormat);{$ENDIF}
              sProfile      := MediaInfo_Get(miHandle, Stream_Audio, I, 'Format_Profile', Info_Text, Info_Name);
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Profile : '+sProfile);{$ENDIF}
              iChannels     := MediaInfo_AudioChannelCount(MediaInfo_Get(miHandle, Stream_Audio, I, 'Channel(s)', Info_Text, Info_Name));
              {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt',IntToStr(I)+'. Channels : '+IntToStr(iChannels));{$ENDIF}
    
              iCodec    := MediaInfo_AudioCodecToNavIcon(sFormat,sProfile,sFormatString);
    
              If (iChannels > mChannels) or
                 ((iconAudio = ni_codecDD       ) and (iCodec in [ni_codecDTS,ni_codecDTS_ES,ni_codecDTS_HD_MA,ni_codecDD_TrueHD] = True)) or
                 ((iconAudio = ni_codecDTS      ) and (iCodec in [ni_codecDTS_ES,ni_codecDTS_HD_MA,ni_codecDD_TrueHD] = True)) or
                 ((iconAudio = ni_codecDTS_ES   ) and (iCodec in [ni_codecDTS_HD_MA,ni_codecDD_TrueHD] = True)) or
                 ((iconAudio = ni_codecDD_TrueHD) and (iCodec in [ni_codecDTS_HD_MA] = True)) then
              Begin
                mChannels    := iChannels;
                iconChannels := MediaInfo_AudioChannelsToNavIcon(mChannels);
                iconAudio    := MediaInfo_AudioCodecToNavIcon(sFormat,sProfile,sFormatString);
              End;
            End;
          End;
          {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','Close Handle');{$ENDIF}
          MediaInfo_Close(miHandle);
        End;
      End;
      {$IFDEF LOCALTRACE}DebugMsgFT('c:\log\MediaInfoThread_'+IntToStr(grabThreadID)+'.txt','MediaInfo_GetMediaInfo (after)'+CRLF);{$ENDIF}
    end;
    
    
    function MediaInfo_ProccessTAGdata(FileName : WideString; mRec : TZPFileClass; var albumArt : TBitmap) : Boolean;
    var
      miHandle       : Cardinal;
      sImage         : String;
      sDecoded       : String;
      fStream        : TMemoryStream;
      S              : String;
    
    begin
      Result         := False;
    
      If MediaInfoLoaded = True then
      Begin
        miHandle        := MediaInfo_New;
        If MediaInfo_Open(miHandle, PWideChar(FileName)) = 1 then
        Begin
          sImage := MediaInfo_Get(miHandle, Stream_General, 0, 'Cover_Data'  , Info_Text, Info_Name);
    
          If sImage <> '' then
          Begin
            sDecoded := Base64DecodeString(sImage);
            Result   := True;
            fStream  := TMemoryStream.Create;
            fStream.Write(sDecoded[1],Length(sDecoded));
            fStream.Position := 0;
            LoadDetectedImage(fStream,albumArt);
            fStream.Free;
          End;
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Track'  , Info_Text, Info_Name);
          If S = '' then S := MediaInfo_Get(miHandle, Stream_General, 0, 'Movie'  , Info_Text, Info_Name);
    
          If mRec.zplTAG.tgTitle = '' then
          Begin
            If S = '' then mRec.zplTAG.tgTitle := mRec.zplName else mRec.zplTAG.tgTitle := UTF8Decode(S);
          End;
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Genre'              , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgGenre     = '') then mRec.zplTAG.tgGenre     := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Track/Position'     , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgTrack     = '') then mRec.zplTAG.tgTrack     := FillZero(S,2);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Performer'          , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgArtist    = '') then mRec.zplTAG.tgArtist    := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Album'              , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgAlbum     = '') then mRec.zplTAG.tgAlbum     := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Recorded_Date'      , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgYear      = '') then mRec.zplTAG.tgYear      := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'WrittenBy'          , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgAuthor    = '') then mRec.zplTAG.tgAuthor    := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Encoded_Application', Info_Text, Info_Name);
          If S = '' then
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Encoded_Library'    , Info_Text, Info_Name);
    
          If (S <> '') and (mRec.zplTAG.tgEncoder   = '') then mRec.zplTAG.tgEncoder   := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Comment'            , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgComment   = '') then mRec.zplTAG.tgComment   := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Track/Url'          , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgURL       = '') then mRec.zplTAG.tgURL       := UTF8Decode(S);
    
          S := MediaInfo_Get(miHandle, Stream_General, 0, 'Copyright'          , Info_Text, Info_Name);
          If (S <> '') and (mRec.zplTAG.tgCopyright = '') then mRec.zplTAG.tgCopyright := UTF8Decode(S);
    
          SendLCDs(2400,strNoMoreData);
        End;
        MediaInfo_Close(miHandle);
      End;
    end;
    
    


  13. I'm the author of Zoom Player a Windows media player/home theater application.

    One of Zoom Player's features is that it scrapes information on the video file using multiple mechanism.

     

    Two of these mechanisms are somehow severely lagging my user interface even though I'm running the code in separate threads with Idle priority:

    1. Running MediaInfo.dll on the media file.

    2. Using a non-visual background directshow graph using LAV Filters (directshow filters) to extract a video frame from the video.

     

    Other than moving this functionality to completely separate processes, is there a method to ensure my UI (running in the main thread) remains responsive?


  14. I managed to debug the SSL DLL's LoadLibrary's GetLastError value and it's #193, which according to microsoft is "ERROR_BAD_EXE_FORMAT".

     

    I don't belive the DLLs were corrupted, but just in case I downloaded the latest versions of the DLLs (v1.0.2.21) and no more errors on my local Win10 machine, but the Win2019 server is still triggering the same exceptions.


  15. I did further testing and it's also failing outside of IIS, when running as a normal process on my local Windows 10 machine (which I also recently upgraded from Windows 7 where the code worked fine).

     

    So is this issue possibly specific to Windows 10/2019?


  16. @Remy Lebeau

    I upgraded to a new server (Win2008 to Win2019) and now I'm getting the same issue (trying to send eMail via Amazon SES).

     

    This is inside an ISAPI 32bit dll that worked just fine when running under Windows 2008, but fails to send email when running under Windows 2019.

    I literally use the same code, same DLLs as the Win2008 machine, all DLLs (my DLL & SSL) are 32bit, everything else in the code works fine except for sending eMail using TLS (SSL).

    Inside IIS's application pool, the DLL is defined as 32bit, classic and "no managed code".

     

    When calling "smtp.send" (TIdSMTP), I get the following exception and additional info:

    
    3/22/2020 10:00:49 AM [       11854 ms] : SMTP Send Exception : SSL negotiation failed.
    
    3/22/2020 10:00:49 AM [       11854 ms] : Inner Exception : Could not load SSL library.
    3/22/2020 10:00:49 AM [       11855 ms] : WhichFailedToLoad : "Failed to load libeay32.dll."
    
    

     

    The DLLs are in the same folder as the ISAPI DLL, I also tried placing them in the Windows/System32 folder but it made no difference.

    Both "libeay32.dll" and "ssleay32.dll" are v1.0.2.19 and I'm using Delphi 10.3.3.

     

×