34 switch(biCompression) {
62 IMediaControl_Stop(ctx->
control);
63 IMediaControl_Release(ctx->
control);
72 r = IGraphBuilder_EnumFilters(ctx->
graph, &fenum);
75 IEnumFilters_Reset(fenum);
76 while (IEnumFilters_Next(fenum, 1, &f,
NULL) ==
S_OK) {
77 if (IGraphBuilder_RemoveFilter(ctx->
graph, f) ==
S_OK)
78 IEnumFilters_Reset(fenum);
80 IBaseFilter_Release(f);
82 IEnumFilters_Release(fenum);
84 IGraphBuilder_Release(ctx->
graph);
111 CloseHandle(ctx->
mutex);
113 CloseHandle(ctx->
event[0]);
115 CloseHandle(ctx->
event[1]);
133 int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
136 WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
143 static const uint8_t dropscore[] = {62, 75, 87, 100};
146 const char *devtypename = (devtype ==
VideoDevice) ?
"video" :
"audio";
150 "real-time buffer [%s] [%s input] too full or near too full (%d%% of size: %d [rtbufsize parameter])! frame dropped!\n",
167 WaitForSingleObject(ctx->
mutex, INFINITE);
182 pktl_next->
pkt.
pts = time;
183 memcpy(pktl_next->
pkt.
data, buf, buf_size);
185 for(ppktl = &ctx->
pktl ; *ppktl ; ppktl = &(*ppktl)->
next);
189 SetEvent(ctx->
event[1]);
190 ReleaseMutex(ctx->
mutex);
194 ReleaseMutex(ctx->
mutex);
210 IEnumMoniker *classenum =
NULL;
217 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
218 &CLSID_AudioInputDeviceCategory };
219 const char *devtypename = (devtype ==
VideoDevice) ?
"video" :
"audio only";
220 const char *sourcetypename = (sourcetype ==
VideoSourceDevice) ?
"video" :
"audio";
222 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[sourcetype],
223 (IEnumMoniker **) &classenum, 0);
231 IPropertyBag *bag =
NULL;
232 char *friendly_name =
NULL;
233 char *unique_name =
NULL;
235 IBindCtx *bind_ctx =
NULL;
237 LPMALLOC co_malloc =
NULL;
240 r = CoGetMalloc(1, &co_malloc);
243 r = CreateBindCtx(0, &bind_ctx);
247 r = IMoniker_GetDisplayName(
m, bind_ctx,
NULL, &olestr);
252 for (i = 0; i < strlen(unique_name); i++) {
253 if (unique_name[i] ==
':')
254 unique_name[i] =
'_';
257 r = IMoniker_BindToStorage(
m, 0, 0, &IID_IPropertyBag, (
void *) &bag);
262 r = IPropertyBag_Read(bag,
L"FriendlyName", &var,
NULL);
272 r = IMoniker_BindToObject(
m, 0, 0, &IID_IBaseFilter, (
void *) &
device_filter);
284 if (olestr && co_malloc)
285 IMalloc_Free(co_malloc, olestr);
287 IBindCtx_Release(bind_ctx);
291 IPropertyBag_Release(bag);
295 IEnumMoniker_Release(classenum);
299 av_log(avctx,
AV_LOG_ERROR,
"Could not find %s device with name [%s] among source devices of type %s.\n",
317 IPin *pin,
int *pformat_set)
326 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (
void **) &config) !=
S_OK)
328 if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) !=
S_OK)
335 for (i = 0; i < n && !format_set; i++) {
336 r = IAMStreamConfig_GetStreamCaps(config, i, &type, (
void *) caps);
344 VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
345 BITMAPINFOHEADER *bih;
351 if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
352 VIDEOINFOHEADER *
v = (
void *) type->pbFormat;
353 fr = &v->AvgTimePerFrame;
355 }
else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
356 VIDEOINFOHEADER2 *
v = (
void *) type->pbFormat;
357 fr = &v->AvgTimePerFrame;
368 av_log(avctx,
AV_LOG_INFO,
" unknown compression type 0x%X", (
int) bih->biCompression);
376 vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
377 1e7 / vcaps->MaxFrameInterval,
378 vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
379 1e7 / vcaps->MinFrameInterval);
393 if (framerate > vcaps->MaxFrameInterval ||
394 framerate < vcaps->MinFrameInterval)
408 AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
413 if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
414 fx = (
void *) type->pbFormat;
419 av_log(avctx,
AV_LOG_INFO,
" min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
420 acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
421 acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
425 if (ctx->
sample_rate > acaps->MaximumSampleFrequency ||
431 if (ctx->
sample_size > acaps->MaximumBitsPerSample ||
437 if (ctx->
channels > acaps->MaximumChannels ||
438 ctx->
channels < acaps->MinimumChannels)
443 if (IAMStreamConfig_SetFormat(config, type) !=
S_OK)
448 CoTaskMemFree(type->pbFormat);
452 IAMStreamConfig_Release(config);
455 *pformat_set = format_set;
466 IAMBufferNegotiation *buffer_negotiation =
NULL;
467 ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
472 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (
void **) &config) !=
S_OK)
474 if (IAMStreamConfig_GetFormat(config, &type) !=
S_OK)
476 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
479 props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
482 if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (
void **) &buffer_negotiation) !=
S_OK)
484 if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) !=
S_OK)
490 if (buffer_negotiation)
491 IAMBufferNegotiation_Release(buffer_negotiation);
494 CoTaskMemFree(type->pbFormat);
498 IAMStreamConfig_Release(config);
508 ISpecifyPropertyPages *property_pages =
NULL;
509 IUnknown *device_filter_iunknown =
NULL;
511 FILTER_INFO filter_info = {0};
512 CAUUID ca_guid = {0};
514 hr = IBaseFilter_QueryInterface(device_filter, &IID_ISpecifyPropertyPages, (
void **)&property_pages);
519 hr = IBaseFilter_QueryFilterInfo(device_filter, &filter_info);
523 hr = IBaseFilter_QueryInterface(device_filter, &IID_IUnknown, (
void **)&device_filter_iunknown);
527 hr = ISpecifyPropertyPages_GetPages(property_pages, &ca_guid);
531 hr = OleCreatePropertyFrame(
NULL, 0, 0, filter_info.achName, 1, &device_filter_iunknown, ca_guid.cElems,
532 ca_guid.pElems, 0, 0,
NULL);
541 ISpecifyPropertyPages_Release(property_pages);
542 if (device_filter_iunknown)
543 IUnknown_Release(device_filter_iunknown);
544 if (filter_info.pGraph)
545 IFilterGraph_Release(filter_info.pGraph);
547 CoTaskMemFree(ca_guid.pElems);
566 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
567 const char *devtypename = (devtype ==
VideoDevice) ?
"video" :
"audio only";
568 const char *sourcetypename = (sourcetype ==
VideoSourceDevice) ?
"video" :
"audio";
578 if (should_show_properties)
581 r = IBaseFilter_EnumPins(device_filter, &pins);
589 devtypename, sourcetypename);
592 while (!device_pin && IEnumPins_Next(pins, 1, &pin,
NULL) ==
S_OK) {
593 IKsPropertySet *p =
NULL;
594 IEnumMediaTypes *types =
NULL;
599 char *name_buf =
NULL;
600 wchar_t *pin_id =
NULL;
601 char *pin_buf =
NULL;
604 IPin_QueryPinInfo(pin, &info);
605 IBaseFilter_Release(info.pFilter);
607 if (info.dir != PINDIR_OUTPUT)
609 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (
void **) &p) !=
S_OK)
611 if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
614 if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
618 r = IPin_QueryId(pin, &pin_id);
626 av_log(avctx,
AV_LOG_INFO,
" Pin \"%s\" (alternative pin name \"%s\")\n", name_buf, pin_buf);
631 if (desired_pin_name) {
632 if(strcmp(name_buf, desired_pin_name) && strcmp(pin_buf, desired_pin_name)) {
634 name_buf, pin_buf, desired_pin_name);
651 if (IPin_EnumMediaTypes(pin, &types) !=
S_OK)
654 IEnumMediaTypes_Reset(types);
656 while (!device_pin && IEnumMediaTypes_Next(types, 1, &type,
NULL) ==
S_OK) {
657 if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
667 IEnumMediaTypes_Release(types);
669 IKsPropertySet_Release(p);
670 if (device_pin != pin)
675 CoTaskMemFree(pin_id);
678 IEnumPins_Release(pins);
681 if (set_format && !format_set) {
687 "Could not find output pin from %s capture device.\n", devtypename);
728 ICaptureGraphBuilder2 *graph_builder2 =
NULL;
732 const wchar_t *filter_name[2] = {
L"Audio capture filter",
L"Video capture filter" };
741 r = IGraphBuilder_AddFilter(graph, device_filter,
NULL);
747 if ((r =
dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, &device_pin)) < 0) {
755 if (!capture_filter) {
761 r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
762 filter_name[devtype]);
769 capture_pin = capture_filter->
pin;
772 r = CoCreateInstance(&CLSID_CaptureGraphBuilder2,
NULL, CLSCTX_INPROC_SERVER,
773 &IID_ICaptureGraphBuilder2, (
void **) &graph_builder2);
778 ICaptureGraphBuilder2_SetFiltergraph(graph_builder2, graph);
784 r = ICaptureGraphBuilder2_RenderStream(graph_builder2,
NULL,
NULL, (IUnknown *) device_pin,
NULL ,
785 (IBaseFilter *) capture_filter);
802 if (graph_builder2 !=
NULL)
803 ICaptureGraphBuilder2_Release(graph_builder2);
810 switch (sample_fmt) {
851 BITMAPINFOHEADER *bih =
NULL;
854 if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
855 VIDEOINFOHEADER *
v = (
void *) type.pbFormat;
856 time_base = (
AVRational) { v->AvgTimePerFrame, 10000000 };
858 }
else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
859 VIDEOINFOHEADER2 *
v = (
void *) type.pbFormat;
860 time_base = (
AVRational) { v->AvgTimePerFrame, 10000000 };
870 codec->
width = bih->biWidth;
871 codec->
height = bih->biHeight;
874 if (bih->biCompression ==
MKTAG(
'H',
'D',
'Y',
'C')) {
883 "Please report type 0x%X.\n", (
int) bih->biCompression);
889 if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
899 WAVEFORMATEX *fx =
NULL;
901 if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
902 fx = (
void *) type.pbFormat;
933 while ((type = strtok(tmp,
"="))) {
934 char *token = strtok(
NULL,
":");
937 if (!strcmp(type,
"video")) {
938 device_name[0] = token;
939 }
else if (!strcmp(type,
"audio")) {
940 device_name[1] = token;
942 device_name[0] =
NULL;
943 device_name[1] =
NULL;
948 if (!device_name[0] && !device_name[1]) {
952 device_name[0] =
av_strdup(device_name[0]);
954 device_name[1] =
av_strdup(device_name[1]);
965 ICreateDevEnum *devenum =
NULL;
968 HANDLE media_event_handle;
985 "video codec is not set or set to rawvideo\n");
998 r = CoCreateInstance(&CLSID_FilterGraph,
NULL, CLSCTX_INPROC_SERVER,
999 &IID_IGraphBuilder, (
void **) &graph);
1006 r = CoCreateInstance(&CLSID_SystemDeviceEnum,
NULL, CLSCTX_INPROC_SERVER,
1007 &IID_ICreateDevEnum, (
void **) &devenum);
1014 av_log(avctx,
AV_LOG_INFO,
"DirectShow video devices (some may be both video and audio devices)\n");
1069 if (!ctx->
event[1]) {
1074 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (
void **) &control);
1081 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaEvent, (
void **) &media_event);
1088 r = IMediaEvent_GetEventHandle(media_event, (
void *) &media_event_handle);
1093 proc = GetCurrentProcess();
1094 r = DuplicateHandle(proc, media_event_handle, proc, &ctx->
event[0],
1095 0, 0, DUPLICATE_SAME_ACCESS);
1101 r = IMediaControl_Run(control);
1104 r = IMediaControl_GetState(control, 0, &pfs);
1107 av_log(avctx,
AV_LOG_ERROR,
"Could not run graph (sometimes caused by a device already in use by other application)\n");
1116 ICreateDevEnum_Release(devenum);
1135 while (IMediaEvent_GetEvent(media_event, &code, &p1, &p2, 0) != E_ABORT) {
1136 if (code == EC_COMPLETE || code ==
EC_DEVICE_LOST || code == EC_ERRORABORT)
1138 IMediaEvent_FreeEventParams(media_event, code, p1, p2);
1149 while (!ctx->
eof && !pktl) {
1150 WaitForSingleObject(ctx->
mutex, INFINITE);
1158 ResetEvent(ctx->
event[1]);
1159 ReleaseMutex(ctx->
mutex);
1166 WaitForMultipleObjects(2, ctx->
event, 0, INFINITE);
1174 #define OFFSET(x) offsetof(struct dshow_ctx, x)
1175 #define DEC AV_OPT_FLAG_DECODING_PARAM
1203 {
"true",
"", 0,
AV_OPT_TYPE_CONST, {.i64=1}, 0, 0,
DEC,
"show_video_crossbar_connection_dialog" },
1204 {
"false",
"", 0,
AV_OPT_TYPE_CONST, {.i64=0}, 0, 0,
DEC,
"show_video_crossbar_connection_dialog" },
1206 {
"true",
"", 0,
AV_OPT_TYPE_CONST, {.i64=1}, 0, 0,
DEC,
"show_audio_crossbar_connection_dialog" },
1207 {
"false",
"", 0,
AV_OPT_TYPE_CONST, {.i64=0}, 0, 0,
DEC,
"show_audio_crossbar_connection_dialog" },
1212 {
"true",
"", 0,
AV_OPT_TYPE_CONST, {.i64=1}, 0, 0,
DEC,
"show_analog_tv_tuner_audio_dialog" },
1213 {
"false",
"", 0,
AV_OPT_TYPE_CONST, {.i64=0}, 0, 0,
DEC,
"show_analog_tv_tuner_audio_dialog" },
1228 .priv_data_size =
sizeof(
struct dshow_ctx),