36 switch(biCompression) {
64 IMediaControl_Stop(
ctx->control);
65 IMediaControl_Release(
ctx->control);
69 IMediaEvent_Release(
ctx->media_event);
74 r = IGraphBuilder_EnumFilters(
ctx->graph, &fenum);
77 IEnumFilters_Reset(fenum);
78 while (IEnumFilters_Next(fenum, 1, &
f,
NULL) ==
S_OK) {
79 if (IGraphBuilder_RemoveFilter(
ctx->graph,
f) ==
S_OK)
80 IEnumFilters_Reset(fenum);
82 IBaseFilter_Release(
f);
84 IEnumFilters_Release(fenum);
86 IGraphBuilder_Release(
ctx->graph);
113 CloseHandle(
ctx->mutex);
115 CloseHandle(
ctx->event[0]);
117 CloseHandle(
ctx->event[1]);
135 int l = WideCharToMultiByte(CP_UTF8, 0,
w, -1, 0, 0, 0, 0);
138 WideCharToMultiByte(CP_UTF8, 0,
w, -1,
s, l, 0, 0);
145 static const uint8_t dropscore[] = {62, 75, 87, 100};
147 unsigned int buffer_fullness = (
ctx->curbufsize[
index]*100)/
s->max_picture_buffer;
148 const char *devtypename = (devtype ==
VideoDevice) ?
"video" :
"audio";
150 if(dropscore[++
ctx->video_frame_num%ndropscores] <= buffer_fullness) {
152 "real-time buffer [%s] [%s input] too full or near too full (%d%% of size: %d [rtbufsize parameter])! frame dropped!\n",
153 ctx->device_name[devtype], devtypename, buffer_fullness,
s->max_picture_buffer);
184 pktl_next->
pkt.
pts = time;
187 for(ppktl = &
ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->
next);
191 SetEvent(
ctx->event[1]);
192 ReleaseMutex(
ctx->mutex);
196 ReleaseMutex(
ctx->mutex);
213 IEnumMoniker *classenum =
NULL;
217 :
ctx->audio_device_number;
220 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
221 &CLSID_AudioInputDeviceCategory };
222 const char *devtypename = (devtype ==
VideoDevice) ?
"video" :
"audio only";
223 const char *sourcetypename = (sourcetype ==
VideoSourceDevice) ?
"video" :
"audio";
225 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[sourcetype],
226 (IEnumMoniker **) &classenum, 0);
234 IPropertyBag *bag =
NULL;
236 char *unique_name =
NULL;
238 IBindCtx *bind_ctx =
NULL;
240 LPMALLOC co_malloc =
NULL;
243 r = CoGetMalloc(1, &co_malloc);
246 r = CreateBindCtx(0, &bind_ctx);
250 r = IMoniker_GetDisplayName(m, bind_ctx,
NULL, &olestr);
255 for (
i = 0;
i < strlen(unique_name);
i++) {
256 if (unique_name[
i] ==
':')
257 unique_name[
i] =
'_';
260 r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (
void *) &bag);
265 r = IPropertyBag_Read(bag,
L"FriendlyName", &var,
NULL);
275 r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (
void *) &
device_filter);
290 if (olestr && co_malloc)
291 IMalloc_Free(co_malloc, olestr);
293 IBindCtx_Release(bind_ctx);
297 IPropertyBag_Release(bag);
301 IEnumMoniker_Release(classenum);
305 av_log(avctx,
AV_LOG_ERROR,
"Could not find %s device with name [%s] among source devices of type %s.\n",
323 IPin *pin,
int *pformat_set)
326 IAMStreamConfig *config =
NULL;
332 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (
void **) &config) !=
S_OK)
334 if (IAMStreamConfig_GetNumberOfCapabilities(config, &
n, &
size) !=
S_OK)
341 for (
i = 0;
i <
n && !format_set;
i++) {
342 r = IAMStreamConfig_GetStreamCaps(config,
i, &
type, (
void *) caps);
350 VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
351 BITMAPINFOHEADER *bih;
357 if (IsEqualGUID(&
type->formattype, &FORMAT_VideoInfo)) {
358 VIDEOINFOHEADER *v = (
void *)
type->pbFormat;
359 fr = &v->AvgTimePerFrame;
361 }
else if (IsEqualGUID(&
type->formattype, &FORMAT_VideoInfo2)) {
362 VIDEOINFOHEADER2 *v = (
void *)
type->pbFormat;
363 fr = &v->AvgTimePerFrame;
374 av_log(avctx,
AV_LOG_INFO,
" unknown compression type 0x%X", (
int) bih->biCompression);
382 vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
383 1e7 / vcaps->MaxFrameInterval,
384 vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
385 1e7 / vcaps->MinFrameInterval);
393 ctx->pixel_format !=
dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
396 if (
ctx->framerate) {
397 int64_t
framerate = ((int64_t)
ctx->requested_framerate.den*10000000)
398 /
ctx->requested_framerate.num;
399 if (
framerate > vcaps->MaxFrameInterval ||
400 framerate < vcaps->MinFrameInterval)
404 if (
ctx->requested_width &&
ctx->requested_height) {
405 if (
ctx->requested_width > vcaps->MaxOutputSize.cx ||
406 ctx->requested_width < vcaps->MinOutputSize.cx ||
407 ctx->requested_height > vcaps->MaxOutputSize.cy ||
408 ctx->requested_height < vcaps->MinOutputSize.cy)
410 bih->biWidth =
ctx->requested_width;
411 bih->biHeight =
ctx->requested_height;
414 AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
419 if (IsEqualGUID(&
type->formattype, &FORMAT_WaveFormatEx)) {
420 fx = (
void *)
type->pbFormat;
425 av_log(avctx,
AV_LOG_INFO,
" min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
426 acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
427 acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
430 if (
ctx->sample_rate) {
431 if (
ctx->sample_rate > acaps->MaximumSampleFrequency ||
432 ctx->sample_rate < acaps->MinimumSampleFrequency)
434 fx->nSamplesPerSec =
ctx->sample_rate;
436 if (
ctx->sample_size) {
437 if (
ctx->sample_size > acaps->MaximumBitsPerSample ||
438 ctx->sample_size < acaps->MinimumBitsPerSample)
440 fx->wBitsPerSample =
ctx->sample_size;
443 if (
ctx->channels > acaps->MaximumChannels ||
444 ctx->channels < acaps->MinimumChannels)
446 fx->nChannels =
ctx->channels;
449 if (IAMStreamConfig_SetFormat(config,
type) !=
S_OK)
454 CoTaskMemFree(
type->pbFormat);
458 IAMStreamConfig_Release(config);
461 *pformat_set = format_set;
472 IAMBufferNegotiation *buffer_negotiation =
NULL;
473 ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
474 IAMStreamConfig *config =
NULL;
478 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (
void **) &config) !=
S_OK)
480 if (IAMStreamConfig_GetFormat(config, &
type) !=
S_OK)
482 if (!IsEqualGUID(&
type->formattype, &FORMAT_WaveFormatEx))
485 props.cbBuffer = (((WAVEFORMATEX *)
type->pbFormat)->nAvgBytesPerSec)
486 *
ctx->audio_buffer_size / 1000;
488 if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (
void **) &buffer_negotiation) !=
S_OK)
490 if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) !=
S_OK)
496 if (buffer_negotiation)
497 IAMBufferNegotiation_Release(buffer_negotiation);
500 CoTaskMemFree(
type->pbFormat);
504 IAMStreamConfig_Release(config);
514 ISpecifyPropertyPages *property_pages =
NULL;
515 IUnknown *device_filter_iunknown =
NULL;
517 FILTER_INFO filter_info = {0};
518 CAUUID ca_guid = {0};
520 hr = IBaseFilter_QueryInterface(
device_filter, &IID_ISpecifyPropertyPages, (
void **)&property_pages);
525 hr = IBaseFilter_QueryFilterInfo(
device_filter, &filter_info);
529 hr = IBaseFilter_QueryInterface(
device_filter, &IID_IUnknown, (
void **)&device_filter_iunknown);
533 hr = ISpecifyPropertyPages_GetPages(property_pages, &ca_guid);
537 hr = OleCreatePropertyFrame(
NULL, 0, 0, filter_info.achName, 1, &device_filter_iunknown, ca_guid.cElems,
538 ca_guid.pElems, 0, 0,
NULL);
547 ISpecifyPropertyPages_Release(property_pages);
548 if (device_filter_iunknown)
549 IUnknown_Release(device_filter_iunknown);
550 if (filter_info.pGraph)
551 IFilterGraph_Release(filter_info.pGraph);
553 CoTaskMemFree(ca_guid.pElems);
572 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
573 const char *devtypename = (devtype ==
VideoDevice) ?
"video" :
"audio only";
574 const char *sourcetypename = (sourcetype ==
VideoSourceDevice) ?
"video" :
"audio";
577 (
ctx->requested_width &&
ctx->requested_height) ||
582 int should_show_properties = (devtype ==
VideoDevice) ?
ctx->show_video_device_dialog :
ctx->show_audio_device_dialog;
584 if (should_show_properties)
595 devtypename, sourcetypename);
599 IKsPropertySet *p =
NULL;
600 IEnumMediaTypes *types =
NULL;
605 char *name_buf =
NULL;
606 wchar_t *pin_id =
NULL;
607 char *pin_buf =
NULL;
608 char *desired_pin_name = devtype ==
VideoDevice ?
ctx->video_pin_name :
ctx->audio_pin_name;
610 IPin_QueryPinInfo(pin, &
info);
611 IBaseFilter_Release(
info.pFilter);
613 if (
info.dir != PINDIR_OUTPUT)
615 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (
void **) &p) !=
S_OK)
617 if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
620 if (!IsEqualGUID(&
category, &PIN_CATEGORY_CAPTURE))
624 r = IPin_QueryId(pin, &pin_id);
632 av_log(avctx,
AV_LOG_INFO,
" Pin \"%s\" (alternative pin name \"%s\")\n", name_buf, pin_buf);
637 if (desired_pin_name) {
638 if(strcmp(name_buf, desired_pin_name) && strcmp(pin_buf, desired_pin_name)) {
640 name_buf, pin_buf, desired_pin_name);
653 av_log(avctx,
AV_LOG_ERROR,
"unable to set audio buffer size %d to pin, using pin anyway...",
ctx->audio_buffer_size);
657 if (IPin_EnumMediaTypes(pin, &types) !=
S_OK)
660 IEnumMediaTypes_Reset(types);
663 if (IsEqualGUID(&
type->majortype, mediatype[devtype])) {
673 IEnumMediaTypes_Release(types);
675 IKsPropertySet_Release(p);
681 CoTaskMemFree(pin_id);
684 IEnumPins_Release(pins);
693 "Could not find output pin from %s capture device.\n", devtypename);
731 char *device_filter_unique_name =
NULL;
736 ICaptureGraphBuilder2 *graph_builder2 =
NULL;
739 IStream *ifile_stream =
NULL;
740 IStream *ofile_stream =
NULL;
741 IPersistStream *pers_stream =
NULL;
744 const wchar_t *filter_name[2] = {
L"Audio capture filter",
L"Video capture filter" };
747 if ( ((
ctx->audio_filter_load_file) && (strlen(
ctx->audio_filter_load_file)>0) && (sourcetype ==
AudioSourceDevice)) ||
748 ((
ctx->video_filter_load_file) && (strlen(
ctx->video_filter_load_file)>0) && (sourcetype ==
VideoSourceDevice)) ) {
750 char *filename =
NULL;
753 filename =
ctx->audio_filter_load_file;
755 filename =
ctx->video_filter_load_file;
757 hr = SHCreateStreamOnFile ((
LPCSTR) filename, STGM_READ, &ifile_stream);
763 hr = OleLoadFromStream(ifile_stream, &IID_IBaseFilter, (
void **) &
device_filter);
773 av_log(avctx,
AV_LOG_INFO,
"Capture filter loaded successfully from file \"%s\".\n", filename);
781 if (
ctx->device_filter[otherDevType]) {
784 if (strcmp(device_filter_unique_name,
ctx->device_unique_name[otherDevType]) == 0) {
785 av_log(avctx,
AV_LOG_DEBUG,
"reusing previous graph capture filter... %s\n", device_filter_unique_name);
788 IBaseFilter_AddRef(
ctx->device_filter[otherDevType]);
790 av_log(avctx,
AV_LOG_DEBUG,
"not reusing previous graph capture filter %s != %s\n", device_filter_unique_name,
ctx->device_unique_name[otherDevType]);
795 ctx->device_unique_name [devtype] = device_filter_unique_name;
817 if ( ((
ctx->audio_filter_save_file) && (strlen(
ctx->audio_filter_save_file)>0) && (sourcetype ==
AudioSourceDevice)) ||
818 ((
ctx->video_filter_save_file) && (strlen(
ctx->video_filter_save_file)>0) && (sourcetype ==
VideoSourceDevice)) ) {
821 char *filename =
NULL;
824 filename =
ctx->audio_filter_save_file;
826 filename =
ctx->video_filter_save_file;
828 hr = SHCreateStreamOnFile ((
LPCSTR) filename, STGM_CREATE | STGM_READWRITE, &ofile_stream);
834 hr = IBaseFilter_QueryInterface(
device_filter, &IID_IPersistStream, (
void **) &pers_stream);
840 hr = OleSaveToStream(pers_stream, ofile_stream);
846 hr = IStream_Commit(ofile_stream, STGC_DEFAULT);
856 av_log(avctx,
AV_LOG_INFO,
"Capture filter saved successfully to file \"%s\".\n", filename);
860 filter_name[devtype]);
870 r = CoCreateInstance(&CLSID_CaptureGraphBuilder2,
NULL, CLSCTX_INPROC_SERVER,
871 &IID_ICaptureGraphBuilder2, (
void **) &graph_builder2);
876 ICaptureGraphBuilder2_SetFiltergraph(graph_builder2,
graph);
900 if (graph_builder2 !=
NULL)
901 ICaptureGraphBuilder2_Release(graph_builder2);
904 IPersistStream_Release(pers_stream);
907 IStream_Release(ifile_stream);
910 IStream_Release(ofile_stream);
917 switch (sample_fmt) {
954 ctx->capture_filter[devtype]->stream_index = st->
index;
960 BITMAPINFOHEADER *bih =
NULL;
963 if (IsEqualGUID(&
type.formattype, &FORMAT_VideoInfo)) {
964 VIDEOINFOHEADER *v = (
void *)
type.pbFormat;
965 time_base = (
AVRational) { v->AvgTimePerFrame, 10000000 };
967 }
else if (IsEqualGUID(&
type.formattype, &FORMAT_VideoInfo2)) {
968 VIDEOINFOHEADER2 *v = (
void *)
type.pbFormat;
969 time_base = (
AVRational) { v->AvgTimePerFrame, 10000000 };
981 par->
width = bih->biWidth;
982 par->
height = bih->biHeight;
985 if (bih->biCompression ==
MKTAG(
'H',
'D',
'Y',
'C')) {
994 "Please report type 0x%X.\n", (
int) bih->biCompression);
1001 if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
1015 WAVEFORMATEX *fx =
NULL;
1017 if (IsEqualGUID(&
type.formattype, &FORMAT_WaveFormatEx)) {
1018 fx = (
void *)
type.pbFormat;
1038 CoTaskMemFree(
type.pbFormat);
1051 while ((
type = strtok(
tmp,
"="))) {
1052 char *token = strtok(
NULL,
":");
1055 if (!strcmp(
type,
"video")) {
1057 }
else if (!strcmp(
type,
"audio")) {
1083 ICreateDevEnum *devenum =
NULL;
1086 HANDLE media_event_handle;
1103 "video codec is not set or set to rawvideo\n");
1108 if (
ctx->framerate) {
1116 r = CoCreateInstance(&CLSID_FilterGraph,
NULL, CLSCTX_INPROC_SERVER,
1117 &IID_IGraphBuilder, (
void **) &
graph);
1124 r = CoCreateInstance(&CLSID_SystemDeviceEnum,
NULL, CLSCTX_INPROC_SERVER,
1125 &IID_ICreateDevEnum, (
void **) &devenum);
1131 if (
ctx->list_devices) {
1132 av_log(avctx,
AV_LOG_INFO,
"DirectShow video devices (some may be both video and audio devices)\n");
1139 if (
ctx->list_options) {
1174 if (
ctx->list_options) {
1179 ctx->curbufsize[0] = 0;
1180 ctx->curbufsize[1] = 0;
1187 if (!
ctx->event[1]) {
1192 r = IGraphBuilder_QueryInterface(
graph, &IID_IMediaControl, (
void **) &
control);
1199 r = IGraphBuilder_QueryInterface(
graph, &IID_IMediaEvent, (
void **) &
media_event);
1206 r = IMediaEvent_GetEventHandle(
media_event, (
void *) &media_event_handle);
1211 proc = GetCurrentProcess();
1212 r = DuplicateHandle(proc, media_event_handle, proc, &
ctx->event[0],
1213 0, 0, DUPLICATE_SAME_ACCESS);
1222 r = IMediaControl_GetState(
control, 0, &pfs);
1225 av_log(avctx,
AV_LOG_ERROR,
"Could not run graph (sometimes caused by a device already in use by other application)\n");
1234 ICreateDevEnum_Release(devenum);
1253 while (IMediaEvent_GetEvent(
media_event, &
code, &p1, &p2, 0) != E_ABORT) {
1272 ctx->pktl =
ctx->pktl->next;
1276 ResetEvent(
ctx->event[1]);
1277 ReleaseMutex(
ctx->mutex);
1284 WaitForMultipleObjects(2,
ctx->event, 0, INFINITE);
1292 #define OFFSET(x) offsetof(struct dshow_ctx, x)
1293 #define DEC AV_OPT_FLAG_DECODING_PARAM
1334 .priv_data_size =
sizeof(
struct dshow_ctx),