Visual Servoing Platform  version 3.0.0
vpDirectShowSampleGrabberI.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * DirectShow framegrabber.
32  *
33  * Authors:
34  * Bruno Renier
35  * Anthony Saunier
36  *
37  *****************************************************************************/
38 #ifndef DOXYGEN_SHOULD_SKIP_THIS
39 
40 #include <visp3/sensor/vpDirectShowSampleGrabberI.h>
41 #include <visp3/core/vpImageConvert.h>
42 
43 #include <visp3/core/vpConfig.h>
44 #if ( defined(VISP_HAVE_DIRECTSHOW) )
45 
46 
47 
51 vpDirectShowSampleGrabberI::vpDirectShowSampleGrabberI()
52  : acqGrayDemand(false), acqRGBaDemand(false), specialMediaType(false), invertedSource(false)
53 {
54  //semaphore(0), max value = 1
55  copySem = CreateSemaphore (NULL,0,1,NULL);
56 }
57 
61 vpDirectShowSampleGrabberI::~vpDirectShowSampleGrabberI()
62 {
63  //destroys the semaphore
64  CloseHandle(copySem);
65 }
66 
67 
68 STDMETHODIMP vpDirectShowSampleGrabberI::QueryInterface(REFIID riid, void **ppvObject)
69 {
70  if (NULL == ppvObject) return E_POINTER;
71  if (riid == __uuidof(IUnknown))
72  {
73  *ppvObject = static_cast<IUnknown*>(this);
74  return S_OK;
75  }
76  if (riid == __uuidof(ISampleGrabberCB))
77  {
78  *ppvObject = static_cast<ISampleGrabberCB*>(this);
79  return S_OK;
80  }
81  return E_NOTIMPL;
82 }
83 
89 STDMETHODIMP vpDirectShowSampleGrabberI::BufferCB(double Time, BYTE *pBuffer, long BufferLen)
90 {
91  //if there has been a frame demand
92  if(acqGrayDemand || acqRGBaDemand)
93  {
94  //check if the connected media is compatible
95  if(connectedMediaType.formattype==FORMAT_VideoInfo)
96  {
97  //retrieve the image information
98  VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(connectedMediaType.pbFormat);
99  BITMAPINFOHEADER bmpInfo = pVih->bmiHeader;
100 
101  //if biHeight > 0 and the source is not special
102  //then the image needs to be verticaly flipped
103  bool flip;
104  if(!specialMediaType)
105  flip = bmpInfo.biHeight>=0;
106  //the source is fourcc and the image is inverted with this compression
107  else if(invertedSource)
108  flip = true;
109  //fourcc and the image doesn't need to be flipped
110  else
111  flip = false;
112 
113  //if the buffer contains a RGB24 image (DS RGB24 <=> BGR)
114  if(connectedMediaType.subtype==MEDIASUBTYPE_RGB24)
115  {
116  //if it was an RGBa image demand
117  if(acqRGBaDemand)
118  {
119  //first, resizes the image as needed
120  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
121  //copy and convert the image
122  vpImageConvert::BGRToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
123  rgbaIm->getWidth() , rgbaIm->getHeight(), flip);
124  //reset the demand boolean
125  acqRGBaDemand = false;
126  }
127  else//if it was a grayscale image demand
128  {
129  //first, resizes the image as needed
130  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
131  //copy and convert the image
132  vpImageConvert::BGRToGrey(pBuffer, grayIm->bitmap,
133  grayIm->getWidth(), grayIm->getHeight(), flip);
134  //reset the demand boolean
135  acqGrayDemand = false;
136  }
137  }
138  else
139  {
140  unsigned long FourCC;
141  FourCC = ((bmpInfo.biCompression&0xFF000000)>>24) |
142  ((bmpInfo.biCompression&0x00FF0000)>>8) |
143  ((bmpInfo.biCompression&0x0000FF00)<<8) |
144  (bmpInfo.biCompression&0x000000FF)<<24;
145  //if the buffer contains a like YUV420 image
146  if(connectedMediaType.subtype==MEDIASUBTYPE_IYUV || FourCC == 'I420')
147  {
148  //if it was an RGBa image demand
149  if(acqRGBaDemand)
150  {
151  //first, resizes the image as needed
152  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
153  //copy and convert the image
154  vpImageConvert::YUV420ToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
155  rgbaIm->getWidth() , rgbaIm->getHeight());
156  //reset the demand boolean
157  acqRGBaDemand = false;
158  }
159  else//if it was a grayscale image demand
160  {
161  //first, resizes the image as needed
162  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
163  //copy and convert the image
164  vpImageConvert::YUV420ToGrey(pBuffer, grayIm->bitmap,
165  grayIm->getWidth() * grayIm->getHeight());
166  //reset the demand boolean
167  acqGrayDemand = false;
168  }
169 
170  }
171  else if(connectedMediaType.subtype==MEDIASUBTYPE_YV12)
172  {
173  //if it was an RGBa image demand
174  if(acqRGBaDemand)
175  {
176  //first, resizes the image as needed
177  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
178  //copy and convert the image
179  vpImageConvert::YV12ToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
180  rgbaIm->getWidth() , rgbaIm->getHeight());
181  //reset the demand boolean
182  acqRGBaDemand = false;
183  }
184  else//if it was a grayscale image demand
185  {
186  //first, resizes the image as needed
187  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
188  //copy and convert the image
189  vpImageConvert::YUV420ToGrey(pBuffer, grayIm->bitmap,
190  grayIm->getWidth() * grayIm->getHeight());
191  //reset the demand boolean
192  acqGrayDemand = false;
193  }
194  }
195  else if(connectedMediaType.subtype==MEDIASUBTYPE_YVU9)
196  {
197  //if it was an RGBa image demand
198  if(acqRGBaDemand)
199  {
200  //first, resizes the image as needed
201  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
202  //copy and convert the image
203  vpImageConvert::YVU9ToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
204  rgbaIm->getWidth() , rgbaIm->getHeight());
205  //reset the demand boolean
206  acqRGBaDemand = false;
207  }
208  else//if it was a grayscale image demand
209  {
210  //first, resizes the image as needed
211  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
212  //copy and convert the image
213  vpImageConvert::YUV420ToGrey(pBuffer, grayIm->bitmap,
214  grayIm->getWidth() * grayIm->getHeight());
215  //reset the demand boolean
216  acqGrayDemand = false;
217  }
218  }
219  else if(connectedMediaType.subtype==MEDIASUBTYPE_YUY2 ||
220  connectedMediaType.subtype==MEDIASUBTYPE_YUYV)
221  {
222  //if it was an RGBa image demand
223  if(acqRGBaDemand)
224  {
225  //first, resizes the image as needed
226  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
227  //copy and convert the image
228  vpImageConvert::YCbCrToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
229  rgbaIm->getWidth()*rgbaIm->getHeight());
230  //reset the demand boolean
231  acqRGBaDemand = false;
232  }
233  else//if it was a grayscale image demand
234  {
235  //first, resizes the image as needed
236  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
237  //copy and convert the image
238  vpImageConvert::YCbCrToGrey(pBuffer, grayIm->bitmap,
239  grayIm->getWidth() * grayIm->getHeight());
240  //reset the demand boolean
241  acqGrayDemand = false;
242  }
243  }
244  else if(connectedMediaType.subtype==MEDIASUBTYPE_YVYU)
245  {
246  //if it was an RGBa image demand
247  if(acqRGBaDemand)
248  {
249  //first, resizes the image as needed
250  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
251  //copy and convert the image
252  vpImageConvert::YCrCbToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
253  rgbaIm->getWidth()*rgbaIm->getHeight());
254  //reset the demand boolean
255  acqRGBaDemand = false;
256  }
257  else//if it was a grayscale image demand
258  {
259  //first, resizes the image as needed
260  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
261  //copy and convert the image
262  vpImageConvert::YCbCrToGrey(pBuffer, grayIm->bitmap,
263  grayIm->getWidth() * grayIm->getHeight());
264  //reset the demand boolean
265  acqGrayDemand = false;
266  }
267  }
268  else if(connectedMediaType.subtype==MEDIASUBTYPE_UYVY)
269  {
270  //if it was an RGBa image demand
271  if(acqRGBaDemand)
272  {
273  //first, resizes the image as needed
274  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
275  //copy and convert the image
276  vpImageConvert::YUV422ToRGBa(pBuffer,(unsigned char*) rgbaIm->bitmap,
277  rgbaIm->getWidth()*rgbaIm->getHeight());
278  //reset the demand boolean
279  acqRGBaDemand = false;
280  }
281  else//if it was a grayscale image demand
282  {
283  //first, resizes the image as needed
284  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
285  //copy and convert the image
286  vpImageConvert::YUV422ToGrey(pBuffer, grayIm->bitmap,
287  grayIm->getWidth() * grayIm->getHeight());
288  //reset the demand boolean
289  acqGrayDemand = false;
290  }
291  }
292  else if(connectedMediaType.subtype==MEDIASUBTYPE_RGB32)
293  {
294  //if it was an RGBa image demand
295  if(acqRGBaDemand)
296  {
297  //first, resizes the image as needed
298  rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
299  //copy and convert the image
300  //copy(pBuffer ,pBuffer + 4*rgbaIm->getWidth()*rgbaIm->getHeight(),rgbaIm->bitmap);
301  memcpy(rgbaIm->bitmap,pBuffer ,4*rgbaIm->getWidth()*rgbaIm->getHeight());
302  //reset the demand boolean
303  acqRGBaDemand = false;
304  }
305  else//if it was a grayscale image demand
306  {
307  //first, resizes the image as needed
308  grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
309  //copy and convert the image
310  vpImageConvert::RGBaToGrey(pBuffer, grayIm->bitmap,
311  grayIm->getWidth() * grayIm->getHeight());
312  //reset the demand boolean
313  acqGrayDemand = false;
314  }
315  }
316  }
317  }
318 
319  //increment the semaphore - allows acquire to continue execution
320  ReleaseSemaphore(copySem, 1, NULL);
321  }
322  return S_OK;
323 }
324 
325 #elif !defined(VISP_BUILD_SHARED_LIBS)
326 // Work arround to avoid warning: libvisp_sensor.a(vpDirectShowSampleGrabberI.cpp.o) has no symbols
327 void dummy_vpDirectShowSampleGrabberI() {};
328 #endif
329 
330 #endif
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YCrCbToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)