Download and install K-Lite Codec pack will solve your problem.
Printable View
Hi Is there a way to extend this to capture image based on physical button press of a camera?
This has nothing to do with still cameras, so you'd want to look at WIA 2.0 or something else. Even then I don't believe there is any communication between a still camera and the PC when the "shutter release" button is pressed.
Hi, my camera was a medical imaging camera. It is not a shutter release camera. Software it came with also uses DirectShow and was able to capture it when camera button is pressed. Any chance we could do similar to their software?
3rd party DLL to wrap the extra functions in? Has anybody done that yet?
Hi Dilettante,
Thanks so much for this, this is the only good DirectShow - VB6 I was able to find. I would like to implement some of your code into Excel using VBA. I have an Excel input form, and I would like users to be able to take a snapshot from webcam video steam, (the snapshot will be stored in an embedded Active X image control). I am having a little trouble extracting the DirectShow part of the code to implement it. I am hoping you can provide some guidance on that. Thanks in advance.
Hello -
I'm not a VBA guy, but from what I could tell trying to bang around a bit in Excel and then trying a few web searches for ideas I can see a few issues that might get in your way.
For one thing you don't have UserControls in most VBA hosts (e.g. Excel) so you'd have to "unwrap" my UserControl code to work directly within a UserForm. However UserForms don't give you access to their hWnd (at least in old Excel 2003 that I have) so you're stuck right there because the video preview window will need it set as its Owner window.
So from where I'm sitting you'd have to extract parts of my code to make an OCX in VB6 that could be used by Excel as a video preview control.
Somebody with more experience trying to squeeze more from Excel might have a better option, but that's all I can think of right now. But the good news (?) is that almost everything but the DSPreview.ctl is more or less plain old VB code that should be doable in VBA UserForms, Classes, etc.
Thanks for your response, you can extend the capability of a VBA userform using Windows API. Please see the following link. http://www.cpearson.com/excel/formcontrol.aspx
The thing I am struggling with is not fully understanding the implementation of the code, I am thinking it is mostly due to "obscuring" but UI stuff like you have mentioned.
Yeah, I've seen that Pearson hack but I don't care for it at all. Window spelunking is an act of desperation at best, and it can easily return the hWnd of the wrong window. It's a "by guess and by golly" approach and hardly a real fix.
But sometimes beggars can't be choosers. I don't have a better suggestion.
Well it has been a while since I last visited this topic in any seriousness. I decided to try starting more or less from scratch and see how much I could strip it down.
Along the way I think I figured out how to eliminate the problematic manual Filter Graph construction. This approach should be easier and require less camera-by-camera configuration. At least it seems to adapt nicely to the two very different USB webcams I have here with me at the moment.
It still needs FSFWrap, so see Visual Basic Questions for the download. It also makes use of my DSDib2Pic.bas module that I think could be a lot cleaner but right now I don't have time to investigate a cleanup of that.
There are also a few gyrations here that (1.) resize things to fit the video capture dimensions, and (2.) allow the capture properties (including size) to be changed from their defaults. However this demo doesn't try to persist any settings at all, so each run you must choose a camera, even if you only have one connected at the time.
I also noted that one of the webcams I have right here sometimes comes up under a specific name, and other times comes up as "USB Video Device" - a generic name. This seems to change when I disconnect and later reconnect the webcam to a USB port. Weird, but something to watch out for if you need to persist settings.
Hopefully this will be a little more helpful.
As a caution: this new program above could be problematic if you have a webcam that defaults to a large picture size. The program tries to put the preview window and a "snapshot" Image control side-by-side at the capture size and size the Form to fit and center it within the default monitor.
So it is possible for it to size the Form such that you can't get to the control widgets in the caption bar's corners since they can end up off-screen.
You could modify the program to do some scaling to keep things in reasonable proportion.
Pretty much as expected, the old DIB-to-StdPicture logic had some issues. I was never happy with it and upon re-examination I even found some glaring GDI handle leaks and such.
Here is one more run at the whole thing again. Basically it changes nothing from the last example I posted just above except:
- The Form is now a fixed-size Form of about 970 pixels width. This should help when testing a webcam supporting hi-res video dimensions.
- The webcam preview window is fixed in width at about 640 pixels. Really part of the fixed-Form stuff.
- The "snapped" picture view is a PictureBox scaled to 50% of the preview to save on Form size. Really part of the fixed-Form stuff.
- The DIB-to-StdPicture logic has been rewritten to be a little cleaner and take care of some flaws in its GDI handling and to return error information.
Almost nothing in the DirectShow logic has been altered, so this version really is quite similar to the previous except for the fixed Form size stuff and the improved DIB to StdPicture code.
Here's my last version of this (I think).
- Cleaned up DIB fetch thanks to a trick to request required size. When porting to VBA be cautious with this.
- Optimized StdPicture creation using SetDIBits instead of MoveMemory.
- Pause/Run on snap to optimize snap-shotting - almost no "blink" now except when Aero is active.
- Added save to disk as JPEG.
----
bummer, it's too bad the source for FSWrapper wasn't available. It shouldn't be too hard to come up with a VB Compatible typelib, to implement the needed classes in VB.
Have you found a solution to this complete lack of VB6 support in quartz.dll, that would allow a VB6 programmer full access to the entirety of the DirectShow framework? I think you can access it all with VC++. Has anybody yet bothered to create a VB6 friendly wrapper (preferably an ActiveX DLL file, or at least an STDCALL DLL File) in VC++, that gives VB6 users the full power of DirectShow? If so, where can I download this DLL file?
Hmm looks like it's high time to go and make a TLB with all the DirectShow interfaces like I just did for Core Audio. Saw this example then saw how easy ICaptureGraphBuilder2 makes capturing**...
The quartz.dll this project uses seems to have extremely few of the interfaces... is there a more thorough one before I go off on another massive interface conversion expedition?
Is there a particular reason a DLL is being used? Do the interfaces require some sort of background code that a TLB wouldn't support?
-----
* I was looking at this code... if I made such a TLB in a VB friendly form like usual, it looks like an easy direct translation:
Code:#include <dshow.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
CoInitialize(NULL);
// 1. フィルタグラフ作成
IGraphBuilder *pGraph = NULL;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGraph);
// 2. システムデバイス列挙子を作成
ICreateDevEnum *pDevEnum = NULL;
CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **)&pDevEnum);
IEnumMoniker *pClassEnum = NULL;
pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
ULONG cFetched;
IMoniker *pMoniker = NULL;
IBaseFilter *pSrc = NULL;
if (pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK){
// 最初のモニカをフィルタオブジェクトにバインドする
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void **)&pSrc);
pMoniker->Release();
}
pClassEnum->Release();
pDevEnum->Release();
pGraph->AddFilter(pSrc, L"Video Capture");
// 3. キャプチャビルダの作成
ICaptureGraphBuilder2 *pBuilder = NULL;
CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **)&pBuilder);
pBuilder->SetFiltergraph(pGraph);
// 4. ファイルライタフィルタの設定
IBaseFilter *pMux = NULL;
IFileSinkFilter *pSink = NULL;
// ファイルへ
pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, L"C:\\dvcap_tmp.avi", &pMux, &pSink);
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pSrc, NULL, pMux);
REFERENCE_TIME rtStart = 50000000, rtStop = 80000000;
pBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pSrc, &rtStart, &rtStop,
0, 0 );
// ディスプレイへ
pBuilder->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pSrc, NULL, NULL );
// 5. キャプチャ開始
IMediaControl *pMediaControl;
pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pMediaControl->Run();
MessageBox(NULL, "Click to stop.", "DirectShow", MB_OK);
// 6. 終了
pSrc->Release();
pMux->Release();
pSink->Release();
pMediaControl->Release();
pEvent->Release();
pBuilder->Release();
pGraph->Release();
CoUninitialize();
cout << "end\n";
return 0;
}
A TLB isn't executable code no. Although I went over this when trying to figure out whether a compiled TLB broke the rules against posting binaries and never got a clear answer as to whether one might be able to craft an exploit based on newer TLBs supporting "cpp_quote" with C++ code in it. Never seen anything more than cpp_quote in newer IDL sources though.
I don't think a TLB would be considered a "binary" for purposes of exclusion in an upload here. They have no executable code, being basically a form of predigested source code (metadata) to be consumed by compilers and related tools.
A simple DirectShow TLB would probably not be enough. Many of the low-level DirectShow entrypoints and data structures are not easily consumed by VB and need to be wrapped with a little code to handle the "impedance mismatch."
I'm looking for a simple way to access pixel data from a webcam. I wonder if anybody has made an easy way of accessing a webcam via DirectShow, as a specific purpose build Webcam Directshow DLL file. It's too much trouble to try to figure out how to build up a graph from scratch. I'd like a way to just easilly add a webcam into my program, and have each frame be an event that is fired, that I can then use to access the raw pixel data from the webcam. And I also need to be able to spawn the driver-defined dialog box for controlling the webcam, as well as the default system dialog box for setting things like the output codec/format of the webcam, image dimensions, and frame rate.
I would like it to be a simple to use DLL file, that hides from the programmer all the complexities of graph building.
Great project idea. Let us know when it is ready. ;)
Seriously though, I haven't found anything like that available off the shelf anywhere. That probably means nobody has ever been motivated enough to create it because as you can see from the rest of this thread there is a ton of work involved. You can look other places and you'll find the same sort of "bits and pieces of the puzzle" here and there but no slick and complete "picture"... er, "ready to hang."
When I started the effort that began this thread I was hoping there wouldn't be too much to it. Surely people were just making this harder than it needed to be? I was wrong.
With VC++, it's theoretically possible to access ALL of the DirectShow framework. Maybe (if you have any VC++ experience) you could take just as much as is required to get a webcam running, and spawn any dialog boxes that might be needed to control the webcam (both driver-provided dialogs for the camera, as well as built-in Windows ones that let you set the format and dimensions of the image), and get the raw pixel bytes from it as a byte array, and then compile a DLL file with those features, so I can use it in my VB6 program.
Are you talking about something different than the C++ code I posted above? That outputs the webcam stream to a file, and there's nothing that would seem to preclude doing it in VB6.
The disadvantage is that you have to figure out just which filter corresponds to your camera. There's TONS of filters in the DirectShow framework.
I was looking for a dedicated ActiveX DLL file, or ActiveX control (OCX file), that I could add to my project, and that would encapsulate ALL of the functionality needed for WEBCAM OPERATION (ignoring all the rest of the DirectShow framework), and present me, the programmer, with a single interface for webcam operation, hiding all of the hard-to-do internal "stuff" within the DLL or OCX file.
Well the example above that I'm planning on porting selects the first video input device it finds... there shouldn't be multiple listings for that if all you have is a webcam, and nothing else like a video capture card.
I tried the first example but it doesn't run properly under Windows 10. Anybody get any kind of video capture working under VB6 with Windows 10?
I just tested that program on Windows 10, and as expected it runs just fine.
Here is another more streamlined example using FSFWrap.dll along with Quartz.dll for simple webcam video capture. Plenty of room for improvement and features.
- It starts and enumerates the Camera filters it can find, adds them to a menu.
- User picks a camera from the menu.
- Camera capture filter graph is built and preview window displayed, picking up a previously-saved camera config if found.
- Snap menu to take a JPEG snapshot becomes visible.
- "Camera-name" menu becomes visible with Camera and Capture Config options, Save and Load Config options.
This really duplicates what previous sample programs above do. However it strips away some redundancy and adds a few comments that might be useful to figure out how to repurpose parts of the code in your own programs.
If I stay interested I might go further and try to pick up frame events and implement audio capture. It seems like a simple one-on-one audio/visual chat program could be built without a huge amount of trouble. I may be underestimating the effort required though.
Edit:
Replaced attachment. Had a ridiculous bug in managing the enabled state of menu items, blocking "save" operations. Sorry for the confusion.
Hi, Can anyone help me for this problem?
i copy the form to my project.but i can not to compile because this problem
Attachment 139013
=================================================
SOLVED PROBLEM.
just active the quartz.dll in reference..
thank you dilettante for ur code.. :D
Hi dilettante,
I think there's a small bug in your 1.3 demo. If you have never saved a config file, then mnuCameraSave will always be disabled (so you can never save a config file). If you get rid of the Else condition in mnuCamerasCamera_Click then it will be enabled and you can subsequently save settings:
Code:With New FSFWRAPLib.StreamConfig
.Pin = VidCapPinInfo
If .SupportsConfig = OATRUE Then
mnuCameraSave.Enabled = True
If Exists(App.Path & "\" & mnuCamera.Caption & ".cfg") Then
mnuCameraLoad.Enabled = True
.Restore App.Path & "\" & mnuCamera.Caption & ".cfg"
' Get rid of the following 2 lines to ensure Save config menu option is enabled even if we have never saved the configuration before
' Else
' mnuCameraSave.Enabled = False
End If
Else
mnuCameraSave.Enabled = False
mnuCameraLoad.Enabled = False
End If
End With
I ran into that myself and I believe I fixed it then re-posted on Jun 20th (couple days back). You are right, there was leftover crud from an earlier version and I failed to test thoroughly (clearly my eyes weren't good enough to see it sticking out at me - got to get new glasses ;)).
I started digging deeper for another project and quickly realized we're about at our limits though. Even FSFWrap.dll only helps just so much and for some things additional typelibs and/or C++ DLLs are required.
Everything we need is all there, but Microsoft never bothered to expose it for use in VB6 and similar langauges. Of course we're used to that by now and this late in the day it probably isn't worth trying to extend what Geraint Davies did for us so long ago.
Ahh sorry, must have grabbed an older version of 1.3 and just got around to looking at it now.
Thanks again for your work on this - it's quite useful as-is even if we're missing out on some stuff that would be available with additional typelibs/dlls.
I'm just glad there wasn't a second place in there with a similar glaring bug... not that there won't be others found, perhaps just a bit less silly.
Too bad we lost out.
It was easier with WIA instead of working with DirectShow. But too many script kiddies ended up using it to pirate videos and Microsoft noticed hardly anyone had started using WIA for webcam capture and such, so most of the support for media files and video cameras was stripped out.
Hello, i'm very impressed reading the code samples. My tests with Quartz and FSWrapper worked very well until today. Now my code is freezing in the IDE (WIN 10 latest build) at the end of SetupVideoWindow...
When i compile an executable version, everything works. The same code on another device (Surface pro 4 with rear / front camera runs perfect in the IDE. But the 10 Euro-Cam on my main developer machine won't work in the IDE anymore. Any Ideas?
Christian
My mod starts with your example DS Webcam Snap 3, but since the freezing problem occured, all of your samples are freezing on this machine with this simple usb-cam. I think, it's a problem between the IDE an the cam-driver. When i build a graph with GraphEdit, just with these filters "USB2.0 PC CAMERA" - "AVI Decompressor" - "Video Renderer" the cam works fine. When i compile your samples, the cam worked again as expected. Maybe it's a dependece between the VB6.exe and DirectShow? This cheap cam worked for a week without any probs with the VB6-IDE. Today i will start my tests with an new (maybe better) USB-Cam.
I've found the reaseon, because one of my compiled sample is freezing too. I've searched the registry looking for the name of the sample and i got these entrys:
Attachment 140999
After deleting those keys everything runs fine, including the VB6-IDE!
Christian
That path appears to be:
HKEY_CURRENT_USER\Software\Microsoft\Direct3D\Shims\EnableOverlays
These are appcompat shims, and I'm not sure what your program did that might trigger Windows to apply them. I did find this:
Overlay mixer seems to be broken in Windows 8
I'll have to do more checking, but I haven't had problems like this recently on post-Win7 OSs myself.
At least you have a "cure" for the issue.
As I have tried working with this over time I think the only thing I really learned is that "minimal code yields minimal results."
When you try to refine it to handle lots of different webcams with lots of flexibility... you end up needing more and more code.
Deleted several posts that were in incorrect thread
Hi,
when I test it I have borders on left, top and bottom.
When I save the picture the borders are stil on the pictures.
How can I fix this?
Andreas
Btw:
I have test it with a videocam at a Pinnacle Dazzle.
With a WebCam there is no border.
Hi,
capturing to a single picture works fine now, but how can I capture an save as Video MP4 or so?
Thanks Andreas
In theory you could use this to snap frames rapidly then use something else to stitch those into an MP4 movie. However the frame rate wouldn't be too high and the encoding process would be a lot more work than what we're talking about above.
You probably would want to take some other direction. This just supports camera preview and snapshots.
Try asking your question in the Q&A forum.
Hi,
I send DSWC 1.3.zip to a friend for testing, and he told me he gets only black/white video picture.
What is the Problem?
Andreas
There might be lots of reasons. As we've found this is a very difficult thing to get to work correctly with every combination of cameras and computers.
There is probably a FilterGraph flaw. That's where you might have to use the Graph Edit developer's tool to experiment. See post #28 above.
Thank you dilettante for open sourcing your code. I have quite a dilemma at the moment and I'm hoping that you or someone else qualified can help.
As a bit of background, I have a legacy program in vb6 that was written by a programmer who is no longer supporting it. As a tech I've managed to make minor changes over the years but now I'm faced with a hardware change that requires either a total rewrite of the original program at great expense or a modification to the existing. Because the new hardware is not as accurate as the original custom hardware I'm trying to use a webcam to course correct (compensate) for the inaccuracy. There are two motors which control xy positioning and there lies the problem. We have many machines doing this and the first one became irreparable. We anticipate this will become an issue in the future with the remaining machines.
I am not a programmer but as I said I have managed to make minor adjustments over the years and I've had experience with programming access 2000 vba. I've made several attempts at capturing the webcam to a picturebox in order to determine the course corrections necessary. It works but my code is too slow. First off I don't need to analyze the entire 640x480 picture and the picture really doesn't need to be displayed at all. At most I only need to analyze a block of 10x10 pixels at a time. As the machine operates the block of pixels will change. How do I either put the select block of pixels from the webcam into memory for analysis OR directly analyze the pixels with getpixel from the dsPreview.ctl? All help will be appreciated. Thanks in advance.
Once you have a bitmap image then you just snip out the portion you want as a new bitmap or array of pixel values. Do a BitBlt, GetDIBits, etc.
But from there analyzing them is another topic altogether. Machine vision isn't a trivial matter.
Thanks for the reply dilettante. The analysis and compensation isn't a problem with my current method. It works but the whole process is too slow. I used your code to 1) capture to picturebox1 and then I copied picturebox1 to hidden picturebox2 at the outset. 2) Moved the stepper motors one step. 3) Captured another pic to picturebox1 and compared to hidden picturebox2. 4) Compensated by stepping appropriate motor as needed. 5) Copy picturebox1 to picturebox2. Repeat steps 2-5.
I have yet to figure out how to use bitblt with your code. In fact I don't even know where to start. That is the direction I thought I needed to go. After more thought I don't think I need picturebox2 with my current method. I'm trying to avoid pictureboxes altogether. Any further guidance will be appreciated.
Well once you have a captured image within a PictureBox you should be able to use its .hDC and its .Image.Handle for blitting or fetching the pixel bits.
Maybe something here might help:
Read pixel, twips or other scalemod coordinates in picturebox.?
Looks like the OP for that the link you provided was looking for a moore neighbour tracing algorithm. I wrote one, it works well and it saves the motor steps to an access db for later use. Precisely what he needed for a CNC I presume. I'm not able to look at the code you provided him at the moment due to illness. Within the next day or so with any luck. Thanks dilettante.
I haven't found a way to set the resolution. There probably is one, but it doesn't seem to be exposed via any of the typelibs I have tried.
Rotating might be possible by adding another filter to the FilterChain.
If found a sourceforge project that includes a rotate filter. https://sourceforge.net/projects/videoprocessing/
The name of the rotate filter is "CSIR VPP Rotate Filter"
My understanding is that the pins from two filters should be connected, but I am struggling with the code to make that happen.
Here is the code from "Webcam Snap":
I am stumped on what to do.Code:Private Sub mnuCamerasCamera_Click(Index As Integer)
Dim Filter As FSFWRAPLib.IFilterClass
Dim Pins As QuartzTypeLib.IAMCollection
Dim RFI As QuartzTypeLib.IRegFilterInfo
Dim FI As QuartzTypeLib.IFilterInfo
mnuCameras.Enabled = False
Set FGM = New QuartzTypeLib.FilgraphManager
Set Filter = Filters.Item(Index)
mnuCamera.Caption = Filter.Name
mnuCamera.Visible = True
Set Filters = Nothing
Set CaptureFilter = Filter.Create(FGM)
Set Pins = CaptureFilter.Pins
For Each CapturePin In Pins
With CapturePin
If .Direction = DIRECTIONOUT Then
If .Name = "Capture" Then
For Each RFI In FGM.RegFilterCollection
If RFI.Name = "AVI Decompressor" Then
RFI.Filter FI 'Adds this filter to FGM. We won't use this FI though,
'we just have to pass an argument to this call.
Exit For
End If
Next
.Render 'Auto-create filter graph, should pick up AVI Decompressor.
SetupVideoWindow
Exit Sub
End If
End If
End With
Next
lblStatus.Caption = " Couldn't find capture pin!"
End Sub
Thanks for this great example!
When I try to run it on my Windows10 machine for evaluating the code, it gives me the error as shown in the screenshot below. Specifically, I am running DSMini4
Attachment 165175