Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Source/DirectShow/Controls/MediaElementBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ public event RoutedEventHandler MediaEnded
#endregion

#region Dependency Properties
#region PlayerState
public static readonly DependencyProperty PlayerStateProperty =
DependencyProperty.Register("PlayerState", typeof(PlayerState), typeof(MediaElementBase),
new FrameworkPropertyMetadata(PlayerState.Closed));

/// <summary>
/// Get the current state of the media player
/// </summary>
public PlayerState PlayerState
{
get { return (PlayerState)GetValue(PlayerStateProperty); }
protected set { SetValue(PlayerStateProperty, value); }
}
#endregion

#region UnloadedBehavior

public static readonly DependencyProperty UnloadedBehaviorProperty =
Expand Down Expand Up @@ -297,6 +312,7 @@ protected virtual void InitializeMediaPlayer()
MediaPlayerBase.MediaClosed += OnMediaPlayerClosedPrivate;
MediaPlayerBase.MediaFailed += OnMediaPlayerFailedPrivate;
MediaPlayerBase.MediaEnded += OnMediaPlayerEndedPrivate;
MediaPlayerBase.PlayerStateChanged += OnPlayerStateChanged;

/* These events fire when we get new D3Dsurfaces or frames */
MediaPlayerBase.NewAllocatorFrame += OnMediaPlayerNewAllocatorFramePrivate;
Expand Down Expand Up @@ -372,6 +388,16 @@ protected virtual void OnMediaPlayerNewAllocatorFrame()
InvalidateVideoImage();
}

/// <summary>
/// /// Called when the state of the player has changed
/// </summary>
/// <param name="oldState">Previous state</param>
/// <param name="newState">New State</param>
protected virtual void OnPlayerStateChanged(PlayerState oldState, PlayerState newState)
{
Dispatcher.BeginInvoke((Action<PlayerState, MediaElementBase>)((a, b) => b.PlayerState = a), newState, this);
}

/// <summary>
/// Called when the media has been closed
/// </summary>
Expand Down
40 changes: 26 additions & 14 deletions Source/DirectShow/Controls/MediaSeekingElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ public abstract class MediaSeekingElement : MediaElementBase
new FrameworkPropertyMetadata((long)0,
new PropertyChangedCallback(OnMediaPositionChanged)));

public static readonly RoutedEvent MediaPositionChangedEvent = EventManager.RegisterRoutedEvent("MediaPositionChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MediaSeekingElement));

/// <summary>
/// Is invoked whenever the current media position is changed.
/// </summary>
public event RoutedEventHandler MediaPositionChanged
{
add
{
this.AddHandler(MediaPositionChangedEvent, value);
}
remove
{
this.RemoveHandler(MediaPositionChangedEvent, value);
}
}


/// <summary>
/// Gets or sets the media position in units of CurrentPositionFormat
/// </summary>
Expand Down Expand Up @@ -59,10 +77,12 @@ protected virtual void OnMediaPositionChanged(DependencyPropertyChangedEventArgs
protected void SetMediaPositionInternal(long value)
{
/* Flag that we want to ignore the next
* PropertyChangedCallback */
m_ignorePropertyChangedCallback = true;
*PropertyChangedCallback
* If the player is not currently paused!(otherwise it would only react every second seek) */
m_ignorePropertyChangedCallback = this.PlayerState != PlayerState.Paused;

MediaPosition = value;
RaiseEvent(new RoutedEventArgs(MediaPositionChangedEvent, this));
}

private void PlayerSetMediaPosition()
Expand Down Expand Up @@ -298,27 +318,19 @@ protected virtual void OnMediaPlayerPositionChanged()
/// </summary>
protected override void OnMediaPlayerOpened()
{
/* Pull out our values of our properties */
MediaPositionFormat positionFormat = MediaSeekingPlayer.CurrentPositionFormat;
long duration = MediaSeekingPlayer.Duration;
long position = 0;// MediaSeekingPlayer.MediaPosition;
double rate = 1; // MediaSeekingPlayer.SpeedRatio;
double volume = 1;

var positionFormat = MediaSeekingPlayer.CurrentPositionFormat;

Dispatcher.BeginInvoke((Action)delegate
{
position = MediaPosition;
/* Set our DP values */
SetCurrentPositionFormat(positionFormat);
SetMediaPositionInternal(0);
SetMediaDuration(duration);
//SetMediaPositionInternal(position);
//SpeedRatio = rate;
rate = SpeedRatio;
volume = Volume;
double rate = SpeedRatio;
double volume = Volume;
MediaSeekingPlayer.Dispatcher.BeginInvoke((Action) delegate
{
//MediaSeekingPlayer.MediaPosition = position;
MediaSeekingPlayer.SpeedRatio = rate;
MediaPlayerBase.Volume = volume;
});
Expand Down
12 changes: 12 additions & 0 deletions Source/DirectShow/Controls/MediaUriElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ private void PlayerSetVideoRenderer()

#endregion

/// <summary>
/// Step the count of frames.
/// </summary>
/// <param name="framecount">count of frames to step</param>
public void FrameStep(int framecount)
{
MediaUriPlayer.Dispatcher.BeginInvoke((Action)delegate
{
MediaUriPlayer.StepFrame(framecount);
});
}

#region AudioRenderer

public static readonly DependencyProperty AudioRendererProperty =
Expand Down
53 changes: 47 additions & 6 deletions Source/DirectShow/MediaPlayers/BaseClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ public enum MediaState
Pause
}

public enum PlayerState
{
Closed,
Playing,
Paused,
Stopped,
SteppingFrames
}

/// <summary>
/// The types of position formats that
/// are available for seeking media
Expand Down Expand Up @@ -148,8 +157,6 @@ public enum VideoRendererType
/// </summary>
public abstract class MediaPlayerBase : WorkDispatcherObject
{
private const string VMR9_ERROR = "Do you have the grahics driver and DirectX properly installed?";

[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr GetDesktopWindow();

Expand Down Expand Up @@ -255,6 +262,11 @@ public abstract class MediaPlayerBase : WorkDispatcherObject
/// </summary>
private System.Timers.Timer m_timer;

/// <summary>
/// The current state of the player
/// </summary>
private PlayerState m_playerState = PlayerState.Closed;

/// <summary>
/// This objects last stand
/// </summary>
Expand Down Expand Up @@ -463,6 +475,22 @@ public virtual double Balance
}
}

/// <summary>
/// Get the current state of the player
/// </summary>
public virtual PlayerState PlayerState
{
get { return this.m_playerState; }
protected set
{
PlayerState oldVal = m_playerState;
m_playerState = value;

if (PlayerStateChanged != null && oldVal != value)
PlayerStateChanged(oldVal, value);
}
}

/// <summary>
/// Event notifies when there is a new video frame
/// to be rendered
Expand All @@ -474,6 +502,11 @@ public virtual double Balance
/// </summary>
public event NewAllocatorSurfaceDelegate NewAllocatorSurface;

/// <summary>
/// Event notifies when the player changes state
/// </summary>
public event Action<PlayerState, PlayerState> PlayerStateChanged;

/// <summary>
/// Frees any remaining memory
/// </summary>
Expand Down Expand Up @@ -923,7 +956,7 @@ private IBaseFilter CreateVideoMixingRenderer9(IGraphBuilder graph, int streamCo
}
catch (COMException ex)
{
throw new WPFMediaKitException("Could not create VMR9. " + VMR9_ERROR, ex);
throw new WPFMediaKitException("Could not create VMR9. " + Vmr9Allocator.VMR9_ERROR, ex);
}
}

Expand All @@ -938,7 +971,7 @@ private IBaseFilter CreateVideoMixingRenderer9Inner(IGraphBuilder graph, int str
IBaseFilter vmr9 = new VideoMixingRenderer9() as IBaseFilter;
var filterConfig = vmr9 as IVMRFilterConfig9;
if (filterConfig == null)
throw new WPFMediaKitException("Could not query VMR9 filter configuration. " + VMR9_ERROR);
throw new WPFMediaKitException("Could not query VMR9 filter configuration. " + Vmr9Allocator.VMR9_ERROR);

/* We will only have one video stream connected to the filter */
int hr = filterConfig.SetNumberOfStreams(streamCount);
Expand All @@ -953,7 +986,7 @@ private IBaseFilter CreateVideoMixingRenderer9Inner(IGraphBuilder graph, int str
/* Query the allocator interface */
var vmrSurfAllocNotify = vmr9 as IVMRSurfaceAllocatorNotify9;
if (vmrSurfAllocNotify == null)
throw new WPFMediaKitException("Could not query the VMR surface allocator. " + VMR9_ERROR);
throw new WPFMediaKitException("Could not query the VMR surface allocator. " + Vmr9Allocator.VMR9_ERROR);

var allocator = new Vmr9Allocator();

Expand Down Expand Up @@ -987,7 +1020,11 @@ public virtual void Play()
}

if (m_mediaControl != null)
{
m_mediaControl.Run();
PlayerState = PlayerState.Playing;
}

}

/// <summary>
Expand Down Expand Up @@ -1015,7 +1052,9 @@ protected void StopInternal()
m_mediaControl.GetState(0, out filterState);

while (filterState != FilterState.Stopped)
m_mediaControl.GetState(0, out filterState);
m_mediaControl.GetState(2, out filterState);

PlayerState = PlayerState.Stopped;
}
}

Expand All @@ -1027,6 +1066,7 @@ public virtual void Close()
VerifyAccess();
StopInternal();
FreeResources();
PlayerState = PlayerState.Closed;
}

/// <summary>
Expand All @@ -1039,6 +1079,7 @@ public virtual void Pause()
if (m_mediaControl != null)
{
m_mediaControl.Pause();
PlayerState = PlayerState.Paused;
}
}

Expand Down
17 changes: 15 additions & 2 deletions Source/DirectShow/MediaPlayers/MediaDetector.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
Expand Down Expand Up @@ -35,8 +35,17 @@ public class MediaDetector : DispatcherObject, IDisposable
private Size m_videoResolution;
private double m_videoStreamLength;
private Guid m_videoSubType;
private double m_videoFrameRate;
#endregion


/// <summary>
/// The video framerate
/// </summary>
public double VideoFrameRate
{
get { return m_videoFrameRate; }
}

/// <summary>
/// The video CODEC tag
/// </summary>
Expand Down Expand Up @@ -169,6 +178,7 @@ private void FreeResources()
m_videoResolution = Size.Empty;
m_videoStreamLength = 0;
m_videoSubType = Guid.Empty;
m_videoFrameRate = 0;
HasAudio = false;
HasVideo = false;

Expand Down Expand Up @@ -248,6 +258,7 @@ private void LoadMedia()
DsError.ThrowExceptionForHR(hr);

var mediaType = new AMMediaType();
double framerate;

/* Gets the AMMediaType so we can read some
* metadata on the stream */
Expand All @@ -257,6 +268,8 @@ private void LoadMedia()
if(majorType == MediaType.Video)
{
ReadVideoFormat(mediaType);
hr = m_mediaDet.get_FrameRate(out framerate);
m_videoFrameRate = framerate;
}
else if(majorType == MediaType.Audio)
{
Expand Down
52 changes: 52 additions & 0 deletions Source/DirectShow/MediaPlayers/MediaUriPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,53 @@ public VideoRendererType VideoRenderer
get;
set;
}

/// <summary>
/// Implementation of framestepinterface to step video forward by minimum of one frame e.g. by mousewheel
/// </summary>
private IVideoFrameStep frameStep;

/// <summary>
/// step the frames
/// </summary>
public void StepFrame(int framecount)
{
int i = frameStep.CanStep(0, null);
if (i == 0)
{
this.Play();
frameStep.Step(framecount, null);
this.PlayerState = PlayerState.SteppingFrames;
}
}

//
// Some video renderers support stepping media frame by frame with the
// IVideoFrameStep interface. See the interface documentation for more
// details on frame stepping.
//
private bool GetFrameStepInterface()
{
int hr = 0;

IVideoFrameStep frameStepTest = null;

// Get the frame step interface, if supported
frameStepTest = (IVideoFrameStep)this.m_graph;

// Check if this decoder can step
hr = frameStepTest.CanStep(0, null);
if (hr == 0)
{
this.frameStep = frameStepTest;
return true;
}
else
{
this.frameStep = null;
return false;
}
}

/// <summary>
/// The name of the audio renderer device
Expand Down Expand Up @@ -419,6 +466,11 @@ protected virtual void OpenSource()
#endif
/* Configure the graph in the base class */
SetupFilterGraph(m_graph);

HasVideo = true;

GetFrameStepInterface();

}
catch (Exception ex)
{
Expand Down
Loading