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