UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
DirectShowGrabber.cpp File Reference
#include <cassert>
#include <cstdio>
#include <iostream>
#include <string>
#include <tchar.h>
#include <dshow.h>
#include <dvdmedia.h>
#include <qedit.h>
#include <oleauto.h>
#include <windows.h>
#include "debug.h"
#include "lib_common.h"
#include "tv.h"
#include "utils/color_out.h"
#include "utils/macros.h"
#include "utils/string.h"
#include "video.h"
#include "video_capture.h"
Include dependency graph for DirectShowGrabber.cpp:

Go to the source code of this file.

Classes

class  SampleGrabberCallback
 
struct  vidcap_dshow_state
 

Macros

#define DEFAULT_DEVNUM   1
 
#define DEFAULT_FPS   15
 
#define DEFAULT_VIDEO_HEIGHT   480
 
#define DEFAULT_VIDEO_WIDTH   640
 
#define GUID_FROM_FOURCC(fourcc)
 
#define HANDLE_ERR(msg, ...)
 
#define HANDLE_ERR(msg, ...)
 
#define HANDLE_ERR(msg, ...)
 
#define HANDLE_ERR(msg, ...)
 
#define HANDLE_ERR_ACTION(res, action, msg, ...)
 
#define MAX_STRING_LEN   1000
 
#define MAX_YUV_CLAMP   535
 
#define MIN_YUV_CLAMP   -276
 
#define MOD_NAME   "[dshow] "
 

Typedefs

typedef void(* convert_t) (int width, int height, const unsigned char *in, unsigned char *out)
 

Functions

static void abgr_flip_and_swap (int width, int height, const unsigned char *in, unsigned char *out)
 convert from ABGR and bottom-to-top
 
static void bgr_flip_lines (int width, int height, const unsigned char *in, unsigned char *out)
 
static bool cleanup (struct vidcap_dshow_state *s)
 
static bool common_init (struct vidcap_dshow_state *s)
 
static HRESULT ConnectFilters (IGraphBuilder *g, IBaseFilter *fromFilter, IBaseFilter *toFilter)
 
static HRESULT ConnectFilters (IGraphBuilder *g, IPin *fromPin, IBaseFilter *toFilter)
 
static void convert_yuv_rgb (BYTE y, BYTE u, BYTE v, BYTE *dst)
 
static void convert_yuyv_rgb (BYTE *src, BYTE *dst, int input_len)
 
static void DeleteMediaType (AM_MEDIA_TYPE *mediaType)
 
static void ErrorDescription (HRESULT hr)
 
static HRESULT FindUnconnectedPin (IBaseFilter *filter, PIN_DIRECTION direction, IPin **pin)
 
static void FreeMediaType (AM_MEDIA_TYPE &mt)
 
static convert_t get_conversion (const GUID *pSubtype)
 
static string get_friendly_name (IMoniker *moniker, int idx=-1)
 
static codec_t get_ug_codec (const GUID *pSubtype)
 
static codec_t get_ug_from_subtype_name (const char *subtype_name)
 
static HRESULT GetPinCategory (IPin *pPin, GUID *pPinCategory)
 
static const CHAR * GetSubtypeName (const GUID *pSubtype)
 
static const CHAR * GetSubtypeNameA (const GUID *pSubtype)
 
static HRESULT GraphPause (IMediaControl *mc)
 
static HRESULT GraphRun (IMediaControl *mc)
 
static int LocateSubtype (const GUID *pSubtype)
 
static void nv12_to_uyvy (int width, int height, const unsigned char *in, unsigned char *out)
 
static HRESULT PinHasDirection (IPin *pin, PIN_DIRECTION direction, bool *result)
 
static HRESULT PinIsConnected (IPin *pin, bool *result)
 
static bool process_args (struct vidcap_dshow_state *s, char *init_fmt)
 
 REGISTER_MODULE (dshow, &vidcap_dshow_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION)
 
static void show_help (struct vidcap_dshow_state *s, const char *help_str)
 
static void vidcap_dshow_done (void *state)
 
static struct video_desc vidcap_dshow_get_video_desc (AM_MEDIA_TYPE *mediaType)
 
static struct video_frame * vidcap_dshow_grab (void *state, struct audio_frame **audio)
 
static int vidcap_dshow_init (struct vidcap_params *params, void **state)
 
static void vidcap_dshow_probe (device_info **available_cards, int *count, void(**deleter)(void *))
 
static void vidcap_dshow_probe_internal (device_info **available_cards, int *count, void(**deleter)(void *), bool include_unsupported)
 
static void vidcap_dshow_should_exit (void *state)
 

Variables

struct { 
 
   convert_t   convert 
 
   const CHAR *   pName 
 
   const GUID *   pSubtype 
 
   codec_t   ug_codec 
 
} BitCountMap [] 
 
EXTERN_C const CLSID CLSID_NullRenderer
 
EXTERN_C const CLSID CLSID_SampleGrabber
 
static const GUID GUID_AV01 = GUID_FROM_FOURCC(to_fourcc('A', 'V', '0', '1'))
 
static const GUID GUID_H264 = GUID_FROM_FOURCC(to_fourcc('H', '2', '6', '4'))
 
static const GUID GUID_HDYC = GUID_FROM_FOURCC(0x43594448)
 
static const GUID GUID_HEVC = GUID_FROM_FOURCC(to_fourcc('H', 'E', 'V', 'C'))
 
static const GUID GUID_I420 = GUID_FROM_FOURCC(0x30323449)
 
static const GUID GUID_R210 = GUID_FROM_FOURCC(0x30313272)
 
static const GUID GUID_V210 = GUID_FROM_FOURCC(0x30313256)
 
static const GUID GUID_v210 = GUID_FROM_FOURCC(0x30313276)
 
const struct video_capture_info vidcap_dshow_info
 
static int * yuv_clamp
 

Detailed Description

Author
Pavel Troubil
Martin Pulec marti.nosp@m.n.pu.nosp@m.lec@c.nosp@m.esne.nosp@m.t.cz

Defines the exported functions for the DLL application.

Definition in file DirectShowGrabber.cpp.

Macro Definition Documentation

◆ DEFAULT_DEVNUM

#define DEFAULT_DEVNUM   1

Definition at line 59 of file DirectShowGrabber.cpp.

◆ DEFAULT_FPS

#define DEFAULT_FPS   15

Definition at line 63 of file DirectShowGrabber.cpp.

Referenced by common_init().

◆ DEFAULT_VIDEO_HEIGHT

#define DEFAULT_VIDEO_HEIGHT   480

Definition at line 62 of file DirectShowGrabber.cpp.

Referenced by common_init().

◆ DEFAULT_VIDEO_WIDTH

#define DEFAULT_VIDEO_WIDTH   640

Definition at line 61 of file DirectShowGrabber.cpp.

Referenced by common_init().

◆ GUID_FROM_FOURCC

#define GUID_FROM_FOURCC ( fourcc)
Value:
{fourcc, 0x0000, 0x10, {0x80,0x0,0x0,0xAA,0x0,0x38,0x9B,0x71}}

Definition at line 1319 of file DirectShowGrabber.cpp.

◆ HANDLE_ERR [1/4]

#define HANDLE_ERR ( msg,
... )
Value:
HANDLE_ERR_ACTION(res, goto error, \
"vidcap_dshow_init: " msg __VA_OPT__(, ) \
__VA_ARGS__)
#define HANDLE_ERR_ACTION(res, action, msg,...)

Referenced by common_init(), get_friendly_name(), vidcap_dshow_init(), and vidcap_dshow_probe_internal().

◆ HANDLE_ERR [2/4]

#define HANDLE_ERR ( msg,
... )
Value:
HANDLE_ERR_ACTION(res, return {}, "%s: " msg, \
__func__ __VA_OPT__(, ) __VA_ARGS__)
struct msghdr msg

◆ HANDLE_ERR [3/4]

#define HANDLE_ERR ( msg,
... )
Value:
HANDLE_ERR_ACTION(res, continue, "vidcap_dshow_help: %s: " msg, \
name __VA_OPT__(, ) __VA_ARGS__)
const char * name
Definition settings.cpp:193

◆ HANDLE_ERR [4/4]

#define HANDLE_ERR ( msg,
... )
Value:
HANDLE_ERR_ACTION(res, goto error, \
"vidcap_dshow_init: " msg __VA_OPT__(, ) __VA_ARGS__)

◆ HANDLE_ERR_ACTION

#define HANDLE_ERR_ACTION ( res,
action,
msg,
... )
Value:
if (res != S_OK) { \
MSG(ERROR, msg ": %s\n", \
__VA_ARGS__ __VA_OPT__(, ) hresult_to_str(res)); \
action; \
} else

Definition at line 224 of file DirectShowGrabber.cpp.

224#define HANDLE_ERR_ACTION(res, action, msg, ...) \
225 if (res != S_OK) { \
226 MSG(ERROR, msg ": %s\n", \
227 __VA_ARGS__ __VA_OPT__(, ) hresult_to_str(res)); \
228 action; \
229 } else

◆ MAX_STRING_LEN

#define MAX_STRING_LEN   1000

Definition at line 60 of file DirectShowGrabber.cpp.

Referenced by get_friendly_name().

◆ MAX_YUV_CLAMP

#define MAX_YUV_CLAMP   535

Definition at line 65 of file DirectShowGrabber.cpp.

Referenced by vidcap_dshow_init().

◆ MIN_YUV_CLAMP

#define MIN_YUV_CLAMP   -276

Definition at line 66 of file DirectShowGrabber.cpp.

Referenced by vidcap_dshow_init().

◆ MOD_NAME

Typedef Documentation

◆ convert_t

typedef void(* convert_t) (int width, int height, const unsigned char *in, unsigned char *out)

Definition at line 37 of file DirectShowGrabber.cpp.

Function Documentation

◆ abgr_flip_and_swap()

static void abgr_flip_and_swap ( int width,
int height,
const unsigned char * in,
unsigned char * out )
static

convert from ABGR and bottom-to-top

Definition at line 1306 of file DirectShowGrabber.cpp.

1308{
1309 const size_t linesize = vc_get_linesize(width, RGBA);
1310 for (int i = 0; i < height; ++i) {
1311 vc_copylineRGBA(out + i * linesize,
1312 in + (height - i - 1) * linesize, linesize, 16,
1313 8, 0);
1314 }
1315}
int vc_get_linesize(unsigned int width, codec_t codec)
decoder_func_t vc_copylineRGBA
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70

References RGBA, vc_copylineRGBA, and vc_get_linesize().

Here is the call graph for this function:

◆ bgr_flip_lines()

static void bgr_flip_lines ( int width,
int height,
const unsigned char * in,
unsigned char * out )
static

Apparently DirectShow uses bottom-to-top line ordering so we want make it top-to-bottom

Definition at line 1294 of file DirectShowGrabber.cpp.

1296{
1297 const size_t linesize = vc_get_linesize(width, BGR);
1298 for (int i = 0; i < height; ++i) {
1299 memcpy(out + i * linesize, in + (height - i - 1) * linesize,
1300 linesize);
1301 }
1302}
@ BGR
8-bit BGR
Definition types.h:88

References BGR, and vc_get_linesize().

Here is the call graph for this function:

◆ cleanup()

static bool cleanup ( struct vidcap_dshow_state * s)
static

Definition at line 185 of file DirectShowGrabber.cpp.

185 {
186 if (s->mediaControl != NULL) s->mediaControl->Release();
187 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Released: mediaControl\n");
188 if (s->nullRenderer != NULL) s->nullRenderer->Release();
189 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Released: nullRenderer\n");
190 if (s->captureFilter != NULL) s->captureFilter->Release();
191 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Released: captureFilter\n");
192 if (s->sampleGrabberFilter != NULL) s->sampleGrabberFilter->Release();
193 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Released: sampleGrabberFilter\n");
194 if (s->moniker != NULL) s->moniker->Release();
195 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Released: moniker\n");
196 /*
197 if (s->videoInputEnumerator != NULL) s->videoInputEnumerator->Release();
198 fprintf(stderr, "[dshow] Released: videoInputEnum\n");
199 if (s->devEnumerator != NULL) s->devEnumerator->Release();
200 fprintf(stderr, "[dshow] Released: devEnum\n");
201 if (s->filterGraph != NULL) s->filterGraph->Release();
202 fprintf(stderr, "[dshow] Released: filterGraph\n");
203 if (s->graphBuilder != NULL) s->graphBuilder->Release();
204 fprintf(stderr, "[dshow] Released: graphBuilder\n");
205 */
206
207 // COM library uninitialization
209
210 if (s->frame != NULL) vf_free(s->frame);
211 if (s->grabBuffer != NULL) free(s->grabBuffer);
212 if (s->returnBuffer != NULL) free(s->returnBuffer);
213 if (s->convert_buffer != NULL) free(s->convert_buffer);
214 if (yuv_clamp != NULL) free(yuv_clamp);
215 free(s->deviceName);
216
217 DeleteCriticalSection(&s->returnBufferCS);
218
219 free(s);
220
221 return true;
222}
static int * yuv_clamp
#define MOD_NAME
void vf_free(struct video_frame *buf)
Frees video_frame structure.
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
IBaseFilter * sampleGrabberFilter
IMediaControl * mediaControl
struct video_frame * frame
CRITICAL_SECTION returnBufferCS
void com_uninitialize(bool *com_initialized)
Definition windows.c:94

References vidcap_dshow_state::captureFilter, vidcap_dshow_state::com_initialized, com_uninitialize(), vidcap_dshow_state::convert_buffer, vidcap_dshow_state::deviceName, vidcap_dshow_state::frame, vidcap_dshow_state::grabBuffer, LOG_LEVEL_VERBOSE, log_msg(), vidcap_dshow_state::mediaControl, MOD_NAME, vidcap_dshow_state::moniker, vidcap_dshow_state::nullRenderer, vidcap_dshow_state::returnBuffer, vidcap_dshow_state::returnBufferCS, vidcap_dshow_state::sampleGrabberFilter, vf_free(), and yuv_clamp.

Here is the call graph for this function:

◆ common_init()

static bool common_init ( struct vidcap_dshow_state * s)
static

Definition at line 231 of file DirectShowGrabber.cpp.

231 {
232#define HANDLE_ERR(msg, ...) \
233 HANDLE_ERR_ACTION(res, goto error, \
234 "vidcap_dshow_init: " msg __VA_OPT__(, ) \
235 __VA_ARGS__)
236 // set defaults
237 s->deviceNumber = 1;
238 s->modeNumber = 0;
241 s->desc.fps = DEFAULT_FPS;
242 s->desc.tile_count = 1;
244 s->com_initialized = false;
245
246 s->frame = NULL;
247 s->grabBufferLen = 0;
248 s->returnBufferLen = 0;
249 s->grabBuffer = NULL;
250 s->returnBuffer = NULL;
251 s->convert_buffer = NULL;
252 s->convert_YUYV_RGB = false;
253 s->no_sync_source = false;
254 yuv_clamp = NULL;
255
256 s->graphBuilder = NULL;
257 s->filterGraph = NULL;
258 s->devEnumerator = NULL;
259 s->videoInputEnumerator = NULL;
260 s->moniker = NULL;
261 s->captureFilter = NULL;
262 s->nullRenderer = NULL;
263 s->sampleGrabberFilter = NULL;
264 s->streamConfig = NULL;
265 s->mediaControl = NULL;
266
267 HRESULT res;
268
269 // Initialize COM library
270 // COINIT_APARTMENTTHREADED is used because we do not expect any other thread to work with the object
271 if (!com_initialize(&s->com_initialized, "widcap_dshow_init: ")) {
272 return false;
273 }
274
275 // Create non-inheritable mutex without a name, owned by this thread
276 InitializeCriticalSectionAndSpinCount(&s->returnBufferCS, 0x40);
277 s->haveNewReturnBuffer = false;
278
279 s->frames = 0;
280
281 // create device enumerator
282 res = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&s->devEnumerator));
283 HANDLE_ERR("Cannot create System Device Enumerator");
284
285 res = s->devEnumerator->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &s->videoInputEnumerator, 0);
286 if (res == S_FALSE) {
287 MSG(ERROR, "no devices found\n");
288 goto error;
289 }
290 HANDLE_ERR("Cannot create Video Input Device enumerator");
291
292 // Media processing classes (filters) are conected to a graph.
293 // Create graph builder -- helper class for connecting of the graph
294 res = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
295 IID_ICaptureGraphBuilder2, (void **) &s->graphBuilder);
296 HANDLE_ERR("Cannot create instance of Capture Graph Builder 2");
297
298 // create the filter graph
299 res = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
300 IID_IGraphBuilder, (void **) &s->filterGraph);
301 HANDLE_ERR("Cannot create instance of Filter Graph");
302
303 // specify the graph builder a graph to be built
304 res = s->graphBuilder->SetFiltergraph(s->filterGraph);
305 HANDLE_ERR("Cannot attach Filter Graph to Graph Builder");
306
307 return true;
308
309error:
310 cleanup(s);
311 return false;
312#undef HANDLE_ERR
313}
#define DEFAULT_VIDEO_HEIGHT
#define HANDLE_ERR(msg,...)
#define DEFAULT_VIDEO_WIDTH
#define DEFAULT_FPS
#define MSG(l, fmt,...)
Definition debug.h:96
static void cleanup()
Definition sdp.c:195
IEnumMoniker * videoInputEnumerator
struct video_desc desc
ICreateDevEnum * devEnumerator
IGraphBuilder * filterGraph
IAMStreamConfig * streamConfig
ICaptureGraphBuilder2 * graphBuilder
unsigned int tile_count
Definition types.h:185
enum interlacing_t interlacing
Definition types.h:184
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
@ PROGRESSIVE
progressive frame
Definition types.h:164
bool com_initialize(bool *com_initialized, const char *err_prefix)
Definition windows.c:65

References vidcap_dshow_state::captureFilter, cleanup(), com_initialize(), vidcap_dshow_state::com_initialized, vidcap_dshow_state::convert_buffer, vidcap_dshow_state::convert_YUYV_RGB, DEFAULT_FPS, DEFAULT_VIDEO_HEIGHT, DEFAULT_VIDEO_WIDTH, vidcap_dshow_state::desc, vidcap_dshow_state::devEnumerator, vidcap_dshow_state::deviceNumber, vidcap_dshow_state::filterGraph, video_desc::fps, vidcap_dshow_state::frame, vidcap_dshow_state::frames, vidcap_dshow_state::grabBuffer, vidcap_dshow_state::grabBufferLen, vidcap_dshow_state::graphBuilder, HANDLE_ERR, vidcap_dshow_state::haveNewReturnBuffer, video_desc::height, video_desc::interlacing, vidcap_dshow_state::mediaControl, vidcap_dshow_state::modeNumber, vidcap_dshow_state::moniker, MSG, vidcap_dshow_state::no_sync_source, vidcap_dshow_state::nullRenderer, PROGRESSIVE, vidcap_dshow_state::returnBuffer, vidcap_dshow_state::returnBufferCS, vidcap_dshow_state::returnBufferLen, vidcap_dshow_state::sampleGrabberFilter, vidcap_dshow_state::streamConfig, video_desc::tile_count, vidcap_dshow_state::videoInputEnumerator, video_desc::width, and yuv_clamp.

Referenced by show_help(), vidcap_dshow_init(), and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ ConnectFilters() [1/2]

static HRESULT ConnectFilters ( IGraphBuilder * g,
IBaseFilter * fromFilter,
IBaseFilter * toFilter )
static

Definition at line 745 of file DirectShowGrabber.cpp.

745 {
746 IPin *fromPin = NULL;
747
748 HRESULT res = FindUnconnectedPin(fromFilter, PINDIR_OUTPUT, &fromPin);
749 if (res == S_OK) {
750 res = ConnectFilters(g, fromPin, toFilter);
751 fromPin->Release();
752 }
753
754 return res;
755}
static HRESULT ConnectFilters(IGraphBuilder *g, IPin *fromPin, IBaseFilter *toFilter)
static HRESULT FindUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION direction, IPin **pin)

References ConnectFilters(), and FindUnconnectedPin().

Here is the call graph for this function:

◆ ConnectFilters() [2/2]

static HRESULT ConnectFilters ( IGraphBuilder * g,
IPin * fromPin,
IBaseFilter * toFilter )
static

Definition at line 733 of file DirectShowGrabber.cpp.

733 {
734 IPin *toPin = NULL;
735
736 HRESULT res = FindUnconnectedPin(toFilter, PINDIR_INPUT, &toPin);
737 if (res == S_OK) {
738 res = g->Connect(fromPin, toPin);
739 toPin->Release();
740 }
741
742 return res;
743}

References FindUnconnectedPin().

Referenced by ConnectFilters(), and vidcap_dshow_init().

Here is the call graph for this function:

◆ convert_yuv_rgb()

static void convert_yuv_rgb ( BYTE y,
BYTE u,
BYTE v,
BYTE * dst )
inlinestatic

Definition at line 1159 of file DirectShowGrabber.cpp.

1159 {
1160 int yy = (y - 16) * 298;
1161 int uu = u - 128;
1162 int vv = v - 128;
1163
1164 dst[0] = yuv_clamp[(yy + uu * 516 + 128) >> 8];
1165 dst[1] = yuv_clamp[(yy - uu * 100 - vv * 208 + 128) >> 8];
1166 dst[2] = yuv_clamp[(yy + 409 * vv + 128) >> 8];
1167}

References yuv_clamp.

Referenced by convert_yuyv_rgb().

◆ convert_yuyv_rgb()

static void convert_yuyv_rgb ( BYTE * src,
BYTE * dst,
int input_len )
static

Definition at line 1169 of file DirectShowGrabber.cpp.

1169 {
1170 BYTE *s = src;
1171 //BYTE *d = dst;
1172
1173 for (int i = 0; i < input_len; i += 4) {
1174 convert_yuv_rgb(s[0], s[1], s[3], dst);
1175 convert_yuv_rgb(s[2], s[1], s[3], dst + 3);
1176 s += 4;
1177 dst += 6;
1178 }
1179}
static void convert_yuv_rgb(BYTE y, BYTE u, BYTE v, BYTE *dst)
unsigned char BYTE
Definition crypt_aes.h:71

References convert_yuv_rgb().

Referenced by vidcap_dshow_grab().

Here is the call graph for this function:

◆ DeleteMediaType()

static void DeleteMediaType ( AM_MEDIA_TYPE * mediaType)
static

Definition at line 1260 of file DirectShowGrabber.cpp.

1260 {
1261 // allow NULL pointers for coding simplicity
1262
1263 if (pmt == NULL) {
1264 return;
1265 }
1266
1267 FreeMediaType(*pmt);
1268 CoTaskMemFree((PVOID)pmt);
1269}
static void FreeMediaType(AM_MEDIA_TYPE &mt)

References FreeMediaType().

Referenced by vidcap_dshow_init(), and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ ErrorDescription()

static void ErrorDescription ( HRESULT hr)
static

Definition at line 51 of file DirectShowGrabber.cpp.

52{
53 if(FACILITY_WINDOWS == HRESULT_FACILITY(hr))
54 hr = HRESULT_CODE(hr);
55
56 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Error: %s\n", get_win32_error(hr));
57}
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59

References LOG_LEVEL_ERROR, log_msg(), and MOD_NAME.

Referenced by GraphPause(), and GraphRun().

Here is the call graph for this function:

◆ FindUnconnectedPin()

static HRESULT FindUnconnectedPin ( IBaseFilter * filter,
PIN_DIRECTION direction,
IPin ** pin )
static

Definition at line 686 of file DirectShowGrabber.cpp.

686 {
687 IEnumPins *pinEnum = NULL;
688 IPin *filterPin = NULL;
689 bool pinFound;
690
691 HRESULT res = filter->EnumPins(&pinEnum);
692 if (res != S_OK) {
693 goto error;
694 }
695
696 pinFound = false;
697 while ((res = pinEnum->Next(1, &filterPin, NULL)) == S_OK) {
698 bool isConnected;
699 res = PinIsConnected(filterPin, &isConnected);
700 if (res == S_OK) {
701 if (isConnected) {
702 continue;
703 }
704 bool hasDirection;
705 res = PinHasDirection(filterPin, direction, &hasDirection);
706 if (res == S_OK) {
707 if (!hasDirection) continue;
708
709 // We found the pin!
710 *pin = filterPin;
711 (*pin)->AddRef();
712 pinFound = true;
713 break;
714 } else {
715 goto error;
716 }
717 } else {
718 goto error;
719 }
720 if (filterPin != NULL) filterPin->Release();
721 }
722
723 if (!pinFound) {
724 res = VFW_E_NOT_FOUND;
725 }
726
727error:
728 if (pinEnum != NULL) pinEnum->Release();
729 if (filterPin != NULL) filterPin->Release();
730 return res;
731}
static HRESULT PinIsConnected(IPin *pin, bool *result)
static HRESULT PinHasDirection(IPin *pin, PIN_DIRECTION direction, bool *result)
static af_result_code filter(void *state, struct audio_frame **frame)

References filter(), PinHasDirection(), and PinIsConnected().

Referenced by ConnectFilters(), and ConnectFilters().

Here is the call graph for this function:

◆ FreeMediaType()

static void FreeMediaType ( AM_MEDIA_TYPE & mt)
static

Definition at line 1245 of file DirectShowGrabber.cpp.

1246{
1247 if (mt.cbFormat != 0) {
1248 CoTaskMemFree((PVOID)mt.pbFormat);
1249
1250 // Strictly unnecessary but tidier
1251 mt.cbFormat = 0;
1252 mt.pbFormat = NULL;
1253 }
1254 if (mt.pUnk != NULL) {
1255 mt.pUnk->Release();
1256 mt.pUnk = NULL;
1257 }
1258}

Referenced by DeleteMediaType().

◆ get_conversion()

static convert_t get_conversion ( const GUID * pSubtype)
static

Definition at line 1365 of file DirectShowGrabber.cpp.

1366{
1367 return BitCountMap[LocateSubtype(pSubtype)].convert;
1368}
const GUID * pSubtype
static const struct @69 BitCountMap[]
static int LocateSubtype(const GUID *pSubtype)

References BitCountMap, LocateSubtype(), and pSubtype.

Referenced by vidcap_dshow_init().

Here is the call graph for this function:

◆ get_friendly_name()

static string get_friendly_name ( IMoniker * moniker,
int idx = -1 )
static

Definition at line 401 of file DirectShowGrabber.cpp.

402{
403#define HANDLE_ERR(msg, ...) \
404 HANDLE_ERR_ACTION(res, return {}, "%s: " msg, \
405 __func__ __VA_OPT__(, ) __VA_ARGS__)
406 IPropertyBag *properties = nullptr;
407 const string device_id = idx == -1 ? "" : to_string(idx) + " ";
408 // Attach structure for reading basic device properties
409 HRESULT res = moniker->BindToStorage(0, 0, IID_PPV_ARGS(&properties));
410 HANDLE_ERR("Failed to read device %s properties", device_id.c_str());
411
412 VARIANT var;
413 VariantInit(&var);
414 res = properties->Read(L"FriendlyName", &var, NULL);
415 HANDLE_ERR("Failed to read device %s FriendlyName", device_id.c_str());
416
417 char buf[MAX_STRING_LEN];
418 // convert to standard C string
419 wcstombs(buf, var.bstrVal, sizeof buf);
420
421 // clean up structures
422 VariantClear(&var);
423 properties->Release();
424
425 return buf;
426#undef HANDLE_ERR
427}
#define MAX_STRING_LEN

References HANDLE_ERR, and MAX_STRING_LEN.

Referenced by vidcap_dshow_init(), and vidcap_dshow_probe_internal().

◆ get_ug_codec()

static codec_t get_ug_codec ( const GUID * pSubtype)
static

Definition at line 1359 of file DirectShowGrabber.cpp.

1360{
1361 return BitCountMap[LocateSubtype(pSubtype)].ug_codec;
1362}

References BitCountMap, LocateSubtype(), and pSubtype.

Referenced by vidcap_dshow_get_video_desc(), vidcap_dshow_init(), and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ get_ug_from_subtype_name()

static codec_t get_ug_from_subtype_name ( const char * subtype_name)
static

Definition at line 1370 of file DirectShowGrabber.cpp.

1370 {
1371 for (unsigned int i = 0; i < sizeof BitCountMap / sizeof BitCountMap[0]; ++i) {
1372 if (strcmp(BitCountMap[i].pName, subtype_name) == 0) {
1373 return BitCountMap[i].ug_codec;
1374 }
1375 }
1376 return VIDEO_CODEC_NONE;
1377}
const CHAR * pName
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66

References BitCountMap, pName, and VIDEO_CODEC_NONE.

Referenced by process_args().

◆ GetPinCategory()

static HRESULT GetPinCategory ( IPin * pPin,
GUID * pPinCategory )
static

Definition at line 797 of file DirectShowGrabber.cpp.

798{
799 IKsPropertySet *pKs = NULL;
800
801 HRESULT hr = pPin->QueryInterface(IID_PPV_ARGS(&pKs));
802 if (FAILED(hr))
803 {
804 return hr;
805 }
806
807 // Try to retrieve the pin category.
808 DWORD cbReturned = 0;
809 hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
810 pPinCategory, sizeof(GUID), &cbReturned);
811
812 // If this succeeded, pPinCategory now contains the category GUID.
813
814 if (pKs != NULL) pKs->Release();
815 return hr;
816}
@ FAILED

References FAILED.

◆ GetSubtypeName()

static const CHAR * GetSubtypeName ( const GUID * pSubtype)
static

Definition at line 1419 of file DirectShowGrabber.cpp.

1420{
1421 // the type is unknown to us, so print FourCC
1422 if (LocateSubtype(pSubtype) == sizeof BitCountMap / sizeof BitCountMap[0] - 1) {
1423 return pretty_print_fourcc(&pSubtype->Data1);
1424 }
1425 return GetSubtypeNameA(pSubtype);
1426}
static const CHAR * GetSubtypeNameA(const GUID *pSubtype)
const char * pretty_print_fourcc(const void *fcc)

References BitCountMap, GetSubtypeNameA(), LocateSubtype(), pretty_print_fourcc(), and pSubtype.

Referenced by vidcap_dshow_init(), and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ GetSubtypeNameA()

static const CHAR * GetSubtypeNameA ( const GUID * pSubtype)
static

Definition at line 1412 of file DirectShowGrabber.cpp.

1413{
1414 return BitCountMap[LocateSubtype(pSubtype)].pName;
1415}

References BitCountMap, LocateSubtype(), and pSubtype.

Referenced by GetSubtypeName().

Here is the call graph for this function:

◆ GraphPause()

static HRESULT GraphPause ( IMediaControl * mc)
static

Definition at line 778 of file DirectShowGrabber.cpp.

778 {
779 HRESULT res;
780
781 if ((res = mc->Pause()) == S_FALSE) {
782 FILTER_STATE fs;
783
784 while ((res = mc->GetState(500, (OAFilterState*) &fs)) != VFW_S_CANT_CUE && !(res == S_OK && fs == State_Paused)) {
785 if (res != VFW_S_STATE_INTERMEDIATE && res != S_OK) break;
786 }
787 }
788
789 if (res != S_OK) {
790 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot pause filter graph.\n");
791 ErrorDescription(res);
792 }
793
794 return res;
795}
static void ErrorDescription(HRESULT hr)

References ErrorDescription(), LOG_LEVEL_ERROR, log_msg(), and MOD_NAME.

Here is the call graph for this function:

◆ GraphRun()

static HRESULT GraphRun ( IMediaControl * mc)
static

Definition at line 757 of file DirectShowGrabber.cpp.

757 {
758 HRESULT res;
759
760 if ((res = mc->Run()) == S_FALSE) {
761 FILTER_STATE fs;
762
763 while ((res = mc->GetState(500, (OAFilterState*) &fs)) != VFW_S_CANT_CUE && !(res == S_OK && fs == State_Running)) {
764 if (res != VFW_S_STATE_INTERMEDIATE && res != S_OK) {
765 break;
766 }
767 }
768 }
769
770 if (res != S_OK) {
771 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot run filter graph.\n");
772 ErrorDescription(res);
773 }
774
775 return res;
776}

References ErrorDescription(), LOG_LEVEL_ERROR, log_msg(), and MOD_NAME.

Here is the call graph for this function:

◆ LocateSubtype()

static int LocateSubtype ( const GUID * pSubtype)
static

Definition at line 1379 of file DirectShowGrabber.cpp.

1380{
1381 assert(pSubtype);
1382 const GUID *pMediaSubtype;
1383 INT iPosition = 0;
1384
1385/* this code is only to optain type data if UNKNOWN
1386 fprintf(stderr, "%s ", &pSubtype->Data1);
1387 fprintf(stderr, "%X ", pSubtype->Data1);
1388 fprintf(stderr, "%hX ", pSubtype->Data2);
1389 fprintf(stderr, "%hX ", pSubtype->Data3);
1390 for (int i = 0;i < 8; ++i)
1391 fprintf(stderr, "%.2hhX", pSubtype->Data4[i]);
1392*/
1393
1394 // Scan the mapping list seeing if the source GUID matches any known
1395 // bitmap subtypes, the list is terminated by a GUID_NULL entry
1396
1397 while (TRUE) {
1398 pMediaSubtype = BitCountMap[iPosition].pSubtype;
1399 if (IsEqualGUID(*pMediaSubtype,*pSubtype) ||
1400 IsEqualGUID(*pMediaSubtype,GUID_NULL)
1401 )
1402 {
1403 break;
1404 }
1405
1406 iPosition++;
1407 }
1408
1409 return iPosition;
1410}
#define TRUE

References BitCountMap, pSubtype, and TRUE.

Referenced by get_conversion(), get_ug_codec(), GetSubtypeName(), and GetSubtypeNameA().

◆ nv12_to_uyvy()

static void nv12_to_uyvy ( int width,
int height,
const unsigned char * in,
unsigned char * out )
static

Definition at line 1272 of file DirectShowGrabber.cpp.

1273{
1274 const int uyvy_linesize = vc_get_linesize(width, UYVY);
1275 for (ptrdiff_t y = 0; y < height; ++y) {
1276 const unsigned char *src_y = in + width * y;
1277 const unsigned char *src_cbcr =
1278 in + (ptrdiff_t) width * height + width * (y / 2);
1279 unsigned char *dst = out + y * uyvy_linesize;
1280
1281 OPTIMIZED_FOR(int x = 0; x < width / 2; ++x)
1282 {
1283 *dst++ = *src_cbcr++;
1284 *dst++ = *src_y++;
1285 *dst++ = *src_cbcr++;
1286 *dst++ = *src_y++;
1287 }
1288 }
1289}
#define OPTIMIZED_FOR
Definition macros.h:127
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71

References OPTIMIZED_FOR, UYVY, and vc_get_linesize().

Here is the call graph for this function:

◆ PinHasDirection()

static HRESULT PinHasDirection ( IPin * pin,
PIN_DIRECTION direction,
bool * result )
static

Definition at line 675 of file DirectShowGrabber.cpp.

675 {
676 PIN_DIRECTION pinDir;
677
678 HRESULT res = pin->QueryDirection(&pinDir);
679 if (res == S_OK) {
680 *result = (pinDir == direction);
681 }
682
683 return res;
684}

Referenced by FindUnconnectedPin().

◆ PinIsConnected()

static HRESULT PinIsConnected ( IPin * pin,
bool * result )
static

Definition at line 660 of file DirectShowGrabber.cpp.

660 {
661 IPin *connectedPin;
662
663 HRESULT res = pin->ConnectedTo(&connectedPin);
664 if (res == S_OK) {
665 *result = true;
666 } else if (res == VFW_E_NOT_CONNECTED) {
667 res = S_OK;
668 *result = false;
669 }
670
671 if (connectedPin != NULL) connectedPin->Release();
672 return res;
673}

Referenced by FindUnconnectedPin().

◆ process_args()

static bool process_args ( struct vidcap_dshow_state * s,
char * init_fmt )
static

Definition at line 554 of file DirectShowGrabber.cpp.

554 {
555 char *token;
556 char *strtok_context;
557 int i = 1;
558
559 if (strchr(init_fmt, '=') == NULL) { // positional arguments
560 while ((token = strtok_s(init_fmt, ":", &strtok_context)) != NULL) {
561 init_fmt = NULL;
562 switch (i) {
563 case 1 :
564 if (strstr(token, "Device") == token) token = token + strlen("Device");
565 if (isdigit(token[0])) { // device specified by number
566 s->deviceNumber = atoi(token);
567 } else { // device specified by name
568 s->deviceName = (char *) malloc(sizeof(char) * (strlen(token) + 100));
569 if (s->deviceName == NULL) return false;
570 strcpy_s(s->deviceName, strlen(token) + 1, token);
571 s->deviceNumber = -1;
572 }
573 break;
574 case 2 :
575 if (strstr(token, "Mode") == token) token = token + strlen("Mode");
576 if (isdigit(token[0])) {
577 s->modeNumber = atoi(token);
578 } else {
579 s->modeNumber = -1;
581 if (s->desc.color_spec == VIDEO_CODEC_NONE) { // try Win subtype name
583 }
584 if (s->desc.color_spec == VIDEO_CODEC_NONE) {
587 "Unsupported video "
588 "format: %s. ",
589 token);
590 return false;
591 }
592 }
593 break;
594 case 3 :
595 if (s->modeNumber != -1) {
596 if (strcmp(token, "RGB") == 0) s->desc.color_spec = BGR;
597 else {
598 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unknown parameter: %s.\n", token);
599 return false;
600 }
601 break;
602 }
603 s->desc.width = atoi(token);
604 if (s->desc.width <= 0) {
605 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Invalid video width parameter: %s.\n", token);
606 return false;
607 }
608 break;
609 case 4 :
610 if (s->modeNumber != -1) break;
611 s->desc.height = atoi(token);
612 if (s->desc.height <= 0) {
613 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Invalid video height parameter: %s.\n", token);
614 return false;
615 }
616 break;
617 case 5 :
618 if (s->modeNumber != -1) break;
619 s->desc.fps = atoi(token);
620 if (s->desc.fps <= 0) {
621 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Invalid video fps parameter: %s.\n", token);
622 return false;
623 }
624 break;
625 default :
626 log_msg(LOG_LEVEL_ERROR, MOD_NAME "More arguments than expected, ignoring.\n");
627 break;
628 }
629 i++;
630 }
631 } else {
632 while ((token = strtok_s(init_fmt, ":", &strtok_context)) != NULL) {
633 init_fmt = NULL;
634 if (IS_KEY_PREFIX(token, "device")) {
635 token = strchr(token, '=') + 1;
636 if (isdigit(token[0])) { // device specified by number
637 s->deviceNumber = atoi(token);
638 } else { // device specified by name
639 s->deviceName = (char *) malloc(sizeof(char) * (strlen(token) + 100));
640 strcpy_s(s->deviceName, strlen(token) + 1, token);
641 s->deviceNumber = -1;
642 }
643 } else if (IS_KEY_PREFIX(token, "mode")) {
644 token = strchr(token, '=') + 1;
645 s->modeNumber = atoi(token);
646 } else if (strcmp(token, "RGB") == 0) {
647 s->desc.color_spec = BGR;
648 } else if (strcmp(token, "no_sync_source") == 0) {
649 s->no_sync_source = true;
650 } else {
651 MSG(ERROR, "Unknown argument: %s\n", token);
652 return false;
653 }
654 }
655 }
656
657 return true;
658}
static codec_t get_ug_from_subtype_name(const char *subtype_name)
codec_t get_codec_from_name(const char *name)
void bug_msg(int level, const char *format,...)
prints the error with the advice to report the bug
Definition debug.cpp:379
#define IS_KEY_PREFIX(tok, key)
expands to true value if <k> from tok in format <k>=<v> is prefix of key
Definition macros.h:138
codec_t color_spec
Definition types.h:182

References BGR, bug_msg(), video_desc::color_spec, vidcap_dshow_state::desc, vidcap_dshow_state::deviceName, vidcap_dshow_state::deviceNumber, video_desc::fps, get_codec_from_name(), get_ug_from_subtype_name(), video_desc::height, IS_KEY_PREFIX, LOG_LEVEL_ERROR, log_msg(), MOD_NAME, vidcap_dshow_state::modeNumber, MSG, vidcap_dshow_state::no_sync_source, VIDEO_CODEC_NONE, and video_desc::width.

Referenced by vidcap_dshow_init().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( dshow ,
& vidcap_dshow_info,
LIBRARY_CLASS_VIDEO_CAPTURE ,
VIDEO_CAPTURE_ABI_VERSION  )

◆ show_help()

static void show_help ( struct vidcap_dshow_state * s,
const char * help_str )
static

Definition at line 351 of file DirectShowGrabber.cpp.

352{
353 const bool short_h = strcmp(help_str, "shorthelp") == 0;
354 const bool full_h = strcmp(help_str, "fullhelp") == 0;
355 printf("dshow grabber options:\n");
356 col() << SBOLD("\t-t dshow:[full|short]help") << "\n";
357 col() << SBOLD(SRED("\t-t dshow") << "[:device=<DeviceNumber>|<DeviceName>][:mode=<ModeNumber>][:RGB]") "\n";
358 col() << "\t Flag " << SBOLD("RGB") << " forces use of RGB codec, otherwise native is used if possible.\n";
359 printf("\tor\n");
360 col() << SBOLD(SRED("\t-t dshow:[Device]<DeviceNumber>:<codec>:<width>:<height>:<fps>")) "\n\n";
361
362 if (!common_init(s)) return;
363
364 color_printf("Devices:\n");
365 device_info *cards = nullptr;
366 int count = 0;
367 void (*deleter)(void *) = NULL;
368 vidcap_dshow_probe_internal(&cards, &count, &deleter, full_h);
369
370 // Enumerate all capture devices
371 for (int n = 0; n < count; ++n) {
372 color_printf("Device %d) " TERM_BOLD "%s\n" TERM_RESET, n + 1, cards[n].name);
373
374 if (short_h) {
375 continue;
376 }
377 int i = 0;
378 // iterate over all capabilities
379 while (strlen(cards[n].modes[i].id) > 0) {
380 fputs(i == 0 ? "" : i % 2 == 0 ? "\n" : "\t", stdout);
381 int mode_idx = -1;
382 sscanf(cards[n].modes[i].id, "{\"mode\":\"%d", &mode_idx);
383 UG_ASSERT_NO_FATAL(mode_idx != -1);
384 printf(" Mode %2d: %s", mode_idx, cards[n].modes[i].name);
385 ++i;
386 }
387
388 printf("\n\n");
389 }
390 deleter = IF_NOT_NULL_ELSE(deleter, (void (*)(void *)) free);
391 deleter(cards);
392
393 printf("%sMode flags:\n", short_h ? "\n" : "");
394 printf("C - codec not natively supported by UG%s\n\n",
395 full_h ? "; F - video format is "
396 "not supported"
397 : "\n(use ':fullhelp' to see also unsupported modes)");
398}
static void vidcap_dshow_probe_internal(device_info **available_cards, int *count, void(**deleter)(void *), bool include_unsupported)
static bool common_init(struct vidcap_dshow_state *s)
int void(** deleter)(void *))
int color_printf(const char *format,...)
#define TERM_BOLD
Definition color_out.h:48
#define SRED(x)
Definition color_out.h:85
#define TERM_RESET
Definition color_out.h:47
#define SBOLD(x)
Definition color_out.h:80
int count
Definition hd-rum.c:44
#define UG_ASSERT_NO_FATAL(cond)
Definition macros.h:90
#define IF_NOT_NULL_ELSE(val, default_val)
Definition macros.h:51

References color_printf(), common_init(), count, deleter, IF_NOT_NULL_ELSE, name, SBOLD, SRED, TERM_BOLD, TERM_RESET, UG_ASSERT_NO_FATAL, and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ vidcap_dshow_done()

static void vidcap_dshow_done ( void * state)
static

Definition at line 1146 of file DirectShowGrabber.cpp.

1146 {
1147 struct vidcap_dshow_state *s = (struct vidcap_dshow_state *) state;
1148
1150
1151 HRESULT res = s->mediaControl->Stop();
1152 if (res != S_OK) {
1153 log_msg(LOG_LEVEL_WARNING, MOD_NAME "vidcap_dshow_init: Failed to stop filter graph.\n");
1154 }
1155
1156 cleanup(s);
1157}
static void vidcap_dshow_should_exit(void *state)
void ** state
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
void unregister_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1158

References cleanup(), LOG_LEVEL_WARNING, log_msg(), vidcap_dshow_state::mediaControl, MOD_NAME, vidcap_dshow_state::parent, state, unregister_should_exit_callback(), and vidcap_dshow_should_exit().

Here is the call graph for this function:

◆ vidcap_dshow_get_video_desc()

static struct video_desc vidcap_dshow_get_video_desc ( AM_MEDIA_TYPE * mediaType)
static

Definition at line 315 of file DirectShowGrabber.cpp.

316{
317 BITMAPINFOHEADER *bmiHeader;
318 struct video_desc desc{};
319 if (mediaType->formattype != FORMAT_VideoInfo && mediaType->formattype != FORMAT_VideoInfo2) {
320 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Unsupported format type!\n";
321 return desc;
322 }
323
324 desc.color_spec = get_ug_codec(&mediaType->subtype);
325 desc.tile_count = 1;
327 if (mediaType->formattype == FORMAT_VideoInfo) {
328 VIDEOINFOHEADER *infoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mediaType->pbFormat);
329 bmiHeader = &infoHeader->bmiHeader;
330 desc.fps = 10000000.0/infoHeader->AvgTimePerFrame;
331 } else {
332 VIDEOINFOHEADER2 *infoHeader = reinterpret_cast<VIDEOINFOHEADER2*>(mediaType->pbFormat);
333 bmiHeader = &infoHeader->bmiHeader;
334 desc.fps = 10000000.0/infoHeader->AvgTimePerFrame;
335 if (infoHeader->dwInterlaceFlags & AMINTERLACE_IsInterlaced) {
336 if (infoHeader->dwInterlaceFlags & AMINTERLACE_1FieldPerSample) {
338 "1 Field Per Sample is not supported! ");
339 } else {
341 }
342 }
343 }
344 desc.width = bmiHeader->biWidth;
345 desc.height = bmiHeader->biHeight;
346
347 return desc;
348}
static codec_t get_ug_codec(const GUID *pSubtype)
struct video_desc desc
#define LOG(level)
Definition debug.h:313
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
Definition types.h:167

References bug_msg(), video_desc::color_spec, desc, video_desc::fps, get_ug_codec(), video_desc::height, INTERLACED_MERGED, video_desc::interlacing, LOG, LOG_LEVEL_WARNING, MOD_NAME, PROGRESSIVE, video_desc::tile_count, and video_desc::width.

Referenced by vidcap_dshow_init(), and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ vidcap_dshow_grab()

static struct video_frame * vidcap_dshow_grab ( void * state,
struct audio_frame ** audio )
static

Definition at line 1181 of file DirectShowGrabber.cpp.

1181 {
1182 struct vidcap_dshow_state *s = (struct vidcap_dshow_state *) state;
1183 *audio = NULL;
1184
1185 LOG(LOG_LEVEL_DEBUG) << MOD_NAME << "GRAB: enter: " << s->deviceNumber << "\n";
1186 EnterCriticalSection(&s->returnBufferCS);
1187 //fprintf(stderr, "[dshow] s: %p\n", s);
1188 while (!s->haveNewReturnBuffer && !s->should_exit) {
1189 LOG(LOG_LEVEL_DEBUG) << MOD_NAME << "Wait CV\n";
1190 SleepConditionVariableCS(&s->grabWaitCV, &s->returnBufferCS, INFINITE);
1191 //fprintf(stderr, "[dshow] s: %p\n", s);
1192 }
1193
1194 if (s->should_exit) {
1195 LeaveCriticalSection(&s->returnBufferCS);
1196 return nullptr;
1197 }
1198
1199 LOG(LOG_LEVEL_DEBUG) << MOD_NAME << "Swap buffers\n";
1200 //fprintf(stderr, "[dshow] s: %p\n", s);
1201 // switch the buffers
1202 BYTE *tmp = s->returnBuffer;
1203 s->returnBuffer = s->grabBuffer;
1204 s->grabBuffer = tmp;
1205 unsigned long tmplen = s->returnBufferLen;
1207 s->grabBufferLen = tmplen;
1208 s->haveNewReturnBuffer = false;
1209 //fprintf(stderr, "[dshow] s: %p\n", s);
1210
1211 LeaveCriticalSection(&s->returnBufferCS);
1212
1213 //fprintf(stderr, "[dshow] GRAB: CS leave: %d\n", s->deviceNumber);
1214 //fprintf(stderr, "[dshow] s: %p\n", s);
1215
1216
1217 if (s->convert_YUYV_RGB) {
1219 }
1220 //fprintf(stderr, "[dshow] s: %p\n", s);
1221
1222 s->frame->tiles[0].data = (char *) s->returnBuffer;
1223 //fprintf(stderr, "[dshow] s: %p\n", s);
1224 //s->tile->data_len = s->width * s->height * 3;
1227
1228/*
1229 fprintf(stderr, "[dshow] s5: %p\n", s);
1230 fprintf(stderr, "[dshow] s6: %p\n", s);
1231 fprintf(stderr, "[dshow] s7: %p\n", s);
1232 fprintf(stderr, "[dshow] s: %p\n", s);
1233 fprintf(stderr, "[dshow] %lf\n", seconds);
1234 */
1235
1236 s->frames++;
1237
1238 return s->frame;
1239}
static void convert_yuyv_rgb(BYTE *src, BYTE *dst, int input_len)
struct audio_frame ** audio
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
unsigned int height
Definition types.h:281
CONDITION_VARIABLE grabWaitCV
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
codec_t color_spec
Definition types.h:306
bool is_codec_opaque(codec_t codec)
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)

References audio, video_frame::color_spec, vidcap_dshow_state::convert_buffer, vidcap_dshow_state::convert_YUYV_RGB, convert_yuyv_rgb(), tile::data, tile::data_len, vidcap_dshow_state::deviceNumber, vidcap_dshow_state::frame, vidcap_dshow_state::frames, vidcap_dshow_state::grabBuffer, vidcap_dshow_state::grabBufferLen, vidcap_dshow_state::grabWaitCV, vidcap_dshow_state::haveNewReturnBuffer, tile::height, is_codec_opaque(), LOG, LOG_LEVEL_DEBUG, MOD_NAME, vidcap_dshow_state::returnBuffer, vidcap_dshow_state::returnBufferCS, vidcap_dshow_state::returnBufferLen, vidcap_dshow_state::should_exit, state, video_frame::tiles, vc_get_datalen(), and tile::width.

Here is the call graph for this function:

◆ vidcap_dshow_init()

static int vidcap_dshow_init ( struct vidcap_params * params,
void ** state )
static

Definition at line 826 of file DirectShowGrabber.cpp.

826 {
827#define HANDLE_ERR(msg, ...) \
828 HANDLE_ERR_ACTION(res, goto error, \
829 "vidcap_dshow_init: " msg __VA_OPT__(, ) __VA_ARGS__)
830 struct vidcap_dshow_state *s;
831 HRESULT res;
832
835 }
836
837 s = (struct vidcap_dshow_state *) calloc(1, sizeof(struct vidcap_dshow_state));
838 if (s == NULL) {
839 log_msg(LOG_LEVEL_ERROR, MOD_NAME "vidcap_dshow_init: memory allocation error\n");
840 return VIDCAP_INIT_FAIL;
841 }
842
843 InitializeConditionVariable(&s->grabWaitCV);
844 InitializeCriticalSection(&s->returnBufferCS);
845
846 if (strstr(vidcap_params_get_fmt(params), "help") != nullptr) {
848 cleanup(s);
849 return VIDCAP_INIT_NOERR;
850 }
851
852 if (!common_init(s)) {
853 goto error;
854 }
855
856 if (vidcap_params_get_fmt(params) != NULL) {
857 char *init_fmt = strdup(vidcap_params_get_fmt(params));
858 if (!process_args(s, init_fmt)) goto error;
859 free(init_fmt);
860 }
861
862 // Select video capture device
863 if (s->deviceNumber != -1) { // Device was specified by number
864 res = E_FAIL;
865 for (int i = 1; i <= s->deviceNumber; i++) {
866 // Take one device. We could take more at once, but it would require allocation of more moniker objects
867 res = s->videoInputEnumerator->Next(1, &s->moniker, NULL);
868 if(i != s->deviceNumber) {
869 if (s->moniker)
870 s->moniker->Release();
871 s->moniker = NULL;
872 }
873 if (res != S_OK) break;
874 }
875 if (res != S_OK) {
876 log_msg(LOG_LEVEL_ERROR, MOD_NAME "vidcap_dshow_init: Device number %d was not found.\n", s->deviceNumber);
877 goto error;
878 }
879 } else { // device specified by name
880 while ((res = s->videoInputEnumerator->Next(1, &s->moniker, NULL)) == S_OK) {
881 string friendly_name = get_friendly_name(s->moniker);
882 if (strcasecmp(s->deviceName, friendly_name.c_str()) == 0) {
883 break;
884 }
885 s->moniker->Release();
886 }
887
888 if (res != S_OK) {
889 log_msg(LOG_LEVEL_ERROR, MOD_NAME "vidcap_dshow_init: Device named %s was not found.\n", s->deviceName);
890 goto error;
891 }
892 }
893
894 if(get_friendly_name(s->moniker).find("OBS Virtual") != std::string::npos){
895 log_msg(LOG_LEVEL_WARNING, MOD_NAME "OBS virtual camera detected. Force setting sync source to NULL!\n");
896 s->no_sync_source = true;
897 }
898
899 LOG(LOG_LEVEL_NOTICE) << MOD_NAME "Capturing from device: "
900 << get_friendly_name(s->moniker) << "\n";
901
902 res = s->moniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void **) &s->captureFilter);
903 HANDLE_ERR("Cannot bind capture filter to device");
904
905 res = s->filterGraph->AddFilter(s->captureFilter, L"Capture filter");
906 HANDLE_ERR("Cannot add capture filter to filter graph");
907
908 res = s->graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, s->captureFilter,
909 IID_IAMStreamConfig, (void **) &s->streamConfig);
910 HANDLE_ERR("Cannot find interface for reading capture capabilites");
911
912 // create instance of sample grabber
913 res = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&s->sampleGrabberFilter));
914 HANDLE_ERR("Cannot create instance of sample grabber");
915
916 // add the sample grabber to filter graph
917 res = s->filterGraph->AddFilter(s->sampleGrabberFilter, L"Sample Grabber");
918 HANDLE_ERR("Cannot add sample grabber to filter graph");
919
920 // query the sample grabber filter for control interface
921 res = s->sampleGrabberFilter->QueryInterface(IID_PPV_ARGS(&s->sampleGrabber));
922 HANDLE_ERR("Cannot query sample grabber filter for control interface");
923
924 // make the sample grabber buffer frames
925 res = s->sampleGrabber->SetBufferSamples(TRUE);
926 HANDLE_ERR("Cannot set sample grabber to buffer samples");
927
928 // set media type for sample grabber; this is not done a very detailed setup, because it would be unneccessarily complicated to do so
929 AM_MEDIA_TYPE sampleGrabberMT;
930 ZeroMemory(&sampleGrabberMT, sizeof(sampleGrabberMT));
931 sampleGrabberMT.majortype = MEDIATYPE_Video;
932 sampleGrabberMT.subtype = MEDIASUBTYPE_RGB24;
933 res = s->sampleGrabber->SetMediaType(&sampleGrabberMT);
934 HANDLE_ERR("Cannot setup media type of grabber filter");
935
936 int capCount, capSize;
937 res = s->streamConfig->GetNumberOfCapabilities(&capCount, &capSize);
938 HANDLE_ERR("Cannot read number of capture capabilites");
939 if (capSize != sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
940 log_msg(LOG_LEVEL_ERROR, MOD_NAME "vidcap_dshow_init: Unknown format of capture capabilites.\n");
941 goto error;
942 }
943
944 bool format_found;
945 format_found = false;
946 AM_MEDIA_TYPE *mediaType;
947 VIDEO_STREAM_CONFIG_CAPS streamCaps;
948
949 if (s->modeNumber >= 0) { // mode number was set by user directly
950 res = s->streamConfig->GetStreamCaps(s->modeNumber, &mediaType, (BYTE*) &streamCaps);
951 // Invalid mode selected
952 if (res == S_FALSE || res == E_INVALIDARG) {
953 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Invalid mode index!\n");
954 goto error;
955 }
956 // Some other error occured
958 "Cannot read stream capabilities #%d (index is correct)",
959 s->modeNumber);
960
961 assert(s->desc.color_spec == VC_NONE || s->desc.color_spec == BGR);
962 if (s->desc.color_spec == VC_NONE) {
963 s->desc.color_spec = get_ug_codec(&mediaType->subtype);
964 if (s->desc.color_spec == VC_NONE) {
965 MSG(WARNING,
966 "Pixel format %.4s not supported directly, "
967 "capturing BGR.\n",
968 (char *) &mediaType->subtype.Data1);
969 s->desc.color_spec = BGR;
970 } else {
971 res = s->sampleGrabber->SetMediaType(mediaType);
972 HANDLE_ERR("Cannot setup media type "
973 "of grabber filter");
974 }
975 }
976
977 struct video_desc desc = vidcap_dshow_get_video_desc(mediaType);
978 s->desc.width = desc.width;
979 s->desc.height = desc.height;
980 s->desc.fps = desc.fps;
982
983 format_found = true;
984 } else {
985 for (int i = 0; i < capCount; i++) {
986 res = s->streamConfig->GetStreamCaps(i, &mediaType, (BYTE*) &streamCaps);
987 if (res != S_OK) {
988 log_msg(LOG_LEVEL_WARNING, MOD_NAME "vidcap_dshow_help: Cannot read stream capabilities #%d.\n", i);
989 continue;
990 }
991 if (s->desc.color_spec !=
992 get_ug_codec(&mediaType->subtype)) {
993 continue;
994 }
995
996 struct video_desc desc = vidcap_dshow_get_video_desc(mediaType);
997 if (desc.height == s->desc.height && desc.width == s->desc.width) {
998 format_found = true;
999 res = s->sampleGrabber->SetMediaType(mediaType);
1000 HANDLE_ERR("Cannot setup media type "
1001 "of grabber filter");
1002 break;
1003 }
1004
1005 DeleteMediaType(mediaType);
1006 }
1007 }
1008
1009 if (!format_found) {
1010 log_msg(LOG_LEVEL_ERROR, MOD_NAME "vidcap_dshow_init: Requested format not supported by the device. Quitting.\n");
1011 goto error;
1012 }
1013
1015 MSG(WARNING,
1016 "Capturing a compressed format directly. You may consider "
1017 "enforcing conversion to RGB (':RGB' option), eg. to "
1018 "use another compression.\n");
1019 }
1020
1021#if 0
1022 if (s->modeNumber < 0) { // mode number was not set by user directly
1023 s->streamConfig->GetFormat(&mediaType);
1024 HANDLE_ERR("Cannot get current capture format");
1025 switch (s->desc.color_spec) {
1026 case BGR : mediaType->subtype = MEDIASUBTYPE_RGB24;
1027 break;
1028 case YUYV : mediaType->subtype = MEDIASUBTYPE_YUY2;
1029 break;
1030 default:
1031 // this is directly from parse_fmt, where, only 2 formats above are permissible
1032 abort();
1033 }
1034 VIDEOINFOHEADER *infoHeader;
1035 infoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mediaType->pbFormat);
1036 infoHeader->rcSource.bottom = s->desc.height;
1037 infoHeader->rcSource.right = s->desc.width;
1038 infoHeader->AvgTimePerFrame = (REFERENCE_TIME) (1e7 / s->desc.fps);
1039 }
1040#endif
1041 res = s->streamConfig->SetFormat(mediaType);
1042 HANDLE_ERR("Cannot set capture format");
1043
1044 if (s->convert_YUYV_RGB) {
1045 s->convert_buffer = (BYTE *) malloc(s->desc.height * s->desc.width * 3);
1046 if (s->convert_buffer == NULL) {
1047 log_msg(LOG_LEVEL_ERROR, MOD_NAME "vidcap_dshow_init: memory allocation error\n");
1048 goto error;
1049 }
1050
1051 yuv_clamp = (int *) malloc((MAX_YUV_CLAMP - MIN_YUV_CLAMP + 1) * sizeof(int));
1052 int i;
1053 for (i = 0; i + MIN_YUV_CLAMP <= 0; i++) {
1054 yuv_clamp[i] = 0;
1055 }
1056 for (int j = 1; j <= 254; j++, i++) {
1057 yuv_clamp[i] = j;
1058 }
1059 for ( ; i < MAX_YUV_CLAMP - MIN_YUV_CLAMP; i++) {
1060 yuv_clamp[i] = 255;
1061 }
1062 }
1063
1064 // Create null renderer discarding all incoming frames
1065 res = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,
1066 (void **) &s->nullRenderer);
1067 HANDLE_ERR("Cannot create NullRenderer");
1068
1069 res = s->filterGraph->AddFilter(s->nullRenderer, L"NullRenderer");
1070 HANDLE_ERR("Cannot add null renderer to filter graph");
1071
1072 IEnumPins *pinEnum;
1073 IPin *pin;
1074
1075 res = s->captureFilter->EnumPins(&pinEnum);
1076 HANDLE_ERR("Error enumerating pins of capture filter");
1077
1078 while (pinEnum->Next(1, &pin, NULL) == S_OK) {
1080 if (pin != NULL) pin->Release();
1081 if (res == S_OK) {
1082 break;
1083 }
1084 }
1085 HANDLE_ERR("Cannot connect capture filter to sample grabber");
1086
1087 res = s->sampleGrabber->GetConnectedMediaType(&sampleGrabberMT);
1088 HANDLE_ERR("Cannot get current grabber format");
1089 MSG(INFO, "streaming type: %s, grabber type: %s, output: %s\n",
1090 GetSubtypeName(&mediaType->subtype),
1091 GetSubtypeName(&sampleGrabberMT.subtype),
1092 ((string) vidcap_dshow_get_video_desc(&sampleGrabberMT)).c_str());
1093 s->convert = get_conversion(&sampleGrabberMT.subtype);
1094 DeleteMediaType(mediaType);
1095
1097 HANDLE_ERR("Cannot connect sample grabber to null renderer");
1098
1099 s->SGCallback = new SampleGrabberCallback(s, &s->frames);
1100 s->sampleGrabber->SetCallback(s->SGCallback, 1);
1101
1102 /*
1103 res = s->graphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, s->captureFilter,
1104 NULL, s->nullRenderer);
1105 if (res != S_OK) {
1106 fprintf(stderr, "[dshow] vidcap_dshow_init: Cannot render stream.\n");
1107 goto error;
1108 }
1109 */
1110
1111 res = s->filterGraph->QueryInterface(IID_IMediaControl, (void **) &s->mediaControl);
1112 HANDLE_ERR("Cannot find media control interface");
1113
1114 if(s->no_sync_source){
1115 IMediaFilter *pMediaFilter;
1116 res = s->filterGraph->QueryInterface(IID_IMediaFilter, (void **) &pMediaFilter);
1117 HANDLE_ERR("Cannot find media filter interface");
1118 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Setting sync source to NULL\n");
1119 pMediaFilter->SetSyncSource(NULL);
1120 }
1121
1122 FILTER_STATE fs;
1123 res = s->mediaControl->Run();
1124 while ((res = s->mediaControl->GetState(500, (OAFilterState*) &fs)) != VFW_S_CANT_CUE && !(res == S_OK && fs == State_Running)) {
1125 if (res != VFW_S_STATE_INTERMEDIATE && res != S_OK) {
1126 break;
1127 }
1128 }
1129 HANDLE_ERR("Cannot run filter graph");
1130 res = s->sampleGrabberFilter->GetState(INFINITE, &fs);
1131 HANDLE_ERR("filter getstate error");
1132
1133 s->frame = vf_alloc_desc(s->desc);
1136
1137 *state = s;
1138 return VIDCAP_INIT_OK;
1139
1140error:
1141 cleanup(s);
1142 return VIDCAP_INIT_FAIL;
1143#undef HANDLE_ERR
1144}
static convert_t get_conversion(const GUID *pSubtype)
#define MAX_YUV_CLAMP
EXTERN_C const CLSID CLSID_NullRenderer
#define MIN_YUV_CLAMP
static const CHAR * GetSubtypeName(const GUID *pSubtype)
static void DeleteMediaType(AM_MEDIA_TYPE *mediaType)
static string get_friendly_name(IMoniker *moniker, int idx=-1)
static bool process_args(struct vidcap_dshow_state *s, char *init_fmt)
EXTERN_C const CLSID CLSID_SampleGrabber
static struct video_desc vidcap_dshow_get_video_desc(AM_MEDIA_TYPE *mediaType)
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
static void show_help()
Definition wasapi.cpp:193
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDCAP_INIT_FAIL
error ocured
#define VIDCAP_INIT_AUDIO_NOT_SUPPORTED
card does not support audio
void register_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1144
SampleGrabberCallback * SGCallback
ISampleGrabber * sampleGrabber
@ YUYV
YCbCr 422 8-bit - Y0 Cb Y1 Cr.
Definition types.h:72
@ VC_NONE
Definition types.h:67
struct module * vidcap_params_get_parent(const struct vidcap_params *params)
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)
#define VIDCAP_FLAG_AUDIO_ANY

References BGR, vidcap_dshow_state::captureFilter, cleanup(), CLSID_NullRenderer, CLSID_SampleGrabber, video_desc::color_spec, common_init(), ConnectFilters(), vidcap_dshow_state::convert, vidcap_dshow_state::convert_buffer, vidcap_dshow_state::convert_YUYV_RGB, DeleteMediaType(), desc, vidcap_dshow_state::desc, vidcap_dshow_state::deviceName, vidcap_dshow_state::deviceNumber, vidcap_dshow_state::filterGraph, video_desc::fps, vidcap_dshow_state::frame, vidcap_dshow_state::frames, get_conversion(), get_friendly_name(), get_ug_codec(), GetSubtypeName(), vidcap_dshow_state::grabWaitCV, vidcap_dshow_state::graphBuilder, HANDLE_ERR, video_desc::height, video_desc::interlacing, is_codec_opaque(), LOG, LOG_LEVEL_ERROR, LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, log_msg(), MAX_YUV_CLAMP, vidcap_dshow_state::mediaControl, MIN_YUV_CLAMP, MOD_NAME, vidcap_dshow_state::modeNumber, vidcap_dshow_state::moniker, MSG, vidcap_dshow_state::no_sync_source, vidcap_dshow_state::nullRenderer, vidcap_dshow_state::parent, process_args(), register_should_exit_callback(), vidcap_dshow_state::returnBufferCS, vidcap_dshow_state::sampleGrabber, vidcap_dshow_state::sampleGrabberFilter, vidcap_dshow_state::SGCallback, show_help(), state, vidcap_dshow_state::streamConfig, TRUE, VC_NONE, vf_alloc_desc(), vidcap_dshow_get_video_desc(), vidcap_dshow_should_exit(), VIDCAP_FLAG_AUDIO_ANY, VIDCAP_INIT_AUDIO_NOT_SUPPORTED, VIDCAP_INIT_FAIL, VIDCAP_INIT_NOERR, VIDCAP_INIT_OK, vidcap_params_get_flags(), vidcap_params_get_fmt(), vidcap_params_get_parent(), vidcap_dshow_state::videoInputEnumerator, video_desc::width, yuv_clamp, and YUYV.

Here is the call graph for this function:

◆ vidcap_dshow_probe()

static void vidcap_dshow_probe ( device_info ** available_cards,
int * count,
void(** deleter )(void *) )
static

Definition at line 549 of file DirectShowGrabber.cpp.

550 {
551 vidcap_dshow_probe_internal(available_cards, count, deleter, false);
552}

References count, deleter, and vidcap_dshow_probe_internal().

Here is the call graph for this function:

◆ vidcap_dshow_probe_internal()

static void vidcap_dshow_probe_internal ( device_info ** available_cards,
int * count,
void(** deleter )(void *),
bool include_unsupported )
static

Definition at line 430 of file DirectShowGrabber.cpp.

432{
433 *deleter = free;
434 struct vidcap_dshow_state *s = (struct vidcap_dshow_state *) calloc(1, sizeof(struct vidcap_dshow_state));
435
436 if (!common_init(s))
437 return;
438
439 device_info *cards = nullptr;
440 int card_count = 0;
441
442 HRESULT res;
443 int n = 0;
444 // Enumerate all capture devices
445 while ((res = s->videoInputEnumerator->Next(1, &s->moniker, NULL)) == S_OK) {
446 n++;
447 card_count = n;
448 cards = (struct device_info *) realloc(cards, n * sizeof(struct device_info));
449 memset(&cards[n - 1], 0, sizeof(struct device_info));
450 snprintf(cards[n-1].dev, sizeof cards[n-1].dev - 1, ":device=%d", n);
451 snprintf(cards[n-1].name, sizeof cards[n-1].name - 1, "_DSHOW_FAILED_TO_READ_NAME_%d_", n);
452
453 string friendly_name = get_friendly_name(s->moniker, n);
454 if (friendly_name.empty()) {
455 log_msg(LOG_LEVEL_WARNING, MOD_NAME "vidcap_dshow_help: Failed to get device %d name.\n", n);
456 // Ignore the device
457 continue;
458 }
459 const char *name = friendly_name.c_str();;
460 snprintf(cards[n - 1].name, sizeof cards[n - 1].name, "%s",
461 name);
462
463#define HANDLE_ERR(msg, ...) \
464 HANDLE_ERR_ACTION(res, continue, "vidcap_dshow_help: %s: " msg, \
465 name __VA_OPT__(, ) __VA_ARGS__)
466 // bind the selected device to the capture filter
467 IBaseFilter *captureFilter;
468 res = s->moniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void **) &captureFilter);
469 HANDLE_ERR("Cannot bind capture filter to device");
470
471 // add the capture filter to the filter graph
472 res = s->filterGraph->AddFilter(captureFilter, L"Capture filter");
473 HANDLE_ERR("Cannot add capture filter to filter graph");
474
475 // connect stream config interface to the capture filter
476 res = s->graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, captureFilter,
477 IID_IAMStreamConfig, (void **) &s->streamConfig);
478 HANDLE_ERR("Cannot find interface for reading capture capabilites");
479
480 int capCount, capSize;
481 // read number of capture device capabilities
482 res = s->streamConfig->GetNumberOfCapabilities(&capCount, &capSize);
483 HANDLE_ERR("Cannot read number of capture capabilites");
484 // check if the format of capture capabilities is the right one
485 if (capSize != sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
486 log_msg(LOG_LEVEL_WARNING, MOD_NAME "vidcap_dshow_help: %s: Unknown format of capture capabilites.\n", name);
487 continue;
488 }
489
490 int mode_idx = 0;
491 // iterate over all capabilities
492 for (int i = 0; i < capCount; i++) {
493 if (mode_idx >=
494 (int) (sizeof cards[card_count - 1].modes /
495 sizeof cards[card_count - 1].modes[0]) -
496 1) { // no space
497 break;
498 }
499
500 AM_MEDIA_TYPE *mediaType;
501 VIDEO_STREAM_CONFIG_CAPS streamCaps;
502
503 res = s->streamConfig->GetStreamCaps(i, &mediaType, (BYTE*) &streamCaps);
504 HANDLE_ERR("Cannot read stream capabilities #%d", i);
505
506 struct video_desc desc = vidcap_dshow_get_video_desc(mediaType);
507 if (desc.width == 0) {
508 DeleteMediaType(mediaType);
509 continue;
510 }
511 if (mediaType->formattype != FORMAT_VideoInfo && !include_unsupported) {
512 DeleteMediaType(mediaType);
513 continue;
514 }
515
516 codec_t ug_codec = get_ug_codec(&mediaType->subtype);
518
519 snprintf(cards[card_count - 1].modes[mode_idx].id,
520 sizeof cards[card_count - 1].modes[mode_idx].id,
521 "{\"mode\":\"%d\", "
522 "\"force_rgb\":\"%c\"}",
523 i, force_rgb ? 't' : 'f');
524 snprintf(cards[card_count - 1].modes[mode_idx].name,
525 sizeof cards[card_count - 1].modes[mode_idx].name,
526 "%s %ux%u @%0.2lf%s %s%s", GetSubtypeName(&mediaType->subtype),
528 desc.color_spec ? "" : "C",
529 mediaType->formattype == FORMAT_VideoInfo ? "" : "F");
530 mode_idx += 1;
531
532 DeleteMediaType(mediaType);
533 }
534
535 s->streamConfig->Release();
536 res = s ->filterGraph->RemoveFilter(captureFilter);
537 HANDLE_ERR("Cannot remove capture filter from filter graph");
538 captureFilter->Release();
539 s->moniker->Release();
540 dev_add_option(&cards[card_count - 1], "Force no sync source", "Only use if capture is stuck", "no_sync_source", ":no_sync_source", true);
541 }
542 cleanup(s);
543 *available_cards = cards;
544 *count = card_count;
545#undef HANDLE_ERR
546}
codec_t ug_codec
struct device_info::mode modes[512]
char dev[1024]
Definition types.h:383
void dev_add_option(struct device_info *dev, const char *name, const char *desc, const char *key, const char *opt_str, bool is_boolean)
codec_t
Definition types.h:65
bool codec_is_planar(codec_t codec)
const char * get_interlacing_suffix(enum interlacing_t interlacing)
Returns suffix describing interlacing Eg. p, i or psf.

References cleanup(), codec_is_planar(), video_desc::color_spec, common_init(), count, DeleteMediaType(), deleter, desc, device_info::dev, dev_add_option(), vidcap_dshow_state::filterGraph, video_desc::fps, get_friendly_name(), get_interlacing_suffix(), get_ug_codec(), GetSubtypeName(), vidcap_dshow_state::graphBuilder, HANDLE_ERR, video_desc::height, INTERLACED_MERGED, video_desc::interlacing, is_codec_opaque(), LOG_LEVEL_WARNING, log_msg(), MOD_NAME, device_info::modes, vidcap_dshow_state::moniker, name, vidcap_dshow_state::streamConfig, ug_codec, vidcap_dshow_get_video_desc(), VIDEO_CODEC_NONE, vidcap_dshow_state::videoInputEnumerator, and video_desc::width.

Referenced by show_help(), and vidcap_dshow_probe().

Here is the call graph for this function:

◆ vidcap_dshow_should_exit()

static void vidcap_dshow_should_exit ( void * state)
static

Definition at line 818 of file DirectShowGrabber.cpp.

818 {
819 auto *s = static_cast<vidcap_dshow_state *>(state);
820 EnterCriticalSection(&s->returnBufferCS);
821 s->should_exit = true;
822 LeaveCriticalSection(&s->returnBufferCS);
823 WakeConditionVariable(&s->grabWaitCV);
824}

References state.

Referenced by vidcap_dshow_done(), and vidcap_dshow_init().

Variable Documentation

◆ [struct]

const struct { ... } BitCountMap[]
Initial value:
= {
{&MEDIASUBTYPE_RGB1, "RGB Monochrome", VC_NONE, nullptr },
{ &MEDIASUBTYPE_RGB4, "RGB VGA", VC_NONE, nullptr },
{ &MEDIASUBTYPE_RGB8, "RGB 8", VC_NONE, nullptr },
{ &MEDIASUBTYPE_RGB565, "RGB 565 (16 bit)", VC_NONE, nullptr },
{ &MEDIASUBTYPE_RGB555, "RGB 555 (16 bit)", VC_NONE, nullptr },
{ &MEDIASUBTYPE_RGB24, "RGB 24", BGR, bgr_flip_lines },
{ &MEDIASUBTYPE_RGB32, "RGB 32", RGBA, abgr_flip_and_swap},
{ &MEDIASUBTYPE_ARGB32, "ARGB 32", VC_NONE, nullptr },
{ &MEDIASUBTYPE_Overlay, "Overlay", VC_NONE, nullptr },
{ &GUID_I420, "I420", UYVY, i420_8_to_uyvy },
{ &MEDIASUBTYPE_YUY2, "YUY2", YUYV, nullptr },
{ &GUID_R210, "r210", VC_NONE, nullptr },
{ &GUID_v210, "v210", v210, nullptr },
{ &GUID_V210, "V210", v210, nullptr },
{ &MEDIASUBTYPE_UYVY, "UYVY", UYVY, nullptr },
{ &GUID_HDYC, "HDYC", UYVY, nullptr },
{ &MEDIASUBTYPE_MJPG, "MJPG", MJPG, nullptr },
{ &GUID_H264, "H264", H264, nullptr },
{ &GUID_HEVC, "HEVC", H265, nullptr },
{ &GUID_AV01, "AV1", AV1, nullptr },
{ &MEDIASUBTYPE_NV12, "NV12", UYVY, nv12_to_uyvy },
{ &GUID_NULL, "UNKNOWN", VC_NONE, nullptr },
}
static const GUID GUID_H264
static void abgr_flip_and_swap(int width, int height, const unsigned char *in, unsigned char *out)
convert from ABGR and bottom-to-top
static const GUID GUID_HDYC
static const GUID GUID_v210
static const GUID GUID_V210
static const GUID GUID_HEVC
static const GUID GUID_I420
static const GUID GUID_AV01
static void nv12_to_uyvy(int width, int height, const unsigned char *in, unsigned char *out)
static void bgr_flip_lines(int width, int height, const unsigned char *in, unsigned char *out)
static const GUID GUID_R210
@ AV1
AOMedia Video 1.
Definition types.h:96
@ MJPG
JPEG image, without restart intervals.
Definition types.h:85
@ H264
H.264 frame.
Definition types.h:83
@ H265
H.264 frame.
Definition types.h:84
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
Definition types.h:75
void i420_8_to_uyvy(int width, int height, const unsigned char *in, unsigned char *out)

Referenced by get_conversion(), get_ug_codec(), get_ug_from_subtype_name(), GetSubtypeName(), GetSubtypeNameA(), and LocateSubtype().

◆ CLSID_NullRenderer

EXTERN_C const CLSID CLSID_NullRenderer

Definition at line 34 of file DirectShowGrabber.cpp.

Referenced by vidcap_dshow_init().

◆ CLSID_SampleGrabber

EXTERN_C const CLSID CLSID_SampleGrabber

Definition at line 35 of file DirectShowGrabber.cpp.

Referenced by vidcap_dshow_init().

◆ convert

◆ GUID_AV01

const GUID GUID_AV01 = GUID_FROM_FOURCC(to_fourcc('A', 'V', '0', '1'))
static

Definition at line 1327 of file DirectShowGrabber.cpp.

◆ GUID_H264

const GUID GUID_H264 = GUID_FROM_FOURCC(to_fourcc('H', '2', '6', '4'))
static

Definition at line 1325 of file DirectShowGrabber.cpp.

◆ GUID_HDYC

const GUID GUID_HDYC = GUID_FROM_FOURCC(0x43594448)
static

Definition at line 1323 of file DirectShowGrabber.cpp.

◆ GUID_HEVC

const GUID GUID_HEVC = GUID_FROM_FOURCC(to_fourcc('H', 'E', 'V', 'C'))
static

Definition at line 1326 of file DirectShowGrabber.cpp.

◆ GUID_I420

const GUID GUID_I420 = GUID_FROM_FOURCC(0x30323449)
static

Definition at line 1324 of file DirectShowGrabber.cpp.

◆ GUID_R210

const GUID GUID_R210 = GUID_FROM_FOURCC(0x30313272)
static

Definition at line 1320 of file DirectShowGrabber.cpp.

◆ GUID_V210

const GUID GUID_V210 = GUID_FROM_FOURCC(0x30313256)
static

Definition at line 1322 of file DirectShowGrabber.cpp.

◆ GUID_v210

const GUID GUID_v210 = GUID_FROM_FOURCC(0x30313276)
static

Definition at line 1321 of file DirectShowGrabber.cpp.

◆ pName

const CHAR* pName

Definition at line 1331 of file DirectShowGrabber.cpp.

Referenced by get_ug_from_subtype_name().

◆ pSubtype

const GUID* pSubtype

◆ ug_codec

codec_t ug_codec

Definition at line 1332 of file DirectShowGrabber.cpp.

Referenced by vidcap_dshow_probe_internal().

◆ vidcap_dshow_info

const struct video_capture_info vidcap_dshow_info
Initial value:
= {
}
static int vidcap_dshow_init(struct vidcap_params *params, void **state)
static void vidcap_dshow_done(void *state)
static struct video_frame * vidcap_dshow_grab(void *state, struct audio_frame **audio)
static void vidcap_dshow_probe(device_info **available_cards, int *count, void(**deleter)(void *))

Definition at line 1428 of file DirectShowGrabber.cpp.

Referenced by cleanup(), is_library_registered(), vidcap_screen_win_grab(), and vidcap_screen_win_init().

◆ yuv_clamp

int* yuv_clamp
static

Definition at line 68 of file DirectShowGrabber.cpp.

Referenced by cleanup(), common_init(), convert_yuv_rgb(), and vidcap_dshow_init().