public void Test_FourCharacterCode_Value() { var fcc = new FourCharacterCode("ABCD"); fcc.Value.Should().Be("ABCD"); fcc.ToString().Should().Be("ABCD"); }
public virtual Type LookupChunkObjectType(FourCharacterCode chunkTypeId) { Check.IfArgumentNull(chunkTypeId, "chunkTypeId"); string chunkId = chunkTypeId.ToString(); if (!chunkId.HasWildcard()) { Type result = null; // try fast lookup first if the requested type has no wildcards if (this.chunkMap.TryGetValue(chunkId, out result)) { return(result); } } // now match wildcards foreach (var item in this.chunkMap) { if (chunkId.MatchesWith(item.Key)) { return(item.Value); } } return(null); }
public void Test_FourCharacterCode_ToInt32() { FourCharacterCode fcc = new FourCharacterCode("ABCD"); int value = fcc.ToInt32(); Assert.AreEqual(0x41424344, value); }
public void Test_FourCharacterCode_Value() { FourCharacterCode fcc = new FourCharacterCode(); fcc.Value = "ABCD"; Assert.AreEqual("ABCD", fcc.Value); Assert.AreEqual("ABCD", fcc.ToString()); }
public void CtorPopulates_CreatChunk_RetrievesInternalChunkObjects_data() { var factory = CreateFactory(); var fourcc = new FourCharacterCode("data"); var chunk = factory.CreateChunkObject(fourcc); Assert.IsNotNull(chunk); }
public void CtorPopulates_CreatChunk_RetrievesInternalChunkObjects_data() { var factory = CreateFactory(); var fourcc = new FourCharacterCode("data"); var chunk = factory.CreateChunkObject(fourcc); chunk.Should().NotBeNull(); }
public Node ReadChunk(FourCharacterCode name, long offset = 0) { long positionStart = Position; Node result = ReadChunks(offset, name).FirstOrDefault(); Position = positionStart; return(result); }
/// <inheritdocs/> public virtual object CreateChunkObject(FourCharacterCode chunkTypeId) { Check.IfArgumentNull(chunkTypeId, "chunkTypeId"); Type result = this.LookupChunkObjectType(chunkTypeId); if (result != null) { return(Activator.CreateInstance(result)); } return(null); }
public static bool HasSubType(byte[] chunk, int offset = 0) { if (chunk == null) { throw new ArgumentNullException(nameof(chunk)); } if (chunk.Length - offset < 4) { throw new ArgumentOutOfRangeException(nameof(offset)); } FourCharacterCode fourCC = (FourCharacterCode)ToFourCC(chunk[0], chunk[1], chunk[2], chunk[3]); return(HasSubType(fourCC)); }
public static bool HasSubType(Node chunk) { if (chunk == null) { throw new ArgumentNullException("chunk"); } FourCharacterCode fourCC = (FourCharacterCode)ToFourCC(chunk.Identifier[0], chunk.Identifier[1], chunk.Identifier[2], chunk.Identifier[3]); return(HasSubType(fourCC)); //switch(fourCC) //{ // case FourCharacterCode.RIFF: // case FourCharacterCode.RIFX: // case FourCharacterCode.RF64: // case FourCharacterCode.ON2: // case FourCharacterCode.odml: // case FourCharacterCode.LIST: // return true; // default: // return false; //} }
public Node ReadNext() { if (Remaining <= MinimumSize) { throw new System.IO.EndOfStreamException(); } byte[] identifier = new byte[IdentifierSize]; byte[] lengthBytes = new byte[LengthSize]; int read = Read(identifier, 0, IdentifierSize); read += Read(lengthBytes, 0, LengthSize); ulong length = (ulong)Common.Binary.Read32(lengthBytes, 0, Media.Common.Binary.IsBigEndian); int identifierSize = IdentifierSize; //Get the fourCC of the node FourCharacterCode fourCC = (FourCharacterCode)Common.Binary.Read32(identifier, 0, Media.Common.Binary.IsBigEndian); //Store the first if (false == m_Type.HasValue) { m_Type = fourCC; } //Determine if 64 bit support is needed by inspecting the first node encountered. if (false == m_Needs64BitInfo.HasValue) { //There may be other nodes to account for also... m_Needs64BitInfo = fourCC == FourCharacterCode.RF64; } //Determine if an identifier follows if (RiffReader.HasSubType(fourCC)) { //Resize the identifier to make room for the sub type Array.Resize(ref identifier, MinimumSize); //Read the sub type read += Read(identifier, IdentifierSize, IdentifierSize); //Not usually supposed to read the identifier length -= IdentifierSize; //Adjust for the bytes read. identifierSize += IdentifierSize; //Store the SubType if needed. if (false == m_SubType.HasValue) { m_SubType = GetSubType(identifier); } } //If this is a 64 bit entry if (length == uint.MaxValue) { //use the dataSize (0 for the first node, otherwise whatever was found) length = m_DataSize; //There are so may ways to handle this it's not funny, this seems to the most documented but probably one of the ugliest. //Not to mention this doesn't really give you compatiblity and doesn't contain a failsafe. //If files can be found which still don't work I will adjust this logic as necessary. } //return a new node, Calculate length as padded size (to word boundary) return(new Node(this, new Common.MemorySegment(identifier), identifierSize, LengthSize, Position, (long)(0 != (length & 1) ? ++length : length), read >= MinimumSize && length <= (ulong)Remaining)); //determine Complete }
public static bool HasSubType(FourCharacterCode fourCC) { return(RiffReader.ParentChunks.Contains(fourCC)); }
public override IEnumerable <Track> GetTracks() { if (m_Tracks != null) { foreach (Track track in m_Tracks) { yield return(track); } yield break; } long position = Position; var tracks = new List <Track>(); int trackId = 0; if (SubType == FourCharacterCode.WAVE) { if (false == m_SampleRate.HasValue) { ParseFmt(); } Track track = new Track(ReadChunk(FourCharacterCode.data), string.Empty, (int)(Length / BlockAlign), FileInfo.CreationTimeUtc, FileInfo.LastWriteTimeUtc, BlockAlign, 0, 0, TimeSpan.Zero, TimeSpan.FromSeconds(Length / (SampleRate * Channels * BitsPerSample / Common.Binary.BitsPerByte)), m_SampleRate.Value, Sdp.MediaType.audio, Common.Binary.GetBytes(m_Format.Value, Common.Binary.IsBigEndian), (byte)m_NumChannels.Value, (byte)m_BitsPerSample.Value, true); tracks.Add(track); yield return(track); } else { //strh has all track level info, strn has stream name.. foreach (var strhChunk in ReadChunks(Root.Offset, FourCharacterCode.strh).ToArray()) { int offset = 0, sampleCount = TotalFrames, startTime = 0, timeScale = 0, duration = (int)Duration.TotalMilliseconds, width = Width, height = Height, rate = MicrosecondsPerFrame; string trackName = string.Empty; Sdp.MediaType mediaType = Sdp.MediaType.unknown; byte[] codecIndication = Media.Common.MemorySegment.EmptyBytes; byte channels = 0, bitDepth = 0; //Expect 56 Bytes FourCharacterCode fccType = (FourCharacterCode)Common.Binary.Read32(strhChunk.Data, offset, Media.Common.Binary.IsBigEndian); offset += 4; switch (fccType) { case FourCharacterCode.iavs: { //Interleaved Audio and Video //Should be audio and video samples together....? //Things like this need a Special TrackType, MediaType doens't really cut it. break; } case FourCharacterCode.vids: { //avg_frame_rate = timebase mediaType = Sdp.MediaType.video; sampleCount = ReadChunks(Root.Offset, ToFourCC(trackId.ToString("D2") + FourCharacterCode.dc.ToString()), ToFourCC(trackId.ToString("D2") + FourCharacterCode.db.ToString())).Count(); break; } case FourCharacterCode.mids: //Midi case FourCharacterCode.auds: { mediaType = Sdp.MediaType.audio; sampleCount = ReadChunks(Root.Offset, ToFourCC(trackId.ToString("D2") + FourCharacterCode.wb.ToString())).Count(); break; } case FourCharacterCode.txts: { sampleCount = ReadChunks(Root.Offset, ToFourCC(trackId.ToString("D2") + FourCharacterCode.tx.ToString())).Count(); mediaType = Sdp.MediaType.text; break; } case FourCharacterCode.data: { mediaType = Sdp.MediaType.data; break; } default: break; } //fccHandler codecIndication = strhChunk.Data.Skip(offset).Take(4).ToArray(); offset += 4 + (DWORDSIZE * 3); //Scale timeScale = Common.Binary.Read32(strhChunk.Data, offset, Media.Common.Binary.IsBigEndian); offset += 4; //Rate rate = Common.Binary.Read32(strhChunk.Data, offset, Media.Common.Binary.IsBigEndian); offset += 4; //Defaults??? Should not be hard coded.... if (false == (timeScale > 0 && rate > 0)) { rate = 25; timeScale = 1; } //Start startTime = Common.Binary.Read32(strhChunk.Data, offset, Media.Common.Binary.IsBigEndian); offset += 4; //Length of stream (as defined in rate and timeScale above) duration = Common.Binary.Read32(strhChunk.Data, offset, Media.Common.Binary.IsBigEndian); offset += 4; //SuggestedBufferSize //Quality //SampleSize //RECT rcFrame (ushort left, top, right, bottom) //Get strf for additional info. switch (mediaType) { case Sdp.MediaType.video: { using (var strf = ReadChunk(FourCharacterCode.strf, strhChunk.Offset)) { if (strf != null) { //BitmapInfoHeader //Read 32 Width width = (int)Common.Binary.ReadU32(strf.Data, 4, Media.Common.Binary.IsBigEndian); //Read 32 Height height = (int)Common.Binary.ReadU32(strf.Data, 8, Media.Common.Binary.IsBigEndian); //Maybe... //Read 16 panes //Read 16 BitDepth bitDepth = (byte)(int)Common.Binary.ReadU16(strf.Data, 14, Media.Common.Binary.IsBigEndian); //Read codec codecIndication = strf.Data.Skip(16).Take(4).ToArray(); } } break; } case Sdp.MediaType.audio: { //Expand Codec Indication based on iD? using (var strf = ReadChunk(FourCharacterCode.strf, strhChunk.Offset)) { if (strf != null) { //WaveFormat (EX) codecIndication = strf.Data.Take(2).ToArray(); channels = (byte)Common.Binary.ReadU16(strf.Data, 2, Media.Common.Binary.IsBigEndian); bitDepth = (byte)Common.Binary.ReadU16(strf.Data, 4, Media.Common.Binary.IsBigEndian); } } break; } //text format.... default: break; } using (var strn = ReadChunk(FourCharacterCode.strn, strhChunk.Offset)) { if (strn != null) { trackName = Encoding.UTF8.GetString(strn.Data, 8, (int)(strn.DataSize - 8)); } //Variable BitRate must also take into account the size of each chunk / nBlockAlign * duration per frame. Track created = new Track(strhChunk, trackName, ++trackId, Created, Modified, sampleCount, height, width, TimeSpan.FromMilliseconds(startTime / timeScale), mediaType == Sdp.MediaType.audio ? TimeSpan.FromSeconds((double)duration / (double)rate) : TimeSpan.FromMilliseconds((double)duration * m_MicroSecPerFrame.Value / (double)Media.Common.Extensions.TimeSpan.TimeSpanExtensions.MicrosecondsPerMillisecond), rate / timeScale, mediaType, codecIndication, channels, bitDepth); yield return(created); tracks.Add(created); } } } m_Tracks = tracks; Position = position; }
/// <summary> /// Instantiates a new instance. /// </summary> /// <param name="chunkId">The identification of the chunk in four characters.</param> public ChunkAttribute(string chunkId) { Check.IfArgumentNullOrEmpty(chunkId, nameof(chunkId)); ChunkId = new FourCharacterCode(chunkId); }
/// <summary> /// Helper to find the runtime Type for a chunk. /// </summary> /// <param name="context">Must not be null.</param> /// <param name="chunkId">Must not be null.</param> /// <returns>Returns null when not found.</returns> private static Type LookupItemType(ChunkFileContext context, FourCharacterCode chunkId) { var factory = context.CompositionContainer.GetService <IChunkTypeFactory>(); return(factory.LookupChunkObjectType(chunkId)); }
public void Test_FourCharacterCode_ConstructChars() { FourCharacterCode fcc = new FourCharacterCode('A', 'B', 'C', 'D'); Assert.AreEqual("ABCD", fcc.ToString()); }
/// <summary> /// Contract. /// </summary> /// <param name="chunkTypeId">Must not be null.</param> /// <returns>Can return null.</returns> Type IChunkTypeFactory.LookupChunkObjectType(FourCharacterCode chunkTypeId) { Contract.Requires(chunkTypeId != null); throw new NotImplementedException(); }
public void Test_FourCharacterCode_ConstructString() { FourCharacterCode fcc = new FourCharacterCode("ABCD"); Assert.AreEqual("ABCD", fcc.ToString()); }
public void Test_FourCharacterCode_ConstructString() { var fcc = new FourCharacterCode("ABCD"); fcc.ToString().Should().Be("ABCD"); }
public void Test_FourCharacterCode_ToInt32() { var fcc = new FourCharacterCode("ABCD"); fcc.ToInt32().Should().Be(0x41424344); }