/// <summary> /// Construct Mpeg file representation from stream. /// </summary> /// <param name="stream">The input stream which contains Mpeg data.</param> public MpegFile(Stream stream, bool leaveOpen) { _stream = stream; _leaveOpen = leaveOpen; _reader = new Decoder.MpegStreamReader(_stream); _decoder = new MpegFrameDecoder(); }
public int Read(MpegStreamReader reader, long offset, Span <byte> destination) { int count = destination.Length; int startIdx = EnsureFilled(reader, offset, ref count); Data.AsSpan(startIdx, count).CopyTo(destination); return(count); }
void Init(System.IO.Stream stream, bool closeStream) { _stream = stream; _closeStream = closeStream; _reader = new Decoder.MpegStreamReader(_stream); _decoder = new MpegFrameDecoder(); }
void Init(System.IO.Stream stream, bool closeStream) { _stream = stream; _closeStream = closeStream; _reader = new Decoder.MpegStreamReader(_stream); _decoder = new MpegFrameDecoder(); }
public int Read(MpegStreamReader reader, long offset, byte[] buffer, int index, int count) { lock (_localLock) { var startIdx = EnsureFilled(reader, offset, ref count); Buffer.BlockCopy(Data, startIdx, buffer, index, count); } return(count); }
public int ReadByte(MpegStreamReader reader, long offset) { int count = 1; int startIdx = EnsureFilled(reader, offset, ref count); if (count == 1) { return(Data[startIdx]); } return(-1); }
public int ReadByte(MpegStreamReader reader, long offset) { lock (_localLock) { var count = 1; var startIdx = EnsureFilled(reader, offset, ref count); if (count == 1) { return(Data[startIdx]); } } return(-1); }
internal bool Validate(long offset, MpegStreamReader reader) { Offset = offset; _reader = reader; var len = Validate(); if (len > 0) { Length = len; return(true); } return(false); }
public bool ValidateFrameHeader(long offset, MpegStreamReader reader) { _reader = reader ?? throw new ArgumentNullException(nameof(reader)); Offset = offset; int length = ValidateFrameHeader(); if (length > 0) { Length = length; return(true); } return(false); }
internal bool Validate(long offset, MpegStreamReader reader) { Offset = offset; _reader = reader; var len = Validate(); if (len > 0) { Length = len; return true; } return false; }
int EnsureFilled(MpegStreamReader reader, long offset, ref int count) { // if the offset & count are inside our buffer's range, just return the appropriate index var startIdx = (int)(offset - BaseOffset); int endIdx = startIdx + count; if (startIdx < 0 || endIdx > End) { int readStart = 0, readCount = 0, moveCount = 0; long readOffset = 0; #region Decision-Making if (startIdx < 0) { // if we can't seek, there's nothing we can do if (!reader._source.CanSeek) { throw new InvalidOperationException("Cannot seek backwards on a forward-only stream!"); } // if there's data in the buffer, try to keep it (up to doubling the buffer size) if (End > 0) { // if doubling the buffer would push it past the max size, don't check it if ((startIdx + Data.Length > 0) || (Data.Length * 2 <= 16384 && startIdx + Data.Length * 2 > 0)) { endIdx = End; } } // we know we'll have to start reading here readOffset = offset; // if the end of the request is before the start of our buffer... if (endIdx < 0) { // ... just truncate and move on Truncate(); // set up our read parameters BaseOffset = offset; startIdx = 0; endIdx = count; // how much do we need to read? readCount = count; } else // i.e., endIdx >= 0 { // we have overlap with existing data... save as much as possible moveCount = -endIdx; readCount = -startIdx; } } else // i.e., startIdx >= 0 { // we only get to here if at least one byte of the request is past the end of the read data // start with the simplest scenario and work our way up // 1) We just need to fill the buffer a bit more if (endIdx < Data.Length) { readCount = endIdx - End; readStart = End; readOffset = BaseOffset + readStart; } // 2) We need to discard some bytes, then fill the buffer else if (endIdx - DiscardCount < Data.Length) { moveCount = DiscardCount; readStart = End; readCount = endIdx - readStart; readOffset = BaseOffset + readStart; } // 3) We need to expand the buffer to hold all the existing & requested data else if (Data.Length * 2 <= 16384) { // by definition, we discard moveCount = DiscardCount; readStart = End; readCount = endIdx - End; readOffset = BaseOffset + readStart; } // 4) We have to throw away some data that hasn't been discarded else { // just truncate Truncate(); // set up our read parameters BaseOffset = offset; readOffset = offset; startIdx = 0; endIdx = count; // how much do we have to read? readCount = count; } } #endregion #region Buffer Resizing & Data Moving if (endIdx - moveCount > Data.Length || readStart + readCount - moveCount > Data.Length) { var newSize = Data.Length * 2; while (newSize < endIdx - moveCount) { newSize *= 2; } var newBuf = new byte[newSize]; if (moveCount < 0) { // reverse copy Buffer.BlockCopy(Data, 0, newBuf, -moveCount, End + moveCount); DiscardCount = 0; } else { // forward or neutral copy Buffer.BlockCopy(Data, moveCount, newBuf, 0, End - moveCount); DiscardCount -= moveCount; } Data = newBuf; } else if (moveCount != 0) { if (moveCount > 0) { // forward move Buffer.BlockCopy(Data, moveCount, Data, 0, End - moveCount); DiscardCount -= moveCount; } else { // backward move for (int i = 0, srcIdx = Data.Length - 1, destIdx = Data.Length - 1 - moveCount; i < moveCount; i++, srcIdx--, destIdx--) { Data[destIdx] = Data[srcIdx]; } DiscardCount = 0; } } BaseOffset += moveCount; readStart -= moveCount; startIdx -= moveCount; endIdx -= moveCount; End -= moveCount; #endregion #region Buffer Filling lock (reader._readLock) { if (readCount > 0 && reader._source.Position != readOffset && readOffset < reader._eofOffset) { if (reader._canSeek) { try { reader._source.Position = readOffset; } catch (EndOfStreamException) { reader._eofOffset = reader._source.Length; readCount = 0; } } else { // ugh, gotta read bytes until we've reached the desired offset var seekCount = readOffset - reader._source.Position; while (--seekCount >= 0) { if (reader._source.ReadByte() == -1) { reader._eofOffset = reader._source.Position; readCount = 0; break; } } } } while (readCount > 0 && readOffset < reader._eofOffset) { var temp = reader._source.Read(Data, readStart, readCount); if (temp == 0) { break; } readStart += temp; readOffset += temp; readCount -= temp; } if (readStart > End) { End = readStart; } if (End < endIdx) { // we didn't get a full read... count = Math.Max(0, End - startIdx); } // NB: if desired, switch to "minimal reads" by commenting-out this clause else if (End < Data.Length) { // try to finish filling the buffer var temp = reader._source.Read(Data, End, Data.Length - End); End += temp; } } #endregion } return(startIdx); }
int EnsureFilled(MpegStreamReader reader, long offset, ref int count) { // if the offset & count are inside our buffer's range, just return the appropriate index var startIdx = (int)(offset - BaseOffset); int endIdx = startIdx + count; if (startIdx < 0 || endIdx > End) { int readStart = 0, readCount = 0, moveCount = 0; long readOffset = 0; #region Decision-Making if (startIdx < 0) { // if we can't seek, there's nothing we can do if (!reader._source.CanSeek) throw new InvalidOperationException("Cannot seek backwards on a forward-only stream!"); // if there's data in the buffer, try to keep it (up to doubling the buffer size) if (End > 0) { // if doubling the buffer would push it past the max size, don't check it if ((startIdx + Data.Length > 0) || (Data.Length * 2 <= 16384 && startIdx + Data.Length * 2 > 0)) { endIdx = End; } } // we know we'll have to start reading here readOffset = offset; // if the end of the request is before the start of our buffer... if (endIdx < 0) { // ... just truncate and move on Truncate(); // set up our read parameters BaseOffset = offset; startIdx = 0; endIdx = count; // how much do we need to read? readCount = count; } else // i.e., endIdx >= 0 { // we have overlap with existing data... save as much as possible moveCount = -endIdx; readCount = -startIdx; } } else // i.e., startIdx >= 0 { // we only get to here if at least one byte of the request is past the end of the read data // start with the simplest scenario and work our way up // 1) We just need to fill the buffer a bit more if (endIdx < Data.Length) { readCount = endIdx - End; readStart = End; readOffset = BaseOffset + readStart; } // 2) We need to discard some bytes, then fill the buffer else if (endIdx - DiscardCount < Data.Length) { moveCount = DiscardCount; readStart = End; readCount = endIdx - readStart; readOffset = BaseOffset + readStart; } // 3) We need to expand the buffer to hold all the existing & requested data else if (Data.Length * 2 <= 16384) { // by definition, we discard moveCount = DiscardCount; readStart = End; readCount = endIdx - End; readOffset = BaseOffset + readStart; } // 4) We have to throw away some data that hasn't been discarded else { // just truncate Truncate(); // set up our read parameters BaseOffset = offset; readOffset = offset; startIdx = 0; endIdx = count; // how much do we have to read? readCount = count; } } #endregion #region Buffer Resizing & Data Moving if (endIdx - moveCount > Data.Length || readStart + readCount - moveCount > Data.Length) { var newSize = Data.Length * 2; while (newSize < endIdx - moveCount) { newSize *= 2; } var newBuf = new byte[newSize]; if (moveCount < 0) { // reverse copy Buffer.BlockCopy(Data, 0, newBuf, -moveCount, End + moveCount); DiscardCount = 0; } else { // forward or neutral copy Buffer.BlockCopy(Data, moveCount, newBuf, 0, End - moveCount); DiscardCount -= moveCount; } Data = newBuf; } else if (moveCount != 0) { if (moveCount > 0) { // forward move Buffer.BlockCopy(Data, moveCount, Data, 0, End - moveCount); DiscardCount -= moveCount; } else { // backward move for (int i = 0, srcIdx = Data.Length - 1, destIdx = Data.Length - 1 - moveCount; i < moveCount; i++, srcIdx--, destIdx--) { Data[destIdx] = Data[srcIdx]; } DiscardCount = 0; } } BaseOffset += moveCount; readStart -= moveCount; startIdx -= moveCount; endIdx -= moveCount; End -= moveCount; #endregion #region Buffer Filling lock (reader._readLock) { if (readCount > 0 && reader._source.Position != readOffset && readOffset < reader._eofOffset) { if (reader._canSeek) { try { reader._source.Position = readOffset; } catch (EndOfStreamException) { reader._eofOffset = reader._source.Length; readCount = 0; } } else { // ugh, gotta read bytes until we've reached the desired offset var seekCount = readOffset - reader._source.Position; while (--seekCount >= 0) { if (reader._source.ReadByte() == -1) { reader._eofOffset = reader._source.Position; readCount = 0; break; } } } } while (readCount > 0 && readOffset < reader._eofOffset) { var temp = reader._source.Read(Data, readStart, readCount); if (temp == 0) { break; } readStart += temp; readOffset += temp; readCount -= temp; } if (readStart > End) { End = readStart; } if (End < endIdx) { // we didn't get a full read... count = Math.Max(0, End - startIdx); } // NB: if desired, switch to "minimal reads" by commenting-out this clause else if (End < Data.Length) { // try to finish filling the buffer var temp = reader._source.Read(Data, End, Data.Length - End); End += temp; } } #endregion } return startIdx; }
public int ReadByte(MpegStreamReader reader, long offset) { lock (_localLock) { var count = 1; var startIdx = EnsureFilled(reader, offset, ref count); if (count == 1) { return Data[startIdx]; } } return -1; }
public int Read(MpegStreamReader reader, long offset, byte[] buffer, int index, int count) { lock (_localLock) { var startIdx = EnsureFilled(reader, offset, ref count); Buffer.BlockCopy(Data, startIdx, buffer, index, count); } return count; }