Jump to content

struct as object's argument, DllStructGetData @error=3


Recommended Posts

I have a Direct Show object with a method that needs two structs as arguments, defined as:

HRESULT GetStreamCaps(
  [in]   int iIndex,
  [out]  AM_MEDIA_TYPE **pmt,
  [out]  BYTE *pSCC
);          [i]pmt[/i] [out]            
Address of a pointer to an AM_MEDIA_TYPE structure. The method allocates the structure and fills it with a media type.

'GetStreamCaps hresult(int;ptr*;struct*);'

so, it has to give me as 2° argument a pointer to a struct AM_MEDIA_TYPE filled with some media samples

the 3° arg: I should receive a struct VIDEO_STREAM_CONFIG_CAPS that it has filled with info of video image.

The important struct is the AM_MEDIA_TYPE and it's the one I don't get... while the VIDEO_STREAM_CONFIG is correctly filled after I pass the pointer to it.

The c++ part of code I use (and it works well) is:

VIDEO_STREAM_CONFIG_CAPS scc;
      AM_MEDIA_TYPE *pmtConfig;
      hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
            
      if (SUCCEEDED(hr))
      {
       /* Examine the format, and possibly use it. */
       if ((pmtConfig->formattype == FORMAT_VideoInfo) &&
        (pmtConfig->pbFormat != NULL))
       {
        VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
        BITMAPINFOHEADER *bmiHeader = &pVIH->bmiHeader;
       ....

So, I get pbFormat.

Instead in autoit I made:

(I insert in the two structs the plain text of the other two GUID and SIZE, as I don't know how to construct nested struct to pass them to the method. with the VIDEO_STREAM worked.)

Local $_GUID = "DWORD Data1;" & _
              "WORD  Data2;" & _
              "WORD  Data3;" & _
              "BYTE  Data4[8];"

            Local $_SIZE = "LONG cx;" & _
              "LONG cy;"

         Local $_VIDEO_STREAM_CONFIG_CAPS = $_GUID & _
              "ULONG    VideoStandard;" & _
              $_SIZE & _
              $_SIZE & _
              $_SIZE & _
              "int    CropGranularityX;" & _
              "int    CropGranularityY;" & _
              "int    CropAlignX;" & _
              "int    CropAlignY;" & _
              $_SIZE & _
            $_SIZE & _
              "int    OutputGranularityX;" & _
              "int    OutputGranularityY;" & _
              "int    StretchTapsX;" & _
              "int    StretchTapsY;" & _
              "int    ShrinkTapsX;" & _
              "int    ShrinkTapsY;" & _
              "int64     MinFrameInterval;" & _
              "int64     MaxFrameInterval;" & _
              "LONG  MinBitsPerSecond;" & _
              "LONG  MaxBitsPerSecond;"
     Local $tVideoStream = DllStructCreate($_VIDEO_STREAM_CONFIG_CAPS)

     Local $_AM_MEDIA =   $_GUID & _
          $_GUID  & _
          'BOOL  bFixedSizeSamples;' & _
          'BOOL  bTemporalCompression;' & _
          'ULONG    lSampleSize;' & _
          $_GUID & _
          'ptr pUnk;' & _
          'ULONG    cbFormat;' & _
          'BYTE  pbFormat;'
     Local $t_AM_MEDIA = DllStructCreate($_AM_MEDIA)

       local $pmtConfig= DllStructGetPtr($t_AM_MEDIA) , $scc= DllStructGetPtr($tVideoStream)
      $oStreamConfig.GetStreamCaps($iFormat, $pmtConfig, $scc);

      ConsoleWrite(DllStructGetData($t_AM_MEDIA, 0 ,$pmtConfig) & @crlf)

The DllStructGetData sets @error at '3 = index would be outside of the struct.'

What should I do ?

Link to comment
Share on other sites

The second argument receives a pointer to a struct. I think It should be something like this:

Local $pmtConfig
$oStreamConfig.GetStreamCaps($iFormat, $pmtConfig, $scc);
$t_AM_MEDIA_TYPE = DLLStructCreate($AM_MEDIA_TYPE, $pmtConfig)

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

I have some other problems:

The last value of AM_MEDIA_TYPE should be the pointer pbFormat that is a ptr to a struct VIDEOINFOHEADER that has other struct inside:

typedef struct tagVIDEOINFOHEADER {
  RECT           rcSource;
  RECT           rcTarget;
  DWORD         dwBitRate;
  DWORD         dwBitErrorRate;
  REFERENCE_TIME   AvgTimePerFrame;
  BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER;
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;
  LONG  biWidth;
  LONG  biHeight;
  WORD  biPlanes;
  WORD  biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG  biXPelsPerMeter;
  LONG  biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER;

So in autoit:

local $_RECT = 'LONG left;' & _
  'LONG top;' & _
  'LONG right;' & _
  'LONG bottom;'

Local $_tagBITMAPINFOHEADER = 'DWORD biSize;' & _
  'LONG  biWidth;' & _
  'LONG  biHeight;' & _
  'WORD  biPlanes;' & _
  'WORD  biBitCount;' & _
  'DWORD biCompression;' & _
  'DWORD biSizeImage;' & _
  'LONG  biXPelsPerMeter;' & _
  'LONG  biYPelsPerMeter;' & _
  'DWORD biClrUsed;' & _
  'DWORD biClrImportant;'

Local $_tagVIDEOINFOHEADER = $_RECT & _
  $_RECT & _
  'DWORD            dwBitRate;' & _
  'DWORD            dwBitErrorRate;' & _
  'int64   AvgTimePerFrame;' & _
  $_tagBITMAPINFOHEADER


Local $ptr = _MemGlobalAlloc(DllStructGetData($t_AM_MEDIA_TYPE,"pbFormat"))
Local $t_VIDEOINFOHEADER = DLLStructCreate($_tagVIDEOINFOHEADER, $ptr )

for $b =1 to 23
ConsoleWrite(DllStructGetData($t_VIDEOINFOHEADER,$b) & '  VIDEOINFOHEADER index='& $b  &' err:'&@error& @CRLF)
Next

I make MemGlobal Alloc on pbFormat, because it says:

"The pbFormat buffer must be allocated by calling CoTaskMemAlloc. To release the format block, call FreeMediaType."

But the VIDEOINFOHEADER is filled randomly, both in index and contents: this example only from index 14 up to 22°:

AM_MEDIA_TYPE struct:
1935960438   index=1 err:0
0   index=2 err:0
16   index=3 err:0
0x800000AA00389B71   index=4 err:0
844715353   index=5 err:0
0   index=6 err:0
16   index=7 err:0
0x800000AA00389B71   index=8 err:0
1   index=9 err:0
0   index=10 err:0
614400   index=11 err:0
89694080   index=12 err:0
50006   index=13 err:0
4558   index=14 err:0
0xBF0100AA0055595A   index=15 err:0
0x00000000   index=16 err:0
88   index=17 err:0
56   index=18 err:0  ; this corresponds to pbFormat

VIDEOINFOHEADER struct:
0  VIDEOINFOHEADER index=1 err:0
0  VIDEOINFOHEADER index=2 err:0
0  VIDEOINFOHEADER index=3 err:0
0  VIDEOINFOHEADER index=4 err:0
0  VIDEOINFOHEADER index=5 err:0
0  VIDEOINFOHEADER index=6 err:0
0  VIDEOINFOHEADER index=7 err:0
0  VIDEOINFOHEADER index=8 err:0
0  VIDEOINFOHEADER index=9 err:0
0  VIDEOINFOHEADER index=10 err:0
0  VIDEOINFOHEADER index=11 err:0
0  VIDEOINFOHEADER index=12 err:0
0  VIDEOINFOHEADER index=13 err:0
-953830003  VIDEOINFOHEADER index=14 err:0
46477  VIDEOINFOHEADER index=15 err:0
50981  VIDEOINFOHEADER index=16 err:0
3477847172  VIDEOINFOHEADER index=17 err:0
1692276246  VIDEOINFOHEADER index=18 err:0
1693178670  VIDEOINFOHEADER index=19 err:0
1686509102  VIDEOINFOHEADER index=20 err:0
1686509102  VIDEOINFOHEADER index=21 err:0
3090988164  VIDEOINFOHEADER index=22 err:0

while I expect for example 640 on 'biwidth' element that should correspond to index 13° and '480' on the 14°.

Edited by frank10
Link to comment
Share on other sites

The data should already been allocated.

Local $_AM_MEDIA =   $_GUID & _
          $_GUID  & _
          'BOOL  bFixedSizeSamples;' & _
          'BOOL  bTemporalCompression;' & _
          'ULONG    lSampleSize;' & _
          $_GUID & _
          'ptr pUnk;' & _
          'ULONG    cbFormat;' & _
          'ptr  pbFormat;' ;<-- !!!

...
$pbFormat = DLLStructGetData($t_AM_MEDIA, "pbFormat")
$tFormat = DLLStructCreate(..., $pbFormat)


... PSEUDOCODE for freeing:
CoTaskMemFree($pbFormat);
$pUnk = DLLStructGetData($t_AM_MEDIA, "pUnk")
If $pUnk Then IUnknown_Release($pUnk)
$pAM_MEDIA = DLLStructGetPtr($t_AM_MEDIA)
$t_AM_MEDIA = 0
CoTaskMemFree($pAM_MEDIA);

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

"BYTE *" states, that it is a pointer to a byte / an array of bytes. Since AutoIt does not support typed pointers, use "ptr"

and in the description they say: The pbFormat buffer must be allocated by calling CoTaskMemAlloc

That is if you create the structure yourself. You just want to read an already existing one. Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...