yading@10
|
1 /*
|
yading@10
|
2 * Directshow capture interface
|
yading@10
|
3 * Copyright (c) 2010 Ramiro Polla
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21
|
yading@10
|
22 #include "libavutil/parseutils.h"
|
yading@10
|
23 #include "libavutil/pixdesc.h"
|
yading@10
|
24 #include "libavutil/opt.h"
|
yading@10
|
25 #include "libavformat/internal.h"
|
yading@10
|
26 #include "libavformat/riff.h"
|
yading@10
|
27 #include "avdevice.h"
|
yading@10
|
28 #include "dshow_capture.h"
|
yading@10
|
29 #include "libavcodec/raw.h"
|
yading@10
|
30
|
yading@10
|
31 struct dshow_ctx {
|
yading@10
|
32 const AVClass *class;
|
yading@10
|
33
|
yading@10
|
34 IGraphBuilder *graph;
|
yading@10
|
35
|
yading@10
|
36 char *device_name[2];
|
yading@10
|
37 int video_device_number;
|
yading@10
|
38 int audio_device_number;
|
yading@10
|
39
|
yading@10
|
40 int list_options;
|
yading@10
|
41 int list_devices;
|
yading@10
|
42 int audio_buffer_size;
|
yading@10
|
43
|
yading@10
|
44 IBaseFilter *device_filter[2];
|
yading@10
|
45 IPin *device_pin[2];
|
yading@10
|
46 libAVFilter *capture_filter[2];
|
yading@10
|
47 libAVPin *capture_pin[2];
|
yading@10
|
48
|
yading@10
|
49 HANDLE mutex;
|
yading@10
|
50 HANDLE event[2]; /* event[0] is set by DirectShow
|
yading@10
|
51 * event[1] is set by callback() */
|
yading@10
|
52 AVPacketList *pktl;
|
yading@10
|
53
|
yading@10
|
54 int eof;
|
yading@10
|
55
|
yading@10
|
56 int64_t curbufsize;
|
yading@10
|
57 unsigned int video_frame_num;
|
yading@10
|
58
|
yading@10
|
59 IMediaControl *control;
|
yading@10
|
60 IMediaEvent *media_event;
|
yading@10
|
61
|
yading@10
|
62 enum AVPixelFormat pixel_format;
|
yading@10
|
63 enum AVCodecID video_codec_id;
|
yading@10
|
64 char *framerate;
|
yading@10
|
65
|
yading@10
|
66 int requested_width;
|
yading@10
|
67 int requested_height;
|
yading@10
|
68 AVRational requested_framerate;
|
yading@10
|
69
|
yading@10
|
70 int sample_rate;
|
yading@10
|
71 int sample_size;
|
yading@10
|
72 int channels;
|
yading@10
|
73 };
|
yading@10
|
74
|
yading@10
|
75 static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
|
yading@10
|
76 {
|
yading@10
|
77 switch(biCompression) {
|
yading@10
|
78 case BI_BITFIELDS:
|
yading@10
|
79 case BI_RGB:
|
yading@10
|
80 switch(biBitCount) { /* 1-8 are untested */
|
yading@10
|
81 case 1:
|
yading@10
|
82 return AV_PIX_FMT_MONOWHITE;
|
yading@10
|
83 case 4:
|
yading@10
|
84 return AV_PIX_FMT_RGB4;
|
yading@10
|
85 case 8:
|
yading@10
|
86 return AV_PIX_FMT_RGB8;
|
yading@10
|
87 case 16:
|
yading@10
|
88 return AV_PIX_FMT_RGB555;
|
yading@10
|
89 case 24:
|
yading@10
|
90 return AV_PIX_FMT_BGR24;
|
yading@10
|
91 case 32:
|
yading@10
|
92 return AV_PIX_FMT_RGB32;
|
yading@10
|
93 }
|
yading@10
|
94 }
|
yading@10
|
95 return avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, biCompression); // all others
|
yading@10
|
96 }
|
yading@10
|
97
|
yading@10
|
98 static int
|
yading@10
|
99 dshow_read_close(AVFormatContext *s)
|
yading@10
|
100 {
|
yading@10
|
101 struct dshow_ctx *ctx = s->priv_data;
|
yading@10
|
102 AVPacketList *pktl;
|
yading@10
|
103
|
yading@10
|
104 if (ctx->control) {
|
yading@10
|
105 IMediaControl_Stop(ctx->control);
|
yading@10
|
106 IMediaControl_Release(ctx->control);
|
yading@10
|
107 }
|
yading@10
|
108
|
yading@10
|
109 if (ctx->media_event)
|
yading@10
|
110 IMediaEvent_Release(ctx->media_event);
|
yading@10
|
111
|
yading@10
|
112 if (ctx->graph) {
|
yading@10
|
113 IEnumFilters *fenum;
|
yading@10
|
114 int r;
|
yading@10
|
115 r = IGraphBuilder_EnumFilters(ctx->graph, &fenum);
|
yading@10
|
116 if (r == S_OK) {
|
yading@10
|
117 IBaseFilter *f;
|
yading@10
|
118 IEnumFilters_Reset(fenum);
|
yading@10
|
119 while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK) {
|
yading@10
|
120 if (IGraphBuilder_RemoveFilter(ctx->graph, f) == S_OK)
|
yading@10
|
121 IEnumFilters_Reset(fenum); /* When a filter is removed,
|
yading@10
|
122 * the list must be reset. */
|
yading@10
|
123 IBaseFilter_Release(f);
|
yading@10
|
124 }
|
yading@10
|
125 IEnumFilters_Release(fenum);
|
yading@10
|
126 }
|
yading@10
|
127 IGraphBuilder_Release(ctx->graph);
|
yading@10
|
128 }
|
yading@10
|
129
|
yading@10
|
130 if (ctx->capture_pin[VideoDevice])
|
yading@10
|
131 libAVPin_Release(ctx->capture_pin[VideoDevice]);
|
yading@10
|
132 if (ctx->capture_pin[AudioDevice])
|
yading@10
|
133 libAVPin_Release(ctx->capture_pin[AudioDevice]);
|
yading@10
|
134 if (ctx->capture_filter[VideoDevice])
|
yading@10
|
135 libAVFilter_Release(ctx->capture_filter[VideoDevice]);
|
yading@10
|
136 if (ctx->capture_filter[AudioDevice])
|
yading@10
|
137 libAVFilter_Release(ctx->capture_filter[AudioDevice]);
|
yading@10
|
138
|
yading@10
|
139 if (ctx->device_pin[VideoDevice])
|
yading@10
|
140 IPin_Release(ctx->device_pin[VideoDevice]);
|
yading@10
|
141 if (ctx->device_pin[AudioDevice])
|
yading@10
|
142 IPin_Release(ctx->device_pin[AudioDevice]);
|
yading@10
|
143 if (ctx->device_filter[VideoDevice])
|
yading@10
|
144 IBaseFilter_Release(ctx->device_filter[VideoDevice]);
|
yading@10
|
145 if (ctx->device_filter[AudioDevice])
|
yading@10
|
146 IBaseFilter_Release(ctx->device_filter[AudioDevice]);
|
yading@10
|
147
|
yading@10
|
148 if (ctx->device_name[0])
|
yading@10
|
149 av_free(ctx->device_name[0]);
|
yading@10
|
150 if (ctx->device_name[1])
|
yading@10
|
151 av_free(ctx->device_name[1]);
|
yading@10
|
152
|
yading@10
|
153 if(ctx->mutex)
|
yading@10
|
154 CloseHandle(ctx->mutex);
|
yading@10
|
155 if(ctx->event[0])
|
yading@10
|
156 CloseHandle(ctx->event[0]);
|
yading@10
|
157 if(ctx->event[1])
|
yading@10
|
158 CloseHandle(ctx->event[1]);
|
yading@10
|
159
|
yading@10
|
160 pktl = ctx->pktl;
|
yading@10
|
161 while (pktl) {
|
yading@10
|
162 AVPacketList *next = pktl->next;
|
yading@10
|
163 av_destruct_packet(&pktl->pkt);
|
yading@10
|
164 av_free(pktl);
|
yading@10
|
165 pktl = next;
|
yading@10
|
166 }
|
yading@10
|
167
|
yading@10
|
168 CoUninitialize();
|
yading@10
|
169
|
yading@10
|
170 return 0;
|
yading@10
|
171 }
|
yading@10
|
172
|
yading@10
|
173 static char *dup_wchar_to_utf8(wchar_t *w)
|
yading@10
|
174 {
|
yading@10
|
175 char *s = NULL;
|
yading@10
|
176 int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
|
yading@10
|
177 s = av_malloc(l);
|
yading@10
|
178 if (s)
|
yading@10
|
179 WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
|
yading@10
|
180 return s;
|
yading@10
|
181 }
|
yading@10
|
182
|
yading@10
|
183 static int shall_we_drop(AVFormatContext *s)
|
yading@10
|
184 {
|
yading@10
|
185 struct dshow_ctx *ctx = s->priv_data;
|
yading@10
|
186 const uint8_t dropscore[] = {62, 75, 87, 100};
|
yading@10
|
187 const int ndropscores = FF_ARRAY_ELEMS(dropscore);
|
yading@10
|
188 unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer;
|
yading@10
|
189
|
yading@10
|
190 if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) {
|
yading@10
|
191 av_log(s, AV_LOG_ERROR,
|
yading@10
|
192 "real-time buffer %d%% full! frame dropped!\n", buffer_fullness);
|
yading@10
|
193 return 1;
|
yading@10
|
194 }
|
yading@10
|
195
|
yading@10
|
196 return 0;
|
yading@10
|
197 }
|
yading@10
|
198
|
yading@10
|
199 static void
|
yading@10
|
200 callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
|
yading@10
|
201 {
|
yading@10
|
202 AVFormatContext *s = priv_data;
|
yading@10
|
203 struct dshow_ctx *ctx = s->priv_data;
|
yading@10
|
204 AVPacketList **ppktl, *pktl_next;
|
yading@10
|
205
|
yading@10
|
206 // dump_videohdr(s, vdhdr);
|
yading@10
|
207
|
yading@10
|
208 WaitForSingleObject(ctx->mutex, INFINITE);
|
yading@10
|
209
|
yading@10
|
210 if(shall_we_drop(s))
|
yading@10
|
211 goto fail;
|
yading@10
|
212
|
yading@10
|
213 pktl_next = av_mallocz(sizeof(AVPacketList));
|
yading@10
|
214 if(!pktl_next)
|
yading@10
|
215 goto fail;
|
yading@10
|
216
|
yading@10
|
217 if(av_new_packet(&pktl_next->pkt, buf_size) < 0) {
|
yading@10
|
218 av_free(pktl_next);
|
yading@10
|
219 goto fail;
|
yading@10
|
220 }
|
yading@10
|
221
|
yading@10
|
222 pktl_next->pkt.stream_index = index;
|
yading@10
|
223 pktl_next->pkt.pts = time;
|
yading@10
|
224 memcpy(pktl_next->pkt.data, buf, buf_size);
|
yading@10
|
225
|
yading@10
|
226 for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next);
|
yading@10
|
227 *ppktl = pktl_next;
|
yading@10
|
228
|
yading@10
|
229 ctx->curbufsize += buf_size;
|
yading@10
|
230
|
yading@10
|
231 SetEvent(ctx->event[1]);
|
yading@10
|
232 ReleaseMutex(ctx->mutex);
|
yading@10
|
233
|
yading@10
|
234 return;
|
yading@10
|
235 fail:
|
yading@10
|
236 ReleaseMutex(ctx->mutex);
|
yading@10
|
237 return;
|
yading@10
|
238 }
|
yading@10
|
239
|
yading@10
|
240 /**
|
yading@10
|
241 * Cycle through available devices using the device enumerator devenum,
|
yading@10
|
242 * retrieve the device with type specified by devtype and return the
|
yading@10
|
243 * pointer to the object found in *pfilter.
|
yading@10
|
244 * If pfilter is NULL, list all device names.
|
yading@10
|
245 */
|
yading@10
|
246 static int
|
yading@10
|
247 dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
|
yading@10
|
248 enum dshowDeviceType devtype, IBaseFilter **pfilter)
|
yading@10
|
249 {
|
yading@10
|
250 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
251 IBaseFilter *device_filter = NULL;
|
yading@10
|
252 IEnumMoniker *classenum = NULL;
|
yading@10
|
253 IMoniker *m = NULL;
|
yading@10
|
254 const char *device_name = ctx->device_name[devtype];
|
yading@10
|
255 int skip = (devtype == VideoDevice) ? ctx->video_device_number
|
yading@10
|
256 : ctx->audio_device_number;
|
yading@10
|
257 int r;
|
yading@10
|
258
|
yading@10
|
259 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
|
yading@10
|
260 &CLSID_AudioInputDeviceCategory };
|
yading@10
|
261 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
|
yading@10
|
262
|
yading@10
|
263 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
|
yading@10
|
264 (IEnumMoniker **) &classenum, 0);
|
yading@10
|
265 if (r != S_OK) {
|
yading@10
|
266 av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n",
|
yading@10
|
267 devtypename);
|
yading@10
|
268 return AVERROR(EIO);
|
yading@10
|
269 }
|
yading@10
|
270
|
yading@10
|
271 while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
|
yading@10
|
272 IPropertyBag *bag = NULL;
|
yading@10
|
273 char *buf = NULL;
|
yading@10
|
274 VARIANT var;
|
yading@10
|
275
|
yading@10
|
276 r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);
|
yading@10
|
277 if (r != S_OK)
|
yading@10
|
278 goto fail1;
|
yading@10
|
279
|
yading@10
|
280 var.vt = VT_BSTR;
|
yading@10
|
281 r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);
|
yading@10
|
282 if (r != S_OK)
|
yading@10
|
283 goto fail1;
|
yading@10
|
284
|
yading@10
|
285 buf = dup_wchar_to_utf8(var.bstrVal);
|
yading@10
|
286
|
yading@10
|
287 if (pfilter) {
|
yading@10
|
288 if (strcmp(device_name, buf))
|
yading@10
|
289 goto fail1;
|
yading@10
|
290
|
yading@10
|
291 if (!skip--)
|
yading@10
|
292 IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
|
yading@10
|
293 } else {
|
yading@10
|
294 av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf);
|
yading@10
|
295 }
|
yading@10
|
296
|
yading@10
|
297 fail1:
|
yading@10
|
298 if (buf)
|
yading@10
|
299 av_free(buf);
|
yading@10
|
300 if (bag)
|
yading@10
|
301 IPropertyBag_Release(bag);
|
yading@10
|
302 IMoniker_Release(m);
|
yading@10
|
303 }
|
yading@10
|
304
|
yading@10
|
305 IEnumMoniker_Release(classenum);
|
yading@10
|
306
|
yading@10
|
307 if (pfilter) {
|
yading@10
|
308 if (!device_filter) {
|
yading@10
|
309 av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
|
yading@10
|
310 devtypename);
|
yading@10
|
311 return AVERROR(EIO);
|
yading@10
|
312 }
|
yading@10
|
313 *pfilter = device_filter;
|
yading@10
|
314 }
|
yading@10
|
315
|
yading@10
|
316 return 0;
|
yading@10
|
317 }
|
yading@10
|
318
|
yading@10
|
319 /**
|
yading@10
|
320 * Cycle through available formats using the specified pin,
|
yading@10
|
321 * try to set parameters specified through AVOptions and if successful
|
yading@10
|
322 * return 1 in *pformat_set.
|
yading@10
|
323 * If pformat_set is NULL, list all pin capabilities.
|
yading@10
|
324 */
|
yading@10
|
325 static void
|
yading@10
|
326 dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
|
yading@10
|
327 IPin *pin, int *pformat_set)
|
yading@10
|
328 {
|
yading@10
|
329 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
330 IAMStreamConfig *config = NULL;
|
yading@10
|
331 AM_MEDIA_TYPE *type = NULL;
|
yading@10
|
332 int format_set = 0;
|
yading@10
|
333 void *caps = NULL;
|
yading@10
|
334 int i, n, size;
|
yading@10
|
335
|
yading@10
|
336 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
|
yading@10
|
337 return;
|
yading@10
|
338 if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
|
yading@10
|
339 goto end;
|
yading@10
|
340
|
yading@10
|
341 caps = av_malloc(size);
|
yading@10
|
342 if (!caps)
|
yading@10
|
343 goto end;
|
yading@10
|
344
|
yading@10
|
345 for (i = 0; i < n && !format_set; i++) {
|
yading@10
|
346 IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
|
yading@10
|
347
|
yading@10
|
348 #if DSHOWDEBUG
|
yading@10
|
349 ff_print_AM_MEDIA_TYPE(type);
|
yading@10
|
350 #endif
|
yading@10
|
351
|
yading@10
|
352 if (devtype == VideoDevice) {
|
yading@10
|
353 VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
|
yading@10
|
354 BITMAPINFOHEADER *bih;
|
yading@10
|
355 int64_t *fr;
|
yading@10
|
356 #if DSHOWDEBUG
|
yading@10
|
357 ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
|
yading@10
|
358 #endif
|
yading@10
|
359 if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
|
yading@10
|
360 VIDEOINFOHEADER *v = (void *) type->pbFormat;
|
yading@10
|
361 fr = &v->AvgTimePerFrame;
|
yading@10
|
362 bih = &v->bmiHeader;
|
yading@10
|
363 } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
|
yading@10
|
364 VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
|
yading@10
|
365 fr = &v->AvgTimePerFrame;
|
yading@10
|
366 bih = &v->bmiHeader;
|
yading@10
|
367 } else {
|
yading@10
|
368 goto next;
|
yading@10
|
369 }
|
yading@10
|
370 if (!pformat_set) {
|
yading@10
|
371 enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
|
yading@10
|
372 if (pix_fmt == AV_PIX_FMT_NONE) {
|
yading@10
|
373 enum AVCodecID codec_id = ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression);
|
yading@10
|
374 AVCodec *codec = avcodec_find_decoder(codec_id);
|
yading@10
|
375 if (codec_id == AV_CODEC_ID_NONE || !codec) {
|
yading@10
|
376 av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression);
|
yading@10
|
377 } else {
|
yading@10
|
378 av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name);
|
yading@10
|
379 }
|
yading@10
|
380 } else {
|
yading@10
|
381 av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
|
yading@10
|
382 }
|
yading@10
|
383 av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
|
yading@10
|
384 vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
|
yading@10
|
385 1e7 / vcaps->MaxFrameInterval,
|
yading@10
|
386 vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
|
yading@10
|
387 1e7 / vcaps->MinFrameInterval);
|
yading@10
|
388 continue;
|
yading@10
|
389 }
|
yading@10
|
390 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
|
yading@10
|
391 if (ctx->video_codec_id != ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression))
|
yading@10
|
392 goto next;
|
yading@10
|
393 }
|
yading@10
|
394 if (ctx->pixel_format != AV_PIX_FMT_NONE &&
|
yading@10
|
395 ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
|
yading@10
|
396 goto next;
|
yading@10
|
397 }
|
yading@10
|
398 if (ctx->framerate) {
|
yading@10
|
399 int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
|
yading@10
|
400 / ctx->requested_framerate.num;
|
yading@10
|
401 if (framerate > vcaps->MaxFrameInterval ||
|
yading@10
|
402 framerate < vcaps->MinFrameInterval)
|
yading@10
|
403 goto next;
|
yading@10
|
404 *fr = framerate;
|
yading@10
|
405 }
|
yading@10
|
406 if (ctx->requested_width && ctx->requested_height) {
|
yading@10
|
407 if (ctx->requested_width > vcaps->MaxOutputSize.cx ||
|
yading@10
|
408 ctx->requested_width < vcaps->MinOutputSize.cx ||
|
yading@10
|
409 ctx->requested_height > vcaps->MaxOutputSize.cy ||
|
yading@10
|
410 ctx->requested_height < vcaps->MinOutputSize.cy)
|
yading@10
|
411 goto next;
|
yading@10
|
412 bih->biWidth = ctx->requested_width;
|
yading@10
|
413 bih->biHeight = ctx->requested_height;
|
yading@10
|
414 }
|
yading@10
|
415 } else {
|
yading@10
|
416 AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
|
yading@10
|
417 WAVEFORMATEX *fx;
|
yading@10
|
418 #if DSHOWDEBUG
|
yading@10
|
419 ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);
|
yading@10
|
420 #endif
|
yading@10
|
421 if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
|
yading@10
|
422 fx = (void *) type->pbFormat;
|
yading@10
|
423 } else {
|
yading@10
|
424 goto next;
|
yading@10
|
425 }
|
yading@10
|
426 if (!pformat_set) {
|
yading@10
|
427 av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
|
yading@10
|
428 acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
|
yading@10
|
429 acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
|
yading@10
|
430 continue;
|
yading@10
|
431 }
|
yading@10
|
432 if (ctx->sample_rate) {
|
yading@10
|
433 if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
|
yading@10
|
434 ctx->sample_rate < acaps->MinimumSampleFrequency)
|
yading@10
|
435 goto next;
|
yading@10
|
436 fx->nSamplesPerSec = ctx->sample_rate;
|
yading@10
|
437 }
|
yading@10
|
438 if (ctx->sample_size) {
|
yading@10
|
439 if (ctx->sample_size > acaps->MaximumBitsPerSample ||
|
yading@10
|
440 ctx->sample_size < acaps->MinimumBitsPerSample)
|
yading@10
|
441 goto next;
|
yading@10
|
442 fx->wBitsPerSample = ctx->sample_size;
|
yading@10
|
443 }
|
yading@10
|
444 if (ctx->channels) {
|
yading@10
|
445 if (ctx->channels > acaps->MaximumChannels ||
|
yading@10
|
446 ctx->channels < acaps->MinimumChannels)
|
yading@10
|
447 goto next;
|
yading@10
|
448 fx->nChannels = ctx->channels;
|
yading@10
|
449 }
|
yading@10
|
450 }
|
yading@10
|
451 if (IAMStreamConfig_SetFormat(config, type) != S_OK)
|
yading@10
|
452 goto next;
|
yading@10
|
453 format_set = 1;
|
yading@10
|
454 next:
|
yading@10
|
455 if (type->pbFormat)
|
yading@10
|
456 CoTaskMemFree(type->pbFormat);
|
yading@10
|
457 CoTaskMemFree(type);
|
yading@10
|
458 }
|
yading@10
|
459 end:
|
yading@10
|
460 IAMStreamConfig_Release(config);
|
yading@10
|
461 if (caps)
|
yading@10
|
462 av_free(caps);
|
yading@10
|
463 if (pformat_set)
|
yading@10
|
464 *pformat_set = format_set;
|
yading@10
|
465 }
|
yading@10
|
466
|
yading@10
|
467 /**
|
yading@10
|
468 * Set audio device buffer size in milliseconds (which can directly impact
|
yading@10
|
469 * latency, depending on the device).
|
yading@10
|
470 */
|
yading@10
|
471 static int
|
yading@10
|
472 dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
|
yading@10
|
473 {
|
yading@10
|
474 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
475 IAMBufferNegotiation *buffer_negotiation = NULL;
|
yading@10
|
476 ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
|
yading@10
|
477 IAMStreamConfig *config = NULL;
|
yading@10
|
478 AM_MEDIA_TYPE *type = NULL;
|
yading@10
|
479 int ret = AVERROR(EIO);
|
yading@10
|
480
|
yading@10
|
481 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
|
yading@10
|
482 goto end;
|
yading@10
|
483 if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
|
yading@10
|
484 goto end;
|
yading@10
|
485 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
|
yading@10
|
486 goto end;
|
yading@10
|
487
|
yading@10
|
488 props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
|
yading@10
|
489 * ctx->audio_buffer_size / 1000;
|
yading@10
|
490
|
yading@10
|
491 if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
|
yading@10
|
492 goto end;
|
yading@10
|
493 if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
|
yading@10
|
494 goto end;
|
yading@10
|
495
|
yading@10
|
496 ret = 0;
|
yading@10
|
497
|
yading@10
|
498 end:
|
yading@10
|
499 if (buffer_negotiation)
|
yading@10
|
500 IAMBufferNegotiation_Release(buffer_negotiation);
|
yading@10
|
501 if (type) {
|
yading@10
|
502 if (type->pbFormat)
|
yading@10
|
503 CoTaskMemFree(type->pbFormat);
|
yading@10
|
504 CoTaskMemFree(type);
|
yading@10
|
505 }
|
yading@10
|
506 if (config)
|
yading@10
|
507 IAMStreamConfig_Release(config);
|
yading@10
|
508
|
yading@10
|
509 return ret;
|
yading@10
|
510 }
|
yading@10
|
511
|
yading@10
|
512 /**
|
yading@10
|
513 * Cycle through available pins using the device_filter device, of type
|
yading@10
|
514 * devtype, retrieve the first output pin and return the pointer to the
|
yading@10
|
515 * object found in *ppin.
|
yading@10
|
516 * If ppin is NULL, cycle through all pins listing audio/video capabilities.
|
yading@10
|
517 */
|
yading@10
|
518 static int
|
yading@10
|
519 dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
|
yading@10
|
520 IBaseFilter *device_filter, IPin **ppin)
|
yading@10
|
521 {
|
yading@10
|
522 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
523 IEnumPins *pins = 0;
|
yading@10
|
524 IPin *device_pin = NULL;
|
yading@10
|
525 IPin *pin;
|
yading@10
|
526 int r;
|
yading@10
|
527
|
yading@10
|
528 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
|
yading@10
|
529 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
|
yading@10
|
530
|
yading@10
|
531 int set_format = (devtype == VideoDevice && (ctx->framerate ||
|
yading@10
|
532 (ctx->requested_width && ctx->requested_height) ||
|
yading@10
|
533 ctx->pixel_format != AV_PIX_FMT_NONE ||
|
yading@10
|
534 ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO))
|
yading@10
|
535 || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
|
yading@10
|
536 int format_set = 0;
|
yading@10
|
537
|
yading@10
|
538 r = IBaseFilter_EnumPins(device_filter, &pins);
|
yading@10
|
539 if (r != S_OK) {
|
yading@10
|
540 av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
|
yading@10
|
541 return AVERROR(EIO);
|
yading@10
|
542 }
|
yading@10
|
543
|
yading@10
|
544 if (!ppin) {
|
yading@10
|
545 av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n",
|
yading@10
|
546 devtypename);
|
yading@10
|
547 }
|
yading@10
|
548 while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
|
yading@10
|
549 IKsPropertySet *p = NULL;
|
yading@10
|
550 IEnumMediaTypes *types = NULL;
|
yading@10
|
551 PIN_INFO info = {0};
|
yading@10
|
552 AM_MEDIA_TYPE *type;
|
yading@10
|
553 GUID category;
|
yading@10
|
554 DWORD r2;
|
yading@10
|
555
|
yading@10
|
556 IPin_QueryPinInfo(pin, &info);
|
yading@10
|
557 IBaseFilter_Release(info.pFilter);
|
yading@10
|
558
|
yading@10
|
559 if (info.dir != PINDIR_OUTPUT)
|
yading@10
|
560 goto next;
|
yading@10
|
561 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
|
yading@10
|
562 goto next;
|
yading@10
|
563 if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
|
yading@10
|
564 NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
|
yading@10
|
565 goto next;
|
yading@10
|
566 if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
|
yading@10
|
567 goto next;
|
yading@10
|
568
|
yading@10
|
569 if (!ppin) {
|
yading@10
|
570 char *buf = dup_wchar_to_utf8(info.achName);
|
yading@10
|
571 av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf);
|
yading@10
|
572 av_free(buf);
|
yading@10
|
573 dshow_cycle_formats(avctx, devtype, pin, NULL);
|
yading@10
|
574 goto next;
|
yading@10
|
575 }
|
yading@10
|
576 if (set_format) {
|
yading@10
|
577 dshow_cycle_formats(avctx, devtype, pin, &format_set);
|
yading@10
|
578 if (!format_set) {
|
yading@10
|
579 goto next;
|
yading@10
|
580 }
|
yading@10
|
581 }
|
yading@10
|
582 if (devtype == AudioDevice && ctx->audio_buffer_size) {
|
yading@10
|
583 if (dshow_set_audio_buffer_size(avctx, pin) < 0)
|
yading@10
|
584 goto next;
|
yading@10
|
585 }
|
yading@10
|
586
|
yading@10
|
587 if (IPin_EnumMediaTypes(pin, &types) != S_OK)
|
yading@10
|
588 goto next;
|
yading@10
|
589
|
yading@10
|
590 IEnumMediaTypes_Reset(types);
|
yading@10
|
591 while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
|
yading@10
|
592 if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
|
yading@10
|
593 device_pin = pin;
|
yading@10
|
594 goto next;
|
yading@10
|
595 }
|
yading@10
|
596 CoTaskMemFree(type);
|
yading@10
|
597 }
|
yading@10
|
598
|
yading@10
|
599 next:
|
yading@10
|
600 if (types)
|
yading@10
|
601 IEnumMediaTypes_Release(types);
|
yading@10
|
602 if (p)
|
yading@10
|
603 IKsPropertySet_Release(p);
|
yading@10
|
604 if (device_pin != pin)
|
yading@10
|
605 IPin_Release(pin);
|
yading@10
|
606 }
|
yading@10
|
607
|
yading@10
|
608 IEnumPins_Release(pins);
|
yading@10
|
609
|
yading@10
|
610 if (ppin) {
|
yading@10
|
611 if (set_format && !format_set) {
|
yading@10
|
612 av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
|
yading@10
|
613 return AVERROR(EIO);
|
yading@10
|
614 }
|
yading@10
|
615 if (!device_pin) {
|
yading@10
|
616 av_log(avctx, AV_LOG_ERROR,
|
yading@10
|
617 "Could not find output pin from %s capture device.\n", devtypename);
|
yading@10
|
618 return AVERROR(EIO);
|
yading@10
|
619 }
|
yading@10
|
620 *ppin = device_pin;
|
yading@10
|
621 }
|
yading@10
|
622
|
yading@10
|
623 return 0;
|
yading@10
|
624 }
|
yading@10
|
625
|
yading@10
|
626 /**
|
yading@10
|
627 * List options for device with type devtype.
|
yading@10
|
628 *
|
yading@10
|
629 * @param devenum device enumerator used for accessing the device
|
yading@10
|
630 */
|
yading@10
|
631 static int
|
yading@10
|
632 dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
|
yading@10
|
633 enum dshowDeviceType devtype)
|
yading@10
|
634 {
|
yading@10
|
635 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
636 IBaseFilter *device_filter = NULL;
|
yading@10
|
637 int r;
|
yading@10
|
638
|
yading@10
|
639 if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0)
|
yading@10
|
640 return r;
|
yading@10
|
641 ctx->device_filter[devtype] = device_filter;
|
yading@10
|
642 if ((r = dshow_cycle_pins(avctx, devtype, device_filter, NULL)) < 0)
|
yading@10
|
643 return r;
|
yading@10
|
644
|
yading@10
|
645 return 0;
|
yading@10
|
646 }
|
yading@10
|
647
|
yading@10
|
648 static int
|
yading@10
|
649 dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
|
yading@10
|
650 enum dshowDeviceType devtype)
|
yading@10
|
651 {
|
yading@10
|
652 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
653 IBaseFilter *device_filter = NULL;
|
yading@10
|
654 IGraphBuilder *graph = ctx->graph;
|
yading@10
|
655 IPin *device_pin = NULL;
|
yading@10
|
656 libAVPin *capture_pin = NULL;
|
yading@10
|
657 libAVFilter *capture_filter = NULL;
|
yading@10
|
658 int ret = AVERROR(EIO);
|
yading@10
|
659 int r;
|
yading@10
|
660
|
yading@10
|
661 const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
|
yading@10
|
662
|
yading@10
|
663 if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
|
yading@10
|
664 ret = r;
|
yading@10
|
665 goto error;
|
yading@10
|
666 }
|
yading@10
|
667
|
yading@10
|
668 ctx->device_filter [devtype] = device_filter;
|
yading@10
|
669
|
yading@10
|
670 r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
|
yading@10
|
671 if (r != S_OK) {
|
yading@10
|
672 av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
|
yading@10
|
673 goto error;
|
yading@10
|
674 }
|
yading@10
|
675
|
yading@10
|
676 if ((r = dshow_cycle_pins(avctx, devtype, device_filter, &device_pin)) < 0) {
|
yading@10
|
677 ret = r;
|
yading@10
|
678 goto error;
|
yading@10
|
679 }
|
yading@10
|
680 ctx->device_pin[devtype] = device_pin;
|
yading@10
|
681
|
yading@10
|
682 capture_filter = libAVFilter_Create(avctx, callback, devtype);
|
yading@10
|
683 if (!capture_filter) {
|
yading@10
|
684 av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
|
yading@10
|
685 goto error;
|
yading@10
|
686 }
|
yading@10
|
687 ctx->capture_filter[devtype] = capture_filter;
|
yading@10
|
688
|
yading@10
|
689 r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
|
yading@10
|
690 filter_name[devtype]);
|
yading@10
|
691 if (r != S_OK) {
|
yading@10
|
692 av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
|
yading@10
|
693 goto error;
|
yading@10
|
694 }
|
yading@10
|
695
|
yading@10
|
696 libAVPin_AddRef(capture_filter->pin);
|
yading@10
|
697 capture_pin = capture_filter->pin;
|
yading@10
|
698 ctx->capture_pin[devtype] = capture_pin;
|
yading@10
|
699
|
yading@10
|
700 r = IGraphBuilder_ConnectDirect(graph, device_pin, (IPin *) capture_pin, NULL);
|
yading@10
|
701 if (r != S_OK) {
|
yading@10
|
702 av_log(avctx, AV_LOG_ERROR, "Could not connect pins\n");
|
yading@10
|
703 goto error;
|
yading@10
|
704 }
|
yading@10
|
705
|
yading@10
|
706 ret = 0;
|
yading@10
|
707
|
yading@10
|
708 error:
|
yading@10
|
709 return ret;
|
yading@10
|
710 }
|
yading@10
|
711
|
yading@10
|
712 static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
|
yading@10
|
713 {
|
yading@10
|
714 switch (sample_fmt) {
|
yading@10
|
715 case AV_SAMPLE_FMT_U8: return AV_CODEC_ID_PCM_U8;
|
yading@10
|
716 case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
|
yading@10
|
717 case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
|
yading@10
|
718 default: return AV_CODEC_ID_NONE; /* Should never happen. */
|
yading@10
|
719 }
|
yading@10
|
720 }
|
yading@10
|
721
|
yading@10
|
722 static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
|
yading@10
|
723 {
|
yading@10
|
724 switch (bits) {
|
yading@10
|
725 case 8: return AV_SAMPLE_FMT_U8;
|
yading@10
|
726 case 16: return AV_SAMPLE_FMT_S16;
|
yading@10
|
727 case 32: return AV_SAMPLE_FMT_S32;
|
yading@10
|
728 default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
|
yading@10
|
729 }
|
yading@10
|
730 }
|
yading@10
|
731
|
yading@10
|
732 static int
|
yading@10
|
733 dshow_add_device(AVFormatContext *avctx,
|
yading@10
|
734 enum dshowDeviceType devtype)
|
yading@10
|
735 {
|
yading@10
|
736 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
737 AM_MEDIA_TYPE type;
|
yading@10
|
738 AVCodecContext *codec;
|
yading@10
|
739 AVStream *st;
|
yading@10
|
740 int ret = AVERROR(EIO);
|
yading@10
|
741
|
yading@10
|
742 st = avformat_new_stream(avctx, NULL);
|
yading@10
|
743 if (!st) {
|
yading@10
|
744 ret = AVERROR(ENOMEM);
|
yading@10
|
745 goto error;
|
yading@10
|
746 }
|
yading@10
|
747 st->id = devtype;
|
yading@10
|
748
|
yading@10
|
749 ctx->capture_filter[devtype]->stream_index = st->index;
|
yading@10
|
750
|
yading@10
|
751 libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
|
yading@10
|
752
|
yading@10
|
753 codec = st->codec;
|
yading@10
|
754 if (devtype == VideoDevice) {
|
yading@10
|
755 BITMAPINFOHEADER *bih = NULL;
|
yading@10
|
756 AVRational time_base;
|
yading@10
|
757
|
yading@10
|
758 if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
|
yading@10
|
759 VIDEOINFOHEADER *v = (void *) type.pbFormat;
|
yading@10
|
760 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
|
yading@10
|
761 bih = &v->bmiHeader;
|
yading@10
|
762 } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
|
yading@10
|
763 VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
|
yading@10
|
764 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
|
yading@10
|
765 bih = &v->bmiHeader;
|
yading@10
|
766 }
|
yading@10
|
767 if (!bih) {
|
yading@10
|
768 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
|
yading@10
|
769 goto error;
|
yading@10
|
770 }
|
yading@10
|
771
|
yading@10
|
772 codec->time_base = time_base;
|
yading@10
|
773 codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@10
|
774 codec->width = bih->biWidth;
|
yading@10
|
775 codec->height = bih->biHeight;
|
yading@10
|
776 codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
|
yading@10
|
777 if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) {
|
yading@10
|
778 av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n");
|
yading@10
|
779 codec->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
|
yading@10
|
780 }
|
yading@10
|
781 if (codec->pix_fmt == AV_PIX_FMT_NONE) {
|
yading@10
|
782 codec->codec_id = ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression);
|
yading@10
|
783 if (codec->codec_id == AV_CODEC_ID_NONE) {
|
yading@10
|
784 av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
|
yading@10
|
785 "Please report type 0x%X.\n", (int) bih->biCompression);
|
yading@10
|
786 return AVERROR_PATCHWELCOME;
|
yading@10
|
787 }
|
yading@10
|
788 codec->bits_per_coded_sample = bih->biBitCount;
|
yading@10
|
789 } else {
|
yading@10
|
790 codec->codec_id = AV_CODEC_ID_RAWVIDEO;
|
yading@10
|
791 if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
|
yading@10
|
792 codec->bits_per_coded_sample = bih->biBitCount;
|
yading@10
|
793 codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE);
|
yading@10
|
794 if (codec->extradata) {
|
yading@10
|
795 codec->extradata_size = 9;
|
yading@10
|
796 memcpy(codec->extradata, "BottomUp", 9);
|
yading@10
|
797 }
|
yading@10
|
798 }
|
yading@10
|
799 }
|
yading@10
|
800 } else {
|
yading@10
|
801 WAVEFORMATEX *fx = NULL;
|
yading@10
|
802
|
yading@10
|
803 if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
|
yading@10
|
804 fx = (void *) type.pbFormat;
|
yading@10
|
805 }
|
yading@10
|
806 if (!fx) {
|
yading@10
|
807 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
|
yading@10
|
808 goto error;
|
yading@10
|
809 }
|
yading@10
|
810
|
yading@10
|
811 codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
yading@10
|
812 codec->sample_fmt = sample_fmt_bits_per_sample(fx->wBitsPerSample);
|
yading@10
|
813 codec->codec_id = waveform_codec_id(codec->sample_fmt);
|
yading@10
|
814 codec->sample_rate = fx->nSamplesPerSec;
|
yading@10
|
815 codec->channels = fx->nChannels;
|
yading@10
|
816 }
|
yading@10
|
817
|
yading@10
|
818 avpriv_set_pts_info(st, 64, 1, 10000000);
|
yading@10
|
819
|
yading@10
|
820 ret = 0;
|
yading@10
|
821
|
yading@10
|
822 error:
|
yading@10
|
823 return ret;
|
yading@10
|
824 }
|
yading@10
|
825
|
yading@10
|
826 static int parse_device_name(AVFormatContext *avctx)
|
yading@10
|
827 {
|
yading@10
|
828 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
829 char **device_name = ctx->device_name;
|
yading@10
|
830 char *name = av_strdup(avctx->filename);
|
yading@10
|
831 char *tmp = name;
|
yading@10
|
832 int ret = 1;
|
yading@10
|
833 char *type;
|
yading@10
|
834
|
yading@10
|
835 while ((type = strtok(tmp, "="))) {
|
yading@10
|
836 char *token = strtok(NULL, ":");
|
yading@10
|
837 tmp = NULL;
|
yading@10
|
838
|
yading@10
|
839 if (!strcmp(type, "video")) {
|
yading@10
|
840 device_name[0] = token;
|
yading@10
|
841 } else if (!strcmp(type, "audio")) {
|
yading@10
|
842 device_name[1] = token;
|
yading@10
|
843 } else {
|
yading@10
|
844 device_name[0] = NULL;
|
yading@10
|
845 device_name[1] = NULL;
|
yading@10
|
846 break;
|
yading@10
|
847 }
|
yading@10
|
848 }
|
yading@10
|
849
|
yading@10
|
850 if (!device_name[0] && !device_name[1]) {
|
yading@10
|
851 ret = 0;
|
yading@10
|
852 } else {
|
yading@10
|
853 if (device_name[0])
|
yading@10
|
854 device_name[0] = av_strdup(device_name[0]);
|
yading@10
|
855 if (device_name[1])
|
yading@10
|
856 device_name[1] = av_strdup(device_name[1]);
|
yading@10
|
857 }
|
yading@10
|
858
|
yading@10
|
859 av_free(name);
|
yading@10
|
860 return ret;
|
yading@10
|
861 }
|
yading@10
|
862
|
yading@10
|
863 static int dshow_read_header(AVFormatContext *avctx)
|
yading@10
|
864 {
|
yading@10
|
865 struct dshow_ctx *ctx = avctx->priv_data;
|
yading@10
|
866 IGraphBuilder *graph = NULL;
|
yading@10
|
867 ICreateDevEnum *devenum = NULL;
|
yading@10
|
868 IMediaControl *control = NULL;
|
yading@10
|
869 IMediaEvent *media_event = NULL;
|
yading@10
|
870 HANDLE media_event_handle;
|
yading@10
|
871 HANDLE proc;
|
yading@10
|
872 int ret = AVERROR(EIO);
|
yading@10
|
873 int r;
|
yading@10
|
874
|
yading@10
|
875 CoInitialize(0);
|
yading@10
|
876
|
yading@10
|
877 if (!ctx->list_devices && !parse_device_name(avctx)) {
|
yading@10
|
878 av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
|
yading@10
|
879 goto error;
|
yading@10
|
880 }
|
yading@10
|
881
|
yading@10
|
882 ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id
|
yading@10
|
883 : AV_CODEC_ID_RAWVIDEO;
|
yading@10
|
884 if (ctx->pixel_format != AV_PIX_FMT_NONE) {
|
yading@10
|
885 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
|
yading@10
|
886 av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when "
|
yading@10
|
887 "video codec is not set or set to rawvideo\n");
|
yading@10
|
888 ret = AVERROR(EINVAL);
|
yading@10
|
889 goto error;
|
yading@10
|
890 }
|
yading@10
|
891 }
|
yading@10
|
892 if (ctx->framerate) {
|
yading@10
|
893 r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate);
|
yading@10
|
894 if (r < 0) {
|
yading@10
|
895 av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
|
yading@10
|
896 goto error;
|
yading@10
|
897 }
|
yading@10
|
898 }
|
yading@10
|
899
|
yading@10
|
900 r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
|
yading@10
|
901 &IID_IGraphBuilder, (void **) &graph);
|
yading@10
|
902 if (r != S_OK) {
|
yading@10
|
903 av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
|
yading@10
|
904 goto error;
|
yading@10
|
905 }
|
yading@10
|
906 ctx->graph = graph;
|
yading@10
|
907
|
yading@10
|
908 r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
|
yading@10
|
909 &IID_ICreateDevEnum, (void **) &devenum);
|
yading@10
|
910 if (r != S_OK) {
|
yading@10
|
911 av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
|
yading@10
|
912 goto error;
|
yading@10
|
913 }
|
yading@10
|
914
|
yading@10
|
915 if (ctx->list_devices) {
|
yading@10
|
916 av_log(avctx, AV_LOG_INFO, "DirectShow video devices\n");
|
yading@10
|
917 dshow_cycle_devices(avctx, devenum, VideoDevice, NULL);
|
yading@10
|
918 av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
|
yading@10
|
919 dshow_cycle_devices(avctx, devenum, AudioDevice, NULL);
|
yading@10
|
920 ret = AVERROR_EXIT;
|
yading@10
|
921 goto error;
|
yading@10
|
922 }
|
yading@10
|
923 if (ctx->list_options) {
|
yading@10
|
924 if (ctx->device_name[VideoDevice])
|
yading@10
|
925 dshow_list_device_options(avctx, devenum, VideoDevice);
|
yading@10
|
926 if (ctx->device_name[AudioDevice])
|
yading@10
|
927 dshow_list_device_options(avctx, devenum, AudioDevice);
|
yading@10
|
928 ret = AVERROR_EXIT;
|
yading@10
|
929 goto error;
|
yading@10
|
930 }
|
yading@10
|
931
|
yading@10
|
932 if (ctx->device_name[VideoDevice]) {
|
yading@10
|
933 if ((r = dshow_open_device(avctx, devenum, VideoDevice)) < 0 ||
|
yading@10
|
934 (r = dshow_add_device(avctx, VideoDevice)) < 0) {
|
yading@10
|
935 ret = r;
|
yading@10
|
936 goto error;
|
yading@10
|
937 }
|
yading@10
|
938 }
|
yading@10
|
939 if (ctx->device_name[AudioDevice]) {
|
yading@10
|
940 if ((r = dshow_open_device(avctx, devenum, AudioDevice)) < 0 ||
|
yading@10
|
941 (r = dshow_add_device(avctx, AudioDevice)) < 0) {
|
yading@10
|
942 ret = r;
|
yading@10
|
943 goto error;
|
yading@10
|
944 }
|
yading@10
|
945 }
|
yading@10
|
946
|
yading@10
|
947 ctx->mutex = CreateMutex(NULL, 0, NULL);
|
yading@10
|
948 if (!ctx->mutex) {
|
yading@10
|
949 av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
|
yading@10
|
950 goto error;
|
yading@10
|
951 }
|
yading@10
|
952 ctx->event[1] = CreateEvent(NULL, 1, 0, NULL);
|
yading@10
|
953 if (!ctx->event[1]) {
|
yading@10
|
954 av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
|
yading@10
|
955 goto error;
|
yading@10
|
956 }
|
yading@10
|
957
|
yading@10
|
958 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
|
yading@10
|
959 if (r != S_OK) {
|
yading@10
|
960 av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
|
yading@10
|
961 goto error;
|
yading@10
|
962 }
|
yading@10
|
963 ctx->control = control;
|
yading@10
|
964
|
yading@10
|
965 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaEvent, (void **) &media_event);
|
yading@10
|
966 if (r != S_OK) {
|
yading@10
|
967 av_log(avctx, AV_LOG_ERROR, "Could not get media event.\n");
|
yading@10
|
968 goto error;
|
yading@10
|
969 }
|
yading@10
|
970 ctx->media_event = media_event;
|
yading@10
|
971
|
yading@10
|
972 r = IMediaEvent_GetEventHandle(media_event, (void *) &media_event_handle);
|
yading@10
|
973 if (r != S_OK) {
|
yading@10
|
974 av_log(avctx, AV_LOG_ERROR, "Could not get media event handle.\n");
|
yading@10
|
975 goto error;
|
yading@10
|
976 }
|
yading@10
|
977 proc = GetCurrentProcess();
|
yading@10
|
978 r = DuplicateHandle(proc, media_event_handle, proc, &ctx->event[0],
|
yading@10
|
979 0, 0, DUPLICATE_SAME_ACCESS);
|
yading@10
|
980 if (!r) {
|
yading@10
|
981 av_log(avctx, AV_LOG_ERROR, "Could not duplicate media event handle.\n");
|
yading@10
|
982 goto error;
|
yading@10
|
983 }
|
yading@10
|
984
|
yading@10
|
985 r = IMediaControl_Run(control);
|
yading@10
|
986 if (r == S_FALSE) {
|
yading@10
|
987 OAFilterState pfs;
|
yading@10
|
988 r = IMediaControl_GetState(control, 0, &pfs);
|
yading@10
|
989 }
|
yading@10
|
990 if (r != S_OK) {
|
yading@10
|
991 av_log(avctx, AV_LOG_ERROR, "Could not run filter\n");
|
yading@10
|
992 goto error;
|
yading@10
|
993 }
|
yading@10
|
994
|
yading@10
|
995 ret = 0;
|
yading@10
|
996
|
yading@10
|
997 error:
|
yading@10
|
998
|
yading@10
|
999 if (devenum)
|
yading@10
|
1000 ICreateDevEnum_Release(devenum);
|
yading@10
|
1001
|
yading@10
|
1002 if (ret < 0)
|
yading@10
|
1003 dshow_read_close(avctx);
|
yading@10
|
1004
|
yading@10
|
1005 return ret;
|
yading@10
|
1006 }
|
yading@10
|
1007
|
yading@10
|
1008 /**
|
yading@10
|
1009 * Checks media events from DirectShow and returns -1 on error or EOF. Also
|
yading@10
|
1010 * purges all events that might be in the event queue to stop the trigger
|
yading@10
|
1011 * of event notification.
|
yading@10
|
1012 */
|
yading@10
|
1013 static int dshow_check_event_queue(IMediaEvent *media_event)
|
yading@10
|
1014 {
|
yading@10
|
1015 LONG_PTR p1, p2;
|
yading@10
|
1016 long code;
|
yading@10
|
1017 int ret = 0;
|
yading@10
|
1018
|
yading@10
|
1019 while (IMediaEvent_GetEvent(media_event, &code, &p1, &p2, 0) != E_ABORT) {
|
yading@10
|
1020 if (code == EC_COMPLETE || code == EC_DEVICE_LOST || code == EC_ERRORABORT)
|
yading@10
|
1021 ret = -1;
|
yading@10
|
1022 IMediaEvent_FreeEventParams(media_event, code, p1, p2);
|
yading@10
|
1023 }
|
yading@10
|
1024
|
yading@10
|
1025 return ret;
|
yading@10
|
1026 }
|
yading@10
|
1027
|
yading@10
|
1028 static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
|
yading@10
|
1029 {
|
yading@10
|
1030 struct dshow_ctx *ctx = s->priv_data;
|
yading@10
|
1031 AVPacketList *pktl = NULL;
|
yading@10
|
1032
|
yading@10
|
1033 while (!ctx->eof && !pktl) {
|
yading@10
|
1034 WaitForSingleObject(ctx->mutex, INFINITE);
|
yading@10
|
1035 pktl = ctx->pktl;
|
yading@10
|
1036 if (pktl) {
|
yading@10
|
1037 *pkt = pktl->pkt;
|
yading@10
|
1038 ctx->pktl = ctx->pktl->next;
|
yading@10
|
1039 av_free(pktl);
|
yading@10
|
1040 ctx->curbufsize -= pkt->size;
|
yading@10
|
1041 }
|
yading@10
|
1042 ResetEvent(ctx->event[1]);
|
yading@10
|
1043 ReleaseMutex(ctx->mutex);
|
yading@10
|
1044 if (!pktl) {
|
yading@10
|
1045 if (dshow_check_event_queue(ctx->media_event) < 0) {
|
yading@10
|
1046 ctx->eof = 1;
|
yading@10
|
1047 } else if (s->flags & AVFMT_FLAG_NONBLOCK) {
|
yading@10
|
1048 return AVERROR(EAGAIN);
|
yading@10
|
1049 } else {
|
yading@10
|
1050 WaitForMultipleObjects(2, ctx->event, 0, INFINITE);
|
yading@10
|
1051 }
|
yading@10
|
1052 }
|
yading@10
|
1053 }
|
yading@10
|
1054
|
yading@10
|
1055 return ctx->eof ? AVERROR(EIO) : pkt->size;
|
yading@10
|
1056 }
|
yading@10
|
1057
|
yading@10
|
1058 #define OFFSET(x) offsetof(struct dshow_ctx, x)
|
yading@10
|
1059 #define DEC AV_OPT_FLAG_DECODING_PARAM
|
yading@10
|
1060 static const AVOption options[] = {
|
yading@10
|
1061 { "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(requested_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
|
yading@10
|
1062 { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, AV_PIX_FMT_NB-1, DEC },
|
yading@10
|
1063 { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
|
yading@10
|
1064 { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
|
yading@10
|
1065 { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },
|
yading@10
|
1066 { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
|
yading@10
|
1067 { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_devices" },
|
yading@10
|
1068 { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_devices" },
|
yading@10
|
1069 { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_devices" },
|
yading@10
|
1070 { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_options" },
|
yading@10
|
1071 { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_options" },
|
yading@10
|
1072 { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_options" },
|
yading@10
|
1073 { "video_device_number", "set video device number for devices with same name (starts at 0)", OFFSET(video_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
|
yading@10
|
1074 { "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
|
yading@10
|
1075 { "audio_buffer_size", "set audio device buffer latency size in milliseconds (default is the device's default)", OFFSET(audio_buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
|
yading@10
|
1076 { NULL },
|
yading@10
|
1077 };
|
yading@10
|
1078
|
yading@10
|
1079 static const AVClass dshow_class = {
|
yading@10
|
1080 .class_name = "dshow indev",
|
yading@10
|
1081 .item_name = av_default_item_name,
|
yading@10
|
1082 .option = options,
|
yading@10
|
1083 .version = LIBAVUTIL_VERSION_INT,
|
yading@10
|
1084 };
|
yading@10
|
1085
|
yading@10
|
1086 AVInputFormat ff_dshow_demuxer = {
|
yading@10
|
1087 .name = "dshow",
|
yading@10
|
1088 .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
|
yading@10
|
1089 .priv_data_size = sizeof(struct dshow_ctx),
|
yading@10
|
1090 .read_header = dshow_read_header,
|
yading@10
|
1091 .read_packet = dshow_read_packet,
|
yading@10
|
1092 .read_close = dshow_read_close,
|
yading@10
|
1093 .flags = AVFMT_NOFILE,
|
yading@10
|
1094 .priv_class = &dshow_class,
|
yading@10
|
1095 };
|