Exemple #1
0
        public void Test_FourCharacterCode_Value()
        {
            var fcc = new FourCharacterCode("ABCD");

            fcc.Value.Should().Be("ABCD");
            fcc.ToString().Should().Be("ABCD");
        }
Exemple #2
0
        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());
        }
Exemple #5
0
        public void CtorPopulates_CreatChunk_RetrievesInternalChunkObjects_data()
        {
            var factory = CreateFactory();
            var fourcc  = new FourCharacterCode("data");

            var chunk = factory.CreateChunkObject(fourcc);

            Assert.IsNotNull(chunk);
        }
Exemple #6
0
        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);
        }
Exemple #8
0
        /// <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));
        }
Exemple #10
0
        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;
            //}
        }
Exemple #11
0
        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
        }
Exemple #12
0
 public static bool HasSubType(FourCharacterCode fourCC)
 {
     return(RiffReader.ParentChunks.Contains(fourCC));
 }
Exemple #13
0
        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);
        }
Exemple #15
0
        /// <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());
        }
Exemple #17
0
        /// <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());
        }
Exemple #19
0
        public void Test_FourCharacterCode_ConstructString()
        {
            var fcc = new FourCharacterCode("ABCD");

            fcc.ToString().Should().Be("ABCD");
        }
Exemple #20
0
        public void Test_FourCharacterCode_ToInt32()
        {
            var fcc = new FourCharacterCode("ABCD");

            fcc.ToInt32().Should().Be(0x41424344);
        }