예제 #1
0
파일: CameraWindow.cs 프로젝트: vmail/main
        private void Record()
        {
            _stopWrite = false;
            MainForm.RecordingThreads++;
            string previewImage = "";
            DateTime recordingStart = DateTime.MinValue;

            if (!String.IsNullOrEmpty(Camobject.recorder.trigger) && TopLevelControl != null)
            {
                string[] tid = Camobject.recorder.trigger.Split(',');
                switch (tid[0])
                {
                    case "1":
                        VolumeLevel vl = ((MainForm)TopLevelControl).GetVolumeLevel(Convert.ToInt32(tid[1]));
                        if (vl != null)
                            vl.RecordSwitch(true);
                        break;
                    case "2":
                        CameraWindow cw = ((MainForm)TopLevelControl).GetCameraWindow(Convert.ToInt32(tid[1]));
                        if (cw != null)
                            cw.RecordSwitch(true);
                        break;
                }
            }

            try {
                if (_writerBuffer != null)
                    _writerBuffer.Clear();
                _writerBuffer = new QueueWithEvents<FrameAction>();
                _writerBuffer.Changed += WriterBufferChanged;
                DateTime date = DateTime.Now;

                string filename = String.Format("{0}-{1}-{2}_{3}-{4}-{5}",
                                                date.Year, Helper.ZeroPad(date.Month), Helper.ZeroPad(date.Day),
                                                Helper.ZeroPad(date.Hour), Helper.ZeroPad(date.Minute),
                                                Helper.ZeroPad(date.Second));

                var vc = VolumeControl;
                if (vc != null && vc.Micobject.settings.active)
                {
                    vc.ForcedRecording = ForcedRecording;
                    vc.StartSaving();
                }

                VideoFileName = Camobject.id + "_" + filename;
                string folder = MainForm.Conf.MediaDirectory + "video\\" + Camobject.directory + "\\";
                string avifilename = folder + VideoFileName + CodecExtension;
                bool error = false;
                double maxAlarm = 0;

                try
                {

                    int w, h;
                    GetVideoSize(out w, out h);
                    Program.WriterMutex.WaitOne();

                    try
                    {
                        Writer = new VideoFileWriter();
                        if (vc == null || vc.AudioSource==null)
                            Writer.Open(avifilename, w, h, Camobject.recorder.crf, Codec,
                                        CalcBitRate(Camobject.recorder.quality), CodecFramerate);
                        else
                        {

                            Writer.Open(avifilename, w, h, Camobject.recorder.crf, Codec,
                                        CalcBitRate(Camobject.recorder.quality), CodecAudio, CodecFramerate,
                                        vc.AudioSource.RecordingFormat.BitsPerSample * vc.AudioSource.RecordingFormat.SampleRate * vc.AudioSource.RecordingFormat.Channels,
                                        vc.AudioSource.RecordingFormat.SampleRate, vc.AudioSource.RecordingFormat.Channels);
                        }
                    }
                    catch
                    {
                        ForcedRecording = false;
                        if (vc != null)
                        {
                            vc.ForcedRecording = false;
                            vc.StopSaving();
                        }
                        throw;
                    }
                    finally
                    {
                        Program.WriterMutex.ReleaseMutex();
                    }

                    FrameAction? peakFrame = null;

                    foreach(FrameAction fa in _videoBuffer.OrderBy(p=>p.Timestamp))
                    {
                        try
                        {
                            using (var ms = new MemoryStream(fa.Frame))
                            {
                                using (var bmp = (Bitmap)Image.FromStream(ms))
                                {
                                    if (recordingStart == DateTime.MinValue)
                                    {
                                        recordingStart = fa.Timestamp;
                                    }
                                    Writer.WriteVideoFrame(ResizeBitmap(bmp), fa.Timestamp - recordingStart);
                                }

                                if (fa.MotionLevel > maxAlarm || peakFrame == null)
                                {
                                    maxAlarm = fa.MotionLevel;
                                    peakFrame = fa;
                                }
                                _motionData.Append(String.Format(CultureInfo.InvariantCulture,
                                                                "{0:0.000}", Math.Min(fa.MotionLevel*1000, 100)));
                                _motionData.Append(",");
                                ms.Close();
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                        }

                    }
                    _videoBuffer.Clear();

                    if (vc != null && vc.AudioBuffer != null)
                    {
                        foreach (VolumeLevel.AudioAction aa in vc.AudioBuffer.OrderBy(p=>p.TimeStamp))
                        {
                            unsafe
                            {
                                fixed (byte* p = aa.Decoded)
                                {
                                    if ((aa.TimeStamp - recordingStart).TotalMilliseconds>=0)
                                        Writer.WriteAudio(p, aa.Decoded.Length);
                                }
                            }
                        }
                        vc.AudioBuffer.Clear();
                    }

                    if (recordingStart == DateTime.MinValue)
                        recordingStart = DateTime.Now;

                    while (!_stopWrite)
                    {
                        while (_writerBuffer.Count > 0)
                        {
                            var fa = _writerBuffer.Dequeue();
                            try
                            {
                                using (var ms = new MemoryStream(fa.Frame))
                                {

                                    var bmp = (Bitmap) Image.FromStream(ms);
                                    Writer.WriteVideoFrame(ResizeBitmap(bmp), fa.Timestamp - recordingStart);
                                    bmp.Dispose();
                                    bmp = null;

                                    if (fa.MotionLevel > maxAlarm || peakFrame == null)
                                    {
                                        maxAlarm = fa.MotionLevel;
                                        peakFrame = fa;
                                    }
                                    _motionData.Append(String.Format(CultureInfo.InvariantCulture,
                                                                    "{0:0.000}",
                                                                    Math.Min(fa.MotionLevel*1000, 100)));
                                    _motionData.Append(",");
                                    ms.Close();
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                            }
                            if (vc != null && vc.WriterBuffer != null)
                            {
                                try
                                {
                                    while (vc.WriterBuffer.Count > 0)
                                    {

                                        var b = vc.WriterBuffer.Dequeue();
                                        unsafe
                                        {
                                            fixed (byte* p = b.Decoded)
                                            {
                                                Writer.WriteAudio(p, b.Decoded.Length);
                                            }
                                        }
                                    }
                                }
                                catch
                                {
                                    //can fail if the control is switched off/removed whilst recording

                                }
                            }

                        }
                        _newRecordingFrame.WaitOne(200);
                    }

                    if (!Directory.Exists(folder + @"thumbs\"))
                        Directory.CreateDirectory(folder + @"thumbs\");

                    if (peakFrame != null)
                    {
                        using (var ms = new MemoryStream(peakFrame.Value.Frame))
                        {
                            using (var bmp = (Bitmap)Image.FromStream(ms))
                            {
                                bmp.Save(folder + @"thumbs\" + VideoFileName + "_large.jpg", MainForm.Encoder,
                                         MainForm.EncoderParams);
                                Image.GetThumbnailImageAbort myCallback = ThumbnailCallback;
                                using (var myThumbnail = bmp.GetThumbnailImage(96, 72, myCallback, IntPtr.Zero))
                                {
                                    myThumbnail.Save(folder + @"thumbs\" + VideoFileName + ".jpg", MainForm.Encoder,
                                                     MainForm.EncoderParams);
                                }
                            }
                            previewImage = folder + @"thumbs\" + VideoFileName + ".jpg";
                            ms.Close();
                        }
                    }
                }
                catch (Exception ex)
                {
                    error = true;
                    Log.Error("Camera " + Camobject.id, ex);
                }
                finally
                {
                    _stopWrite = false;
                    if (Writer != null)
                    {
                        Program.WriterMutex.WaitOne();
                        try
                        {

                            Writer.Close();
                            Writer.Dispose();
                        }
                        catch (Exception ex)
                        {
                            Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                        }
                        finally
                        {
                            Program.WriterMutex.ReleaseMutex();
                        }

                        Writer = null;
                    }

                    try
                    {
                        _writerBuffer.Clear();
                    }
                    catch
                    {
                    }

                    _writerBuffer = null;
                    _recordingTime = 0;
                    if (vc != null && vc.Micobject.settings.active)
                        VolumeControl.StopSaving();
                }
                if (error)
                {
                    try
                    {
                        FileOperations.Delete(filename + CodecExtension);
                    }
                    catch
                    {
                    }
                    MainForm.RecordingThreads--;
                    return;
                }

                string path = MainForm.Conf.MediaDirectory + "video\\" + Camobject.directory + "\\" +
                              VideoFileName;

                bool yt = Camobject.settings.youtube.autoupload && MainForm.Conf.Subscribed;

                string[] fnpath = (path + CodecExtension).Split('\\');
                string fn = fnpath[fnpath.Length - 1];
                var fpath = MainForm.Conf.MediaDirectory + "video\\" + Camobject.directory + "\\thumbs\\";
                var fi = new FileInfo(path + CodecExtension);
                var dSeconds = Convert.ToInt32((DateTime.Now - recordingStart).TotalSeconds);

                FilesFile ff = FileList.FirstOrDefault(p => p.Filename.EndsWith(fn));
                bool newfile = false;
                if (ff == null)
                {
                    ff = new FilesFile();
                    newfile = true;
                }

                ff.CreatedDateTicks = DateTime.Now.Ticks;
                ff.Filename = fn;
                ff.MaxAlarm = Math.Min(maxAlarm * 1000, 100);
                ff.SizeBytes = fi.Length;
                ff.DurationSeconds = dSeconds;
                ff.IsTimelapse = false;
                ff.AlertData = Helper.GetMotionDataPoints(_motionData);
                _motionData.Clear();
                ff.TriggerLevel = (100-Camobject.detector.minsensitivity); //adjusted

                if (newfile)
                {
                    FileList.Insert(0, ff);

                    if (!MainForm.MasterFileList.Any(p => p.Filename.EndsWith(fn)))
                    {
                        MainForm.MasterFileList.Add(new FilePreview(fn, dSeconds, Camobject.name, DateTime.Now.Ticks, 2,
                                                                    Camobject.id, ff.MaxAlarm));
                        if (TopLevelControl != null)
                        {
                            string thumb = fpath + fn.Replace(CodecExtension, ".jpg");

                            ((MainForm)TopLevelControl).AddPreviewControl(thumb, path + CodecExtension, dSeconds,
                                                                           DateTime.Now, true);
                        }
                    }

                    if (yt)
                    {
                        if (CodecExtension!=".mp4")
                            Log.Info("Skipped youtube upload (only upload mp4 files).");
                        else
                        {
                            try
                            {
                                YouTubeUploader.AddUpload(Camobject.id, fn, Camobject.settings.youtube.@public, "", "");
                            }
                            catch (Exception ex)
                            {
                                Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                            }
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
            }
            MainForm.RecordingThreads--;
            Camobject.newrecordingcount++;

            if (!String.IsNullOrEmpty(Camobject.recorder.trigger) && TopLevelControl != null)
            {
                string[] tid = Camobject.recorder.trigger.Split(',');
                switch (tid[0])
                {
                    case "1":
                        VolumeLevel vl = ((MainForm)TopLevelControl).GetVolumeLevel(Convert.ToInt32(tid[1]));
                        if (vl != null)
                            vl.RecordSwitch(false);
                        break;
                    case "2":
                        CameraWindow cw = ((MainForm)TopLevelControl).GetCameraWindow(Convert.ToInt32(tid[1]));
                        if (cw != null)
                            cw.RecordSwitch(false);
                        break;
                }
            }

            if (Notification != null)
                Notification(this, new NotificationType("NewRecording", Camobject.name, previewImage));
        }