2013-10-31 136 views
1

嗨,我試圖使用ISampleGrabberCB::SampleCB從我的窗體內顯示之前,它們的實時預覽中獲取圖像。使用ISampleGrabberCB :: SampleCB

我希望能夠將每一個新的幀轉換成一個位圖來處理(例如掃描+添加水印型圖像)。

目前,我試圖做到這一點通過以下方式:

int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample sample) 
    { 
     int hr; 
     IntPtr buffer; 
     AMMediaType mediaType; 
     VideoInfoHeader videoInfo; 
     int frameWidth; 
     int frameHeight; 
     int stride; 
     int bufferLength; 


     hr = sample.GetPointer(out buffer); 
     DsError.ThrowExceptionForHR(hr); 

     hr = sample.GetMediaType(out mediaType); 
     DsError.ThrowExceptionForHR(hr); 

     bufferLength = sample.GetSize(); 

     try 
     { 
      videoInfo = new VideoInfoHeader(); 
      Marshal.PtrToStructure(mediaType.formatPtr, videoInfo); 

      frameWidth = videoInfo.BmiHeader.Width; 
      frameHeight = videoInfo.BmiHeader.Height; 
      stride = frameWidth * (videoInfo.BmiHeader.BitCount/8); 

      CopyMemory(imageBuffer, buffer, bufferLength);     

      Bitmap bitmapOfFrame = new Bitmap(frameWidth, frameHeight, stride, PixelFormat.Format24bppRgb, buffer); 
      bitmapOfFrame.Save("C:\\Users\\...\\...\\...\\....jpg"); 


     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 

     return 0; 
    } 

這在理論上應該得到的媒體類型,然後將其用於獲取圖像的寬度,高度和步幅,然後用創建位圖。然後從IMediaSample的指針獲取緩衝區。

但是,這似乎並沒有工作(我假設這是位圖從不保存)。那麼我將如何將每個新幀轉換爲位圖?

產生額外的功能,其中引腳設置:

public void setupGraphForSampleGrabber(DsDevice webcamDevice, Control displayBox) 
    { 
     int hr; 
     ISampleGrabber sampleGrabber = null; 
     IPin capturePin = null; 
     IPin samplePin = null; 
     IPin renderPin = null; 
     IBaseFilter captureFilter; 
     filtergraph = new FilterGraph() as IFilterGraph2; 

     try 
     { 


      //Add the webcam 
      hr = filtergraph.AddSourceFilterForMoniker(webcamDevice.Mon, null, webcamDevice.Name, out captureFilter); 
      DsError.ThrowExceptionForHR(hr); 

      //Get the still pin 
      stillPin = DsFindPin.ByCategory(captureFilter, PinCategory.Still, 0); 

      if (stillPin == null) 
      { 
       stillPin = DsFindPin.ByCategory(captureFilter, PinCategory.Preview, 0); 
      } 

      if (stillPin == null) 
      { 
       IPin outputPin = null; 
       IPin inputPin = null; 

       //As there is still no still pin set this to null 
       videoControl = null; 

       // Add a splitter 
       IBaseFilter smartTee = (IBaseFilter)new SmartTee(); 

       try 
       { 
        hr = filtergraph.AddFilter(smartTee, "SmartTee"); 
        DsError.ThrowExceptionForHR(hr); 

        //Obtain the capture pin from the webcam and the input pin from the spliter and assign them to the outputPin and inputPin respectivly 
        outputPin = DsFindPin.ByCategory(captureFilter, PinCategory.Capture, 0); 
        inputPin = DsFindPin.ByDirection(smartTee, PinDirection.Input, 0); 

        //Then connect both of them to the graph 
        hr = filtergraph.Connect(outputPin, inputPin); 
        DsError.ThrowExceptionForHR(hr); 

        //Set the capture and still pins so we can use them with the rest of the program 
        stillPin = DsFindPin.ByName(smartTee, "Preview"); 
        capturePin = DsFindPin.ByName(smartTee, "Capture"); 

        setParameters(outputPin); 

       } 
        //Release all the com objects to avoid problems as the program is to be used for extended periods 

       finally 
       { 
        if (outputPin != null) 
        { 
         Marshal.ReleaseComObject(outputPin); 
        } 
        if (outputPin != inputPin) 
        { 
         Marshal.ReleaseComObject(inputPin); 
        } 
        if (outputPin != smartTee) 
        { 
         Marshal.ReleaseComObject(smartTee); 
        } 
       } 
      } 
      else 
      { 
       videoControl = captureFilter as IAMVideoControl; 
       capturePin = DsFindPin.ByCategory(captureFilter, PinCategory.Capture, 0); 
       setParameters(stillPin); 
      } 

      //Get interface 
      sampleGrabber = new SampleGrabber() as ISampleGrabber; 

      //Configure the samplegrabber 
      IBaseFilter baseFilter = sampleGrabber as IBaseFilter; 
      configureSampleGrabber(sampleGrabber); 
      samplePin = DsFindPin.ByDirection(baseFilter, PinDirection.Input, 0); 

      //Video Renderer 
      IBaseFilter render = new VideoRendererDefault() as IBaseFilter; 
      hr = filtergraph.AddFilter(render, "Renderer"); 
      DsError.ThrowExceptionForHR(hr); 

      renderPin = DsFindPin.ByDirection(render, PinDirection.Input, 0); 

      //Add samplegrabber to graph 
      hr = filtergraph.AddFilter(baseFilter, "SampleGrabber"); 
      DsError.ThrowExceptionForHR(hr); 

      if (videoControl == null) 
      { 
       //Connect still pin to samplegrabber 
       hr = filtergraph.Connect(stillPin, samplePin); 
       DsError.ThrowExceptionForHR(hr); 

       //Connect capture pin to render 
       hr = filtergraph.Connect(capturePin, renderPin); 
       DsError.ThrowExceptionForHR(hr); 
      } 
      else 
      { 
       //Connect capture pin to render 
       hr = filtergraph.Connect(capturePin, renderPin); 
       DsError.ThrowExceptionForHR(hr); 

       //Connect still pin to samplegrabber 
       hr = filtergraph.Connect(stillPin, samplePin); 
       DsError.ThrowExceptionForHR(hr); 
      } 

      //Get video properties 
      saveVideoInfo(sampleGrabber); 
      ConfigureVideoLocation(displayBox); 

      //Run Graph 
      IMediaControl mediaControl = filtergraph as IMediaControl; 
      hr = mediaControl.Run(); 
      DsError.ThrowExceptionForHR(hr); 


     } 
     finally 
     { 
      if (sampleGrabber != null) 
      { 
       Marshal.ReleaseComObject(sampleGrabber); 
       sampleGrabber = null; 
      } 
      if (capturePin != null) 
      { 
       Marshal.ReleaseComObject(capturePin); 
       capturePin = null; 
      } 
      if (renderPin != null) 
      { 
       Marshal.ReleaseComObject(renderPin); 
       renderPin = null; 
      } 
      if (samplePin != null) 
      { 
       Marshal.ReleaseComObject(samplePin); 
       samplePin = null; 
      } 
     } 
    } 

而且配置我samplegrabber這樣的:

public void configureSampleGrabber(ISampleGrabber sampleGrabber) 
    { 
     int hr; 
     AMMediaType mediaType = new AMMediaType(); 

     //Set the values for media type and format 
     mediaType.majorType = MediaType.Video; 
     mediaType.subType = MediaSubType.RGB24; 
     mediaType.formatType = FormatType.VideoInfo; 
     hr = sampleGrabber.SetMediaType(mediaType); 
     DsError.ThrowExceptionForHR(hr); 

     DsUtils.FreeAMMediaType(mediaType); 
     mediaType = null; 

     //Configure 
     hr = sampleGrabber.SetCallback(this, 0); 
     DsError.ThrowExceptionForHR(hr); 

    } 
+0

您繼續保存到相同的文件,這可能會導致併發寫入。 – Matthias

+0

這仍然不會留下文件的名稱?目前它不保存任何內容。除此之外,這是轉換圖像的正確方式嗎? – legohead

回答

1

樣品採集卡不會給正確的MediaType每個樣品抓住,所以也懶得從這裏的樣品請求它。取而代之的是獲取抓取器的輸入引腳或相機的輸出引腳,並調用IPin.ConnectionMediaType()來了解此流的正確媒體類型。

+0

我該如何去做這件事?我將捕獲和輸入引腳設置在另一個函數中?我會用這個方法更新這個問題。 – legohead

+0

您需要查詢引腳連接媒體類型,而不是媒體採樣媒體類型。媒體示例媒體類型具有不同的含義([記錄在MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/dd407009%28v=vs.85%29.aspx))。 –

1

我認爲你的圖形設置不正確,並且採樣從未通過採樣器。乍看之下,我認爲採樣卡從來不會被渲染。將示例抓取器輸出引腳連接到null渲染器,並且應該起作用。

+0

我在哪裏添加空渲染器?在'SampleCB'中還是在圖形制作過程中? – legohead

+1

在製圖過程中。將null渲染器添加到圖中,並將採樣器的輸出引腳連接到null渲染器。 – Saibal

+0

你能否向我解釋一下這個事情到底是什麼(只是想了解更多關於這個庫的信息)。 – legohead