ioan 45 Posted January 6, 2021 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
David Heffernan 2345 Posted January 6, 2021 You missed the language member. And probably the enum is actually an int and so 4 bytes. 1 Share this post Link to post
ioan 45 Posted January 6, 2021 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
David Heffernan 2345 Posted January 7, 2021 Leave it as an enum, but set the right enum size http://docwiki.embarcadero.com/RADStudio/Sydney/en/Minimum_enumeration_size_(Delphi) 2 Share this post Link to post
Remy Lebeau 1394 Posted January 7, 2021 (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 January 7, 2021 by Remy Lebeau 1 Share this post Link to post
FPiette 383 Posted January 7, 2021 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
David Heffernan 2345 Posted January 7, 2021 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
Remy Lebeau 1394 Posted January 7, 2021 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
ioan 45 Posted January 7, 2021 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
David Heffernan 2345 Posted January 7, 2021 Then an untyped pointer will do. 1 Share this post Link to post
FPiette 383 Posted January 8, 2021 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
David Heffernan 2345 Posted January 8, 2021 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
FPiette 383 Posted January 8, 2021 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
Pat Foley 51 Posted January 8, 2021 (edited) On the Gary Darby site http://delphiforfun.org/Programs/oscilloscope.htm said "I cleaned up a few things ... using Windows wavein API multistep protocol" It is a fantastic straddle. Edited January 8, 2021 by Pat Foley hyperlink Share this post Link to post
David Heffernan 2345 Posted January 8, 2021 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
ioan 45 Posted January 8, 2021 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
Remy Lebeau 1394 Posted January 8, 2021 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
ioan 45 Posted January 8, 2021 (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 January 9, 2021 by ioan I a word Share this post Link to post