PC Review


Reply
Thread Tools Rate Thread

Acessing pointers from capSetCallbackOnFrame (avicap32.dll)

 
 
Workgroups
Guest
Posts: n/a
 
      12th Aug 2005
I'm writing a piece of video software, sort of like a webcam, that's meant
to show a preview on the screen from any WDM capable cam. I want to give
the user RGB sliders, and process each frame by running it through a color
matrix before it's displayed on the screen.

So far I've succesfully created a preview window and established a
capSetCallbackOnFrame callback function that fires every time a new frame of
video is available from the camera. So now I need to copy the video buffer
(image) I vicariously receive a pointer to in the callback function into an
image, transform the image's color w/ a color matrix and then paint the
colorized image to some control (like a picturebox, probably).

But I'm stumped when it comes to "doing something" with the data that's
coming back from capSetCallbackOnFrame. It's a pointer to a structure, and
one of the elements of the structure contains the pointer to the video
buffer. The documentation for this is really hard to come by, although
there is a popular VB6 example of this floating around that I've been using
for a guide that looks like this:

Function MyFrameCallback(ByVal lwnd As Long, ByVal lpVHdr As Long) As Long

Dim VideoHeader As VIDEOHDR
Dim VideoData() As Byte

RtlMoveMemory VarPtr(VideoHeader), lpVHdr, Len(VideoHeader)
ReDim VideoData(VideoHeader.dwBytesUsed)
RtlMoveMemory VarPtr(VideoData(0)), VideoHeader.lpData,
VideoHeader.dwBytesUsed

End Function

The VIDEOHDR structure looks like this:

Type VIDEOHDR
lpData As Long 'address of video buffer
dwBufferLength As Long 'size, in bytes, of the Data buffer
dwBytesUsed As Long
dwTimeCaptured As Long
dwUser As Long
dwFlags As Long
dwReserved(3) As Long '// reserved; do not use
End Type

I've tried to reporduce this in .NET but I haven't been too successful so
far... I've tried to use Marshal.Copy and Marshal.PtrToStructure, to copy
the data referenced at lpVHdr into it's appropriate structure format on the
managed side, but I don't think I'm doing it right; my structure ends up
with what I'm pretty sure is erroneous data; all the values are 0 except
for dwFlags = 64, so... "something" is getting copied in there but it's not
correct. I am at a loss as to how to get that video buffer turned into an
image object.


 
Reply With Quote
 
 
 
 
Ken Tucker [MVP]
Guest
Posts: n/a
 
      12th Aug 2005
Hi,

capCreateCaptureWindow will display the incoming video for you. Here
is an link to an example.

http://www.windowsformsdatagridhelp....6-e5cf2ebb86b6

Ken
--------------------------
"Workgroups" <(E-Mail Removed)> wrote in message
news:cKidnWgPNvYWhWHfRVn-(E-Mail Removed)...
I'm writing a piece of video software, sort of like a webcam, that's meant
to show a preview on the screen from any WDM capable cam. I want to give
the user RGB sliders, and process each frame by running it through a color
matrix before it's displayed on the screen.

So far I've succesfully created a preview window and established a
capSetCallbackOnFrame callback function that fires every time a new frame of
video is available from the camera. So now I need to copy the video buffer
(image) I vicariously receive a pointer to in the callback function into an
image, transform the image's color w/ a color matrix and then paint the
colorized image to some control (like a picturebox, probably).

But I'm stumped when it comes to "doing something" with the data that's
coming back from capSetCallbackOnFrame. It's a pointer to a structure, and
one of the elements of the structure contains the pointer to the video
buffer. The documentation for this is really hard to come by, although
there is a popular VB6 example of this floating around that I've been using
for a guide that looks like this:

Function MyFrameCallback(ByVal lwnd As Long, ByVal lpVHdr As Long) As Long

Dim VideoHeader As VIDEOHDR
Dim VideoData() As Byte

RtlMoveMemory VarPtr(VideoHeader), lpVHdr, Len(VideoHeader)
ReDim VideoData(VideoHeader.dwBytesUsed)
RtlMoveMemory VarPtr(VideoData(0)), VideoHeader.lpData,
VideoHeader.dwBytesUsed

End Function

The VIDEOHDR structure looks like this:

Type VIDEOHDR
lpData As Long 'address of video buffer
dwBufferLength As Long 'size, in bytes, of the Data buffer
dwBytesUsed As Long
dwTimeCaptured As Long
dwUser As Long
dwFlags As Long
dwReserved(3) As Long '// reserved; do not use
End Type

I've tried to reporduce this in .NET but I haven't been too successful so
far... I've tried to use Marshal.Copy and Marshal.PtrToStructure, to copy
the data referenced at lpVHdr into it's appropriate structure format on the
managed side, but I don't think I'm doing it right; my structure ends up
with what I'm pretty sure is erroneous data; all the values are 0 except
for dwFlags = 64, so... "something" is getting copied in there but it's not
correct. I am at a loss as to how to get that video buffer turned into an
image object.



 
Reply With Quote
 
Workgroups
Guest
Posts: n/a
 
      12th Aug 2005
Thanks for the reply Ken. I wish my only goal were to show the preview (my
life would be easier). Thanks to that code in the link I could do that
fairly easily.

What I need to add is a way for the user to adjust R, G, B to modify the
color hue of the video preview. I have created a test app that can
successfully change the color of a normal static (non-cam) image using a
color matrix, so my idea for the cam is to capture each frame from at frame
call back, create an image object from the supplied video buffer, perform a
color matrix transformation on the image (just as I had done in my test app)
and then display the new, colorized image to a picturebox. And this would
occur on every frame callback, so essentially I take data from the raw
stream, filter it, and display my own "colorized preview window" (as it
were) in a picturebox.

I got the preview working, I got the callback "working" (well, it gets
called) but I'm hung up on the logistics of accessing the video buffer
pointer that is supposedly sent to me in a structure (VIDEOHDR) in the
callback function. I've defined the structure like this:

Public Structure VIDEOHDR
Dim lpData As IntPtr
Dim dwBufferLength As Integer
Dim dwBytesUsed As Integer
Dim dwTimeCaptured As Integer
Dim dwUser As Integer
Dim dwFlags As Integer
<VBFixedArray(3)> Dim dwReserved() As Integer
End Structure

But my values in the callback are always this:

lpData = 0
dwBufferLength = 0
dwBytesUsed = 0
dwTimeCaptured = 0
dwUser = 0
dwFlags = 64


"Ken Tucker [MVP]" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> Hi,
>
> capCreateCaptureWindow will display the incoming video for you. Here
> is an link to an example.
>
> http://www.windowsformsdatagridhelp....6-e5cf2ebb86b6
>
> Ken
> --------------------------
> "Workgroups" <(E-Mail Removed)> wrote in message
> news:cKidnWgPNvYWhWHfRVn-(E-Mail Removed)...
> I'm writing a piece of video software, sort of like a webcam, that's meant
> to show a preview on the screen from any WDM capable cam. I want to give
> the user RGB sliders, and process each frame by running it through a color
> matrix before it's displayed on the screen.
>
> So far I've succesfully created a preview window and established a
> capSetCallbackOnFrame callback function that fires every time a new frame
> of
> video is available from the camera. So now I need to copy the video
> buffer
> (image) I vicariously receive a pointer to in the callback function into
> an
> image, transform the image's color w/ a color matrix and then paint the
> colorized image to some control (like a picturebox, probably).
>
> But I'm stumped when it comes to "doing something" with the data that's
> coming back from capSetCallbackOnFrame. It's a pointer to a structure,
> and
> one of the elements of the structure contains the pointer to the video
> buffer. The documentation for this is really hard to come by, although
> there is a popular VB6 example of this floating around that I've been
> using
> for a guide that looks like this:
>
> Function MyFrameCallback(ByVal lwnd As Long, ByVal lpVHdr As Long) As Long
>
> Dim VideoHeader As VIDEOHDR
> Dim VideoData() As Byte
>
> RtlMoveMemory VarPtr(VideoHeader), lpVHdr, Len(VideoHeader)
> ReDim VideoData(VideoHeader.dwBytesUsed)
> RtlMoveMemory VarPtr(VideoData(0)), VideoHeader.lpData,
> VideoHeader.dwBytesUsed
>
> End Function
>
> The VIDEOHDR structure looks like this:
>
> Type VIDEOHDR
> lpData As Long 'address of video buffer
> dwBufferLength As Long 'size, in bytes, of the Data buffer
> dwBytesUsed As Long
> dwTimeCaptured As Long
> dwUser As Long
> dwFlags As Long
> dwReserved(3) As Long '// reserved; do not use
> End Type
>
> I've tried to reporduce this in .NET but I haven't been too successful so
> far... I've tried to use Marshal.Copy and Marshal.PtrToStructure, to copy
> the data referenced at lpVHdr into it's appropriate structure format on
> the
> managed side, but I don't think I'm doing it right; my structure ends up
> with what I'm pretty sure is erroneous data; all the values are 0 except
> for dwFlags = 64, so... "something" is getting copied in there but it's
> not
> correct. I am at a loss as to how to get that video buffer turned into an
> image object.
>
>
>



 
Reply With Quote
 
Workgroups
Guest
Posts: n/a
 
      13th Aug 2005
This was a newbie interop problem. The structure passed to my callback
function was not being populated correctly because I was initially
establishing callback by calling a mal-overloaded SendMessage in the first
place:

SendMessage (intPtr, integer, integer, intPtr) as intPtr

with this data:

(PreviewWndHandle, _
WM_CAP_SET_CALLBACK_FRAME, _
0, _
MyDelegate.Method.MethodHandle.GetFunctionPointer)

Someone in the interop ng clued me in that I should create a SendMessage
overload specific for the call:

SendMessage (intPtr, integer, intPtr, MyDelegateType)

Which now I call with similar data,

(PreviewWndHandle, _
WM_CAP_SET_CALLBACK_FRAME, _
IntPtr.Zero, _
MyDelegate)

Passing the delegate itself (instead of using the .GetFunctionPointer method
of the delegate) seems to have made the difference between my callback
function receiving valid and invalid data. Once the callback was setup
properly the structure arrived to my callback populated correctly, and I was
able to create a new managed bitmap from the unmanaged buffer, via the
pointer in the structure:

oBmp = New Bitmap(640, 480, 640 * 3, PixelFormat.Format24bppRgb,
lpVIDEOHDR.lpData)

I draw oBmp onto a 2nd bitmap with an imageAttributes containing a
colorMatrix reflecting user slider values for
r/g/b/brightness/contrast/saturation and essentially create my own
"filtered" preview window. Takes a fair amount of cpu power depending upon
preview rate of the camera, but it's doing it ;-)

"Workgroups" <(E-Mail Removed)> wrote in message
news:BLqdneQcHd8iTGHfRVn-(E-Mail Removed)...
> Thanks for the reply Ken. I wish my only goal were to show the preview
> (my life would be easier). Thanks to that code in the link I could do
> that fairly easily.
>
> What I need to add is a way for the user to adjust R, G, B to modify the
> color hue of the video preview. I have created a test app that can
> successfully change the color of a normal static (non-cam) image using a
> color matrix, so my idea for the cam is to capture each frame from at
> frame call back, create an image object from the supplied video buffer,
> perform a color matrix transformation on the image (just as I had done in
> my test app) and then display the new, colorized image to a picturebox.
> And this would occur on every frame callback, so essentially I take data
> from the raw stream, filter it, and display my own "colorized preview
> window" (as it were) in a picturebox.
>
> I got the preview working, I got the callback "working" (well, it gets
> called) but I'm hung up on the logistics of accessing the video buffer
> pointer that is supposedly sent to me in a structure (VIDEOHDR) in the
> callback function. I've defined the structure like this:
>
> Public Structure VIDEOHDR
> Dim lpData As IntPtr
> Dim dwBufferLength As Integer
> Dim dwBytesUsed As Integer
> Dim dwTimeCaptured As Integer
> Dim dwUser As Integer
> Dim dwFlags As Integer
> <VBFixedArray(3)> Dim dwReserved() As Integer
> End Structure
>
> But my values in the callback are always this:
>
> lpData = 0
> dwBufferLength = 0
> dwBytesUsed = 0
> dwTimeCaptured = 0
> dwUser = 0
> dwFlags = 64
>
>
> "Ken Tucker [MVP]" <(E-Mail Removed)> wrote in message
> news:%(E-Mail Removed)...
>> Hi,
>>
>> capCreateCaptureWindow will display the incoming video for you.
>> Here
>> is an link to an example.
>>
>> http://www.windowsformsdatagridhelp....6-e5cf2ebb86b6
>>
>> Ken
>> --------------------------
>> "Workgroups" <(E-Mail Removed)> wrote in message
>> news:cKidnWgPNvYWhWHfRVn-(E-Mail Removed)...
>> I'm writing a piece of video software, sort of like a webcam, that's
>> meant
>> to show a preview on the screen from any WDM capable cam. I want to give
>> the user RGB sliders, and process each frame by running it through a
>> color
>> matrix before it's displayed on the screen.
>>
>> So far I've succesfully created a preview window and established a
>> capSetCallbackOnFrame callback function that fires every time a new frame
>> of
>> video is available from the camera. So now I need to copy the video
>> buffer
>> (image) I vicariously receive a pointer to in the callback function into
>> an
>> image, transform the image's color w/ a color matrix and then paint the
>> colorized image to some control (like a picturebox, probably).
>>
>> But I'm stumped when it comes to "doing something" with the data that's
>> coming back from capSetCallbackOnFrame. It's a pointer to a structure,
>> and
>> one of the elements of the structure contains the pointer to the video
>> buffer. The documentation for this is really hard to come by, although
>> there is a popular VB6 example of this floating around that I've been
>> using
>> for a guide that looks like this:
>>
>> Function MyFrameCallback(ByVal lwnd As Long, ByVal lpVHdr As Long) As
>> Long
>>
>> Dim VideoHeader As VIDEOHDR
>> Dim VideoData() As Byte
>>
>> RtlMoveMemory VarPtr(VideoHeader), lpVHdr, Len(VideoHeader)
>> ReDim VideoData(VideoHeader.dwBytesUsed)
>> RtlMoveMemory VarPtr(VideoData(0)), VideoHeader.lpData,
>> VideoHeader.dwBytesUsed
>>
>> End Function
>>
>> The VIDEOHDR structure looks like this:
>>
>> Type VIDEOHDR
>> lpData As Long 'address of video buffer
>> dwBufferLength As Long 'size, in bytes, of the Data buffer
>> dwBytesUsed As Long
>> dwTimeCaptured As Long
>> dwUser As Long
>> dwFlags As Long
>> dwReserved(3) As Long '// reserved; do not use
>> End Type
>>
>> I've tried to reporduce this in .NET but I haven't been too successful so
>> far... I've tried to use Marshal.Copy and Marshal.PtrToStructure, to copy
>> the data referenced at lpVHdr into it's appropriate structure format on
>> the
>> managed side, but I don't think I'm doing it right; my structure ends up
>> with what I'm pretty sure is erroneous data; all the values are 0 except
>> for dwFlags = 64, so... "something" is getting copied in there but it's
>> not
>> correct. I am at a loss as to how to get that video buffer turned into
>> an
>> image object.
>>
>>
>>

>
>



 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
avicap32 - Please Help Macias Microsoft C# .NET 0 27th Aug 2008 11:52 AM
avicap32.dll corrupt? =?Utf-8?B?aTJtZWVr?= Windows XP General 3 11th Dec 2006 05:24 AM
avicap32.dll =?Utf-8?B?aTJtZWVr?= Windows XP General 0 24th Nov 2006 02:48 AM
AVICAP32 and VIDEOHDR to Bitmap Daniel Friend Microsoft VB .NET 1 29th Oct 2005 12:58 PM
AVICAP32 =?Utf-8?B?VDIxMA==?= Windows XP Accessibility 0 6th Oct 2005 09:22 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 09:28 PM.