Jump to content
ioan

Converting C struct to Delphi

Recommended Posts

 

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

Share this post


Link to post
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;

Share this post


Link to post
Posted (edited)
17 hours ago, ioan said:

Thank you for pointing the missed language member. 

The language member is an 'unsigned char' array on the C side, so make sure you use an AnsiChar array, or better a Byte array, on the Delphi side.  Don't mistakenly use a (Wide)Char array:

language: array[0..3] of AnsiChar;

or

language: array[0..3] of Byte;
Quote

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


track_media_kind: integer;

You could do it that way, yes (I would suggest (U)Int32 or DWORD instead).  Or, you could use {$MINENUMSIZE 4} like David suggested.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

Is 'FILE *' equivalent to THandle?

Share this post


Link to post
8 minutes ago, ioan said:

Is 'FILE *' equivalent to THandle?

It isn't. FILE * is a high level item to access a file. A THandle is a low level item.

Around FILE * there are a number of C standard I/O routines.

Share this post


Link to post
50 minutes ago, ioan said:

Is 'FILE *' equivalent to THandle?

This question is only useful to you if the answer is yes. The answer is no. And you are none the wiser. What you perhaps should have asked about was the underlying reason why you are concerned with a FILE*

Share this post


Link to post
1 hour ago, David Heffernan said:

What you perhaps should have asked about was the underlying reason why you are concerned with a FILE*

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.

Share this post


Link to post
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;

 

Share this post


Link to post
10 hours ago, ioan said:

I just need to convert some structs and one of them has a FILE * member

If this member is just transported between the DLL and your application back and forth, then in Delphi you can declare it as pointer. But if the Delphi application has to open the file or otherwise access it, it will be very difficult to port to Delphi. Exact implementation of FILE * is compiler dependent. So you must know which compiler has been used.

Share this post


Link to post
27 minutes ago, FPiette said:

But if the Delphi application has to open the file or otherwise access it, it will be very difficult to port to Delphi.

Not really. You still declare it as a pointer and call the library function to open the file, and a pointer is returned. Only the library needs to know the implementation. It's a pointer to an opaque struct. 

Share this post


Link to post
32 minutes ago, David Heffernan said:

Not really. You still declare it as a pointer and call the library function to open the file, and a pointer is returned. Only the library needs to know the implementation. It's a pointer to an opaque struct. 

Sure it is. It is likely that the DLL the OP want to use do not come with library routine such as fopen() are not made available.

As I said, if the Delphi code has just to transport the FILE * member (that is the DLL open, read, write and close the FILE *), there will be no problem. If the Delphi code has to open the file and provide a FILE * that will be problematic.

 

Share this post


Link to post
10 minutes ago, FPiette said:

Sure it is. It is likely that the DLL the OP want to use do not come with library routine such as fopen() are not made available.

As I said, if the Delphi code has just to transport the FILE * member (that is the DLL open, read, write and close the FILE *), there will be no problem. If the Delphi code has to open the file and provide a FILE * that will be problematic.

 

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.

Share this post


Link to post
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.

Share this post


Link to post
3 hours ago, ioan said:

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.

Then the C struct should use an untyped pointer to begin with.  Since the EXE can't make use of the pointer anyway, it is just for the DLL's private use.  So the DLL can open a file and store the FILE* (or whatever) in the pointer, then cast it back when needing to access the file again.  The EXE shouldn't have any knowledge about HOW the DLL accesses the file.

3 hours ago, ioan said:

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.

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

3 hours ago, ioan said:

My pet project is to get rtsp/h264 working on Roku.

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

Share this post


Link to post
Posted (edited)
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.

 

 

Edited by ioan
I a word

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×