Jump to content

ioan

Members
  • Content Count

    72
  • Joined

  • Last visited

  • Days Won

    3

Posts posted by ioan


  1. 4 hours ago, Remy Lebeau said:

    Seems like a waste of effort to port the C code twice to two separate and unrelated languages.

    Well, I agree with you, but, for me, before I start to put effort into porting it to BrightScript I want to make sure it works on Delphi, where I can debug it and change the var types and structures to whatever is supported in BrightScript. Of course, this could be done directly in C, but I'm way more comfortable with Delphi... so I prefer to work twice just so I'm comfortable.

     

    Quote

    Some Roku devices already support H.264.  And there are some existing 3rd party solutions for streaming RTSP to Roku.

    Roku supports H.264, but not from a RTSP stream. The only RTSP that's available on Roku right now, as far as I know, it's in IP Camera Viewer, which is made by me and I had to implement RTSP by myself. Right now it only supports jpeg encoded RTSP streams (ONVIF compliant IP cameras must provide a JPEG encoded RTSP stream, but surprise, not all of them do).

     

    The only H.264 streaming Roku supports is HLS. Of course, it can play .mp4 and .ts files and the .ts files can be mp4 format. It cannot play raw h264 stream even if it's saved in a file.

    The RTSP part is identical for JPEG encoded streams and H.264 encoded streams. I also already implemented the capture of the raw h264 stream and now I'm trying to convert, on the fly, to mp4 (.ts) so Roku can play it as HLS. I won't even save the .ts as files. When Roku ask for the next chunk, I'll just serve the next buffered chunk I have. Of course, that means I have to have a webserver running on Roku... I have one in my application to provide an easier way to config the application and backup, but I'm not sure yet if it's performant enough to be able to serve hls.

     

    Majority of cheap Chinese IP cameras that people buy advertise as ONVIF compliant but provide only H264 stream. I receive emails daily from people asking why their camera doesn't work with my application. I got sick of answering so I'm trying to fix the problem. Now, if I'll be successful, I don't know. But I'll frustrate myself trying, that's for sure. Beats answering the same email every day.

     

     


  2. 8 hours ago, David Heffernan said:

    That's not a problem with the Delphi side of things, that would be a basic design flaw of the library.  If the consumer of the library has to call functions that it can't access, in order to use the library, then the library is unusable.

     

    You are better off not to speculate and guess like this. If the asker has a question, trust them to ask it.

    I created the dll myself from source code I got from github (https://github.com/aspt/mp4) and I modified the C source to open the file inside the dll, I just have to provide the name. The problem was that one of the struct that I needed to use to access the library had a FILE * member, where the handle to the opened file is stored. I got everything working late last night. 

     

    Off topic: Now the hard part starts. I want to use this code on a Roku media player, but the problem is that to develop on Roku you have to use a scripting language called BrightScript. My plan is to convert the C code to Delphi and in the same time to understand the code, and then port it to BrightScript. My pet project is to get rtsp/h264 working on Roku.


  3. 59 minutes ago, Remy Lebeau said:

    The C code is likely using a FILE* stream to read/write MP4E_track_t data from/to a media file on disk.  In Delphi, you can use TFileStream for that same purpose.

    Yeah, I would probably convert the code to Delphi, but for now, for testing, I just need to convert some structs and one of them has a FILE * member:

     

    typedef struct MP4E_mux_tag
    {
        asp_vector_t tracks;            // mp4 file tracks
        FILE * mp4file;                 // output file handle
        mp4e_size_t write_pos;          // ## of bytes written ~ current file position (until 1st fseek)
        char * text_comment;            // application-supplied file comment
        int enable_fragmentation;         // flag, indicating streaming-friendly 'fragmentation' mode
        int fragments_count;            // # of fragments in 'fragmentation' mode
    } MP4E_mux_t;

     


  4. 16 minutes ago, David Heffernan said:

    You missed the language member. And probably the enum is actually an int and so 4 bytes. 

    Thank you for pointing the missed language member. 

     

    About the enum, not sure what do you mean. How should it look like? Should I change like this? 

    track_media_kind: integer;

  5.  

    Does this C struct conversion to Delphi looks right to you? 

     

    From C

     

    typedef struct
    {
        unsigned object_type_indication;
        unsigned char language[4];
        enum
        {
            e_audio,
            e_video,
            e_private
        } track_media_kind;
        unsigned time_scale;
        unsigned default_duration;
        union
        {
            struct  
            {
                unsigned channelcount;
            } a;
    
            struct 
            {
                int width;
                int height;
            } v;
        } u;
    } MP4E_track_t;

     

    to Delphi:

    type
      track_media_kind_enum = (e_audio, e_video, e_private);
    
    type
      MP4E_track_t = record
        object_type_indication: LongWord;
        track_media_kind: track_media_kind_enum;
        time_scale: LongWord;
        default_duration: LongWord;
        case integer of
           0: (
                channelcount: LongWord
              );
           1: (
                width: Integer;
                height: Integer;
              );
      end;

    TIA


  6. I'm using TTrayIcon to show notifications and I would like to change the notification title(?) from exe's name to my custom string (circled in the attached picture). Is it possible?

     

    This is my code to show the notification:

     

    procedure TfrmQueue.ShowMyNotification(ATitle, ABody: string);
    begin
      TrayIcon.BalloonTimeout := 3000;
      TrayIcon.BalloonTitle := ATitle;
      TrayIcon.BalloonHint := ABody;
      TrayIcon.ShowBalloonHint;
    end;

     

    notification.png


  7. I'm trying to use Vcl.Graphics.TWICImage on a Windows Server 2012 R2 and the following exception thrown:

    EInvalidGraphicOperation: Cannot create instance of class CLSID_WICImagingFactory (800401F0)

    Anyone knows the reason? On my development machine with Windows 10 Pro works fine.

     

    Oops, never mind, it seems that I forgot CoInitialize/CoUninitialize


  8. Well, I found the problem... I had to save to file the stream Data, not the original WicImage. Also, I had to keep the width/height as the original:

     

    uses
      avconst,
      activex, varutils, wincodec, consts;
    
    procedure ChangeTiffCompression(tiffFilename: string; tiffNewFileName: string);
    var
      Encoder: IWICBitmapEncoder;
      Frame: IWICBitmapFrameEncode;
      Props: IPropertyBag2;
      LStreamAdapter: IStream;
      PixelFormat: TGUID;
      LStream: IWICStream;
      Palette: IWICPalette;
      Data: TMemoryStream;
      ImagingFactory: IWICImagingFactory;
      WicImage: TWICImage;
      Options: TPropBag2;
      varValue: TPropVariant;
      hr: HRESULT;
    begin
        Data := TMemoryStream.Create;
        WicImage := TWICImage.Create;
        try
          WicImage.LoadFromFile(tiffFilename);
    
          Data.Clear;
          LStreamAdapter := TStreamAdapter.Create(Data);
    
          ImagingFactory := TWICImage.ImagingFactory;
          ImagingFactory.CreateStream(LStream);
          LStream.InitializeFromIStream(LStreamAdapter);
          ImagingFactory.CreateEncoder(WicImage.EncoderContainerFormat, guid_null, Encoder);
    
          Encoder.Initialize(LStream, WICBitmapEncoderNoCache);
          Encoder.CreateNewFrame(Frame, Props);
          FillChar(Options, SizeOf(Options), 0);
          Options.pstrName :=  POleStr('TiffCompressionMethod');
          varValue.vt := VT_UI1;
          varValue.bVal := WICTiffCompressionCCITT3;
          hr := Props.Write(1, @Options, @varValue);
          if not SUCCEEDED(hr) then
            raise Exception.Create('Error Props.Write');
    
          hr := Frame.Initialize(Props);
          if not SUCCEEDED(hr) then
            raise Exception.Create('Error Frame.Initialize');
    
          WicImage.Handle.GetPixelFormat(PixelFormat);
          Frame.SetPixelFormat(PixelFormat);
    
          Frame.SetSize(WicImage.Width, WicImage.Height);
    
          ImagingFactory.CreatePalette(Palette);
          WicImage.Handle.CopyPalette(Palette);
          Frame.SetPalette(Palette);
          Frame.WriteSource(WicImage.Handle, nil);
          Frame.Commit;
          Encoder.Commit;
    
          Data.Position := 0;
          Data.SaveToFile(tiffNewFileName);
        finally
          Encoder := nil;
          ImagingFactory := nil;
          Data.Free;
          WicImage.Free;
        end;
    end;

     


  9. I advanced a little with this puzzle, but still the compression method is not changed in the new created tiff. I used this example from Windows documentation:

    https://docs.microsoft.com/en-us/windows/win32/wic/-wic-creating-encoder?redirectedfrom=MSDN#tiff-encoding-example

     

    Also, I used as a starting point the procedure TWICImage.SaveToStream(Stream: TStream); from unit Vcl.Graphics;

     

    The procedure bellow creates a new tiff, but the compression method is the same as the old tiff.  Any idea how to do this right?

     

    uses
      avconst,
      activex, varutils, wincodec, consts;
    
    const
      FAX_WIDTH = 1728;
      FAX_HEIGHT = 2150;
    
    procedure ChangeTiffCompression(tiffFilename: string; tiffNewFileName: string);
    var
      Encoder: IWICBitmapEncoder;
      Frame: IWICBitmapFrameEncode;
      Props: IPropertyBag2;
      LStreamAdapter: IStream;
      PixelFormat: TGUID;
      LStream: IWICStream;
      Palette: IWICPalette;
      Data: TMemoryStream;
      ImagingFactory: IWICImagingFactory;
      WicBitmap: TWICImage;
      Options: TPropBag2;
      varValue: TPropVariant;
    begin
        Data := TMemoryStream.Create;
        WicBitmap := TWICImage.Create;
        try
          WicBitmap.LoadFromFile(tiffFilename);
          LStreamAdapter := TStreamAdapter.Create(Data);
    
          ImagingFactory := TWICImage.ImagingFactory;
          ImagingFactory.CreateStream(LStream);
          LStream.InitializeFromIStream(LStreamAdapter);
          ImagingFactory.CreateEncoder(GUID_ContainerFormatTiff, guid_null, Encoder);
    
          Encoder.Initialize(LStream, WICBitmapEncoderNoCache);
          Encoder.CreateNewFrame(Frame, Props);
          
          FillChar(Options, SizeOf(Options), 0);
          Options.pstrName :=  POleStr('TiffCompressionMethod');
          varValue.vt := VT_UI1;
          varValue.bVal := WICTiffCompressionCCITT3;
          Props.Write(1, @Options, @varValue);
    
          Frame.Initialize(Props);
    
          WicBitmap.Handle.GetPixelFormat(PixelFormat);
          Frame.SetPixelFormat(PixelFormat);
    
          Frame.SetSize(FAX_WIDTH, FAX_HEIGHT);
    
          ImagingFactory.CreatePalette(Palette);
          WicBitmap.Handle.CopyPalette(Palette);
          Frame.SetPalette(Palette);
          Frame.WriteSource(WicBitmap.Handle, nil);
          Frame.Commit;
          Encoder.Commit;
          WicBitmap.SaveToFile(tiffNewFileName);
          Encoder := nil;
          ImagingFactory := nil;
        finally
          Data.Free;
          WicBitmap.Free;
        end;
    end;

     


  10. I'm want to change the compression for a tiff file and I can't find any way to do it. I searched all the code samples from Microsoft, everything I found in Delphi, but no luck.

     

    I don't have much to show, everything I tried failed. Here is my code, any idea how to do this?

     

    procedure ChangeTiffCompression(tiffFilename: string; tiffNewFileName: string);
    var
      Source : TWICImage;
      Factory: IWICImagingFactory;
      Encoder: IWICBitmapEncoder;
    begin
      Source:= TWICImage.Create;
      try
        Source.LoadFromFile(tiffFilename);
        Factory := TWICImage.ImagingFactory;
        Factory.CreateEncoder(CLSID_WICTiffEncoder, guid_null, Encoder);
        // black magic here....
        // and set compression to WICTiffCompressionCCITT3
        // ?????
        Source.Handle := IWICBitmap(Encoder);
        Source.SaveToFile(tiffNewFileName);
        Encoder := nil;
        Factory := nil;
      finally
        Source.Free;
      end;
    end;

     


  11. After installing 10.4.1 it seems that "Right click -> Find Declaration" in the source code doesn't find the declaration most of the time. It seems that if I open the source where the the function or object is declared, it finds it, but most of the time it fails. You can see in the screenshot that "Declared in..." it's empty when I hover over TFaxPrepareTh. Does any of you have this problem also? 

     

     image.thumb.png.aad4ea9f15628cc1e6cdb99b5bc60c6b.png


  12. Today, I have no idea why, every time I try to open pas file from the current project the IDE closes itself. Same if I try to open another project. This only started happening constantly today, to the point that I practically can't use it. Yesterday and the days before, I saw it happen few times, but I thought "oh well, it's almost normal to have the Delphi IDE crash from time to time". Today it got so bad and rebooting the system doesn't fix the problem.

     

    Have any of you see the same problem? Any fix? I will try to uninstall Patch 3, but it was installed when it came out, and this problem started only few days ago and now it got to the point of being unable to use it.

     

×