0

Working on an application in C++ Builder which brings in video from 2 different web cams. I use 2 TVideoCaptureDevice objects.

A button starts the capturing of the video. I can only get 1 web cam to work. Web Cam #2 activates (green light on) for a split second then stops capturing. Web Cam #1 continues to capture ok.

//The Code in the button's onClick event:

void __fastcall TForm2::StartButtonClick(TObject *Sender)
{
    
int DIndex1, DIndex2;
TCaptureDeviceManager *TheManager;
TCaptureDeviceList TheDeviceList;
    
TheManager = NULL;
TheManager = TCaptureDeviceManager::Current;
TheDeviceList = TCaptureDeviceManager::Current->GetDevicesByMediaType(TMediaType::Video);
    
// Create the Video Capture Devices
    
DIndex1 = CameraIndex[0];
CAM1VideoCamera = dynamic_cast<TVideoCaptureDevice*> (TheDeviceList->Items[DIndex1]);
if(NumbCameras > 1) {
    DIndex2 = CameraIndex[1];
    CAM2VideoCamera = dynamic_cast<TVideoCaptureDevice*> (TheDeviceList->Items[DIndex2]);
    }
    
if (CAM1VideoCamera != NULL) StartButton->Enabled=true;
    else StartButton->Enabled=false;
    
// Prepare the Camera Sample Threads
CAM1VideoCamera->OnSampleBufferReady = CAM1SampleBufferReady;
CAM1VideoCamera->Quality = TVideoCaptureQuality::PhotoQuality;
if(NumbCameras > 1) {
    CAM2VideoCamera->OnSampleBufferReady = CAM2SampleBufferReady;
    CAM2VideoCamera->Quality = TVideoCaptureQuality::PhotoQuality;
    }
    
// Now start capturing frames from the camera
CAM1VideoCamera->StartCapture();
if(NumbCameras > 1) CAM2VideoCamera->StartCapture();
return;
}    

The code for the Sample Buffer for CAM1

//---------------------------------------------------------------------------
void __fastcall TForm2::CAM1SampleBufferReady(TObject *Sender, const TMediaTime ATime)
{
TThread::Synchronize(TThread::CurrentThread, (TThreadMethod)&CAM1SampleBufferSync);
return;
}
    
void __fastcall TForm2::CAM1SampleBufferSync()
{
    TRectF ZoomRectangle;
    TPointF Center;
    int ZWidth, ZHeight;
    int CX, CY;
    int CTop, CBottom, CLeft, CRight;
    TRect SourceRect;
    TRectF src, trg;
    Graphics::TBitmap *TemporaryBitmap;
    int TestValue;
    
    try {
        CAM1VideoCamera->SampleBufferToBitmap(ZoomBitmap1, true);
    
        RawBitmap1->Assign(ZoomBitmap1);
        RawWidth = RawBitmap1->Width;
        RawHeight = RawBitmap1->Height;
        Camera1FullWidth = RawWidth;
        Camera1FullHeight = RawHeight;
    
        // This routine stretches the bitmap to the size of the screen.
        ZWidth = ZoomBitmap1->Width;
        ZHeight = ZoomBitmap1->Height;
    
        // Find the Center point of the bitmap
        CX = ZWidth / 2;
        CY = ZHeight / 2;
        ZWidth /= ZoomFactor1;
        ZHeight /= ZoomFactor1;
    
        // Now find the zoom rectangle co-ordinates
        // Must check if the panning is outside the Full size of the camera bitmap
    
        TestValue = CY - (ZHeight/2) + Camera1DY;   if(TestValue < 0 ) Camera1DY = -1*(CY-(ZHeight/2));
        CTop      = CY - (ZHeight/2) + Camera1DY;
        TestValue = CY + (ZHeight/2) + Camera1DY;   if(TestValue > Camera1FullHeight ) Camera1DY = Camera1FullHeight - (CY+(ZHeight/2));
        CBottom   = CY + (ZHeight/2) + Camera1DY;
        TestValue = CX - (ZWidth/2) + Camera1DX;    if(TestValue < 0 ) Camera1DX = -1*(CX-(ZWidth/2));
        CLeft     = CX - (ZWidth/2) + Camera1DX;
        TestValue = CX + (ZWidth/2) + Camera1DX;    if(TestValue > Camera1FullWidth )  Camera1DX = Camera1FullWidth - (CX+(ZWidth/2));
        CRight    = CX + (ZWidth/2) + Camera1DX;
    
        CalibrationForm->Camera1DY = Camera1DY;
        CalibrationForm->Camera1DX = Camera1DX;
    
        SourceRect.Left = CLeft;
        SourceRect.Right = CRight;
        SourceRect.Top = CTop;
        SourceRect.Bottom = CBottom;
    
        CutBitmap->Height = ZHeight;
        CutBitmap->Width = ZWidth;
        CutBitmap->Canvas->BeginScene();
        CutBitmap->CopyFromBitmap(ZoomBitmap1, SourceRect, 0,0);
        CutBitmap->Canvas->EndScene();
    
        src = TRectF(0,0,CutBitmap->Width, CutBitmap->Height);
        trg = TRectF(0,0,WImageWidth, WImageHeight);
    
        TemporaryBitmap = NULL;
        TemporaryBitmap = new Graphics::TBitmap;
        TemporaryBitmap->Width = WImageWidth;
        TemporaryBitmap->Height = WImageHeight;
    
        TemporaryBitmap->Canvas->BeginScene();
        TemporaryBitmap->Canvas->DrawBitmap(CutBitmap,src,trg,1);
        TemporaryBitmap->Canvas->EndScene();
    
        WImage->Bitmap->Assign(TemporaryBitmap);
        delete TemporaryBitmap;
        TemporaryBitmap = NULL;
        }
    
    catch (...) {
        }
    
    return;
    }

The sample buffer code for the 2nd web cam is almost identical in nature but has it's own parameters for zooming and offsets. So I won't post the code here for it.

Any ideas as to why the second web cam won't continue to stay on and capture video????

  • Which platform(s) are you targeting? – Remy Lebeau May 19 '23 at 16:47
  • Remy, Windows 11 Pro and the application is a 64 bit Firemonkey application. And here is an interesting update, I tried it using 2 different web cams and it works ok. There is definitely a bug in the compiler which needs to be addressed by Embarcadero.. If I use 2 identical web cams that have the same name property, then it doesn't work. If I use 2 different web cams from different manufacturers, then it works ok. – Drewski7280 May 19 '23 at 17:54
  • Did you check to make sure you are not simply acting on 2 `TVideoCaptureDevice*` pointers to the same object in memory? On Windows, the device's `Name` is not used to control captures. Each device has a unique `IMoniker` and `IBaseFilter` to handle that.. – Remy Lebeau May 19 '23 at 18:02
  • Remy, I am using different indices to address the different TVideoCaptureDevice pointers. I will run a check now that you have me thinking. – Drewski7280 May 19 '23 at 18:03
  • "*I am using different indices*" - that is not what I asked. And we know from your [previous question](https://stackoverflow.com/questions/76267496/) that you have had issues before with managing your indexes correctly. – Remy Lebeau May 19 '23 at 18:04
  • The pointers are different on the 2 TVideoCaptureDevice objects. I have a total of 4 web cams on my development computer. 2 of which are identical. When I run with these 2 together, the second camera doesn't run. When I run one of these cams with 1 of the other 2 cams, it works fine. The indices were never the problem. In the device manager of my computer the 4 web cams come up as: Logi C270 HD Web Cam USB Camera USB Camera USB Camera The last 2 USB Camera entries are the 2 identical ones and the first USB Camera entry is almost the same as these 2 identical ones. – Drewski7280 May 19 '23 at 18:14
  • 1
    If they are two physical objects in memory, then they are indeed separate devices reported by the OS, and all capturing is handled by the `IMoniker`/`IBaseFilter` that the OS provided for them, so any problem in capturing them simultaneously is going to be an OS issue, not a FMX issue. – Remy Lebeau May 19 '23 at 19:45
  • Or even hardware (i.e. if they are connected to the same USB controller depending on resolution and encoding there may not be sufficient bandwidth). – Mike Versteeg May 19 '23 at 20:15
  • Remy, is there any way of finding out the IMoniker and IBaseFilter parameters? – Drewski7280 May 19 '23 at 21:02
  • Mike Versteeg, I think you are on to something. I was using a hub for the 2 identical web cams. When I take out the hub and plug them directly into available ports, they now work together. Question now is, how to get this to work properly with the 2 web cams on a single hub???? – Drewski7280 May 19 '23 at 22:26

0 Answers0