Ejemplo n.º 1
0
        /// <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();
        }
Ejemplo n.º 2
0
            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);
            }
Ejemplo n.º 3
0
        void Init(System.IO.Stream stream, bool closeStream)
        {
            _stream      = stream;
            _closeStream = closeStream;

            _reader = new Decoder.MpegStreamReader(_stream);

            _decoder = new MpegFrameDecoder();
        }
Ejemplo n.º 4
0
        void Init(System.IO.Stream stream, bool closeStream)
        {
            _stream = stream;
            _closeStream = closeStream;

            _reader = new Decoder.MpegStreamReader(_stream);

            _decoder = new MpegFrameDecoder();
        }
Ejemplo n.º 5
0
            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);
            }
Ejemplo n.º 6
0
            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);
            }
Ejemplo n.º 7
0
 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);
 }
Ejemplo n.º 8
0
        internal bool Validate(long offset, MpegStreamReader reader)
        {
            Offset  = offset;
            _reader = reader;

            var len = Validate();

            if (len > 0)
            {
                Length = len;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        internal bool Validate(long offset, MpegStreamReader reader)
        {
            Offset = offset;
            _reader = reader;

            var len = Validate();

            if (len > 0)
            {
                Length = len;
                return true;
            }
            return false;
        }
Ejemplo n.º 11
0
            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);
            }
Ejemplo n.º 12
0
            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;
            }
Ejemplo n.º 13
0
 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;
 }
Ejemplo n.º 14
0
 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;
 }