• Welcome to Jose's Read Only Forum 2023.
 

FreeBASIC Movie Control

Started by Juergen Kuehlwein, June 22, 2018, 06:25:36 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Juergen Kuehlwein

Hi José,


again i need your help...


Trying to port a movie control for PowerBASIC to FreeBASIC i run into (maybe COM related) problems i don´t understand. Attached is my sample code, which is reduced in size removing all unnecessary things but still demonstrating my problems.

Based on code i found in your WinFBX and a movie example for FreeBASIC it wasn´t to hard to get it running in 32 bit and unicode defined. But if i don´t define unicode in 32 bit, the GraphBuilder object isn´ created, the app shows random behavior and sometimes crashes (in user32.dll or ntdll.dll). For 64 bit the GraphBuilder object is created regardless if unicode is defined or not, but the movie doesn´t run and the app doesn´t end gracefully, it gets stuck when releasing the objects in "resetmovie". 

What am i doing wrong ?


Thanks


JK

José Roca

Sorry, but I don't find where is the problem. Sometimes works and sometimes don't, but it doesn't fail consistently in the same place.

Juergen Kuehlwein

Quotebut it doesn't fail consistently in the same place


that´s exactly what i experience too! The general approach seems to be sound, because it´s PB equivalent works. I have several implementations of it running for years now without any problem.

This erratic behavior makes me think of memory corruption - but how and where? In PB i don´t have to initialize the common controls and i don´t have to call coinitialize because PB does it for me, the rest is more or less the same. To my (limited) experience COM seems to be much more sensitive to improper arguments compared to the Windows API. That is, it is much easier to crash an app by passing wrong arguments to a COM object than to the Windows API (even if it is possible there too).

With unicode defined it runs for 32 bit, as soon as you don´t define it, the problems begin. COM needs wide strings, i account for this. Maybe a problem with the include files ?

The FreeBASIC sample code (examples\win32\COM\MoviePlayer) doesn´t compile, it throws a linker error i don´t understand, so no help either...


So as far as you can tell, there isn´t a fundamental error in my implementation of COM in my code ?   


JK

José Roca

I translated my PowerBasic example to FreeBasic and it worked fine:

http://www.planetsquires.com/protect/forum/index.php?topic=4023.msg30348#msg30348

although for the moment it can't be recompiled because of bugs in windowsx.bi.

The only problem that I remember was that I had to use

hr = pIMediaControl->lpvtbl->RenderFile(pIMediaControl, @wszFileName)

instead of the RenderFile method of the IGraphBuilder interface.

Pierre Bellisle

hr = IGraphBuilder_RenderFile(c->pIGraphBuilder, @wtext, NULL)

Juergen Kuehlwein

Hey Pierre,


RenderFile is possible in IGraphBuilder and in IMediaControl - both work (32 bit unicode defined), Changing the syntax to "->lpvtbl->..." all over the code, doesn´t help either.


José,


thanks for the code - how could i make it compile? I see you added your own windowsxx.bi (as a replacement ?)


JK

José Roca

You need to change #include windowsx.bi to #include windowsxx.bi in the FB includes that use it.

Juergen Kuehlwein

José


fortunately windowsx.bi is only included one time. After changing it in dshow.bi to afx\windowsxx.bi your code runs like a charm in 32 bit and 64 bit regardless, if unicode is defined or not! Taking a closer look you can get rid of dshow.bi at all by replacing 3 constants (oatrue, oafalse, ec_complete) with their values or redefining them in your code.

That arises the question, where is the difference making my code fail? At least i now have some working code i can start with.


Thanks,


JK

José Roca

#8
Regardless of if UNICODE is defined or not, I always use unicode in my code by explicitily calling the "W" functions. I think that using ansi GUI's is a useless complication.

Since I wrote the code, I changed the AfxSafeRelease function to set the passed pointer to null. Therefore, pIMediaControl = NULL, etc., are no longer needed.

I advice you of always specify BYVAL or BYREF with the parameters. Otherwise, the compiler will fail to compile and report errors when using an switch like -w pedantic. Reusable code must be written to work with all the available compiler preferences.

I would suggest to use wce.cbWndExtra = SIZEOF(HANDLE) instead of wce.cbWndExtra = 8. This way, cbWndExtra will be 4 bits with 32-bit and 8 bits with 64 bits.

Beware of using UINTEGER or INTEGER with variables that alwyas should be DWORD or LONG.


DIM wstyle    as UINTEGER
DIM xstyle    as UINTEGER
DIM fixedsize as UINTEGER
DIM wflag     as UINTEGER
DIM hflag     as UINTEGER
DIM cx        AS uinteger                             'x
DIM cy        AS uinteger                             'y
DIM p         AS uinteger                             'percentage
DIM w         AS uinteger                             'width
DIM h         AS uinteger                             'height


I never use them. Because they don't behave like in C++, it can lead to confussions and mistakes when traslating code.

Juergen Kuehlwein

José,


i got it! I was so close and i was so blind, there were more than enough clues - memory corruption due improper allocation of control´s private data.


Translating from PB to PB i made a fatal error, it must be:

c = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SIZEOF(movie_data))      'allocate memory for data



In FB "sizeof(@c)" returns the size of a pointer, in PB it returns the the size of the type the pointer points to...


JK

José Roca

#10
I'm glad you have find it. The symptoms of memory corruption were clear. I remember that I once had this kind of problem because FB uses * to deference pointers, unlike PB that uses @. In FB, @ is equivalent to VARPTR.

Anyway, please read my above recommendations. Your code will be more solid and reusable. Currently I need to change my settings in WinFBE if I want to compile your code.

BTW I'm currently making an small modification to CWSTR.inc and CVAR.inc, consisting in changing BYREF AS WSTRING to BYREF AS CONST WSTRING. Without the CONST typifier, if you pass a CWSTR to a function that has a WSTRING or WSTRING PTR as the parameter, you can indirectly modify the passed CWSTR by modyfing the parameter, which can lead to a buffer overrun, e.g.


' // This will modify the passed WSTRING
SUB Foo (BYREF x AS WSTRING)
   x = "some text"
   ...
END SUB


You can also use


SUB Foo (BYREF x AS CONST WSTRING)
   DIM cws AS CWSTR = x
   cws = "some text"
   ...
END SUB

Juergen Kuehlwein

Hi José,


are you done with your changes ?


Quote
consisting in changing BYREF AS WSTRING to BYREF AS CONST WSTRING


did you change it in all places or only in special places ?


Thanks


JK

José Roca

#12
No changes are needed in my code because I don't have any procedure that modifies directly the passed wstring.

Just be aware of it and use CWSTR if you intend to modify it or CONST AS WSTRING if you don't want to accidentally modify it. No changes are needed if your code does not modify the string.

José Roca

#13
This is not a problem related to CWSTR only. It will happen the same if you pas a WSTRING, e.g.


SUB Foo (BYREF x AS WSTRING)
   x = "some text"
END SUB

DIM ws AS WSTRING * 260 = "Test string"
Foo ws
print ws


No problem if the assignment is shorter than the length of the string, but you will get a buffer overrun if it is bigger.

Juergen Kuehlwein