File: BoxHeader.cs

package info (click to toggle)
banshee 0.11.2%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 11,976 kB
  • ctags: 9,958
  • sloc: cs: 54,529; xml: 21,240; sh: 8,835; ansic: 2,040; makefile: 1,248
file content (177 lines) | stat: -rw-r--r-- 5,981 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
namespace TagLib.Mpeg4
{
   public class BoxHeader
   {
      //////////////////////////////////////////////////////////////////////////
      // private properties
      //////////////////////////////////////////////////////////////////////////
      private File       file;
      private long       position;
      
      private ByteVector box_type;
      private ByteVector extended_type;
      private ulong      large_size;
      private uint       size;
      
      //////////////////////////////////////////////////////////////////////////
      // public methods
      //////////////////////////////////////////////////////////////////////////
      
      // Create a new header and read its info from the file.
      public BoxHeader (File file, long position)
      {
         this.file      = file;
         this.position  = position;
         box_type       = null;
         extended_type  = null;
         large_size     = 0;
         size           = 0;
         
         Read ();
      }
      
      // Create a new header with the provided box type.
      public BoxHeader (ByteVector type)
      {
         this.file      = null;
         this.position  = -1;
         box_type       = type;
         extended_type  = null;
         large_size     = 0;
         size           = 0;
      }
      
      // Render the box header and try to keep the size the same.
      public ByteVector Render ()
      {
         // The size is zero because the box header was created not read.
         // Increase the sizes to account for this.
         if (size == 0)
         {
            size = (uint) (extended_type != null ? 24 : 8);
            large_size += size;
         }
         
         // Enlarge for large size if necessary. If large size is in use, the
         // header will be 16 or 32 big as opposed to 8 or 24.
         if ((size == 8 || size == 24) && large_size > System.UInt32.MaxValue)
         {
            size += 8;
            large_size += 8;
         }
         
         // Get ready to output.
         ByteVector output = new ByteVector ();
         
         // Add the box size and type to the output.
         output += ByteVector.FromUInt ((size == 8 || size == 24) ? (uint) large_size : 1);
         output += box_type;
         
         // If the box size is 16 or 32, we must have more a large header to
         // append.
         if (size == 16 || size == 32)
            output += ByteVector.FromLong ((long) large_size);
         
         // The only reason for such a big size is an extended type. Extend!!!
         if (size >= 24)
            output += (extended_type != null) ? extended_type.Mid (0, 16) : new ByteVector (16);
         
         return output;
      }
      
      // Get header information from the file.
      private void Read ()
      {
         // How much can we actually read?
         long space_available = file.Length - position;
         
         // The size has to be at least 8.
         size = 8;
         
         // If we can't read that much, return.
         if (space_available < size)
            return;
         
         // Get into position.
         file.Seek (position);
         
         // Read the size and type of the block.
         large_size = file.ReadBlock (4).ToUInt ();
         box_type = file.ReadBlock (4);
         
         // If the size is zero, the block includes the rest of the file.
         if (large_size == 0)
            large_size = (ulong) space_available;
         // If the size is 1, that just tells us we have a massive ULONG size
         // waiting for us in the next 8 bytes.
         else if (large_size == 1)
         {
            // The size is 8 bigger.
            size += 8;
            
            // If we don't have room, we're lost. Abort.
            if (space_available < size)
            {
               large_size = 0;
               return;
            }
            
            // This file is huge. 4GB+ I don't think we can even read it.
            large_size = (ulong) file.ReadBlock (8).ToLong ();
         }
         
         // UUID has a special header with 16 extra bytes.
         if (box_type == "uuid")
         {
            // Size is 16 bigger.
            size += 16;
            
            // If we don't have room, we're lost. Abort.
            if (space_available < size)
            {
               large_size = 0;
               return;
            }
            
            // Load the extended type.
            extended_type = file.ReadBlock (16);
         }
      }
      
      //////////////////////////////////////////////////////////////////////////
      // public properties
      //////////////////////////////////////////////////////////////////////////
      
      // The file the data is loaded from.
      public File File               {get {return file;}}
      
      // If data was read, then the size is non-zero. If the size is non-zero,
      // the header is valid. p-> q -> r.
      public bool  IsValid           {get {return large_size != 0;}}
      
      // the box's type.
      public ByteVector BoxType      {get {return box_type;}}
      
      // The extended type (for UUID only)
      public ByteVector ExtendedType {get {return extended_type;}}

      // The total size of the box.
      public ulong BoxSize           {get {return large_size;}}
      
      // The size of the header.
      public uint  HeaderSize        {get {return size;}}
      
      // The size of the data.
      public ulong DataSize          {get {return large_size - size;} set {large_size = value + size;}}
      
      // The position of the box.
      public long Position           {get {return position;}}
      
      // The position of the data.
      public long DataPosition       {get {return position + size;}}
      
      // the position of the next box.
      public long NextBoxPosition    {get {return (long) (position + (long) large_size);}}
      
   }
}