| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- using Accord;
- using Accord.Video.FFMPEG;
- using Ionic.Zip;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Imaging;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- namespace Funscripta
- {
- public partial class Unpack_Manager : Form
- {
- private static List<PackThread> PackThreads { get; set; } = new List<PackThread>();
- private OpenFileDialog ofd = new OpenFileDialog();
- private List<string> Videos = new List<string>();
-
-
- public Unpack_Manager()
- {
- InitializeComponent();
- ofd.Filter = "Media Files|*.mpg;*.avi;*.mov;*.mp4;*.flv|All Files|*.*";
- ofd.DefaultExt = ".mp4";
- ofd.Multiselect = true;
- listView1.DrawColumnHeader += listView1_DrawColumnHeader;
- listView1.DrawItem += ListView1_DrawItem;
- listView1.DrawSubItem += ListView1_DrawSubItem;
- foreach ( var thread in PackThreads )
- {
- var lvi = new ListViewItem( thread.Video.Name );
- thread.Item = lvi;
- listView1.Items.Add( lvi );
- Videos.Add( thread.Video.FullName );
- }
- }
-
- private void ListView1_DrawSubItem( object sender, DrawListViewSubItemEventArgs e )
- {
- TextFormatFlags flags = TextFormatFlags.Left;
-
- using ( StringFormat sf = new StringFormat() )
- {
- // Store the column text alignment, letting it default
- // to Left if it has not been set to Center or Right.
- switch ( e.Header.TextAlign )
- {
- case HorizontalAlignment.Center:
- sf.Alignment = StringAlignment.Center;
- flags = TextFormatFlags.HorizontalCenter;
- break;
- case HorizontalAlignment.Right:
- sf.Alignment = StringAlignment.Far;
- flags = TextFormatFlags.Right;
- break;
- }
-
- // Draw the text and background for a subitem with a
- // negative value.
- double subItemValue;
- if ( e.ColumnIndex > 0 && Double.TryParse(
- e.SubItem.Text, NumberStyles.Currency,
- NumberFormatInfo.CurrentInfo, out subItemValue ) &&
- subItemValue < 0 )
- {
- // Unless the item is selected, draw the standard
- // background to make it stand out from the gradient.
- if ( ( e.ItemState & ListViewItemStates.Selected ) == 0 )
- {
- e.DrawBackground();
- }
-
- // Draw the subitem text in red to highlight it.
- e.Graphics.DrawString( e.SubItem.Text,
- listView1.Font, Brushes.Red, e.Bounds, sf );
-
- return;
- }
-
- // Draw normal text for a subitem with a nonnegative
- // or nonnumerical value.
- e.DrawText( flags );
- }
- }
-
- private void ListView1_DrawItem( object sender, DrawListViewItemEventArgs e )
- {
- if ( ( e.State & ListViewItemStates.Selected ) != 0 )
- {
- // Draw the background and focus rectangle for a selected item.
- e.Graphics.FillRectangle( Brushes.DarkBlue, e.Bounds );
- e.DrawFocusRectangle();
- }
- else
- {
- // Draw the background for an unselected item.
- using ( LinearGradientBrush brush =
- new LinearGradientBrush( e.Bounds, Color.DarkBlue,
- Color.DarkGreen, LinearGradientMode.Horizontal ) )
- {
- e.Graphics.FillRectangle( brush, e.Bounds );
- }
- }
-
- // Draw the item text for views other than the Details view.
- if ( listView1.View != View.Details )
- {
- e.DrawText();
- }
- }
-
- private void listView1_DrawColumnHeader( object sender, DrawListViewColumnHeaderEventArgs e )
- {
- var strFormat = new StringFormat();
-
-
- if ( e.Header.TextAlign == HorizontalAlignment.Center )
- strFormat.Alignment = StringAlignment.Center;
- else if ( e.Header.TextAlign == HorizontalAlignment.Right )
- strFormat.Alignment = StringAlignment.Far;
-
- e.DrawBackground();
- e.Graphics.FillRectangle( new SolidBrush( Color.FromArgb( 65, 65, 65 ) ), e.Bounds );
- e.Graphics.DrawLine( new Pen( Color.White ), new PointF( e.Bounds.Width + e.Bounds.X - 1, 0 ), new PointF( e.Bounds.Width + e.Bounds.X - 1, e.Bounds.Height ) );
- var headerFont = new Font( "Arial", 8, FontStyle.Bold );
-
- e.Graphics.DrawString( e.Header.Text, headerFont, Brushes.White, e.Bounds, strFormat );
- }
- private void timer1_Tick( object sender, EventArgs e )
- {
- if ( !backgroundWorker1.IsBusy ) backgroundWorker1.RunWorkerAsync();
- }
-
- public class PackThread : IDisposable
- {
- private bool _frozen = true;
-
- private Task Task { get; set; }
- public bool Frozen { get => _frozen; set {
- if ( Frozen == value || Done ) return;
- if ( value ) Freezing = true;
- if ( !value && Task.Status != TaskStatus.Running ) Task.Start();
- _frozen = value;
- } }
- public bool Freezing { get; private set; }
- public bool Done { get; private set; } = false;
-
- public FileInfo Video { get; set; }
- private DirectoryInfo Raw { get; set; }
- private FileInfo RawCompressed { get; set; }
- private VideoFileReader VFR { get; set; }
- private ZipFile Zip { get; set; }
- public ListViewItem Item { get; set; }
-
- public int CurrentFrame { get; private set; }
- public long MaxFrames => VFR.FrameCount;
- public float Progress => ( ( float ) CurrentFrame ) / MaxFrames * 100;
- public float ElementsPerSecond => ElementsPerSeconds.Count > 0 ? ElementsPerSeconds.Average() : 0;
- private Buffer<float> ElementsPerSeconds { get; set; } = new Buffer<float>( 10 );
- public string TimeLeft => ElementsPerSecond <= 0 ? "infinite" : TimeSpan.FromSeconds( ( MaxFrames - CurrentFrame ) / ElementsPerSecond ).ToString( @"hh\:mm\:ss" );
-
- private static readonly DateTime Jan1st1970 = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );
-
- public static long CurrentTimeMillis()
- {
- return ( long ) ( DateTime.UtcNow - Jan1st1970 ).TotalMilliseconds;
- }
-
- public PackThread( FileInfo video )
- {
- Video = video;
- var stripped = Video.FullName.Substring( 0, Video.FullName.Length - Video.Extension.Length );
- Raw = new DirectoryInfo( $"{ stripped }.raw" );
- RawCompressed = new FileInfo( $"{ stripped }.rawc" );
- VFR = new VideoFileReader();
- VFR.Open( video.FullName );
- Zip = new ZipFile( RawCompressed.FullName );
-
- Task = new Task( () => {
- if ( !Raw.Exists ) Raw.Create();
- while( true )
- {
- if ( Frozen )
- {
- Freezing = false;
- return;
- }
- // Zip.Save( RawCompressed.FullName );
- var timestamp = CurrentTimeMillis();
- Bitmap bmp = VFR.ReadVideoFrame();
- CurrentFrame++;
- if ( bmp == null )
- {
- Zip.Save();
- Done = true;
- _frozen = true;
- return;
- }
- //var ms = new MemoryStream();
- bmp.Save( $"{ Raw.FullName }/{ CurrentFrame }", ImageFormat.Jpeg );
- //Zip.AddEntry( CurrentFrame.ToString(), ms );
- bmp.Dispose();
- var dif = CurrentTimeMillis() - timestamp;
- if ( dif != 0 )
- {
- //ElementsPerSecond = 1000F / dif;
- ElementsPerSeconds.Add( 1000F / dif );
- }
- }
- } );
- }
- public PackThread( string video ) : this( new FileInfo( video ) )
- {
- }
-
- public void Dispose()
- {
- // VFR.Dispose();
- Zip.Dispose();
- }
- }
-
- private void backgroundWorker1_DoWork( object sender, DoWorkEventArgs e )
- {
- if ( PackThreads.Count <= 0 ) return;
- var active = 0;
- var maxActive = maxActiveThreads.Value;
- try
- {
- foreach ( var thread in PackThreads )
- {
- listView1.MayInvoke( () => {
- for ( var i = thread.Item.SubItems.Count; i < 5; i++ ) thread.Item.SubItems.Add( "" );
- thread.Item.SubItems[ 1 ].Text = $"{ thread.Progress.DecimalStrip() } %";
- thread.Item.SubItems[ 2 ].Text = $"{ thread.CurrentFrame } / { thread.MaxFrames }";
- thread.Item.SubItems[ 3 ].Text = $"{ thread.ElementsPerSecond.DecimalStrip() } items/s";
- } );
- if ( thread.Done )
- {
- PackThreads.Remove( thread );
- Videos.Remove( thread.Video.FullName );
- listView1.MayInvoke( () => thread.Item.SubItems[ 4 ].Text = "Done" );
- thread.Dispose();
- }
- else
- {
- if ( !thread.Frozen )
- {
- if ( active < maxActive ) active++;
- else thread.Frozen = true;
- }
- listView1.MayInvoke( () => thread.Item.SubItems[ 4 ].Text = $"{ thread.TimeLeft }" );
- }
- }
- if ( active < maxActive )
- {
- foreach ( var thread in PackThreads )
- {
- if ( thread.Frozen && active < maxActive )
- {
- thread.Frozen = false;
- active++;
- }
- else if ( active >= maxActive ) break;
- }
- }
- } catch ( Exception ex )
- {
-
- }
- // listView1.MayInvoke( () => listView1.Refresh() );
- }
-
- private void button1_Click( object sender, EventArgs e )
- {
- if ( ofd.ShowDialog() == DialogResult.OK )
- {
- foreach( var file in ofd.FileNames )
- {
- var f = new FileInfo( file );
- if ( Videos.Contains( f.FullName ) ) continue;
- var thread = new PackThread( f );
- var lvi = new ListViewItem( f.Name );
- thread.Item = lvi;
- PackThreads.Add( thread );
- listView1.Items.Add( lvi );
- Videos.Add( f.FullName );
- }
- }
- }
-
- private void button2_Click( object sender, EventArgs e )
- {
- foreach( ListViewItem lvi in listView1.SelectedItems )
- {
- var thread = Find( lvi );
- if ( thread == null ) continue;
- PackThreads.Remove( thread );
- if ( !thread.Frozen ) thread.Frozen = true;
- Videos.Remove( thread.Video.FullName );
- thread.Dispose();
- lvi.SubItems[ 4 ].Text = "Canceled";
- }
- }
-
- private PackThread Find( ListViewItem lvi )
- {
- PackThread _thread = null;
- foreach( var thread in PackThreads )
- {
- if ( thread.Item == lvi ) _thread = thread;
- }
- return _thread;
- }
-
- public class Buffer<T> : Queue<T>
- {
- private int? maxCapacity { get; set; }
-
- public Buffer() { maxCapacity = null; }
- public Buffer( int capacity ) { maxCapacity = capacity; }
-
- public void Add( T newElement )
- {
- if ( this.Count == ( maxCapacity ?? -1 ) ) this.Dequeue(); // no limit if maxCapacity = null
- this.Enqueue( newElement );
- }
- }
- }
- }
|