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); } }
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 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; } } }
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); }
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--; } }
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); } }