FFmpeg
dshow_capture.h
Go to the documentation of this file.
1 /*
2  * DirectShow capture interface
3  * Copyright (c) 2010 Ramiro Polla
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #ifndef AVDEVICE_DSHOW_CAPTURE_H
23 #define AVDEVICE_DSHOW_CAPTURE_H
24 
25 #define DSHOWDEBUG 0
26 
27 #include "avdevice.h"
28 
29 #define COBJMACROS
30 #define WIN32_LEAN_AND_MEAN
31 #include <windows.h>
32 #define NO_DSHOW_STRSAFE
33 #include <dshow.h>
34 #include <dvdmedia.h>
35 
36 #include "libavcodec/internal.h"
37 
38 /* EC_DEVICE_LOST is not defined in MinGW dshow headers. */
39 #ifndef EC_DEVICE_LOST
40 #define EC_DEVICE_LOST 0x1f
41 #endif
42 
43 long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src);
44 void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps);
45 void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps);
46 void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type);
47 void ff_printGUID(const GUID *g);
48 
50 #define dshowdebug(...) ff_dlog(&ff_dshow_context_class_ptr, __VA_ARGS__)
51 
52 static inline void nothing(void *foo)
53 {
54 }
55 
56 struct GUIDoffset {
57  const GUID *iid;
58  int offset;
59 };
60 
64 };
65 
69 };
70 
71 #define DECLARE_QUERYINTERFACE(prefix, class, ...) \
72 long \
73 ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \
74 { \
75  struct GUIDoffset ifaces[] = __VA_ARGS__; \
76  int i; \
77  dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_QueryInterface(%p, %p, %p)\n", this, riid, ppvObject); \
78  ff_printGUID(riid); \
79  if (!ppvObject) \
80  return E_POINTER; \
81  for (i = 0; i < sizeof(ifaces)/sizeof(ifaces[0]); i++) { \
82  if (IsEqualGUID(riid, ifaces[i].iid)) { \
83  void *obj = (void *) ((uint8_t *) this + ifaces[i].offset); \
84  ff_dshow_##prefix##_AddRef(this); \
85  dshowdebug("\tfound %d with offset %d\n", i, ifaces[i].offset); \
86  *ppvObject = (void *) obj; \
87  return S_OK; \
88  } \
89  } \
90  dshowdebug("\tE_NOINTERFACE\n"); \
91  *ppvObject = NULL; \
92  return E_NOINTERFACE; \
93 }
94 #define DECLARE_ADDREF(prefix, class) \
95 unsigned long \
96 ff_dshow_##prefix##_AddRef(class *this) \
97 { \
98  dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_AddRef(%p)\t%ld\n", this, this->ref+1); \
99  return InterlockedIncrement(&this->ref); \
100 }
101 #define DECLARE_RELEASE(prefix, class) \
102 unsigned long \
103 ff_dshow_##prefix##_Release(class *this) \
104 { \
105  long ref = InterlockedDecrement(&this->ref); \
106  dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_Release(%p)\t%ld\n", this, ref); \
107  if (!ref) \
108  ff_dshow_##prefix##_Destroy(this); \
109  return ref; \
110 }
111 
112 #define DECLARE_DESTROY(prefix, class, func) \
113 void ff_dshow_##prefix##_Destroy(class *this) \
114 { \
115  dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_Destroy(%p)\n", this); \
116  func(this); \
117  if (this) { \
118  if (this->vtbl) \
119  CoTaskMemFree(this->vtbl); \
120  CoTaskMemFree(this); \
121  } \
122 }
123 #define DECLARE_CREATE(prefix, class, setup, ...) \
124 class *ff_dshow_##prefix##_Create(__VA_ARGS__) \
125 { \
126  class *this = CoTaskMemAlloc(sizeof(class)); \
127  void *vtbl = CoTaskMemAlloc(sizeof(*this->vtbl)); \
128  dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_Create(%p)\n", this); \
129  if (!this || !vtbl) \
130  goto fail; \
131  ZeroMemory(this, sizeof(class)); \
132  ZeroMemory(vtbl, sizeof(*this->vtbl)); \
133  this->ref = 1; \
134  this->vtbl = vtbl; \
135  if (!setup) \
136  goto fail; \
137  dshowdebug("created ff_dshow_"AV_STRINGIFY(prefix)" %p\n", this); \
138  return this; \
139 fail: \
140  ff_dshow_##prefix##_Destroy(this); \
141  dshowdebug("could not create ff_dshow_"AV_STRINGIFY(prefix)"\n"); \
142  return NULL; \
143 }
144 
145 #define SETVTBL(vtbl, prefix, fn) \
146  do { (vtbl)->fn = (void *) ff_dshow_##prefix##_##fn; } while(0)
147 
148 /*****************************************************************************
149  * Forward Declarations
150  ****************************************************************************/
151 typedef struct DShowPin DShowPin;
153 typedef struct DShowEnumPins DShowEnumPins;
155 typedef struct DShowFilter DShowFilter;
156 
157 /*****************************************************************************
158  * DShowPin
159  ****************************************************************************/
160 struct DShowPin {
161  IPinVtbl *vtbl;
162  long ref;
164  IPin *connectedto;
165  AM_MEDIA_TYPE type;
166  IMemInputPinVtbl *imemvtbl;
167 };
168 
169 long ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **);
170 unsigned long ff_dshow_pin_AddRef (DShowPin *);
171 unsigned long ff_dshow_pin_Release (DShowPin *);
172 long ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *);
173 long ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *);
175 long ff_dshow_pin_ConnectedTo (DShowPin *, IPin **);
176 long ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *);
177 long ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *);
178 long ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *);
179 long ff_dshow_pin_QueryId (DShowPin *, wchar_t **);
180 long ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *);
181 long ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **);
182 long ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *);
186 long ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double);
187 
188 long ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **);
191 long ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **);
192 long ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL);
194 long ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *);
195 long ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *);
197 
200 
202 
203 /*****************************************************************************
204  * DShowEnumPins
205  ****************************************************************************/
207  IEnumPinsVtbl *vtbl;
208  long ref;
209  int pos;
212 };
213 
214 long ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **);
215 unsigned long ff_dshow_enumpins_AddRef (DShowEnumPins *);
216 unsigned long ff_dshow_enumpins_Release (DShowEnumPins *);
217 long ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *);
218 long ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long);
221 
224 
225 /*****************************************************************************
226  * DShowEnumMediaTypes
227  ****************************************************************************/
229  IEnumMediaTypesVtbl *vtbl;
230  long ref;
231  int pos;
232  AM_MEDIA_TYPE type;
233 };
234 
235 long ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **);
238 long ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *);
239 long ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long);
242 
245 
246 /*****************************************************************************
247  * DShowFilter
248  ****************************************************************************/
249 struct DShowFilter {
250  IBaseFilterVtbl *vtbl;
251  long ref;
252  const wchar_t *name;
254  FILTER_INFO info;
255  FILTER_STATE state;
256  IReferenceClock *clock;
258  void *priv_data;
260  int64_t start_time;
261  void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type);
262 };
263 
264 long ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **);
265 unsigned long ff_dshow_filter_AddRef (DShowFilter *);
266 unsigned long ff_dshow_filter_Release (DShowFilter *);
267 long ff_dshow_filter_GetClassID (DShowFilter *, CLSID *);
270 long ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME);
271 long ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *);
272 long ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *);
273 long ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **);
274 long ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **);
275 long ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **);
276 long ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *);
277 long ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *);
278 long ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **);
279 
281 DShowFilter *ff_dshow_filter_Create (void *, void *, enum dshowDeviceType);
282 
283 /*****************************************************************************
284  * dshow_ctx
285  ****************************************************************************/
286 struct dshow_ctx {
287  const AVClass *class;
288 
289  IGraphBuilder *graph;
290 
291  char *device_name[2];
292  char *device_unique_name[2];
293 
296 
314 
315  IBaseFilter *device_filter[2];
316  IPin *device_pin[2];
317  DShowFilter *capture_filter[2];
318  DShowPin *capture_pin[2];
319 
320  HANDLE mutex;
321  HANDLE event[2]; /* event[0] is set by DirectShow
322  * event[1] is set by callback() */
324 
325  int eof;
326 
327  int64_t curbufsize[2];
328  unsigned int video_frame_num;
329 
330  IMediaControl *control;
331  IMediaEvent *media_event;
332 
333  enum AVPixelFormat pixel_format;
334  enum AVCodecID video_codec_id;
335  char *framerate;
336 
340 
343  int channels;
344 };
345 
346 /*****************************************************************************
347  * CrossBar
348  ****************************************************************************/
349 HRESULT ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2,
350  IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx);
351 
352 void ff_dshow_show_filter_properties(IBaseFilter *pFilter, AVFormatContext *avctx);
353 
354 #endif /* AVDEVICE_DSHOW_CAPTURE_H */
void * priv_data
long ff_dshow_pin_QueryId(DShowPin *, wchar_t **)
Definition: dshow_pin.c:126
unsigned long ff_dshow_enummediatypes_AddRef(DShowEnumMediaTypes *)
int requested_width
void ff_dshow_pin_Destroy(DShowPin *)
char * audio_filter_load_file
void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps)
Definition: dshow_common.c:85
long ff_dshow_filter_Pause(DShowFilter *)
Definition: dshow_filter.c:41
long ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *)
const char * g
Definition: vf_curves.c:117
int list_devices
DShowPin * pin
long ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **)
Definition: dshow_filter.c:142
int audio_device_number
dshowDeviceType
Definition: dshow_capture.h:61
DShowFilter * filter
IMediaEvent * media_event
char * video_filter_load_file
void ff_dshow_filter_Destroy(DShowFilter *)
GLint GLenum type
Definition: opengl_enc.c:104
unsigned long ff_dshow_pin_AddRef(DShowPin *)
long ff_dshow_pin_EndOfStream(DShowPin *)
Definition: dshow_pin.c:163
long ff_dshow_filter_GetClassID(DShowFilter *, CLSID *)
long ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *)
Definition: dshow_filter.c:119
HRESULT ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx)
Given a fully constructed graph, check if there is a cross bar filter, and configure its pins if so...
int show_analog_tv_tuner_audio_dialog
int show_audio_crossbar_connection_dialog
Format I/O context.
Definition: avformat.h:1243
long ff_dshow_filter_Stop(DShowFilter *)
Definition: dshow_filter.c:35
DShowPin * ff_dshow_pin_Create(DShowFilter *filter)
long ff_dshow_pin_Disconnect(DShowPin *)
Definition: dshow_pin.c:65
long ff_dshow_pin_ConnectionMediaType(DShowPin *, AM_MEDIA_TYPE *)
Definition: dshow_pin.c:91
long ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *, DShowEnumMediaTypes **)
long ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *)
Definition: dshow_pin.c:157
uint8_t
unsigned long ff_dshow_filter_AddRef(DShowFilter *)
char * video_filter_save_file
long ff_dshow_pin_EnumMediaTypes(DShowPin *, IEnumMediaTypes **)
Definition: dshow_pin.c:142
AVPacketList * pktl
long ff_dshow_pin_QueryPinInfo(DShowPin *, PIN_INFO *)
Definition: dshow_pin.c:102
unsigned long ff_dshow_filter_Release(DShowFilter *)
long ff_dshow_pin_Connect(DShowPin *, IPin *, const AM_MEDIA_TYPE *)
int audio_buffer_size
long ff_dshow_filter_GetSyncSource(DShowFilter *, IReferenceClock **)
Definition: dshow_filter.c:76
long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *)
Definition: dshow_pin.c:283
unsigned long ff_dshow_enumpins_Release(DShowEnumPins *)
dshowSourceFilterType
Definition: dshow_capture.h:66
long ff_dshow_pin_NewSegment(DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double)
Definition: dshow_pin.c:181
long ff_dshow_meminputpin_Receive(DShowMemInputPin *, IMediaSample *)
Definition: dshow_pin.c:289
Main libavdevice API header.
#define src
Definition: vp8dsp.c:255
FILTER_STATE state
long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src)
Definition: dshow_common.c:24
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
HANDLE mutex
IPin * connectedto
IMemInputPinVtbl * imemvtbl
AM_MEDIA_TYPE type
IReferenceClock * clock
DShowFilter * ff_dshow_filter_Create(void *, void *, enum dshowDeviceType)
long ff_dshow_enumpins_Next(DShowEnumPins *, unsigned long, IPin **, unsigned long *)
unsigned long ff_dshow_enummediatypes_Release(DShowEnumMediaTypes *)
static void callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType devtype)
Definition: dshow.c:161
long ff_dshow_pin_EndFlush(DShowPin *)
Definition: dshow_pin.c:175
unsigned long ff_dshow_meminputpin_AddRef(DShowMemInputPin *)
Definition: dshow_pin.c:260
unsigned long ff_dshow_enumpins_AddRef(DShowEnumPins *)
void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps)
Definition: dshow_common.c:115
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
IEnumPinsVtbl * vtbl
IEnumMediaTypesVtbl * vtbl
AVRational requested_framerate
char * audio_filter_save_file
void ff_dshow_enummediatypes_Destroy(DShowEnumMediaTypes *)
long ff_dshow_enumpins_Clone(DShowEnumPins *, DShowEnumPins **)
long ff_dshow_filter_Run(DShowFilter *, REFERENCE_TIME)
Definition: dshow_filter.c:47
char * video_pin_name
DShowFilter * filter
long ff_dshow_filter_EnumPins(DShowFilter *, IEnumPins **)
Definition: dshow_filter.c:88
long ff_dshow_pin_BeginFlush(DShowPin *)
Definition: dshow_pin.c:169
long ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *)
Definition: dshow_filter.c:131
FILTER_INFO info
IPinVtbl * vtbl
long ff_dshow_filter_GetState(DShowFilter *, DWORD, FILTER_STATE *)
Definition: dshow_filter.c:54
long ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *)
Definition: dshow_pin.c:357
IBaseFilterVtbl * vtbl
void ff_printGUID(const GUID *g)
Definition: dshow_common.c:42
long ff_dshow_enumpins_Reset(DShowEnumPins *)
unsigned long ff_dshow_meminputpin_Release(DShowMemInputPin *)
Definition: dshow_pin.c:266
long ff_dshow_pin_ReceiveConnection(DShowPin *, IPin *, const AM_MEDIA_TYPE *)
Definition: dshow_pin.c:38
AM_MEDIA_TYPE type
int list_options
DShowEnumPins * ff_dshow_enumpins_Create(DShowPin *pin, DShowFilter *filter)
Describe the class of an AVClass context structure.
Definition: log.h:67
long ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *, IMemAllocator **)
Definition: dshow_pin.c:272
int index
Definition: gxfenc.c:89
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int show_audio_device_dialog
int show_video_device_dialog
long ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **)
int requested_height
const GUID * iid
Definition: dshow_capture.h:57
DShowPin * pin
long ff_dshow_pin_QueryInterface(DShowPin *, const GUID *, void **)
static void nothing(void *foo)
Definition: dshow_capture.h:52
int crossbar_audio_input_pin_number
long ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *, IMemAllocator *, BOOL)
Definition: dshow_pin.c:277
const AVClass * ff_dshow_context_class_ptr
Definition: dshow_common.c:60
long ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *, unsigned long)
char * audio_pin_name
int video_device_number
common internal api header.
long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *)
int64_t start_time
void ff_dshow_meminputpin_Destroy(DShowMemInputPin *)
Definition: dshow_pin.c:364
long ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *, const GUID *, void **)
Definition: dshow_pin.c:253
IMediaControl * control
long ff_dshow_enumpins_Skip(DShowEnumPins *, unsigned long)
long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *, IMediaSample **, long, long *)
Definition: dshow_pin.c:345
unsigned long ff_dshow_pin_Release(DShowPin *)
int crossbar_video_input_pin_number
DShowEnumMediaTypes * ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type)
void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
Definition: dshow_common.c:134
long ff_dshow_pin_QueryAccept(DShowPin *, const AM_MEDIA_TYPE *)
Definition: dshow_pin.c:137
struct DShowMemInputPin DShowMemInputPin
long ff_dshow_filter_QueryInterface(DShowFilter *, const GUID *, void **)
int show_video_crossbar_connection_dialog
unsigned int video_frame_num
long ff_dshow_pin_ConnectedTo(DShowPin *, IPin **)
Definition: dshow_pin.c:78
long ff_dshow_pin_QueryDirection(DShowPin *, PIN_DIRECTION *)
Definition: dshow_pin.c:118
const wchar_t * name
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
long ff_dshow_filter_FindPin(DShowFilter *, const wchar_t *, IPin **)
Definition: dshow_filter.c:102
int show_analog_tv_tuner_dialog
void ff_dshow_show_filter_properties(IBaseFilter *pFilter, AVFormatContext *avctx)
Pops up a user dialog allowing them to adjust properties for the given filter, if possible...
Definition: dshow.c:513
long ff_dshow_filter_SetSyncSource(DShowFilter *, IReferenceClock *)
Definition: dshow_filter.c:62
void ff_dshow_enumpins_Destroy(DShowEnumPins *)
long ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **)
IGraphBuilder * graph
char * framerate