예제 #1
0
        private bool NextChunkByIndex(out int streamID, out StreamChunkInfo chunkInfo)
        {
            long minOffset   = Int64.MaxValue;
            int  minStreamID = -1;

            for (int i = 0; i < _streamList.Count; i++)
            {
                AVIStream stream = _streamList[i];

                if (stream.ChunkIndex < stream.ChunkList.Count)
                {
                    long thisOffset = stream.ChunkList[stream.ChunkIndex].Offset;
                    if (thisOffset < minOffset)
                    {
                        minOffset   = thisOffset;
                        minStreamID = i;
                    }
                }
            }

            if (minStreamID != -1)
            {
                streamID  = minStreamID;
                chunkInfo = _streamList[streamID].ChunkList[_streamList[streamID].ChunkIndex];
                _streamList[streamID].ChunkIndex++;
                return(true);
            }
            else
            {
                streamID  = -1;
                chunkInfo = new StreamChunkInfo();
                return(false);
            }
        }
예제 #2
0
        private byte[] MakeOpenDMLStandardIndexChunk(List <StreamChunkInfo> chunkList, int start, int length, uint streamFourCC)
        {
            const byte AVI_INDEX_OF_CHUNKS = 0x01;

            long             baseOffset = chunkList[start].Offset + 8;
            AVISTDINDEX      header     = new AVISTDINDEX();
            AVISTDINDEXENTRY entry;

            byte[] buff    = new byte[OpenDMLStandardIndexSize((uint)length)];
            int    buffPos = 0;

            header.wLongsPerEntry = 2;
            header.bIndexSubType  = 0;
            header.bIndexType     = AVI_INDEX_OF_CHUNKS;
            header.nEntriesInUse  = (uint)length;
            header.dwChunkID      = streamFourCC;
            header.qwBaseOffset   = (ulong)baseOffset;

            buffPos += StructHelper <AVISTDINDEX> .ToBytes(header, buff, buffPos, false);

            for (int i = 0; i < length; i++)
            {
                StreamChunkInfo c = chunkList[start + i];

                entry.dwOffset = (uint)((c.Offset + 8) - baseOffset);
                entry.dwSize   = c.Size | (c.IsKeyFrame ? 0 : 0x80000000);

                BitConverterLE.WriteBytes(entry.dwOffset, buff, buffPos);
                BitConverterLE.WriteBytes(entry.dwSize, buff, buffPos + 4);
                buffPos += 8;
            }

            return(buff);
        }
예제 #3
0
        private void ParseOldIndex(byte[] data)
        {
            const uint AVIIF_KEYFRAME = 0x10;

            int              dataPos   = 0;
            StreamChunkInfo  chunkInfo = new StreamChunkInfo();
            AVIOLDINDEXENTRY entry;
            int              streamID;
            long             firstVideoChunkOffset = -1;
            long             offsetCorrection;

            while (dataPos <= (data.Length - 16))
            {
                entry.dwChunkID = BitConverterLE.ToUInt32(data, dataPos);
                entry.dwFlags   = BitConverterLE.ToUInt32(data, dataPos + 4);
                entry.dwOffset  = BitConverterLE.ToUInt32(data, dataPos + 8);
                entry.dwSize    = BitConverterLE.ToUInt32(data, dataPos + 12);
                dataPos        += 16;

                streamID = AVIHelper.StreamID(entry.dwChunkID, false);
                if ((streamID == -1) || (streamID >= _streamList.Count))
                {
                    continue;
                }
                if (_streamList[streamID].FourCC == 0)
                {
                    _streamList[streamID].FourCC = entry.dwChunkID;
                }
                chunkInfo.Offset     = (long)entry.dwOffset;
                chunkInfo.Size       = entry.dwSize;
                chunkInfo.IsKeyFrame = (entry.dwFlags & AVIIF_KEYFRAME) != 0;

                if ((firstVideoChunkOffset == -1) && (streamID == _videoStreamID))
                {
                    firstVideoChunkOffset = chunkInfo.Offset;
                }

                _streamList[streamID].ChunkList.Add(chunkInfo);
            }

            if ((_firstVideoChunkOffset == -1) || (firstVideoChunkOffset == -1))
            {
                throw new Exception("Video stream not found.");
            }

            // Add 8 because the offset needs to point to the start of the data
            offsetCorrection = (_firstVideoChunkOffset - firstVideoChunkOffset) + 8;

            foreach (AVIStream stream in _streamList)
            {
                for (int i = 0; i < stream.ChunkList.Count; i++)
                {
                    chunkInfo           = stream.ChunkList[i];
                    chunkInfo.Offset   += offsetCorrection;
                    stream.ChunkList[i] = chunkInfo;
                }
            }
        }
예제 #4
0
        public void WriteChunk(int streamID, byte[] buff, bool isKeyFrame, int duration)
        {
            if (!_isFileStarted)
            {
                StartFile();
            }

            CheckExtend((uint)buff.Length);

            StreamChunkInfo x = new StreamChunkInfo();

            x.Offset     = WriteChunk(_streamList[streamID].FourCC, buff);
            x.Size       = (uint)buff.Length;
            x.Duration   = (uint)duration;
            x.IsKeyFrame = isKeyFrame;
            _streamList[streamID].ChunkList.Add(x);
        }
예제 #5
0
        private void ParseOpenDMLStandardIndex(byte[] data)
        {
            AVISTDINDEX      header;
            AVISTDINDEXENTRY entry;
            int dataPos = 0;
            int streamID;
            List <StreamChunkInfo> chunkList;
            StreamChunkInfo        ci = new StreamChunkInfo();

            header = StructHelper <AVISTDINDEX> .FromBytes(data, 0, false);

            dataPos += StructHelper <AVISTDINDEX> .SizeOf;

            streamID = AVIHelper.StreamID(header.dwChunkID, false);
            if ((streamID == -1) || (streamID >= _streamList.Count))
            {
                throw new Exception("Invalid chunk ID in OpenDML standard index.");
            }
            if (_streamList[streamID].FourCC == 0)
            {
                _streamList[streamID].FourCC = header.dwChunkID;
            }
            chunkList = _streamList[streamID].ChunkList;

            while (dataPos <= (data.Length - 8))
            {
                if (header.nEntriesInUse == 0)
                {
                    break;
                }

                entry.dwOffset = BitConverterLE.ToUInt32(data, dataPos);
                entry.dwSize   = BitConverterLE.ToUInt32(data, dataPos + 4);
                dataPos       += 8;

                ci.Offset     = (long)(header.qwBaseOffset + entry.dwOffset);
                ci.Size       = entry.dwSize & 0x7FFFFFFF;
                ci.IsKeyFrame = ((entry.dwSize & 0x80000000) == 0);
                chunkList.Add(ci);

                header.nEntriesInUse--;
            }
        }
예제 #6
0
        private bool NextChunkByMOVI(out int streamID, out StreamChunkInfo chunkInfo)
        {
            uint chunkID, dataSize, listType;

            streamID  = -1;
            chunkInfo = new StreamChunkInfo();

            Seek(_nextChunkOffset);

            while (true)
            {
                chunkInfo.Offset = ReadChunkHeader(out chunkID, out dataSize, out listType);
                if (chunkInfo.Offset == -1)
                {
                    return(false);
                }
                chunkInfo.Offset += 8;

                if ((chunkID == ckIDLIST) || (chunkID == ckIDRIFF))
                {
                    continue;
                }

                streamID = AVIHelper.StreamID(chunkID, false);
                if ((streamID != -1) && (streamID < _streamList.Count))
                {
                    if (_streamList[streamID].FourCC == 0)
                    {
                        _streamList[streamID].FourCC = chunkID;
                    }
                    chunkInfo.Size       = dataSize;
                    chunkInfo.IsKeyFrame = _streamList[streamID].IsFirstChunk ||
                                           (_streamList[streamID].Type != AVIStreamType.Video);
                    _streamList[streamID].IsFirstChunk = false;
                    _nextChunkOffset = _fileOffset + ((dataSize + 1) & 0xFFFFFFFE);
                    return(true);
                }

                SkipChunkData(dataSize);
            }
        }