Exemple #1
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);
        }
Exemple #2
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;
            }
        }
Exemple #3
0
        private void WriteHeaders()
        {
            const uint AVIF_HASINDEX      = 0x00000010;
            const uint AVIF_ISINTERLEAVED = 0x00000100;

            AVIMAINHEADER    aviH    = new AVIMAINHEADER();
            AVIStream        vidStr  = _streamList[_videoStreamID];
            AVISTREAMHEADER  vidStrH = vidStr.Header;
            BITMAPINFOHEADER vidStrF = vidStr.VideoFormat;

            if (vidStrH.dwRate != 0)
            {
                aviH.dwMicroSecPerFrame = Convert.ToUInt32(((double)vidStrH.dwScale / vidStrH.dwRate) * 1000000.0);
            }
            aviH.dwFlags       = AVIF_HASINDEX | AVIF_ISINTERLEAVED;
            aviH.dwTotalFrames = (uint)vidStr.ChunksInFirstMOVI;
            aviH.dwStreams     = (uint)_streamList.Count;
            aviH.dwWidth       = (uint)vidStrF.biWidth;
            aviH.dwHeight      = (uint)Math.Abs(vidStrF.biHeight);

            Seek(_avihOffset);
            WriteChunk("avih", StructHelper <AVIMAINHEADER> .ToBytes(aviH, false));

            for (int i = 0; i < _streamList.Count; i++)
            {
                AVIStream       s       = _streamList[i];
                AVISTREAMHEADER sHeader = s.Header;

                sHeader.dwLength = (s.Type == AVIStreamType.Video) ? (uint)s.ChunkList.Count :
                                   CalculateDuration(s.ChunkList, 0, s.ChunkList.Count);
                sHeader.dwSuggestedBufferSize = FindLargestChunk(s.ChunkList);

                Seek(s.STRHOffset);
                WriteChunk("strh", StructHelper <AVISTREAMHEADER> .ToBytes(sHeader, false));

                Seek(s.STRFOffset);
                WriteChunk("strf", s.MakeSTRFChunk());

                if (s.OpenDMLSuperIndex != null)
                {
                    Seek(s.INDXOffset);
                    WriteChunk("indx", s.OpenDMLSuperIndex);
                }
            }

            Seek(_dmlhOffset);
            WriteChunk("dmlh", MakeDMLHChunk((uint)vidStr.ChunkList.Count));
        }
Exemple #4
0
        private bool ParseOpenDMLSuperIndex(byte[] data)
        {
            AVISUPERINDEX      header;
            AVISUPERINDEXENTRY entry;
            int  dataPos = 0;
            long oldOffset = _fileOffset;
            uint chunkID, dataSize, listType;

            byte[] standardIndex;

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

            dataPos += StructHelper <AVISUPERINDEX> .SizeOf;

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

                entry.qwOffset   = BitConverterLE.ToUInt64(data, dataPos);
                entry.dwSize     = BitConverterLE.ToUInt32(data, dataPos + 8);
                entry.dwDuration = BitConverterLE.ToUInt32(data, dataPos + 12);
                dataPos         += 16;

                Seek((long)entry.qwOffset);
                if (ReadChunkHeader(out chunkID, out dataSize, out listType) == -1)
                {
                    return(false);
                }
                standardIndex = ReadChunkData(dataSize);
                if (standardIndex.Length < dataSize)
                {
                    return(false);
                }
                ParseOpenDMLStandardIndex(standardIndex);

                header.nEntriesInUse--;
            }

            Seek(oldOffset);
            return(true);
        }
Exemple #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--;
            }
        }
Exemple #6
0
            public byte[] MakeSTRFChunk()
            {
                byte[] header, full;

                if (Type == AVIStreamType.Video)
                {
                    header = StructHelper <BITMAPINFOHEADER> .ToBytes(VideoFormat, false);
                }
                else if (Type == AVIStreamType.Audio)
                {
                    header = StructHelper <WAVEFORMATEX> .ToBytes(AudioFormat, false);
                }
                else
                {
                    header = new byte[0];
                }

                full = new byte[header.Length + FormatExtra.Length];
                Buffer.BlockCopy(header, 0, full, 0, header.Length);
                Buffer.BlockCopy(FormatExtra, 0, full, header.Length, FormatExtra.Length);

                return(full);
            }
Exemple #7
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();
        }