Esempio n. 1
0
        private void MakeOpenDMLIndexes()
        {
            for (int iStream = 0; iStream < _streamList.Count; iStream++)
            {
                const byte AVI_INDEX_OF_INDEXES = 0x00;

                AVIStream stream = _streamList[iStream];
                List <StreamChunkInfo> chunkList = stream.ChunkList;

                AVISUPERINDEX      header = new AVISUPERINDEX();
                AVISUPERINDEXENTRY entry;
                int    entriesPerChunk, entryOffset, chunksLeft, buffPos;
                uint   indexChunkID = AVIHelper.StreamFourCC(AVIHelper.StreamID(stream.FourCC, false), "ix", true);
                byte[] buff;

                buffPos         = 0;
                buff            = new byte[OpenDMLSuperIndexSize(MaxOpenDMLSuperIndexEntries)];
                entriesPerChunk = (int)CalculateOpenDMLStandardIndexEntryCount(chunkList);
                entryOffset     = 0;
                chunksLeft      = chunkList.Count;

                header.wLongsPerEntry = 4;
                header.bIndexSubType  = 0;
                header.bIndexType     = AVI_INDEX_OF_INDEXES;
                header.nEntriesInUse  = (uint)((chunksLeft + (entriesPerChunk - 1)) / entriesPerChunk);
                header.dwChunkID      = stream.FourCC;

                if (header.nEntriesInUse > MaxOpenDMLSuperIndexEntries)
                {
                    throw new Exception("Too many super-index entries.");
                }

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

                while (chunksLeft > 0)
                {
                    int    length = Math.Min(entriesPerChunk, chunksLeft);
                    byte[] tmp    = MakeOpenDMLStandardIndexChunk(chunkList, entryOffset, length,
                                                                  stream.FourCC);

                    CheckExtend((uint)tmp.Length);

                    entry.qwOffset   = (ulong)WriteChunk(indexChunkID, tmp);
                    entry.dwSize     = (uint)tmp.Length + 8;
                    entry.dwDuration = (stream.Type == AVIStreamType.Video) ? (uint)length :
                                       CalculateDuration(chunkList, entryOffset, length);

                    BitConverterLE.WriteBytes(entry.qwOffset, buff, buffPos);
                    BitConverterLE.WriteBytes(entry.dwSize, buff, buffPos + 8);
                    BitConverterLE.WriteBytes(entry.dwDuration, buff, buffPos + 12);
                    buffPos += 16;

                    entryOffset += length;
                    chunksLeft  -= length;
                }

                stream.OpenDMLSuperIndex = buff;
            }
        }
Esempio n. 2
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;
                }
            }
        }
Esempio n. 3
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--;
            }
        }
Esempio n. 4
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);
            }
        }
Esempio n. 5
0
        private void ReadHeaders()
        {
            uint chunkID, dataSize, listType;
            long chunkOffset, firstRIFFEnd, moviEnd;

            byte[] data;
            bool   inMOVI;

            moviEnd = -1;

            chunkOffset = ReadChunkHeader(out chunkID, out dataSize, out listType);
            if ((chunkOffset == -1) || (chunkID != AVIHelper.FourCC("RIFF")) ||
                (listType != AVIHelper.FourCC("AVI ")))
            {
                throw new Exception("File isn't an AVI.");
            }
            firstRIFFEnd = _fileOffset + dataSize;

            while (_fileOffset < firstRIFFEnd)
            {
                chunkOffset = ReadChunkHeader(out chunkID, out dataSize, out listType);
                if (chunkOffset == -1)
                {
                    break;
                }

                if (chunkID == ckIDLIST)
                {
                    if (listType == AVIHelper.FourCC("movi"))
                    {
                        if (_videoStreamID == -1)
                        {
                            throw new Exception("Video stream not found.");
                        }
                        _moviOffset = chunkOffset;
                        moviEnd     = _fileOffset + dataSize;
                    }
                    continue;
                }

                inMOVI = (_moviOffset != -1) && (chunkOffset >= _moviOffset) && (chunkOffset < moviEnd);

                if (!inMOVI)
                {
                    data = ReadChunkData(dataSize);
                    if (data.Length < dataSize)
                    {
                        break;
                    }
                }
                else
                {
                    SkipChunkData(dataSize);
                    data = null;
                }

                if (chunkID == AVIHelper.FourCC("strh"))
                {
                    AVISTREAMHEADER strH = StructHelper <AVISTREAMHEADER> .FromBytes(data, 0, false);

                    AVIStream s;

                    if (strH.fccType == AVIHelper.FourCC("vids"))
                    {
                        s = new AVIStream(AVIStreamType.Video);
                        if (_videoStreamID == -1)
                        {
                            _videoStreamID = _streamList.Count;
                        }
                    }
                    else if (strH.fccType == AVIHelper.FourCC("auds"))
                    {
                        s = new AVIStream(AVIStreamType.Audio);
                    }
                    else
                    {
                        s = new AVIStream(AVIStreamType.Other);
                    }

                    s.Header = strH;
                    _streamList.Add(s);
                }
                if (chunkID == AVIHelper.FourCC("strf"))
                {
                    AVIStream stream  = _streamList[_streamList.Count - 1];
                    int       fmtSize = 0;
                    int       fmtExtraSize;

                    if (stream.Type == AVIStreamType.Video)
                    {
                        stream.VideoFormat = StructHelper <BITMAPINFOHEADER> .FromBytes(data, 0, false);

                        fmtSize = StructHelper <BITMAPINFOHEADER> .SizeOf;
                    }
                    else if (stream.Type == AVIStreamType.Audio)
                    {
                        stream.AudioFormat = StructHelper <WAVEFORMATEX> .FromBytes(data, 0, false);

                        fmtSize = StructHelper <WAVEFORMATEX> .SizeOf;
                    }
                    else
                    {
                        fmtSize = 0;
                    }

                    fmtExtraSize = data.Length - fmtSize;
                    if (fmtExtraSize > 0)
                    {
                        stream.FormatExtra = new byte[fmtExtraSize];
                        Buffer.BlockCopy(data, fmtSize, stream.FormatExtra, 0, fmtExtraSize);
                    }
                }
                if (chunkID == AVIHelper.FourCC("strn"))
                {
                    _streamList[_streamList.Count - 1].STRNData = data;
                }
                if (inMOVI && (AVIHelper.StreamID(chunkID, false) == _videoStreamID))
                {
                    _firstVideoChunkOffset = chunkOffset;
                    Seek(moviEnd);
                }
                if (chunkID == AVIHelper.FourCC("indx"))
                {
                    _isOpenDML  = true;
                    _foundIndex = ParseOpenDMLIndex(data);
                }
                if (chunkID == AVIHelper.FourCC("idx1"))
                {
                    if (!_isOpenDML)
                    {
                        ParseOldIndex(data);
                        _foundIndex = true;
                    }
                }
            }
            if (_moviOffset == -1)
            {
                throw new Exception("\"movi\" list not found.");
            }

            SeekToStart();
        }