Registra video con Accord.net (AForge)

Ho usato Accord.net (AForge) per collegarmi alla webcam e registrare video, ma i video salvati sono al rallentatore … questo è il mio progetto:

using AForge.Video; using AForge.Video.DirectShow; using AForge.Video.FFMPEG; using System; using System.Drawing; using System.IO; using System.Threading; using System.Windows.Forms; namespace CaptureWebcam { public partial class Form1 : Form { private VideoCaptureDeviceForm captureDevice; private string path = Path.GetDirectoryName(Application.ExecutablePath) + @"\Videos\"; private FilterInfoCollection videoDevice; private VideoCaptureDevice videoSource; private VideoFileWriter FileWriter = new VideoFileWriter(); private Bitmap video; bool isRecord = false; public Form1() { InitializeComponent(); } private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs) { video = (Bitmap)eventArgs.Frame.Clone(); pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone(); } private void btnStartCam_Click(object sender, EventArgs e) { videoDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice); captureDevice = new VideoCaptureDeviceForm(); if (captureDevice.ShowDialog(this) == DialogResult.OK) { videoSource = captureDevice.VideoDevice; videoSource = captureDevice.VideoDevice; videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame); videoSource.Start(); timer1.Enabled = true; } //videoSource.DisplayPropertyPage(IntPtr.Zero); } private Thread workerThread = null; private bool stopProcess = false; private void recordLiveCam() { if (!stopProcess) { while (isRecord) { FileWriter.WriteVideoFrame(video); } FileWriter.Close(); } else { workerThread.Abort(); } } private void btnRecord_Click(object sender, EventArgs e) { //try //{ isRecord = true; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height; int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width; FileWriter.Open(path + "recorded at " + DateTime.Now.ToString("HH-mm-ss") + ".mp4", w, h, 25, VideoCodec.MPEG4); stopProcess = false; workerThread = new Thread(new ThreadStart(recordLiveCam)); workerThread.Start(); //} //catch (Exception ex) //{ // MessageBox.Show(ex.Message); //} } private void Form1_Load(object sender, EventArgs e) { } private void btnStopRecord_Click(object sender, EventArgs e) { stopProcess = true; isRecord = false; FileWriter.Close(); workerThread.Abort(); video = null; } private void btnStopCam_Click(object sender, EventArgs e) { try { if (videoSource.IsRunning) { videoSource.SignalToStop(); videoSource.Stop(); pictureBox1.Image = null; pictureBox1.Invalidate(); if (FileWriter.IsOpen) { FileWriter.Close(); video = null; } } else return; } catch { videoSource.Stop(); FileWriter.Close(); video = null; } } float fts = 0.0f; private void timer1_Tick(object sender, EventArgs e) { fts = videoSource.FramesReceived; label1.Text = "Frame Rate : " + fts.ToString("F2") + " fps"; } } } 

E quando fai clic sul seguente errore btnStopRecord:

Ulteriori informazioni: Tentativo di leggere o scrivere memoria protetta. Questo è spesso un’indicazione che un’altra memoria è corrotta.

    “Slow motion” può avere più motivi. Per prima cosa è necessario sapere se il framerate effettivo, al quale i NewFrames vengono generati, è così lento (quanti HZ allora?) O se la CPU è troppo occupata. O forse la scheda grafica.

    Per tutto ciò che riguarda DirectShow, suggerisco caldamente di utilizzare GraphEdit e AMCap per vedere quali sono le reali capacità del dispositivo. AForge era incline al sovracampionamento e non mi chiedevo se fosse simile in Accord.

    Inoltre, puoi sempre fare affidamento sul buon vecchio processexplorer per vedere se il carico (se esiste) è causato da SYSTEM o INTERRUPRS o è effettivamente prodotto dal tuo eseguibile.

    Un’altra cosa che mi è successo è stata PictureBox. VideoSourcePlayer è di gran lunga migliore e ho finito per fare il mio stesso blitter.

    Vale la pena ricordare queste tre ottimizzazioni:

    • NON UTILIZZARE Bitmap.GetPixel !
    • Usa videoSource.DisplayPinPropertyPage(IntPtr.Zero)
    • Controlla lo spazio colore della videostream

    Bitmap.GetPixel

    Il problema con GetPixel è che è molto lento in quanto deve gestire / gestire un lotto per ogni singolo pixel. Va bene finché si ottiene solo un piccolo numero di chiamate e lo si utilizza su una bitmap caricata. È sicuramente l’approccio sbagliato se si vuole usarlo su tutti i pixelx ogni paio di millisecondi. Il carico della CPU da questo fenomeno è associato alla tua applicazione e verrà mostrato come tale in Process Explorer. Alla fine ho scritto le mie routine di pixel a partire da qui: Lavora con bitmap più velocemente con Csharp Se vuoi solo un kernel o qualcosa di più del solito, implementa un filtro personalizzato.

    VideoSource.DisplayPinPropertyPage

    Se si utilizza il meccanismo AForge-buit-in per scegliere la risoluzione e avviare il stream video, non è ansible impostare il Framerate (non considero questo un bug in AForge). Quindi AForge sceglie sempre il framerate più alto. Se eludete videoSource.VideoCapabilities e mostrate direttamente la finestra di dialogo di configurazione del dispositivo nativo (è formalmente chiamata “Finestra di dialogo delle proprietà di Video Capture Pin”). Qui puoi impostare tutti i parametri manualmente e la finestra di dialogo riempirà il framerate appropriato. In questo modo, riceverai la frequenza di aggiornamento “reale” (hardware) nei tuoi callback. Il carico della CPU di questo sovracampionamento si verifica nel processo SYSTEM.

    Conversione dello spazio colore

    Nel mio caso, la fotocamera supporta tre formati di output: YUY2, MJPG e RGB24. A seconda del formato utilizzato, l’immagine viene trasformata da AForge in RGB (penso che in realtà sia ARGB32). I grafici di DirectShow renderizzati per tutti e tre i formati sono diversi e RGB utilizza ovviamente molto meno CPU rispetto agli altri, in quanto la conversione del colore è piuttosto banale. Il carico derivante da questa conversione viene visualizzato anche nel processo SYSTEM e non nelle applicazioni exe.

    Puoi provare a mettere alcuni timer per capire quale operazione sta rallentando il processo (la lezione di cronometro sarà perfetta)
    Non conosco il formato del tuo Frame ma solitamente la conversione in Bitmap è il collo della bottiglia, AForge è piuttosto veloce. Inoltre è ansible passare un timestamp al metodo WriteVideoFrame, quindi la frequenza fotogrammi indicata in Open è solo per la riproduzione del video. Aforge ordinerà i frame nell’ordine giusto al momento giusto.
    Questo è secondo la mia esperienza. Spero che possa aiutare.