static int dshow_read_close(AVFormatContext *s) { struct dshow_ctx *ctx = s->priv_data; AVPacketList *pktl; if (ctx->control) { IMediaControl_Stop(ctx->control); IMediaControl_Release(ctx->control); } if (ctx->media_event) IMediaEvent_Release(ctx->media_event); if (ctx->graph) { IEnumFilters *fenum; int r; r = IGraphBuilder_EnumFilters(ctx->graph, &fenum); if (r == S_OK) { IBaseFilter *f; IEnumFilters_Reset(fenum); while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK) { if (IGraphBuilder_RemoveFilter(ctx->graph, f) == S_OK) IEnumFilters_Reset(fenum); /* When a filter is removed, * the list must be reset. */ IBaseFilter_Release(f); } IEnumFilters_Release(fenum); } IGraphBuilder_Release(ctx->graph); } if (ctx->capture_pin[VideoDevice]) libAVPin_Release(ctx->capture_pin[VideoDevice]); if (ctx->capture_pin[AudioDevice]) libAVPin_Release(ctx->capture_pin[AudioDevice]); if (ctx->capture_filter[VideoDevice]) libAVFilter_Release(ctx->capture_filter[VideoDevice]); if (ctx->capture_filter[AudioDevice]) libAVFilter_Release(ctx->capture_filter[AudioDevice]); if (ctx->device_pin[VideoDevice]) IPin_Release(ctx->device_pin[VideoDevice]); if (ctx->device_pin[AudioDevice]) IPin_Release(ctx->device_pin[AudioDevice]); if (ctx->device_filter[VideoDevice]) IBaseFilter_Release(ctx->device_filter[VideoDevice]); if (ctx->device_filter[AudioDevice]) IBaseFilter_Release(ctx->device_filter[AudioDevice]); if (ctx->device_name[0]) av_freep(&ctx->device_name[0]); if (ctx->device_name[1]) av_freep(&ctx->device_name[1]); if(ctx->mutex) CloseHandle(ctx->mutex); if(ctx->event[0]) CloseHandle(ctx->event[0]); if(ctx->event[1]) CloseHandle(ctx->event[1]); pktl = ctx->pktl; while (pktl) { AVPacketList *next = pktl->next; av_free_packet(&pktl->pkt); av_free(pktl); pktl = next; } CoUninitialize(); return 0; }
static HRESULT GetSplitter(MediaDetImpl *This) { IFileSourceFilter *file; LPOLESTR name; AM_MEDIA_TYPE mt; GUID type[2]; IFilterMapper2 *map; IEnumMoniker *filters; IMoniker *mon; VARIANT var; GUID clsid; IBaseFilter *splitter; IEnumPins *pins; IPin *source_pin, *splitter_pin; HRESULT hr; hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (void **) &map); if (FAILED(hr)) return hr; hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter, (void **) &file); if (FAILED(hr)) { IFilterMapper2_Release(map); return hr; } hr = IFileSourceFilter_GetCurFile(file, &name, &mt); IFileSourceFilter_Release(file); CoTaskMemFree(name); if (FAILED(hr)) { IFilterMapper2_Release(map); return hr; } type[0] = mt.majortype; type[1] = mt.subtype; CoTaskMemFree(mt.pbFormat); hr = IFilterMapper2_EnumMatchingFilters(map, &filters, 0, TRUE, MERIT_UNLIKELY, FALSE, 1, type, NULL, NULL, FALSE, TRUE, 0, NULL, NULL, NULL); IFilterMapper2_Release(map); if (FAILED(hr)) return hr; hr = E_NOINTERFACE; while (IEnumMoniker_Next(filters, 1, &mon, NULL) == S_OK) { hr = GetFilterInfo(mon, &clsid, &var); IMoniker_Release(mon); if (FAILED(hr)) continue; hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (void **) &splitter); if (FAILED(hr)) { VariantClear(&var); goto retry; } hr = IGraphBuilder_AddFilter(This->graph, splitter, V_UNION(&var, bstrVal)); VariantClear(&var); This->splitter = splitter; if (FAILED(hr)) goto retry; hr = IBaseFilter_EnumPins(This->source, &pins); if (FAILED(hr)) goto retry; IEnumPins_Next(pins, 1, &source_pin, NULL); IEnumPins_Release(pins); hr = IBaseFilter_EnumPins(splitter, &pins); if (FAILED(hr)) { IPin_Release(source_pin); goto retry; } IEnumPins_Next(pins, 1, &splitter_pin, NULL); IEnumPins_Release(pins); hr = IPin_Connect(source_pin, splitter_pin, NULL); IPin_Release(source_pin); IPin_Release(splitter_pin); if (SUCCEEDED(hr)) break; retry: IBaseFilter_Release(splitter); This->splitter = NULL; } IEnumMoniker_Release(filters); if (FAILED(hr)) return hr; return S_OK; }
static void test_media_streams(void) { HRESULT hr; IMediaStream *video_stream = NULL; IMediaStream *audio_stream = NULL; IMediaStream *dummy_stream; IMediaStreamFilter* media_stream_filter = NULL; if (!create_ammultimediastream()) return; if (!create_directdraw()) { release_ammultimediastream(); return; } hr = IAMMultiMediaStream_Initialize(pams, STREAMTYPE_READ, 0, NULL); ok(hr == S_OK, "IAMMultiMediaStream_Initialize returned: %x\n", hr); /* Retrieve media stream filter */ hr = IAMMultiMediaStream_GetFilter(pams, NULL); ok(hr == E_POINTER, "IAMMultiMediaStream_GetFilter returned: %x\n", hr); hr = IAMMultiMediaStream_GetFilter(pams, &media_stream_filter); ok(hr == S_OK, "IAMMultiMediaStream_GetFilter returned: %x\n", hr); /* Verify behaviour with invalid purpose id */ hr = IAMMultiMediaStream_GetMediaStream(pams, &IID_IUnknown, &dummy_stream); ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &IID_IUnknown, 0, NULL); ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr); /* Verify there is no video media stream */ hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream); ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); /* Verify there is no default renderer for video stream */ hr = IAMMultiMediaStream_AddMediaStream(pams, (IUnknown*)pdd7, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL); ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr); hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream); ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL); ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr); hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream); ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); /* Verify normal case for video stream */ hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, 0, NULL); ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr); hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream); ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); /* Verify the video stream has been added to the media stream filter */ if (media_stream_filter) { hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryVideo, &dummy_stream); ok(hr == S_OK, "IMediaStreamFilter_GetMediaStream returned: %x\n", hr); ok(dummy_stream == video_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, video_stream); if (SUCCEEDED(hr)) IMediaStream_Release(dummy_stream); } /* Check interfaces and samples for video */ if (video_stream) { IAMMediaStream* am_media_stream; IAudioMediaStream* audio_media_stream; IDirectDrawMediaStream *ddraw_stream = NULL; IDirectDrawStreamSample *ddraw_sample = NULL; hr = IMediaStream_QueryInterface(video_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream); ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr); ok((void*)am_media_stream == (void*)video_stream, "Not same interface, got %p expected %p\n", am_media_stream, video_stream); if (hr == S_OK) IAMMediaStream_Release(am_media_stream); hr = IMediaStream_QueryInterface(video_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream); ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %x\n", hr); hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream); ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr); if (SUCCEEDED(hr)) { DDSURFACEDESC current_format, desired_format; IDirectDrawPalette *palette; DWORD flags; hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, &palette, &desired_format, &flags); ok(hr == MS_E_NOSTREAM, "IDirectDrawoMediaStream_GetFormat returned: %x\n", hr); hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample); ok(hr == S_OK, "IDirectDrawMediaStream_CreateSample returned: %x\n", hr); } if (ddraw_sample) IDirectDrawStreamSample_Release(ddraw_sample); if (ddraw_stream) IDirectDrawMediaStream_Release(ddraw_stream); } /* Verify there is no audio media stream */ hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream); ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); /* Verify no stream is created when using the default renderer for audio stream */ hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL); ok((hr == S_OK) || (hr == VFW_E_NO_AUDIO_HARDWARE), "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr); if (hr == S_OK) { IGraphBuilder* filtergraph = NULL; IBaseFilter* filter = NULL; const WCHAR name[] = {'0','0','0','1',0}; CLSID clsid; hr = IAMMultiMediaStream_GetFilterGraph(pams, &filtergraph); ok(hr == S_OK, "IAMMultiMediaStream_GetFilterGraph returned: %x\n", hr); if (hr == S_OK) { hr = IGraphBuilder_FindFilterByName(filtergraph, name, &filter); ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr); } if (hr == S_OK) { hr = IBaseFilter_GetClassID(filter, &clsid); ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr); } if (hr == S_OK) ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got wrong CLSID\n"); if (filter) IBaseFilter_Release(filter); if (filtergraph) IGraphBuilder_Release(filtergraph); } hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream); ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); /* Verify a stream is created when no default renderer is used */ hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, 0, NULL); ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr); hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream); ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); /* verify the audio stream has been added to the media stream filter */ if (media_stream_filter) { hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryAudio, &dummy_stream); ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr); ok(dummy_stream == audio_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, audio_stream); if (SUCCEEDED(hr)) IMediaStream_Release(dummy_stream); } /* Check interfaces and samples for audio */ if (audio_stream) { IAMMediaStream* am_media_stream; IDirectDrawMediaStream* ddraw_stream = NULL; IAudioMediaStream* audio_media_stream = NULL; IAudioStreamSample *audio_sample = NULL; hr = IMediaStream_QueryInterface(audio_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream); ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr); ok((void*)am_media_stream == (void*)audio_stream, "Not same interface, got %p expected %p\n", am_media_stream, audio_stream); if (hr == S_OK) IAMMediaStream_Release(am_media_stream); hr = IMediaStream_QueryInterface(audio_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream); ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %x\n", hr); hr = IMediaStream_QueryInterface(audio_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream); ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr); if (SUCCEEDED(hr)) { IAudioData* audio_data = NULL; WAVEFORMATEX format; hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data); ok(hr == S_OK, "CoCreateInstance returned: %x\n", hr); hr = IAudioMediaStream_GetFormat(audio_media_stream, NULL); ok(hr == E_POINTER, "IAudioMediaStream_GetFormat returned: %x\n", hr); hr = IAudioMediaStream_GetFormat(audio_media_stream, &format); ok(hr == MS_E_NOSTREAM, "IAudioMediaStream_GetFormat returned: %x\n", hr); hr = IAudioMediaStream_CreateSample(audio_media_stream, NULL, 0, &audio_sample); ok(hr == E_POINTER, "IAudioMediaStream_CreateSample returned: %x\n", hr); hr = IAudioMediaStream_CreateSample(audio_media_stream, audio_data, 0, &audio_sample); ok(hr == S_OK, "IAudioMediaStream_CreateSample returned: %x\n", hr); if (audio_data) IAudioData_Release(audio_data); if (audio_sample) IAudioStreamSample_Release(audio_sample); if (audio_media_stream) IAudioMediaStream_Release(audio_media_stream); } } if (media_stream_filter) { IEnumPins *enum_pins; hr = IMediaStreamFilter_EnumPins(media_stream_filter, &enum_pins); ok(hr == S_OK, "IBaseFilter_EnumPins returned: %x\n", hr); if (hr == S_OK) { IPin* pins[3] = { NULL, NULL, NULL }; ULONG nb_pins; ULONG expected_nb_pins = audio_stream ? 2 : 1; int i; hr = IEnumPins_Next(enum_pins, 3, pins, &nb_pins); ok(SUCCEEDED(hr), "IEnumPins_Next returned: %x\n", hr); ok(nb_pins == expected_nb_pins, "Number of pins is %u instead of %u\n", nb_pins, expected_nb_pins); for (i = 0; i < min(nb_pins, expected_nb_pins); i++) { IEnumMediaTypes* enum_media_types; AM_MEDIA_TYPE* media_types[10]; ULONG nb_media_types; IPin* pin; PIN_INFO info; WCHAR id[40]; /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */ id[0] = 'I'; StringFromGUID2(i ? &MSPID_PrimaryAudio : &MSPID_PrimaryVideo, id + 1, 40); hr = IPin_ConnectedTo(pins[i], &pin); ok(hr == VFW_E_NOT_CONNECTED, "IPin_ConnectedTo returned: %x\n", hr); hr = IPin_QueryPinInfo(pins[i], &info); ok(hr == S_OK, "IPin_QueryPinInfo returned: %x\n", hr); IBaseFilter_Release(info.pFilter); ok(info.dir == PINDIR_INPUT, "Pin direction is %u instead of %u\n", info.dir, PINDIR_INPUT); ok(!lstrcmpW(info.achName, id), "Pin name is %s instead of %s\n", wine_dbgstr_w(info.achName), wine_dbgstr_w(id)); hr = IPin_EnumMediaTypes(pins[i], &enum_media_types); ok(hr == S_OK, "IPin_EnumMediaTypes returned: %x\n", hr); hr = IEnumMediaTypes_Next(enum_media_types, sizeof(media_types) / sizeof(AM_MEDIA_TYPE), media_types, &nb_media_types); ok(SUCCEEDED(hr), "IEnumMediaTypes_Next returned: %x\n", hr); ok(nb_media_types == 0, "nb_media_types should be 0 instead of %u\n", nb_media_types); IEnumMediaTypes_Release(enum_media_types); IPin_Release(pins[i]); } IEnumPins_Release(enum_pins); } } /* Test open file with no filename */ hr = IAMMultiMediaStream_OpenFile(pams, NULL, 0); ok(hr == E_POINTER, "IAMMultiMediaStream_OpenFile returned %x instead of %x\n", hr, E_POINTER); if (video_stream) IMediaStream_Release(video_stream); if (audio_stream) IMediaStream_Release(audio_stream); if (media_stream_filter) IMediaStreamFilter_Release(media_stream_filter); release_directdraw(); release_ammultimediastream(); }
static HRESULT FGEVENT_KeepEvent( CFilterGraph* This, BOOL bKeep, long lEventCode, LONG_PTR lParam1, LONG_PTR lParam2 ) { switch ( lEventCode ) { case EC_COMPLETE: if ( ++This->m_cCompletes < This->m_cRenders ) return E_FAIL; /* don't tell app */ break; case EC_USERABORT: break; case EC_ERRORABORT: break; case EC_TIME: break; /*case EC_REPAINT:*/ case EC_STREAM_ERROR_STOPPED: break; case EC_STREAM_ERROR_STILLPLAYING: break; case EC_ERROR_STILLPLAYING: break; case EC_PALETTE_CHANGED: break; case EC_VIDEO_SIZE_CHANGED: break; case EC_QUALITY_CHANGE: break; /*case EC_SHUTTING_DOWN:*/ case EC_CLOCK_CHANGED: break; case EC_OPENING_FILE: break; case EC_BUFFERING_DATA: break; case EC_FULLSCREEN_LOST: if ( bKeep ) { if ( ((IBaseFilter*)lParam2) != NULL ) IBaseFilter_AddRef( (IBaseFilter*)lParam2 ); } else { if ( ((IBaseFilter*)lParam2) != NULL ) IBaseFilter_Release( (IBaseFilter*)lParam2 ); } break; /*case EC_ACTIVATE:*/ /*case EC_NEED_RESTART:*/ /*case EC_WINDOW_DESTROYED:*/ /*case EC_DISPLAY_CHANGED:*/ /*case EC_STARVATION:*/ /*case EC_OLE_EVENT:*/ /*case EC_NOTIFY_WINDOW:*/ /*case EC_STREAM_CONTROL_STOPPED:*/ /*case EC_STREAM_CONTROL_STARTED:*/ /*case EC_END_OF_SEGMENT:*/ /*case EC_SEGMENT_STARTED:*/ case EC_LENGTH_CHANGED: break; default: if ( lEventCode < EC_USER ) { FIXME( "unknown system event %08lx\n", lEventCode ); return E_INVALIDARG; } TRACE( "user event %08lx\n", lEventCode ); break; } return NOERROR; }
/** * Cycle through available pins using the device_filter device, of type * devtype, retrieve the first output pin and return the pointer to the * object found in *ppin. * If ppin is NULL, cycle through all pins listing audio/video capabilities. */ static int dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, IBaseFilter *device_filter, IPin **ppin) { struct dshow_ctx *ctx = avctx->priv_data; IEnumPins *pins = 0; IPin *device_pin = NULL; IPin *pin; int r; const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio }; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; int set_format = (devtype == VideoDevice && (ctx->framerate || (ctx->requested_width && ctx->requested_height) || ctx->pixel_format != AV_PIX_FMT_NONE || ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate)); int format_set = 0; r = IBaseFilter_EnumPins(device_filter, &pins); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n"); return AVERROR(EIO); } if (!ppin) { av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n", devtypename); } while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { IKsPropertySet *p = NULL; IEnumMediaTypes *types = NULL; PIN_INFO info = {0}; AM_MEDIA_TYPE *type; GUID category; DWORD r2; IPin_QueryPinInfo(pin, &info); IBaseFilter_Release(info.pFilter); if (info.dir != PINDIR_OUTPUT) goto next; if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK) goto next; if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, &category, sizeof(GUID), &r2) != S_OK) goto next; if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE)) goto next; if (!ppin) { char *buf = dup_wchar_to_utf8(info.achName); av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf); av_free(buf); dshow_cycle_formats(avctx, devtype, pin, NULL); goto next; } if (set_format) { dshow_cycle_formats(avctx, devtype, pin, &format_set); if (!format_set) { goto next; } } if (devtype == AudioDevice && ctx->audio_buffer_size) { if (dshow_set_audio_buffer_size(avctx, pin) < 0) goto next; } if (IPin_EnumMediaTypes(pin, &types) != S_OK) goto next; IEnumMediaTypes_Reset(types); while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { if (IsEqualGUID(&type->majortype, mediatype[devtype])) { device_pin = pin; goto next; } CoTaskMemFree(type); } next: if (types) IEnumMediaTypes_Release(types); if (p) IKsPropertySet_Release(p); if (device_pin != pin) IPin_Release(pin); } IEnumPins_Release(pins); if (ppin) { if (set_format && !format_set) { av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename); return AVERROR(EIO); } if (!device_pin) { av_log(avctx, AV_LOG_ERROR, "Could not find output pin from %s capture device.\n", devtypename); return AVERROR(EIO); } *ppin = device_pin; } return 0; }