public override PlaybackReadResponse ReadData(Guid playbackId) { DateTime cur; lock (_playbackLockObj) { if (!_playbackCursors.TryGetValue(playbackId, out cur)) { throw new KeyNotFoundException(nameof(playbackId)); } } try { // TODO: request real data byte[] data = new byte[] { }; if (data == null) { Toolbox.Log.Trace("--- No data returned "); return(null); } // TODO: Change to correct values - potentially different codec. VideoHeader jpegHeader = new VideoHeader(); jpegHeader.CodecType = VideoCodecType.JPEG; jpegHeader.SyncFrame = true; PlaybackFrame frame = new PlaybackFrame() { Data = data, Header = jpegHeader, AnyMotion = true }; jpegHeader.SequenceNumber = 0; jpegHeader.Length = (ulong)data.Length; jpegHeader.TimestampFrame = cur; jpegHeader.TimestampSync = cur; DateTime prev = cur - TimeSpan.FromSeconds(1); DateTime next = cur + TimeSpan.FromSeconds(1); return(new PlaybackReadResponse() { SequenceNumber = _sequenceNumbers[playbackId], Next = next, Previous = prev, Frames = new[] { frame }, }); } catch (Exception e) { Toolbox.Log.Trace("{0}: Exception={1}", nameof(ReadData), e.Message + e.StackTrace); return(null); } }
public override PlaybackReadResponse ReadData(Guid playbackId) { PlaybackSession session; DateTime cur; lock (_playbackLockObj) { if (!_playbackSessions.TryGetValue(playbackId, out session)) { throw new KeyNotFoundException(nameof(playbackId)); } } cur = session.Cursor; bool atVideo = IsAtVideo(cur); Toolbox.Log.Trace("{0} at {1}, AtVideo: {2}", nameof(ReadData), cur.ToString("o"), atVideo); int channel = 0; try { if (!atVideo) { return(null); } byte[] data = Container.ConnectionManager.GetPlaybackFrame(channel, cur); if (data == null) { Toolbox.Log.Trace("--- No data returned "); return(null); } // Just as is the case for the live stream, information in a remote playback or remote retrieval scenario // is transferred to the recorder frame by frame (whether that be a video frame or an audio frame, and in the case of e.g. // H.264 or H.265 video, whether it be a P-frame, I-frame, etc.) VideoHeader jpegHeader = new VideoHeader(); jpegHeader.CodecType = VideoCodecType.JPEG; jpegHeader.SyncFrame = true; // Only set this to true for key frames. PlaybackFrame frame = new PlaybackFrame() { Data = data, Header = jpegHeader, AnyMotion = true }; jpegHeader.SequenceNumber = 0; jpegHeader.Length = (ulong)data.Length; jpegHeader.TimestampFrame = cur; // The time stamp of the current frame. jpegHeader.TimestampSync = cur; // The time stamp of the most recent keyframe. If the codec does not differentiate between frame types, or if this is a keyframe, set it to the same as TimestampFrame. DateTime prev = cur - _frameDistance; // The time stamp of the previous frame. DateTime next = cur + _frameDistance; // The time stamp of the next frame. if (!IsAtVideo(next)) { next = NextSequence(next); } return(new PlaybackReadResponse() { SequenceNumber = session.SequenceNumber, Next = next, Previous = prev, Frames = new[] { frame }, }); } catch (Exception e) { Toolbox.Log.Trace("{0}: Exception={1}", nameof(ReadData), e.Message + e.StackTrace); throw; } }