diff --git a/EVR Presenter/EVRPresenter.vcxproj b/EVR Presenter/EVRPresenter.vcxproj
index 383dafa..9563059 100644
--- a/EVR Presenter/EVRPresenter.vcxproj
+++ b/EVR Presenter/EVRPresenter.vcxproj
@@ -106,6 +106,7 @@
MachineX86
+ true
diff --git a/EVR Presenter/Helpers.h b/EVR Presenter/Helpers.h
index 11ac896..9c62bcb 100644
--- a/EVR Presenter/Helpers.h
+++ b/EVR Presenter/Helpers.h
@@ -133,6 +133,7 @@ class ThreadSafeQueue
ComPtrList m_list;
};
+//#define FILE_LOGGING
#if defined FILE_LOGGING
@@ -176,6 +177,7 @@ static void LogGUID(const char *msg, REFGUID guid )
#else
+
#define LOG_MSG(msg)
#define LOG_GUID(msg, guid)
#define LOG_IF_FAILED(msg, hr)
diff --git a/Source/DirectShow/Controls/MediaUriElement.cs b/Source/DirectShow/Controls/MediaUriElement.cs
index 5ce8994..884477a 100644
--- a/Source/DirectShow/Controls/MediaUriElement.cs
+++ b/Source/DirectShow/Controls/MediaUriElement.cs
@@ -28,7 +28,7 @@ public MediaUriPlayer MediaUriPlayer
public static readonly DependencyProperty VideoRendererProperty =
DependencyProperty.Register("VideoRenderer", typeof(VideoRendererType), typeof(MediaUriElement),
- new FrameworkPropertyMetadata(VideoRendererType.VideoMixingRenderer9,
+ new FrameworkPropertyMetadata(VideoRendererType.EnhancedVideoRenderer,
new PropertyChangedCallback(OnVideoRendererChanged)));
public VideoRendererType VideoRenderer
diff --git a/Source/DirectShow/MediaPlayers/BaseClasses.cs b/Source/DirectShow/MediaPlayers/BaseClasses.cs
index 6d5e8d9..da3a9ce 100644
--- a/Source/DirectShow/MediaPlayers/BaseClasses.cs
+++ b/Source/DirectShow/MediaPlayers/BaseClasses.cs
@@ -1,7 +1,6 @@
#region Includes
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
@@ -12,7 +11,7 @@
using WPFMediaKit.MediaFoundation;
using WPFMediaKit.MediaFoundation.Interop;
using WPFMediaKit.Threading;
-using Size=System.Windows.Size;
+using Size = System.Windows.Size;
#endregion
namespace WPFMediaKit.DirectShow.MediaPlayers
@@ -305,7 +304,7 @@ private void GetMainWindowHwndHelper()
if (m_window.Handle == IntPtr.Zero)
{
- lock(m_window)
+ lock (m_window)
{
m_window.CreateHandle(new CreateParams());
}
@@ -495,7 +494,7 @@ protected virtual void Dispose(bool disposing)
//if (m_disposed)
// return;
- if(!disposing)
+ if (!disposing)
return;
if (m_window != null)
@@ -509,8 +508,8 @@ protected virtual void Dispose(bool disposing)
m_timer.Dispose();
m_timer = null;
-
- if(CheckAccess())
+
+ if (CheckAccess())
{
FreeResources();
Dispatcher.BeginInvokeShutdown();
@@ -637,7 +636,7 @@ private void RemoveWndProcHook()
///
private void AddWndProcHook()
{
- // HwndHelper.AddHook(WndProcHook);
+ // HwndHelper.AddHook(WndProcHook);
}
///
@@ -771,14 +770,16 @@ protected void FreeCustomAllocator()
if (m_customAllocator == null)
return;
- m_customAllocator.Dispose();
-
m_customAllocator.NewAllocatorFrame -= CustomAllocatorNewAllocatorFrame;
m_customAllocator.NewAllocatorSurface -= CustomAllocatorNewAllocatorSurface;
- if(Marshal.IsComObject(m_customAllocator))
+ m_customAllocator.Dispose();
+
+
+
+ if (Marshal.IsComObject(m_customAllocator))
Marshal.ReleaseComObject(m_customAllocator);
-
+
m_customAllocator = null;
}
@@ -798,7 +799,7 @@ private void ResetLocalGraphResources()
Marshal.ReleaseComObject(m_mediaControl);
m_mediaControl = null;
- if(m_mediaEvent != null)
+ if (m_mediaEvent != null)
Marshal.ReleaseComObject(m_mediaEvent);
m_mediaEvent = null;
}
@@ -859,7 +860,7 @@ private IBaseFilter CreateEnhancedVideoRenderer(IGraphBuilder graph, int streamC
EvrPresenter presenter;
IBaseFilter filter;
- lock(m_videoRendererInitLock)
+ lock (m_videoRendererInitLock)
{
var evr = new EnhancedVideoRenderer();
filter = evr as IBaseFilter;
@@ -883,7 +884,7 @@ private IBaseFilter CreateEnhancedVideoRenderer(IGraphBuilder graph, int streamC
var presenterSettings = presenter.VideoPresenter as IEVRPresenterSettings;
if (presenterSettings == null)
throw new Exception("Could not QueryInterface for the IEVRPresenterSettings");
-
+
presenterSettings.SetBufferCount(3);
/* Use our interop hWnd */
@@ -900,12 +901,12 @@ private IBaseFilter CreateEnhancedVideoRenderer(IGraphBuilder graph, int streamC
DsError.ThrowExceptionForHR(hr);
var filterConfig = filter as IEVRFilterConfig;
-
+
if (filterConfig != null)
filterConfig.SetNumberOfStreams(streamCount);
}
-
-
+
+
RegisterCustomAllocator(presenter);
return filter;
@@ -939,7 +940,7 @@ private IBaseFilter CreateVideoMixingRenderer9(IGraphBuilder graph, int streamCo
if (vmrSurfAllocNotify == null)
throw new Exception("Could not query the VMR surface allocator.");
-
+
var allocator = new Vmr9Allocator();
/* We supply our custom allocator to the renderer */
@@ -951,7 +952,7 @@ private IBaseFilter CreateVideoMixingRenderer9(IGraphBuilder graph, int streamCo
RegisterCustomAllocator(allocator);
- hr = graph.AddFilter(vmr9,
+ hr = graph.AddFilter(vmr9,
string.Format("Renderer: {0}", VideoRendererType.VideoMixingRenderer9));
DsError.ThrowExceptionForHR(hr);
@@ -1104,7 +1105,7 @@ protected void InvokeNewAllocatorSurface(IntPtr pSurface)
}
#endregion
-
+
#region Helper Methods
///
/// Sets the natural pixel resolution the video in the graph
@@ -1136,14 +1137,14 @@ protected static Size GetVideoSize(IBaseFilter renderer, PinDirection direction,
if (pin == null)
goto done;
-
+
int hr = pin.ConnectionMediaType(mediaType);
-
+
if (hr != 0)
goto done;
/* Check to see if its a video media type */
- if (mediaType.formatType != FormatType.VideoInfo2 &&
+ if (mediaType.formatType != FormatType.VideoInfo2 &&
mediaType.formatType != FormatType.VideoInfo)
{
goto done;
@@ -1159,8 +1160,8 @@ protected static Size GetVideoSize(IBaseFilter renderer, PinDirection direction,
done:
DsUtils.FreeAMMediaType(mediaType);
-
- if(pin != null)
+
+ if (pin != null)
Marshal.ReleaseComObject(pin);
return size;
}
@@ -1210,69 +1211,69 @@ protected static void RemoveAllFilters(IGraphBuilder graphBuilder)
{
graphBuilder.RemoveFilter(filtersArray[i]);
while (Marshal.ReleaseComObject(filtersArray[i]) > 0)
- {}
+ { }
}
}
- ///
- /// Adds a filter to a DirectShow graph based on it's name and filter category
- ///
- /// The graph builder to add the filter to
- /// The category the filter belongs to
- /// The friendly name of the filter
- /// Reference to the IBaseFilter that was added to the graph or returns null if unsuccessful
- protected static IBaseFilter AddFilterByName(IGraphBuilder graphBuilder, Guid deviceCategory, string friendlyName)
- {
- var devices = DsDevice.GetDevicesOfCat(deviceCategory);
-
- var deviceList = (from d in devices
- where d.Name == friendlyName
- select d);
- DsDevice device = null;
- if (deviceList.Count() > 0)
- device = deviceList.Take(1).Single();
-
- foreach (var item in deviceList)
- {
+ ///
+ /// Adds a filter to a DirectShow graph based on it's name and filter category
+ ///
+ /// The graph builder to add the filter to
+ /// The category the filter belongs to
+ /// The friendly name of the filter
+ /// Reference to the IBaseFilter that was added to the graph or returns null if unsuccessful
+ protected static IBaseFilter AddFilterByName(IGraphBuilder graphBuilder, Guid deviceCategory, string friendlyName)
+ {
+ var devices = DsDevice.GetDevicesOfCat(deviceCategory);
+
+ var deviceList = (from d in devices
+ where d.Name == friendlyName
+ select d);
+ DsDevice device = null;
+ if (deviceList.Count() > 0)
+ device = deviceList.Take(1).Single();
+
+ foreach (var item in deviceList)
+ {
if (item != device)
item.Dispose();
- }
+ }
- return AddFilterByDevice(graphBuilder, device);
- }
+ return AddFilterByDevice(graphBuilder, device);
+ }
- protected static IBaseFilter AddFilterByDevicePath(IGraphBuilder graphBuilder, Guid deviceCategory, string devicePath)
- {
- var devices = DsDevice.GetDevicesOfCat(deviceCategory);
+ protected static IBaseFilter AddFilterByDevicePath(IGraphBuilder graphBuilder, Guid deviceCategory, string devicePath)
+ {
+ var devices = DsDevice.GetDevicesOfCat(deviceCategory);
- var deviceList = (from d in devices
- where d.DevicePath == devicePath
- select d);
- DsDevice device = null;
- if (deviceList.Count() > 0)
- device = deviceList.Take(1).Single();
+ var deviceList = (from d in devices
+ where d.DevicePath == devicePath
+ select d);
+ DsDevice device = null;
+ if (deviceList.Count() > 0)
+ device = deviceList.Take(1).Single();
- return AddFilterByDevice(graphBuilder, device);
- }
+ return AddFilterByDevice(graphBuilder, device);
+ }
- private static IBaseFilter AddFilterByDevice(IGraphBuilder graphBuilder, DsDevice device)
- {
- if (graphBuilder == null)
- throw new ArgumentNullException("graphBuilder");
+ private static IBaseFilter AddFilterByDevice(IGraphBuilder graphBuilder, DsDevice device)
+ {
+ if (graphBuilder == null)
+ throw new ArgumentNullException("graphBuilder");
- var filterGraph = graphBuilder as IFilterGraph2;
+ var filterGraph = graphBuilder as IFilterGraph2;
- if (filterGraph == null)
- return null;
+ if (filterGraph == null)
+ return null;
- IBaseFilter filter = null;
- if (device != null)
- {
- int hr = filterGraph.AddSourceFilterForMoniker(device.Mon, null, device.Name, out filter);
- DsError.ThrowExceptionForHR(hr);
- }
- return filter;
- }
+ IBaseFilter filter = null;
+ if (device != null)
+ {
+ int hr = filterGraph.AddSourceFilterForMoniker(device.Mon, null, device.Name, out filter);
+ DsError.ThrowExceptionForHR(hr);
+ }
+ return filter;
+ }
///
/// Finds a pin that exists in a graph.
@@ -1284,7 +1285,7 @@ private static IBaseFilter AddFilterByDevice(IGraphBuilder graphBuilder, DsDevic
protected static IPin FindPinInGraphByMediaType(Guid majorOrMinorMediaType, PinDirection pinDirection, IGraphBuilder graph)
{
IEnumFilters enumFilters;
-
+
/* Get the filter enum */
graph.EnumFilters(out enumFilters);
@@ -1308,7 +1309,7 @@ protected static IPin FindPinInGraphByMediaType(Guid majorOrMinorMediaType, PinD
pin.EnumMediaTypes(out mediaTypesEnum);
var mediaTypesFetched = IntPtr.Zero;
var mediaTypes = new AMMediaType[1];
-
+
/* Enumerate the media types on the pin */
while (mediaTypesEnum.Next(1, mediaTypes, mediaTypesFetched) == 0)
{
diff --git a/Source/DirectShow/MediaPlayers/DirectShowUtil.cs b/Source/DirectShow/MediaPlayers/DirectShowUtil.cs
index 150f3f2..89ef12c 100644
--- a/Source/DirectShow/MediaPlayers/DirectShowUtil.cs
+++ b/Source/DirectShow/MediaPlayers/DirectShowUtil.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Runtime.InteropServices;
using DirectShowLib;
@@ -122,5 +123,83 @@ public static bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin)
}
return allDisconnected;
}
+
+ public static void RemoveFilters(IGraphBuilder graphBuilder)
+ {
+ RemoveFilters(graphBuilder, string.Empty);
+ }
+ public static void RemoveFilters(IGraphBuilder graphBuilder, string filterName)
+ {
+ if (graphBuilder == null)
+ {
+ return;
+ }
+
+ int hr = 0;
+ IEnumFilters enumFilters = null;
+ ArrayList filtersArray = new ArrayList();
+
+ try
+ {
+ hr = graphBuilder.EnumFilters(out enumFilters);
+ DsError.ThrowExceptionForHR(hr);
+
+ IBaseFilter[] filters = new IBaseFilter[1];
+ IntPtr fetched = IntPtr.Zero;
+
+ while (enumFilters.Next(filters.Length, filters, fetched) == 0)
+ {
+ filtersArray.Add(filters[0]);
+ }
+
+ foreach (IBaseFilter filter in filtersArray)
+ {
+ FilterInfo info;
+ filter.QueryFilterInfo(out info);
+ Marshal.ReleaseComObject(info.pGraph);
+
+ try
+ {
+ if (!String.IsNullOrEmpty(filterName))
+ {
+ if (String.Equals(info.achName, filterName))
+ {
+ DisconnectAllPins(graphBuilder, filter);
+ hr = graphBuilder.RemoveFilter(filter);
+ DsError.ThrowExceptionForHR(hr);
+ Marshal.ReleaseComObject(filter);
+ System.Diagnostics.Trace.WriteLine("Remove filter from graph: {0}", info.achName);
+ }
+ }
+ else
+ {
+ DisconnectAllPins(graphBuilder, filter);
+ hr = graphBuilder.RemoveFilter(filter);
+ DsError.ThrowExceptionForHR(hr);
+ int i = Marshal.ReleaseComObject(filter);
+ System.Diagnostics.Trace.WriteLine(string.Format("Remove filter from graph: {0} {1}", info.achName, i));
+ }
+ }
+ catch (Exception error)
+ {
+ System.Diagnostics.Trace.TraceError("Remove of filter: {0}, failed with code (HR): {1}, explanation: {2}", info.achName, hr.ToString(),
+ error.Message);
+ }
+ }
+ }
+ catch (Exception)
+ {
+ return;
+ }
+ finally
+ {
+ if (enumFilters != null)
+ {
+ Marshal.ReleaseComObject(enumFilters);
+ }
+ }
+ }
+
+
}
}
diff --git a/Source/DirectShow/MediaPlayers/MediaUriPlayer.cs b/Source/DirectShow/MediaPlayers/MediaUriPlayer.cs
index 11343cd..4431db4 100644
--- a/Source/DirectShow/MediaPlayers/MediaUriPlayer.cs
+++ b/Source/DirectShow/MediaPlayers/MediaUriPlayer.cs
@@ -1,5 +1,6 @@
#region Usings
using System;
+using System.Diagnostics;
using System.Runtime.InteropServices;
using DirectShowLib;
#endregion
@@ -278,12 +279,9 @@ protected virtual void OpenSource()
IBaseFilter sourceFilter;
int hr;
- //var file = System.IO.File.CreateText(@"M:\DirectShowLog.txt");
- //filterGraph.SetLogFile((file.BaseStream as System.IO.FileStream).SafeFileHandle.DangerousGetHandle());
-
// Set LAV Splitter
- LAVSplitterSource reader = new LAVSplitterSource();
+ /* LAVSplitterSource reader = new LAVSplitterSource();
sourceFilter = reader as IBaseFilter;
var objectWithSite = reader as IObjectWithSite;
if (objectWithSite != null)
@@ -291,9 +289,11 @@ protected virtual void OpenSource()
objectWithSite.SetSite(this);
}
+
hr = m_graph.AddFilter(sourceFilter, SplitterSource);
- DsError.ThrowExceptionForHR(hr);
+ DsError.ThrowExceptionForHR(hr);*/
+ sourceFilter = DirectShowUtil.AddFilterToGraph(m_graph, SplitterSource, Guid.Empty);
IFileSourceFilter interfaceFile = (IFileSourceFilter)sourceFilter;
hr = interfaceFile.Load(fileSource, null);
@@ -328,41 +328,170 @@ protected virtual void OpenSource()
DirectShowUtil.AddFilterToGraph(m_graph, VideoDecoder, Guid.Empty);
- // Set Audio Codec
- // Remove Pin
- var audioPinFrom = DirectShowLib.DsFindPin.ByName(sourceFilter, "Audio");
- IPin audioPinTo;
- if (audioPinFrom != null)
+ try
{
- hr = audioPinFrom.ConnectedTo(out audioPinTo);
- if (hr >= 0 && audioPinTo != null)
+ // Set Audio Codec
+ // Remove Pin
+ var audioPinFrom = DirectShowLib.DsFindPin.ByName(sourceFilter, "Audio");
+ IPin audioPinTo;
+ if (audioPinFrom != null)
{
- PinInfo pInfo;
- audioPinTo.QueryPinInfo(out pInfo);
- FilterInfo fInfo;
- pInfo.filter.QueryFilterInfo(out fInfo);
+ hr = audioPinFrom.ConnectedTo(out audioPinTo);
+ if (hr >= 0 && audioPinTo != null)
+ {
+ PinInfo pInfo;
+ audioPinTo.QueryPinInfo(out pInfo);
+ FilterInfo fInfo;
+ pInfo.filter.QueryFilterInfo(out fInfo);
+
+ DirectShowUtil.DisconnectAllPins(m_graph, pInfo.filter);
+ m_graph.RemoveFilter(pInfo.filter);
+
+ DsUtils.FreePinInfo(pInfo);
+ Marshal.ReleaseComObject(fInfo.pGraph);
+ Marshal.ReleaseComObject(audioPinTo);
+ audioPinTo = null;
+ }
+ Marshal.ReleaseComObject(audioPinFrom);
+ audioPinFrom = null;
+ }
- DirectShowUtil.DisconnectAllPins(m_graph, pInfo.filter);
- m_graph.RemoveFilter(pInfo.filter);
+ DirectShowUtil.AddFilterToGraph(m_graph, AudioDecoder, Guid.Empty);
- DsUtils.FreePinInfo(pInfo);
- Marshal.ReleaseComObject(fInfo.pGraph);
- Marshal.ReleaseComObject(audioPinTo);
- audioPinTo = null;
+
+ /* Add our prefered audio renderer */
+ InsertAudioRenderer(AudioRenderer);
+ }
+ catch
+ {
+ // No Audio available
+ Trace.TraceError("No Audio Device found!");
+ }
+
+ IBaseFilter renderer = CreateVideoRenderer(VideoRenderer, m_graph, 2);
+
+ /* We will want to enum all the pins on the source filter */
+ IEnumPins pinEnum;
+
+ hr = sourceFilter.EnumPins(out pinEnum);
+ DsError.ThrowExceptionForHR(hr);
+
+ IntPtr fetched = IntPtr.Zero;
+ IPin[] pins = { null };
+
+ /* Counter for how many pins successfully rendered */
+ int pinsRendered = 0;
+
+ if (VideoRenderer == VideoRendererType.VideoMixingRenderer9)
+ {
+ var mixer = renderer as IVMRMixerControl9;
+
+ if (mixer != null)
+ {
+ VMR9MixerPrefs dwPrefs;
+ mixer.GetMixingPrefs(out dwPrefs);
+ dwPrefs &= ~VMR9MixerPrefs.RenderTargetMask;
+ dwPrefs |= VMR9MixerPrefs.RenderTargetRGB;
+ //mixer.SetMixingPrefs(dwPrefs);
}
- Marshal.ReleaseComObject(audioPinFrom);
- audioPinFrom = null;
}
- DirectShowUtil.AddFilterToGraph(m_graph, AudioDecoder, Guid.Empty);
+ /* Loop over each pin of the source filter */
+ while (pinEnum.Next(pins.Length, pins, fetched) == 0)
+ {
+ if (filterGraph.RenderEx(pins[0],
+ AMRenderExFlags.RenderToExistingRenderers,
+ IntPtr.Zero) >= 0)
+ pinsRendered++;
+
+
+ Marshal.ReleaseComObject(pins[0]);
+ }
+
+
+ Marshal.ReleaseComObject(pinEnum);
+ Marshal.ReleaseComObject(sourceFilter);
+
+ if (pinsRendered == 0)
+ throw new Exception("Could not render any streams from the source Uri");
+
+#if DEBUG
+ /* Adds the GB to the ROT so we can view
+ * it in graphedit */
+ m_dsRotEntry = new DsROTEntry(m_graph);
+#endif
+ /* Configure the graph in the base class */
+ SetupFilterGraph(m_graph);
+
+ HasVideo = true;
+
+ }
+ catch (Exception ex)
+ {
+ /* This exection will happen usually if the media does
+ * not exist or could not open due to not having the
+ * proper filters installed */
+
+
+ // Fallback try auto graph:
+ var result = oldOpenSource();
+
+ if (!result)
+ {
+ FreeResources();
+
+ /* Fire our failed event */
+ InvokeMediaFailed(new MediaFailedEventArgs(ex.Message, ex));
+ }
+ }
+
+ InvokeMediaOpened();
+ }
+
+ private bool oldOpenSource()
+ {
+ /* Make sure we clean up any remaining mess */
+ FreeResources();
+ if (m_sourceUri == null)
+ return false;
- /* Add our prefered audio renderer */
- InsertAudioRenderer(AudioRenderer);
+ string fileSource = m_sourceUri.OriginalString;
+
+ if (string.IsNullOrEmpty(fileSource))
+ return false;
+
+ try
+ {
+ /* Creates the GraphBuilder COM object */
+ m_graph = new FilterGraphNoThread() as IGraphBuilder;
+
+ if (m_graph == null)
+ throw new Exception("Could not create a graph");
+
+ try
+ {
+ /* Add our prefered audio renderer */
+ InsertAudioRenderer(AudioRenderer);
+ }
+ catch
+ {
+ // No Audio device found
+ Trace.TraceError("No Audio Device found!");
+ }
IBaseFilter renderer = CreateVideoRenderer(VideoRenderer, m_graph, 2);
+ var filterGraph = m_graph as IFilterGraph2;
+
+ if (filterGraph == null)
+ throw new Exception("Could not QueryInterface for the IFilterGraph2");
+
+ IBaseFilter sourceFilter;
+ /* Have DirectShow find the correct source filter for the Uri */
+ int hr = filterGraph.AddSourceFilter(fileSource, fileSource, out sourceFilter);
+ DsError.ThrowExceptionForHR(hr);
/* We will want to enum all the pins on the source filter */
IEnumPins pinEnum;
@@ -389,14 +518,7 @@ protected virtual void OpenSource()
//mixer.SetMixingPrefs(dwPrefs);
}
}
-
- /* Test using FFDShow Video Decoder Filter
- var ffdshow = new FFDShow() as IBaseFilter;
-
- if (ffdshow != null)
- m_graph.AddFilter(ffdshow, "ffdshow");
- */
-
+
/* Loop over each pin of the source filter */
while (pinEnum.Next(pins.Length, pins, fetched) == 0)
@@ -406,11 +528,9 @@ protected virtual void OpenSource()
IntPtr.Zero) >= 0)
pinsRendered++;
-
Marshal.ReleaseComObject(pins[0]);
}
-
Marshal.ReleaseComObject(pinEnum);
Marshal.ReleaseComObject(sourceFilter);
@@ -438,9 +558,13 @@ protected virtual void OpenSource()
/* Fire our failed event */
InvokeMediaFailed(new MediaFailedEventArgs(ex.Message, ex));
+
+ return false;
}
InvokeMediaOpened();
+
+ return true;
}
///
@@ -481,6 +605,7 @@ protected override void FreeResources()
if (m_graph != null)
{
+ DirectShowUtil.RemoveFilters(m_graph);
Marshal.ReleaseComObject(m_graph);
m_graph = null;
diff --git a/Source/MediaFoundation/EvrPresenter.cs b/Source/MediaFoundation/EvrPresenter.cs
index 23ed011..785c0a1 100644
--- a/Source/MediaFoundation/EvrPresenter.cs
+++ b/Source/MediaFoundation/EvrPresenter.cs
@@ -64,8 +64,9 @@ internal interface IEVRPresenterSettings
[ComVisible(true)]
public class EvrPresenter : ICustomAllocator, IEVRPresenterCallback
{
- private IntPtr m_lastSurface;
private const int PRESENTER_BUFFER_COUNT = 5;
+ private IntPtr m_lastSurface;
+ private IMFVideoPresenter m_VideoPresenter;
private EvrPresenter()
{
@@ -120,7 +121,11 @@ private static int ProcessBits
///
/// The custom EVR video presenter COM object
///
- public IMFVideoPresenter VideoPresenter { get; private set; }
+ public IMFVideoPresenter VideoPresenter
+ {
+ get { return m_VideoPresenter; }
+ private set { m_VideoPresenter = value; }
+ }
#region ICustomAllocator Members
///
@@ -138,17 +143,18 @@ private static int ProcessBits
public void Dispose()
{
- GC.SuppressFinalize(this);
Dispose(true);
+ GC.SuppressFinalize(this);
}
protected void Dispose(bool disp)
{
- if (VideoPresenter != null)
- {
- Marshal.FinalReleaseComObject(VideoPresenter);
- VideoPresenter = null;
- }
+ var settings = m_VideoPresenter as IEVRPresenterSettings;
+
+ if (settings != null)
+ settings.RegisterCallback(null);
+
+ COMUtil.TryFinalRelease(ref m_VideoPresenter);
}
#endregion
diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs
index f0477ae..232cb14 100644
--- a/Source/Properties/AssemblyInfo.cs
+++ b/Source/Properties/AssemblyInfo.cs
@@ -25,4 +25,4 @@
-[assembly: AssemblyVersion("2.0.0")]
+[assembly: AssemblyVersion("2.1.0")]
diff --git a/Test Application/App.xaml b/Test Application/App.xaml
new file mode 100644
index 0000000..b0bf271
--- /dev/null
+++ b/Test Application/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Test Application/App.xaml.cs b/Test Application/App.xaml.cs
new file mode 100644
index 0000000..04bee97
--- /dev/null
+++ b/Test Application/App.xaml.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+namespace Test_Application
+{
+ ///
+ /// Interaktionslogik für "App.xaml"
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/Test Application/EVRPresenter32.dll b/Test Application/EVRPresenter32.dll
new file mode 100644
index 0000000..9d95297
Binary files /dev/null and b/Test Application/EVRPresenter32.dll differ
diff --git a/Test Application/MainWindow.xaml b/Test Application/MainWindow.xaml
new file mode 100644
index 0000000..5da99a4
--- /dev/null
+++ b/Test Application/MainWindow.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Test Application/MainWindow.xaml.cs b/Test Application/MainWindow.xaml.cs
new file mode 100644
index 0000000..59a7cc3
--- /dev/null
+++ b/Test Application/MainWindow.xaml.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Microsoft.Win32;
+
+namespace Test_Application
+{
+ ///
+ /// Interaktionslogik für MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void btnStop_Click(object sender, RoutedEventArgs e)
+ {
+ mediaUriElement.Stop();
+ }
+
+ private void btnOpen_Click(object sender, RoutedEventArgs e)
+ {
+ var dlg = new OpenFileDialog();
+ var result = dlg.ShowDialog();
+ if (result == true)
+ mediaUriElement.Source = new Uri(dlg.FileName);
+ }
+ }
+}
diff --git a/Test Application/Properties/AssemblyInfo.cs b/Test Application/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..56409f5
--- /dev/null
+++ b/Test Application/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die einer Assembly zugeordnet sind.
+[assembly: AssemblyTitle("Test Application")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Test Application")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
+[assembly: ComVisible(false)]
+
+//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
+//ImCodeVerwendeteKultur in der .csproj-Datei
+//in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
+//(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
+//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
+//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
+ //(wird verwendet, wenn eine Ressource auf der Seite
+ // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
+ ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
+ //(wird verwendet, wenn eine Ressource auf der Seite, in der Anwendung oder einem
+ // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
+)]
+
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Test Application/Properties/Resources.Designer.cs b/Test Application/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..f4aae7a
--- /dev/null
+++ b/Test Application/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion: 4.0.30319.42000
+//
+// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
+// der Code neu generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace Test_Application.Properties
+{
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
+ // über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Test_Application.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Test Application/Properties/Resources.resx b/Test Application/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Test Application/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Test Application/Properties/Settings.Designer.cs b/Test Application/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..6d89d45
--- /dev/null
+++ b/Test Application/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Test_Application.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Test Application/Properties/Settings.settings b/Test Application/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/Test Application/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Test Application/Test Application.csproj b/Test Application/Test Application.csproj
new file mode 100644
index 0000000..5c6e644
--- /dev/null
+++ b/Test Application/Test Application.csproj
@@ -0,0 +1,112 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {77DD70C4-DE32-4A31-AE22-675F5758FB5F}
+ WinExe
+ Properties
+ Test_Application
+ Test Application
+ v4.0
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+ {73154957-3d91-48da-8068-d425b523ed93}
+ WPF MediaKit
+
+
+
+
+ PreserveNewest
+
+
+
+
+
\ No newline at end of file
diff --git a/WPF MediaKit.sln b/WPF MediaKit.sln
index ef5adcc..75c1734 100644
--- a/WPF MediaKit.sln
+++ b/WPF MediaKit.sln
@@ -1,10 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.31101.0
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPF MediaKit", "Source\WPF MediaKit.csproj", "{73154957-3D91-48DA-8068-D425B523ED93}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test Application", "Test Application\Test Application.csproj", "{77DD70C4-DE32-4A31-AE22-675F5758FB5F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{73154957-3D91-48DA-8068-D425B523ED93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73154957-3D91-48DA-8068-D425B523ED93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73154957-3D91-48DA-8068-D425B523ED93}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DD70C4-DE32-4A31-AE22-675F5758FB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DD70C4-DE32-4A31-AE22-675F5758FB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DD70C4-DE32-4A31-AE22-675F5758FB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DD70C4-DE32-4A31-AE22-675F5758FB5F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE