private string GetChannelName(MaterialFolderIndexRecord aIndexRecord) { switch (aIndexRecord.DataType) { case DataType.Audio: return("Audio"); case DataType.Text: return("Text"); } return("Camera"); }
public void AddRecord(MaterialFolderIndexRecord aRecord) { if (aRecord.ChannelId == ChannelId.Number && aRecord.DataType == ChannelId.DataType) { Records.Add(aRecord); if (Begin == DateTime.MinValue || aRecord.BeginTimestamp < Begin) { Begin = aRecord.BeginTimestamp; } if (End == DateTime.MinValue || aRecord.EndTimestamp > End) { End = aRecord.EndTimestamp; } } }
private bool ProcessFile(Guid aFolderId, string aSourceFilePath, MaterialFolderIndexRecord aNewRecord, TimeInterval aInterval, string aNewFilePath) { bool result = false; bool waitforIntra = true; Guid clientGuid = Guid.NewGuid(); try { using (FileStream file = File.OpenRead(aSourceFilePath)) { using (IMaterialFile newFile = MaterialFileFactory.CreateMaterialFile(aFolderId, aNewRecord, aNewFilePath)) { int readBytes = 0; int startFrameOffset = 0; bool startFound = false; byte[] buffer = new byte[16 * 1024]; DateTime lastFrameTimeStamp = DateTime.MinValue; List <byte> frameBuffer = new List <byte>(); do { if (_stopTask.IsCancellationRequested) { return(false); } startFrameOffset = 0; readBytes = file.Read(buffer, 0, buffer.Length); for (int pos = 0; pos < readBytes - Constants.FrameStart.Length; ++pos) { if (IsEqual(buffer, pos, Constants.FrameStart)) { startFound = true; startFrameOffset = pos; frameBuffer.Clear(); } if (IsEqual(buffer, pos, Constants.FrameEnd)) { int endFramePos = pos + Constants.FrameEnd.Length; CopyBuffer(frameBuffer, buffer, startFrameOffset, endFramePos); startFound = false; startFrameOffset = 0; Frame frame = null; try { using (MemoryStream stream = new MemoryStream(frameBuffer.ToArray())) { try { frame = new Frame(); frame.Deserialize(stream); } catch { continue; } if (frame.Metadata.Timestamp <= lastFrameTimeStamp) { // Skip old frames continue; } if (frame.Metadata.ChannelId != aNewRecord.ChannelId || frame.DataType != aNewRecord.DataType) { // Skip other data continue; } if (waitforIntra && !frame.Metadata.IsIntra) { // Skip non intra if we wait intra continue; } waitforIntra = false; if (aInterval.Contains(frame.Metadata.Timestamp)) { MaterialPosition position = null; WriteStatus writeStatus = newFile.Write(frame, ref position); if (writeStatus == WriteStatus.OK) { // Update material folder index record if (aNewRecord.BeginTimestamp.Ticks == 0) { aNewRecord.BeginTimestamp = frame.Metadata.Timestamp; } aNewRecord.EndTimestamp = frame.Metadata.Timestamp; // Update result result = true; // Add to frame times lastFrameTimeStamp = frame.Metadata.Timestamp; } else { SendError($"Write frame error, status: {writeStatus}, source file {aSourceFilePath}, destination file {aNewFilePath}!"); waitforIntra = true; } } } } catch (Exception ex) { SendError(ex.Message); waitforIntra = true; } finally { frame?.Release(); } } } if (startFound) { CopyBuffer(frameBuffer, buffer, startFrameOffset, buffer.Length); } } while (readBytes > 0); } } } catch (Exception ex) { SendError(ex.Message); } return(result); }
private bool ShouldSkipFile(MaterialFolderIndexRecord aRecord, TimeInterval aTimeInterval) { return(aRecord.EndTimestamp < aTimeInterval.Begin || aRecord.BeginTimestamp > aTimeInterval.End); }
private void ProcessSelectedChannels(IEnumerable <Channel> aChannels, TimeInterval aTimeInterval) { try { IEnumerable <Channel> channels = aChannels.Where(x => x.IsChecked); int count = channels.Count(); if (count == 0) { return; } string destination = Path.Combine(DestinationPath, $"Export_{DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff")}"); if (!Directory.Exists(destination)) { Directory.CreateDirectory(destination); } ArchiveInfo archiveInfo = new ArchiveInfo(); // Set material file id int materialFileId = 0; // Create new material folder index MaterialFolderIndex index = new MaterialFolderIndex() { MaterialFolderId = Guid.NewGuid() }; double progress = 0; double channelProgress = 100.0 / count; var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = 1 }; Parallel.ForEach(channels, parallelOptions, (channel) => { if (_stopTask.IsCancellationRequested) { return; } var files = channel.Records.Where(x => !ShouldSkipFile(x, aTimeInterval)).OrderBy(x => x.BeginTimestamp); double fileProgress = channelProgress / files.Count(); foreach (var fileIndexRecord in files) { if (_stopTask.IsCancellationRequested) { return; } string sourceFilePath = Path.Combine(SelectedPath, Helpers.GetFileName(fileIndexRecord.MaterialFileId)); if (File.Exists(sourceFilePath)) { var fileId = Interlocked.Increment(ref materialFileId); // Generate new file name string newFilePath = Path.Combine(destination, Helpers.GetFileName(fileId)); _logger.Info($"Source file: {sourceFilePath}, destination file: {newFilePath}"); if (File.Exists(newFilePath)) { File.SetAttributes(newFilePath, FileAttributes.Normal); File.Delete(newFilePath); } MaterialFolderIndexRecord indexRecord = new MaterialFolderIndexRecord() { ChannelId = fileIndexRecord.ChannelId, DataType = fileIndexRecord.DataType, ChannelType = ChannelType.Material, MaterialFileId = fileId }; if (ProcessFile(index.MaterialFolderId, sourceFilePath, indexRecord, aTimeInterval, newFilePath)) { lock (_indexLock) { // Update index index.IndexRecords.Add(indexRecord); // Update arhive info archiveInfo.UpdateArchiveInfo(indexRecord, new AdditionalInfo() { Name = GetChannelName(indexRecord) + " " + indexRecord.ChannelId }); // Flush index time limits indexRecord.Flush(); // Update file info archiveInfo.UpdateFileInfo(newFilePath); } } } lock (_progressLock) { progress += fileProgress; SendProgress(progress); } } }); if (index.IndexRecords.Count > 0 && !_stopTask.IsCancellationRequested) { SaveMaterialFolderIndex(index, destination); ArchiveInfo.SaveArchiveInfo(archiveInfo, destination); } } catch (Exception ex) { SendError(ex.Message); } finally { SendExportCompleted(); } }