static void Main(string[] args) { const int indent = 4; long totalSize = 0; int totalBoxes = 0; long mediaData = 0; long totalFreeBoxSpace = 0; using (FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read)) { using (Mpeg4TagBoxAwareReader reader = new Mpeg4TagBoxAwareReader(fs)) { while (reader.Read()) { Console.WriteLine("Box {1} @ {2} of size: {3}, ends @ {4} {5}".PadLeft(reader.Depth * indent), reader.GetTypeAsString(), reader.BoxPosition, reader.CalculatedSize + (reader.Size == 0 ? " (0*)" : string.Empty), reader.BoxPosition + reader.CalculatedSize, (reader.IsRecognizedType && reader.IsRecognizedVersion.GetValueOrDefault(true)) ? string.Empty : "~"); if (reader.Depth == 0) { totalSize += reader.CalculatedSize; } if (reader.TypeString == "mdat") { mediaData = reader.CalculatedSize; } if (reader.TypeString == "free" || reader.TypeString == "skip") { totalFreeBoxSpace += reader.CalculatedSize; } totalBoxes++; } Console.WriteLine(" (*)denotes length of atom goes to End-of-File"); Console.WriteLine(); Console.WriteLine(" ~ denotes an unknown box"); Console.WriteLine("------------------------------------------------------"); Console.WriteLine("Total size: {0} bytes; {1} atoms total.", totalSize, totalBoxes); Console.WriteLine("Media data: {0} bytes; {1} bytes all other boxes ({2} box overhead).", mediaData, totalSize - mediaData, ((totalSize - mediaData) / (double)totalSize).ToString("0.000%")); Console.WriteLine("Total free box space: {0} bytes; {1} waste. Padding avaliable: {2} bytes.", totalFreeBoxSpace, (totalFreeBoxSpace / (double)totalSize).ToString("0.000%"), "?"); Console.WriteLine("------------------------------------------------------"); Console.ReadLine(); } } }
static void Main(string[] args) { string[] moovMeta = new string[] { "moov", "udta", "meta" }; string[] appleTagPath = new string[] { "moov", "udta", "meta", "ilst" }; bool foundUserDataBox = false; uint? handlerType = null; Tags tags = new Tags(); Tags currentTags = new Tags(); const string s1 = @"D:\Users\Jonathan\Videos\test.m4v"; const string s3 = @"D:\Users\Jonathan\Documents\Expression\Expression Encoder\Output\JONATHAN-PC 10-12-2010 4.31.43 AM\d.mp4"; const string s2 = @"D:\Users\Jonathan\Documents\Visual Studio 2010\Projects\IsoBaseMediaFormatParser\trailer.m4v"; using (FileStream fs = new FileStream(s3, FileMode.Open, FileAccess.Read)) { using (FileStream output = new FileStream(@"test.m4v", FileMode.Create, FileAccess.Write)) { Stack <KeyValuePair <uint, bool> > boxes = new Stack <KeyValuePair <uint, bool> >(); IsoBaseMediaFileFormatReader reader = new Mpeg4TagBoxAwareReader(fs); IsoBaseMediaFormatWriter writer = new IsoBaseMediaFormatWriter(output); bool foundMetaPath = false; bool endOnMetaPath = false; int previousMetaPathLength = 0; while (reader.Read()) { while (boxes.Count > reader.Depth) { if (boxes.Peek().Value) { writer.WriteEndBox(); } boxes.Pop(); } if (reader.Depth == boxes.Count) { boxes.Push(new KeyValuePair <uint, bool>(reader.Type, false)); } var boxTypes = boxes.Reverse().Select(b => Conversions.GetTypeAsString(b.Key)).ToArray(); int onMetaPathLength = OnPath(moovMeta, boxTypes); foundMetaPath = foundMetaPath || onMetaPathLength > 0; endOnMetaPath = foundMetaPath && onMetaPathLength < previousMetaPathLength; foundUserDataBox = foundUserDataBox || onMetaPathLength == 2; if (endOnMetaPath) { if ((handlerType.HasValue && Conversions.GetTypeAsString(handlerType.Value) == "mdir")) { foreach (string tag in currentTags.tags.Keys) { if (!tags.tags.ContainsKey(tag)) { tags.tags.Add(tag, currentTags.tags[tag]); } } } if (!foundUserDataBox) { writer.WriteStartBox("udta"); } WriteMeta(writer, tags); if (!foundUserDataBox) { writer.WriteEndBox(); } } if (reader.GetTypeAsString() == "Xtra") { using (MemoryStream ms = new MemoryStream()) { byte[] buffer = new byte[4096]; int byteCount; while ((byteCount = reader.ReadContent(buffer, 0, buffer.Length)) != 0) { ms.Write(buffer, 0, byteCount); } ms.Position = 0; while (ms.Position < ms.Length) { var obj = Mpeg4Tagging.WindowsMedia.ContentDescriptor.Parse(ms); Console.WriteLine("Name: " + obj.Name); Console.WriteLine("Data: " + obj.GetValueAsObject().ToString() + ":"); } } } if (OnPath(moovMeta, boxTypes) == 3 && reader.GetTypeAsString() == "hdlr") { reader.ReadContentAsUnsignedInt32(); handlerType = reader.ReadContentAsUnsignedInt32(); reader.ReadContent(new byte[12], 0, 12); byte[] buffer = new byte[reader.Size]; int bytesRead = reader.ReadContent(buffer, 0, buffer.Length); Console.WriteLine("Handler"); Console.WriteLine(" Type: " + Conversions.GetTypeAsString(handlerType.Value)); Console.WriteLine(" Name: " + Encoding.UTF8.GetString(buffer, 0, bytesRead)); } if (OnPath(appleTagPath, boxTypes) >= appleTagPath.Length && reader.GetTypeAsString() == "data") { byte[] flags = new byte[4]; reader.Flags.CopyTo(flags, 1); flags = BitConverter.IsLittleEndian ? flags.Reverse().ToArray() : flags; uint flagsValue = BitConverter.ToUInt32(flags, 0); object data = ReadData(reader); /* if (data is byte[]) * Console.WriteLine(BitConverter.ToString(data as byte[])); * else * Console.WriteLine(data); */ currentTags.SetData(Conversions.GetTypeAsString(reader.Container.Value), data); } else if (onMetaPathLength < moovMeta.Length) { Console.WriteLine(string.Join("->", boxTypes)); if (reader.IsRecognizedType && reader.IsFullBox) { writer.WriteStartFullBox(reader.Type, reader.Version.Value, reader.Flags); } else { writer.WriteStartBox(reader.Type, reader.UserType); } if (!reader.IsContainer) { int bytesRead; byte[] buffer = new byte[4096]; while ((bytesRead = reader.ReadContent(buffer, 0, buffer.Length)) > 0) { writer.WriteContent(buffer, 0, bytesRead); } } boxes.Push(new KeyValuePair <uint, bool>(boxes.Pop().Key, true)); } previousMetaPathLength = onMetaPathLength; } } } Console.ReadLine(); }