Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpDirectShowSampleGrabberI.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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 https://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#ifndef DOXYGEN_SHOULD_SKIP_THIS
38
39#include <visp3/core/vpImageConvert.h>
40#include <visp3/sensor/vpDirectShowSampleGrabberI.h>
41
42#include <visp3/core/vpConfig.h>
43#if (defined(VISP_HAVE_DIRECTSHOW))
44
49vpDirectShowSampleGrabberI::vpDirectShowSampleGrabberI()
50 : acqGrayDemand(false), acqRGBaDemand(false), specialMediaType(false), invertedSource(false)
51{
52 // semaphore(0), max value = 1
53 copySem = CreateSemaphore(nullptr, 0, 1, nullptr);
54}
55
59vpDirectShowSampleGrabberI::~vpDirectShowSampleGrabberI()
60{
61 // destroys the semaphore
62 CloseHandle(copySem);
63}
64
65STDMETHODIMP vpDirectShowSampleGrabberI::QueryInterface(REFIID riid, void **ppvObject)
66{
67 if (nullptr == ppvObject)
68 return E_POINTER;
69 if (riid == __uuidof(IUnknown)) {
70 *ppvObject = static_cast<IUnknown *>(this);
71 return S_OK;
72 }
73 if (riid == __uuidof(ISampleGrabberCB)) {
74 *ppvObject = static_cast<ISampleGrabberCB *>(this);
75 return S_OK;
76 }
77 return E_NOTIMPL;
78}
79
85STDMETHODIMP vpDirectShowSampleGrabberI::BufferCB(double Time, BYTE *pBuffer, long BufferLen)
86{
87 // if there has been a frame demand
88 if (acqGrayDemand || acqRGBaDemand) {
89 // check if the connected media is compatible
90 if (connectedMediaType.formattype == FORMAT_VideoInfo) {
91 // retrieve the image information
92 VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER *>(connectedMediaType.pbFormat);
93 BITMAPINFOHEADER bmpInfo = pVih->bmiHeader;
94
95 // if biHeight > 0 and the source is not special
96 // then the image needs to be vertically flipped
97 bool flip;
98 if (!specialMediaType)
99 flip = bmpInfo.biHeight >= 0;
100 // the source is fourcc and the image is inverted with this compression
101 else if (invertedSource)
102 flip = true;
103 // fourcc and the image doesn't need to be flipped
104 else
105 flip = false;
106
107 // if the buffer contains a RGB24 image (DS RGB24 <=> BGR)
108 if (connectedMediaType.subtype == MEDIASUBTYPE_RGB24) {
109 // if it was an RGBa image demand
110 if (acqRGBaDemand) {
111 // first, resizes the image as needed
112 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
113 // copy and convert the image
114 vpImageConvert::BGRToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap, rgbaIm->getWidth(), rgbaIm->getHeight(),
115 flip);
116 // reset the demand boolean
117 acqRGBaDemand = false;
118 }
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 }
129 else {
130 unsigned long FourCC;
131 FourCC = ((bmpInfo.biCompression & 0xFF000000) >> 24) | ((bmpInfo.biCompression & 0x00FF0000) >> 8) |
132 ((bmpInfo.biCompression & 0x0000FF00) << 8) | (bmpInfo.biCompression & 0x000000FF) << 24;
133 // if the buffer contains a like YUV420 image
134 if (connectedMediaType.subtype == MEDIASUBTYPE_IYUV || FourCC == 'I420') {
135 // if it was an RGBa image demand
136 if (acqRGBaDemand) {
137 // first, resizes the image as needed
138 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
139 // copy and convert the image
140 vpImageConvert::YUV420ToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap, rgbaIm->getWidth(),
141 rgbaIm->getHeight());
142 // reset the demand boolean
143 acqRGBaDemand = false;
144 }
145 else // if it was a grayscale image demand
146 {
147 // first, resizes the image as needed
148 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
149 // copy and convert the image
150 vpImageConvert::YUV420ToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
151 // reset the demand boolean
152 acqGrayDemand = false;
153 }
154
155 }
156 else if (connectedMediaType.subtype == MEDIASUBTYPE_YV12) {
157 // if it was an RGBa image demand
158 if (acqRGBaDemand) {
159 // first, resizes the image as needed
160 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
161 // copy and convert the image
162 vpImageConvert::YV12ToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap, rgbaIm->getWidth(),
163 rgbaIm->getHeight());
164 // reset the demand boolean
165 acqRGBaDemand = false;
166 }
167 else // if it was a grayscale image demand
168 {
169 // first, resizes the image as needed
170 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
171 // copy and convert the image
172 vpImageConvert::YUV420ToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
173 // reset the demand boolean
174 acqGrayDemand = false;
175 }
176 }
177 else if (connectedMediaType.subtype == MEDIASUBTYPE_YVU9) {
178 // if it was an RGBa image demand
179 if (acqRGBaDemand) {
180 // first, resizes the image as needed
181 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
182 // copy and convert the image
183 vpImageConvert::YVU9ToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap, rgbaIm->getWidth(),
184 rgbaIm->getHeight());
185 // reset the demand boolean
186 acqRGBaDemand = false;
187 }
188 else // if it was a grayscale image demand
189 {
190 // first, resizes the image as needed
191 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
192 // copy and convert the image
193 vpImageConvert::YUV420ToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
194 // reset the demand boolean
195 acqGrayDemand = false;
196 }
197 }
198 else if (connectedMediaType.subtype == MEDIASUBTYPE_YUY2 || connectedMediaType.subtype == MEDIASUBTYPE_YUYV) {
199 // if it was an RGBa image demand
200 if (acqRGBaDemand) {
201 // first, resizes the image as needed
202 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
203 // copy and convert the image
204 vpImageConvert::YCbCrToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap,
205 rgbaIm->getWidth() * rgbaIm->getHeight());
206 // reset the demand boolean
207 acqRGBaDemand = false;
208 }
209 else // if it was a grayscale image demand
210 {
211 // first, resizes the image as needed
212 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
213 // copy and convert the image
214 vpImageConvert::YCbCrToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
215 // reset the demand boolean
216 acqGrayDemand = false;
217 }
218 }
219 else if (connectedMediaType.subtype == MEDIASUBTYPE_YVYU) {
220 // if it was an RGBa image demand
221 if (acqRGBaDemand) {
222 // first, resizes the image as needed
223 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
224 // copy and convert the image
225 vpImageConvert::YCrCbToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap,
226 rgbaIm->getWidth() * rgbaIm->getHeight());
227 // reset the demand boolean
228 acqRGBaDemand = false;
229 }
230 else // if it was a grayscale image demand
231 {
232 // first, resizes the image as needed
233 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
234 // copy and convert the image
235 vpImageConvert::YCbCrToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
236 // reset the demand boolean
237 acqGrayDemand = false;
238 }
239 }
240 else if (connectedMediaType.subtype == MEDIASUBTYPE_UYVY) {
241 // if it was an RGBa image demand
242 if (acqRGBaDemand) {
243 // first, resizes the image as needed
244 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
245 // copy and convert the image
246 vpImageConvert::YUV422ToRGBa(pBuffer, (unsigned char *)rgbaIm->bitmap,
247 rgbaIm->getWidth() * rgbaIm->getHeight());
248 // reset the demand boolean
249 acqRGBaDemand = false;
250 }
251 else // if it was a grayscale image demand
252 {
253 // first, resizes the image as needed
254 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
255 // copy and convert the image
256 vpImageConvert::YUV422ToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
257 // reset the demand boolean
258 acqGrayDemand = false;
259 }
260 }
261 else if (connectedMediaType.subtype == MEDIASUBTYPE_RGB32) {
262 // if it was an RGBa image demand
263 if (acqRGBaDemand) {
264 // first, resizes the image as needed
265 rgbaIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
266 // copy and convert the image
267 // copy(pBuffer ,pBuffer +
268 // 4*rgbaIm->getWidth()*rgbaIm->getHeight(),rgbaIm->bitmap);
269 memcpy(rgbaIm->bitmap, pBuffer, 4 * rgbaIm->getWidth() * rgbaIm->getHeight());
270 // reset the demand boolean
271 acqRGBaDemand = false;
272 }
273 else // if it was a grayscale image demand
274 {
275 // first, resizes the image as needed
276 grayIm->resize(abs(bmpInfo.biHeight), bmpInfo.biWidth);
277 // copy and convert the image
278 vpImageConvert::RGBaToGrey(pBuffer, grayIm->bitmap, grayIm->getWidth() * grayIm->getHeight());
279 // reset the demand boolean
280 acqGrayDemand = false;
281 }
282 }
283 }
284 }
285
286 // increment the semaphore - allows acquire to continue execution
287 ReleaseSemaphore(copySem, 1, nullptr);
288 }
289 return S_OK;
290}
291END_VISP_NAMESPACE
292#elif !defined(VISP_BUILD_SHARED_LIBS)
293// Work around to avoid warning:
294// libvisp_sensor.a(vpDirectShowSampleGrabberI.cpp.o) has no symbols
295void dummy_vpDirectShowSampleGrabberI() { }
296#endif
297
298#endif
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 YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV420ToGrey(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 RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)