daily pastebin goal
33%
SHARE
TWEET

Untitled

a guest May 23rd, 2018 53 Never
Upgrade to PRO!
ENDING IN00days00hours00mins00secs
 
  1. using System;
  2. using System.IO;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using System.Windows.Interop;
  6. using WPFMediaKit.DirectShow.Controls;
  7. using WPFMediaKit.DirectShow.MediaPlayers;
  8.  
  9. namespace Test_Application
  10. {
  11.     /// <summary>
  12.     /// Class to simplify video screen grabbing by the async tasks.
  13.     /// </summary>
  14.     public class VideoScreenGrabber : IDisposable
  15.     {
  16.         private TaskCompletionSource<bool> taskCompletionOpen;
  17.         private TaskCompletionSource<IntPtr> taskCompletionGrab;
  18.         private CancellationTokenRegistration cancellationRegistrationGrab;
  19.  
  20.         public MediaUriPlayer Player { get; private set; }
  21.  
  22.         /// <summary>
  23.         /// Current back buffer.
  24.         /// </summary>
  25.         public IntPtr BackBuffer { get; private set; }
  26.  
  27.         /// <summary>
  28.         /// Media duration in 100ns units.
  29.         /// </summary>
  30.         public long MediaDuration
  31.         {
  32.             get
  33.             {
  34.                 CheckPlayer();
  35.                 return Player.Duration;
  36.             }
  37.         }
  38.  
  39.         /// <summary>
  40.         /// Media duration [sec].
  41.         /// </summary>
  42.         public double MediaDurationSecond
  43.             => (double)MediaDuration / MediaPlayerBase.DSHOW_ONE_SECOND_UNIT;
  44.  
  45.         /// <summary>
  46.         /// Busy with grabbing.
  47.         /// </summary>
  48.         public bool IsGrabbing
  49.             => taskCompletionGrab != null;
  50.  
  51.         /// <summary>
  52.         /// Open given source. Fails with exception if the file cannot be played.
  53.         /// </summary>
  54.         public Task Open(Uri source)
  55.         {
  56.             if (Player != null)
  57.                 throw new ArgumentException("Cannot open twice!");
  58.             taskCompletionOpen = new TaskCompletionSource<bool>();
  59.  
  60.             Player = new MediaUriPlayer();
  61.             Player.EnsureThread(ApartmentState.MTA);
  62.             Player.MediaOpened += MediaUriPlayer_MediaOpened;
  63.             Player.MediaFailed += MediaUriPlayer_MediaFailed;
  64.             Player.NewAllocatorFrame += Player_NewAllocatorFrame;
  65.             Player.NewAllocatorSurface += Player_NewAllocatorSurface;
  66.  
  67.             Player.Dispatcher.BeginInvoke(new Action(() =>
  68.             {
  69.                 Player.AudioDecoder = null;
  70.                 Player.AudioRenderer = null;
  71.                 Player.Source = source;
  72.             }));
  73.  
  74.             return taskCompletionOpen.Task;
  75.         }
  76.  
  77.         /// <summary>
  78.         /// Grab a buffer at given position [sec].
  79.         /// See <see cref="GrabAtPosition(long)"/>.
  80.         /// </summary>
  81.         public Task<IntPtr> GrabAtSecond(double second)
  82.             => GrabAtPosition((long)(second * MediaPlayerBase.DSHOW_ONE_SECOND_UNIT));
  83.  
  84.         /// <summary>
  85.         /// Grab a buffer at given position.
  86.         /// </summary>
  87.         /// <param name="position">Video position in 100ns units.</param>
  88.         /// <param name="cancellationToken">CancellationToken, may be used for timeout.</param>
  89.         /// <returns>Buffer for D3DImage.</returns>
  90.         public Task<IntPtr> GrabAtPosition(long position, CancellationToken cancellationToken = default(CancellationToken))
  91.         {
  92.             CheckPlayer();
  93.             if (taskCompletionGrab != null)
  94.                 throw new InvalidOperationException("Still grabbing previous frame.");
  95.             if (position < 0)
  96.                 throw new ArgumentException("position negative.");
  97.             if (position > MediaDuration)
  98.                 throw new ArgumentException("position beyond the media duration.");
  99.  
  100.             taskCompletionGrab = new TaskCompletionSource<IntPtr>();
  101.             cancellationRegistrationGrab = cancellationToken.Register(CancelGrab);
  102.             Player.Dispatcher.BeginInvoke(new Action(() =>
  103.             {
  104.                 Player.MediaPosition = position;
  105.                 Player.Pause();
  106.             }));
  107.  
  108.             return taskCompletionGrab.Task;
  109.         }
  110.  
  111.         public void CancelGrab()
  112.         {
  113.             taskCompletionGrab?.TrySetCanceled();
  114.             taskCompletionGrab = null;
  115.             cancellationRegistrationGrab.Dispose();
  116.         }
  117.  
  118.         private void CheckPlayer()
  119.         {
  120.             if (Player == null)
  121.                 throw new InvalidOperationException("Player not opened, call Open() first.");
  122.         }
  123.  
  124.         private void MediaUriPlayer_MediaFailed(object sender, MediaFailedEventArgs e)
  125.         {
  126.             Exception exc = e.Exception;
  127.             if (exc == null)
  128.                 exc = new WPFMediaKit.WPFMediaKitException(e.Message);
  129.             taskCompletionOpen.TrySetException(exc);
  130.         }
  131.  
  132.         private void MediaUriPlayer_MediaOpened()
  133.             => taskCompletionOpen.TrySetResult(true);
  134.  
  135.         private void Player_NewAllocatorSurface(object sender, IntPtr pSurface)
  136.             => BackBuffer = pSurface;
  137.  
  138.         private void Player_NewAllocatorFrame()
  139.         {
  140.             if (taskCompletionGrab == null)
  141.                 return;
  142.             taskCompletionGrab.TrySetResult(BackBuffer);
  143.             // not exactly thread safe, but do the job in common scenarios
  144.             taskCompletionGrab = null;
  145.         }
  146.  
  147.         public void Dispose()
  148.         {
  149.             Dispose(true);
  150.         }
  151.  
  152.         protected virtual void Dispose(bool disposing)
  153.         {
  154.             if (!disposing)
  155.                 return;
  156.             CancelGrab();
  157.             if (Player != null)
  158.             {
  159.                 Player.Dispose();
  160.                 Player = null;
  161.             }
  162.         }
  163.     }
  164.  
  165.     /// <summary>
  166.     /// Helper class for one time frame grabbing.
  167.     /// </summary>
  168.     public static class VideoScreenGrabberUtils
  169.     {
  170.         private const int TIMEOUT_MS = 5000;
  171.  
  172.         /// <summary>
  173.         /// Grab a D3DImage with timeout.
  174.         /// </summary>
  175.         /// <param name="source">Video source Uri.</param>
  176.         /// <param name="position">Position in DSHOW_ONE_SECOND_UNIT units.</param>
  177.         /// <param name="timeout">Timeout in millis. If zero, then wait infinitely.</param>
  178.         /// <returns>Created D3DImage.</returns>
  179.         /// <exception cref="TimeoutException">When the opearion has timeed out.</exception>
  180.         public static async Task<D3DImage> GrabScreenAtPosition(Uri source, long position, int timeout = TIMEOUT_MS)
  181.         {
  182.             using (VideoScreenGrabber grabber = new VideoScreenGrabber())
  183.             {
  184.                 await grabber.Open(source);
  185.                 long duration = grabber.MediaDuration;
  186.                 // if the video is too short, grab the screen at half
  187.                 if (position > duration - (MediaPlayerBase.DSHOW_ONE_SECOND_UNIT / 2))
  188.                     position = duration / 2;
  189.                 IntPtr buffer;
  190.                 if (timeout > 0)
  191.                 {
  192.                     try
  193.                     {
  194.                         buffer = await grabber.GrabAtPosition(position, new CancellationTokenSource(timeout).Token);
  195.                     }
  196.                     catch (TaskCanceledException)
  197.                     {
  198.                         throw new TimeoutException("The operation has timed-out.");
  199.                     }
  200.                 }
  201.                 else
  202.                 {
  203.                     buffer = await grabber.GrabAtPosition(position);
  204.                 }
  205.                 D3DImage d3d = new D3DImage();
  206.                 D3DImageUtils.SetBackBufferWithLock(d3d, buffer);
  207.                 return d3d;
  208.             }
  209.         }
  210.     }
  211. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top