mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-21 18:52:36 +01:00
MPV support for linux first imlementation.
This commit is contained in:
parent
a091491c35
commit
13d870bdd3
1
.gitignore
vendored
1
.gitignore
vendored
@ -32,3 +32,4 @@ SubtitleEdit-*-setup.exe
|
||||
/src/SubtitleEdit.VC.opendb
|
||||
/src/SubtitleEdit.VC.VC.opendb
|
||||
/src/SubtitleEdit.VC.db
|
||||
/src/SubtitleEdit.userprefs
|
@ -668,7 +668,7 @@ namespace Nikse.SubtitleEdit.Core
|
||||
OpenSubtitleExtraExtensions = "*.mp4;*.m4v;*.mkv;*.ts"; // matroska/mp4/m4v files (can contain subtitles)
|
||||
ListViewColumnsRememberSize = true;
|
||||
VlcWaveTranscodeSettings = "acodec=s16l"; // "acodec=s16l,channels=1,ab=64,samplerate=8000";
|
||||
MpvVideoOutput = "direct3d_shaders"; // mpv "vo" option
|
||||
MpvVideoOutput = "vaapi"; // mpv "vo" option
|
||||
UseTimeFormatHHMMSSFF = false;
|
||||
ClearStatusBarAfterSeconds = 10;
|
||||
MoveVideo100Or500MsPlaySmallSample = false;
|
||||
|
@ -2327,7 +2327,10 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private void RefreshMpvSettings()
|
||||
{
|
||||
radioButtonVideoPlayerMPV.Enabled = LibMpvDynamic.IsInstalled;
|
||||
labelMpvSettings.Text = "--vo=" + Configuration.Settings.General.MpvVideoOutput;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
labelMpvSettings.Text = "--vo=" + Configuration.Settings.General.MpvVideoOutput;
|
||||
else
|
||||
labelMpvSettings.Text = "--vo=vaapi";
|
||||
}
|
||||
|
||||
private void linkLabelBingSubscribe_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
|
45
src/Forms/SettingsMpv.Designer.cs
generated
45
src/Forms/SettingsMpv.Designer.cs
generated
@ -1,5 +1,7 @@
|
||||
namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
using Nikse.SubtitleEdit.Core;
|
||||
|
||||
sealed partial class SettingsMpv
|
||||
{
|
||||
/// <summary>
|
||||
@ -38,23 +40,37 @@
|
||||
//
|
||||
// buttonDownload
|
||||
//
|
||||
this.buttonDownload.Location = new System.Drawing.Point(12, 24);
|
||||
this.buttonDownload.Name = "buttonDownload";
|
||||
this.buttonDownload.Size = new System.Drawing.Size(186, 23);
|
||||
this.buttonDownload.TabIndex = 0;
|
||||
this.buttonDownload.Text = "Download mpv dll";
|
||||
this.buttonDownload.UseVisualStyleBackColor = true;
|
||||
this.buttonDownload.Click += new System.EventHandler(this.buttonDownload_Click_1);
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
{
|
||||
this.buttonDownload.Location = new System.Drawing.Point(12, 24);
|
||||
this.buttonDownload.Name = "buttonDownload";
|
||||
this.buttonDownload.Size = new System.Drawing.Size(186, 23);
|
||||
this.buttonDownload.TabIndex = 0;
|
||||
this.buttonDownload.Text = "Download mpv dll";
|
||||
this.buttonDownload.UseVisualStyleBackColor = true;
|
||||
this.buttonDownload.Click += new System.EventHandler(this.buttonDownload_Click_1);
|
||||
}
|
||||
//
|
||||
// comboBoxVideoOutput
|
||||
//
|
||||
this.comboBoxVideoOutput.FormattingEnabled = true;
|
||||
this.comboBoxVideoOutput.Items.AddRange(new object[] {
|
||||
"direct3d_shaders",
|
||||
"direct3d ",
|
||||
"sdl",
|
||||
"vaapi",
|
||||
"vdpau"});
|
||||
if (Configuration.IsRunningOnLinux())
|
||||
{
|
||||
this.comboBoxVideoOutput.Items.AddRange(new object[] {
|
||||
"sdl",
|
||||
"vaapi",
|
||||
"vdpau"});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.comboBoxVideoOutput.Items.AddRange(new object[] {
|
||||
"direct3d_shaders",
|
||||
"direct3d ",
|
||||
"sdl",
|
||||
"vaapi",
|
||||
"vdpau"});
|
||||
}
|
||||
|
||||
this.comboBoxVideoOutput.Location = new System.Drawing.Point(12, 109);
|
||||
this.comboBoxVideoOutput.Name = "comboBoxVideoOutput";
|
||||
this.comboBoxVideoOutput.Size = new System.Drawing.Size(186, 21);
|
||||
@ -113,7 +129,8 @@
|
||||
this.Controls.Add(this.buttonCancel);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.comboBoxVideoOutput);
|
||||
this.Controls.Add(this.buttonDownload);
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
this.Controls.Add(this.buttonDownload);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.KeyPreview = true;
|
||||
this.MaximizeBox = false;
|
||||
|
@ -13,11 +13,15 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
InitializeComponent();
|
||||
labelPleaseWait.Text = string.Empty;
|
||||
comboBoxVideoOutput.Text = Configuration.Settings.General.MpvVideoOutput;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
comboBoxVideoOutput.Text = Configuration.Settings.General.MpvVideoOutput;
|
||||
else
|
||||
comboBoxVideoOutput.Text = "vaapi";
|
||||
buttonCancel.Text = Configuration.Settings.Language.General.Cancel;
|
||||
buttonOK.Text = Configuration.Settings.Language.General.Ok;
|
||||
Text = Configuration.Settings.Language.SettingsMpv.Title;
|
||||
buttonDownload.Text = Configuration.Settings.Language.SettingsMpv.DownloadMpv;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
buttonDownload.Text = Configuration.Settings.Language.SettingsMpv.DownloadMpv;
|
||||
}
|
||||
|
||||
private void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
|
||||
@ -27,7 +31,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
MessageBox.Show(Configuration.Settings.Language.SettingsMpv.DownloadMpvFailed);
|
||||
labelPleaseWait.Text = string.Empty;
|
||||
buttonOK.Enabled = true;
|
||||
buttonDownload.Enabled = true;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
buttonDownload.Enabled = true;
|
||||
Cursor = Cursors.Default;
|
||||
return;
|
||||
}
|
||||
@ -53,7 +58,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
Cursor = Cursors.Default;
|
||||
labelPleaseWait.Text = string.Empty;
|
||||
buttonOK.Enabled = true;
|
||||
buttonDownload.Enabled = true;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
buttonDownload.Enabled = true;
|
||||
MessageBox.Show(Configuration.Settings.Language.SettingsMpv.DownloadMpvOk);
|
||||
}
|
||||
|
||||
@ -63,7 +69,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
labelPleaseWait.Text = Configuration.Settings.Language.General.PleaseWait;
|
||||
buttonOK.Enabled = false;
|
||||
buttonDownload.Enabled = false;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
buttonDownload.Enabled = false;
|
||||
Refresh();
|
||||
Cursor = Cursors.WaitCursor;
|
||||
|
||||
@ -80,7 +87,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
labelPleaseWait.Text = string.Empty;
|
||||
buttonOK.Enabled = true;
|
||||
buttonDownload.Enabled = true;
|
||||
if (!Configuration.IsRunningOnLinux())
|
||||
buttonDownload.Enabled = true;
|
||||
Cursor = Cursors.Default;
|
||||
MessageBox.Show(exception.Message + Environment.NewLine + Environment.NewLine + exception.StackTrace);
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
GeneralSettings gs = Configuration.Settings.General;
|
||||
|
||||
if (Configuration.IsRunningOnLinux())
|
||||
return new MPlayer();
|
||||
return new LibMpvMono();
|
||||
|
||||
// Mono on OS X is 32 bit and thus requires 32 bit VLC. Place VLC in the same
|
||||
// folder as Subtitle Edit and add this to the app.config inside the
|
||||
|
431
src/Logic/VideoPlayers/LibMpvMono.cs
Normal file
431
src/Logic/VideoPlayers/LibMpvMono.cs
Normal file
@ -0,0 +1,431 @@
|
||||
using Nikse.SubtitleEdit.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Nikse.SubtitleEdit.Core.SubtitleFormats;
|
||||
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.VideoPlayers
|
||||
{
|
||||
public class LibMpvMono : VideoPlayer, IDisposable
|
||||
{
|
||||
|
||||
|
||||
#region mpv dll methods
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr mpv_create();
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_initialize(IntPtr mpvHandle);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_command(IntPtr mpvHandle, IntPtr utf8Strings);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_terminate_destroy(IntPtr mpvHandle);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr mpv_wait_event(IntPtr mpvHandle, double wait);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_set_option(IntPtr mpvHandle, byte[] name, int format, ref long data);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_set_option_string(IntPtr mpvHandle, byte[] name, byte[] value);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr mpv_get_property_string(IntPtr mpvHandle, byte[] name);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, int format, ref double data);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, int format, ref byte[] data);
|
||||
|
||||
|
||||
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int mpv_free(IntPtr data);
|
||||
|
||||
#endregion
|
||||
|
||||
private IntPtr _libMpvDll;
|
||||
private IntPtr _mpvHandle;
|
||||
private Timer _videoLoadedTimer;
|
||||
// private Timer _videoEndedTimer;
|
||||
|
||||
public override event EventHandler OnVideoLoaded;
|
||||
public override event EventHandler OnVideoEnded;
|
||||
|
||||
private const int MpvFormatString = 1;
|
||||
|
||||
private object GetDllType(Type type, string name)
|
||||
{
|
||||
IntPtr address = NativeMethods.GetProcAddress(_libMpvDll, name);
|
||||
if (address != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer(address, type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static byte[] GetUtf8Bytes(string s)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(s + "\0");
|
||||
}
|
||||
|
||||
public static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
|
||||
{
|
||||
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
|
||||
byteArrayPointers = new IntPtr[numberOfStrings];
|
||||
IntPtr rootPointer = Marshal.AllocCoTaskMem(IntPtr.Size * numberOfStrings);
|
||||
for (int index = 0; index < arr.Length; index++)
|
||||
{
|
||||
var bytes = GetUtf8Bytes(arr[index]);
|
||||
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
|
||||
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
|
||||
byteArrayPointers[index] = unmanagedPointer;
|
||||
}
|
||||
Marshal.Copy(byteArrayPointers, 0, rootPointer, numberOfStrings);
|
||||
return rootPointer;
|
||||
}
|
||||
|
||||
private void DoMpvCommand(params string[] args)
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
IntPtr[] byteArrayPointers;
|
||||
var mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out byteArrayPointers);
|
||||
mpv_command(_mpvHandle, mainPtr);
|
||||
foreach (var ptr in byteArrayPointers)
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
Marshal.FreeHGlobal(mainPtr);
|
||||
}
|
||||
|
||||
public override string PlayerName
|
||||
{
|
||||
get { return "MPV Player"; }
|
||||
}
|
||||
|
||||
private int _volume = 75;
|
||||
public override int Volume
|
||||
{
|
||||
get
|
||||
{
|
||||
return _volume;
|
||||
}
|
||||
set
|
||||
{
|
||||
DoMpvCommand("set", "volume", value.ToString());
|
||||
_volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override double Duration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return 0;
|
||||
|
||||
int mpvFormatDouble = 5;
|
||||
double d = 0;
|
||||
mpv_get_property(_mpvHandle, GetUtf8Bytes("duration"), mpvFormatDouble, ref d);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
public override double CurrentPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return 0;
|
||||
|
||||
int mpvFormatDouble = 5;
|
||||
double d = 0;
|
||||
mpv_get_property(_mpvHandle, GetUtf8Bytes("time-pos"), mpvFormatDouble, ref d);
|
||||
return d;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
DoMpvCommand("seek", value.ToString(CultureInfo.InvariantCulture), "absolute");
|
||||
}
|
||||
}
|
||||
|
||||
private double _playRate = 2.0;
|
||||
public override double PlayRate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _playRate;
|
||||
}
|
||||
set
|
||||
{
|
||||
DoMpvCommand("set", "speed", value.ToString(CultureInfo.InvariantCulture));
|
||||
_playRate = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetNextFrame()
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
DoMpvCommand("frame-step");
|
||||
}
|
||||
|
||||
public void GetPreviousFrame()
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
DoMpvCommand("frame-back-step");
|
||||
}
|
||||
|
||||
public override void Play()
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
var bytes = GetUtf8Bytes("no");
|
||||
mpv_set_property(_mpvHandle, GetUtf8Bytes("pause"), MpvFormatString, ref bytes);
|
||||
}
|
||||
|
||||
public override void Pause()
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
var bytes = GetUtf8Bytes("yes");
|
||||
mpv_set_property(_mpvHandle, GetUtf8Bytes("pause"), MpvFormatString, ref bytes);
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
Pause();
|
||||
CurrentPosition = 0;
|
||||
}
|
||||
|
||||
public override bool IsPaused
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mpvHandle == IntPtr.Zero)
|
||||
return true;
|
||||
|
||||
var lpBuffer = mpv_get_property_string(_mpvHandle, GetUtf8Bytes("pause"));
|
||||
string s = Marshal.PtrToStringAnsi(lpBuffer);
|
||||
bool isPaused = s == "yes";
|
||||
mpv_free(lpBuffer);
|
||||
return isPaused;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsPlaying
|
||||
{
|
||||
get { return !IsPaused; }
|
||||
}
|
||||
|
||||
private List<string> _audioTrackIds;
|
||||
public int AudioTrackCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_audioTrackIds == null)
|
||||
{
|
||||
_audioTrackIds = new List<string>();
|
||||
var lpBuffer = mpv_get_property_string(_mpvHandle, GetUtf8Bytes("track-list"));
|
||||
string trackListJson = Marshal.PtrToStringAnsi(lpBuffer);
|
||||
foreach (var json in Json.ReadObjectArray(trackListJson))
|
||||
{
|
||||
string trackType = Json.ReadTag(json, "type");
|
||||
string id = Json.ReadTag(json, "id");
|
||||
if (trackType == "audio")
|
||||
{
|
||||
_audioTrackIds.Add(id);
|
||||
}
|
||||
}
|
||||
mpv_free(lpBuffer);
|
||||
}
|
||||
return _audioTrackIds.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public int AudioTrackNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
var lpBuffer = mpv_get_property_string(_mpvHandle, GetUtf8Bytes("aid"));
|
||||
string str = Marshal.PtrToStringAnsi(lpBuffer);
|
||||
int number = 0;
|
||||
if (AudioTrackCount > 1 && _audioTrackIds.Contains(str))
|
||||
{
|
||||
number = _audioTrackIds.IndexOf(str);
|
||||
}
|
||||
mpv_free(lpBuffer);
|
||||
return number;
|
||||
}
|
||||
set
|
||||
{
|
||||
string id = "1";
|
||||
if (AudioTrackCount > 1 && value >= 0 && value < _audioTrackIds.Count)
|
||||
{
|
||||
id = _audioTrackIds[value];
|
||||
}
|
||||
DoMpvCommand("set", "aid", id);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsInstalled
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetMpvPath(string fileName)
|
||||
{
|
||||
var path = Path.Combine(Configuration.DataDirectory, fileName);
|
||||
if (File.Exists(path))
|
||||
return path;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Initialize(Control ownerControl, string videoFileName, EventHandler onVideoLoaded, EventHandler onVideoEnded)
|
||||
{
|
||||
_mpvHandle = mpv_create();
|
||||
OnVideoLoaded = onVideoLoaded;
|
||||
OnVideoEnded = onVideoEnded;
|
||||
|
||||
if (!string.IsNullOrEmpty(videoFileName))
|
||||
{
|
||||
//Mono.Unix.
|
||||
mpv_initialize(_mpvHandle);
|
||||
|
||||
string videoOutput = "vaapi";
|
||||
if (!string.IsNullOrWhiteSpace(Configuration.Settings.General.MpvVideoOutput))
|
||||
videoOutput = Configuration.Settings.General.MpvVideoOutput;
|
||||
mpv_set_option_string(_mpvHandle, GetUtf8Bytes("vo"), GetUtf8Bytes(videoOutput)); // "direct3d_shaders" is default, "direct3d" could be used for compabality with old systems
|
||||
|
||||
mpv_set_option_string(_mpvHandle, GetUtf8Bytes("keep-open"), GetUtf8Bytes("always")); // don't auto close video
|
||||
mpv_set_option_string(_mpvHandle, GetUtf8Bytes("no-sub"), GetUtf8Bytes("")); // don't load subtitles
|
||||
if (ownerControl != null)
|
||||
{
|
||||
int mpvFormatInt64 = 4;
|
||||
var windowId = ownerControl.Handle.ToInt64();
|
||||
mpv_set_option(_mpvHandle, GetUtf8Bytes("wid"), mpvFormatInt64, ref windowId);
|
||||
}
|
||||
DoMpvCommand("loadfile", videoFileName);
|
||||
|
||||
_videoLoadedTimer = new Timer { Interval = 50 };
|
||||
_videoLoadedTimer.Tick += VideoLoadedTimer_Tick;
|
||||
_videoLoadedTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void VideoLoadedTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
_videoLoadedTimer.Stop();
|
||||
const int mpvEventFileLoaded = 8;
|
||||
int l = 0;
|
||||
while (l < 10000)
|
||||
{
|
||||
Application.DoEvents();
|
||||
try
|
||||
{
|
||||
if (_mpvHandle != IntPtr.Zero)
|
||||
{
|
||||
var eventIdHandle = mpv_wait_event(_mpvHandle, 0);
|
||||
var eventId = Convert.ToInt64(Marshal.PtrToStructure(eventIdHandle, typeof(int)));
|
||||
if (eventId == mpvEventFileLoaded)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
l++;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
Application.DoEvents();
|
||||
if (OnVideoLoaded != null)
|
||||
OnVideoLoaded.Invoke(this, null);
|
||||
Application.DoEvents();
|
||||
Pause();
|
||||
}
|
||||
|
||||
|
||||
public override void DisposeVideoPlayer()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void ReleaseUnmangedResources()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_mpvHandle != IntPtr.Zero)
|
||||
{
|
||||
mpv_terminate_destroy(_mpvHandle);
|
||||
_mpvHandle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (_libMpvDll != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.FreeLibrary(_libMpvDll);
|
||||
_libMpvDll = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
~LibMpvMono()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_mpvHandle != IntPtr.Zero)
|
||||
DoMpvCommand("quit");
|
||||
ReleaseUnmangedResources();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -378,7 +378,7 @@ namespace Nikse.SubtitleEdit.Logic.VideoPlayers
|
||||
{
|
||||
_mpvInitialize.Invoke(_mpvHandle);
|
||||
|
||||
string videoOutput = "direct3d_shaders";
|
||||
string videoOutput = "vaapi";
|
||||
if (!string.IsNullOrWhiteSpace(Configuration.Settings.General.MpvVideoOutput))
|
||||
videoOutput = Configuration.Settings.General.MpvVideoOutput;
|
||||
_mpvSetOptionString(_mpvHandle, GetUtf8Bytes("vo"), GetUtf8Bytes(videoOutput)); // "direct3d_shaders" is default, "direct3d" could be used for compabality with old systems
|
||||
|
@ -866,6 +866,7 @@
|
||||
<Compile Include="Logic\UiGetPacEncoding.cs" />
|
||||
<Compile Include="Logic\UiGetYouTubeAnnotationStyles.cs" />
|
||||
<Compile Include="Logic\UiUtil.cs" />
|
||||
<Compile Include="Logic\VideoPlayers\LibMpvMono.cs" />
|
||||
<Compile Include="Logic\VideoPlayers\LibMpvDynamic.cs" />
|
||||
<Compile Include="Logic\VideoPlayers\LibVlcDynamic.cs" />
|
||||
<Compile Include="Logic\VideoPlayers\LibVlcMono.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user