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); }
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; } }
public static string FourCC(uint fourCC) { byte[] bytes = new byte[4]; string s; BitConverterLE.WriteBytes(fourCC, bytes, 0); s = Encoding.ASCII.GetString(bytes).Replace('\0', ' '); return((s.Length == 4) ? s : new string(' ', 4)); }
private void FinalizeLists() { byte[] hdr = new byte[4]; foreach (ListInfo li in _closedLists) { Seek(li.Offset + 4); BitConverterLE.WriteBytes(li.Size, hdr, 0); _fs.Write(hdr, 0, 4); } _fileOffset += 4; }
private long StartList(string chunkID, string listType) { long offset = _fileOffset; byte[] hdr = new byte[12]; _openLists.Push(offset); BitConverterLE.WriteBytes(AVIHelper.FourCC(chunkID), hdr, 0); BitConverterLE.WriteBytes((uint)0, hdr, 4); BitConverterLE.WriteBytes(AVIHelper.FourCC(listType), hdr, 8); _fs.Write(hdr, 0, 12); _fileOffset += 12; return(offset); }
private long WriteChunk(uint chunkID, byte[] data) { long offset = _fileOffset; byte[] hdr = new byte[8]; uint len = (uint)data.Length; BitConverterLE.WriteBytes(chunkID, hdr, 0); BitConverterLE.WriteBytes(len, hdr, 4); _fs.Write(hdr, 0, 8); _fs.Write(data, 0, (int)len); _fileOffset += (long)len + 8; if ((len & 1) != 0) { _fs.WriteByte(0); _fileOffset += 1; } return(offset); }
private byte[] MakeOldIndexChunk() { const uint AVIIF_KEYFRAME = 0x10; List <List <StreamChunkInfo> > cilList = new List <List <StreamChunkInfo> >(); List <int> cilIndex = new List <int>(); List <int> cilLength = new List <int>(); List <uint> cilFourCC = new List <uint>(); AVIOLDINDEXENTRY entry; byte[] buff; int i, entryCount, buffPos, u; entryCount = 0; for (i = 0; i < _streamList.Count; i++) { AVIStream s = _streamList[i]; if (s.ChunkList.Count > 0) { cilList.Add(s.ChunkList); cilIndex.Add(0); cilLength.Add(s.ChunksInFirstMOVI); cilFourCC.Add(s.FourCC); entryCount += s.ChunksInFirstMOVI; } } buffPos = 0; buff = new byte[entryCount * 16]; while (entryCount > 0) { // Find the chunk with the lowest offset u = 0; for (i = 1; i < cilList.Count; i++) { if (cilList[i][cilIndex[i]].Offset < cilList[u][cilIndex[u]].Offset) { u = i; } } entry.dwChunkID = cilFourCC[u]; entry.dwFlags = cilList[u][cilIndex[u]].IsKeyFrame ? AVIIF_KEYFRAME : 0; entry.dwOffset = (uint)(cilList[u][cilIndex[u]].Offset - (_moviOffset + 8)); entry.dwSize = cilList[u][cilIndex[u]].Size; BitConverterLE.WriteBytes(entry.dwChunkID, buff, buffPos); BitConverterLE.WriteBytes(entry.dwFlags, buff, buffPos + 4); BitConverterLE.WriteBytes(entry.dwOffset, buff, buffPos + 8); BitConverterLE.WriteBytes(entry.dwSize, buff, buffPos + 12); buffPos += 16; // If all the chunks from this stream have been written in the index, // stop checking this stream cilIndex[u]++; if (cilIndex[u] >= cilLength[u]) { cilList.RemoveAt(u); cilIndex.RemoveAt(u); cilLength.RemoveAt(u); cilFourCC.RemoveAt(u); } entryCount--; } return(buff); }
private byte[] MakeDMLHChunk(uint dwTotalFrames) { byte[] buff = new byte[248]; BitConverterLE.WriteBytes(dwTotalFrames, buff, 0); return(buff); }