MovieHeaderBox.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. namespace MatrixIO.IO.Bmff.Boxes
  7. {
  8. /// <summary>
  9. /// Movie Header Box ("mvhd")
  10. /// </summary>
  11. [Box("mvhd", "Movie Header Box")]
  12. public class MovieHeaderBox : FullBox
  13. {
  14. public MovieHeaderBox() : base()
  15. {
  16. _Rate = 0x00010000; // 1.0 normal rate
  17. _Volume = 0x0100; // 1.0 full volume
  18. Matrix = new int[] { 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 }; // Unity Matrix
  19. }
  20. public MovieHeaderBox(Stream stream) : base(stream) { }
  21. internal override ulong CalculateSize()
  22. {
  23. return base.CalculateSize() +
  24. (ulong)(Version == 1 ? 8 + 8 + 4 + 8 : 4 + 4 + 4 + 4) + 4 + 2 + 2 + (2 * 4) + (9 * 4) + (6 * 4) + 4;
  25. }
  26. protected override void LoadFromStream(Stream stream)
  27. {
  28. base.LoadFromStream(stream);
  29. if (Version == 1)
  30. {
  31. _CreationTime = stream.ReadBEUInt64();
  32. _ModificationTime = stream.ReadBEUInt64();
  33. TimeScale = stream.ReadBEUInt32();
  34. Duration = stream.ReadBEUInt64();
  35. }
  36. else // if(Version == 0)
  37. {
  38. _CreationTime = stream.ReadBEUInt32();
  39. _ModificationTime = stream.ReadBEUInt32();
  40. TimeScale = stream.ReadBEUInt32();
  41. Duration = stream.ReadBEUInt32();
  42. }
  43. _Rate = stream.ReadBEInt32();
  44. _Volume = stream.ReadBEInt16();
  45. Reserved = stream.ReadBytes(2 + (2 * 4));
  46. for (int i = 0; i < 9; i++) Matrix[i] = stream.ReadBEInt32();
  47. PreDefined = stream.ReadBytes(6 * 4);
  48. NextTrackID = stream.ReadBEUInt32();
  49. }
  50. protected override void SaveToStream(Stream stream)
  51. {
  52. if (Version==0 &&
  53. (_CreationTime > uint.MaxValue ||
  54. _ModificationTime > uint.MaxValue ||
  55. Duration > uint.MaxValue)) Version = 1;
  56. base.SaveToStream(stream);
  57. if (Version == 1)
  58. {
  59. stream.WriteBEUInt64(_CreationTime);
  60. stream.WriteBEUInt64(_ModificationTime);
  61. stream.WriteBEUInt32(TimeScale);
  62. stream.WriteBEUInt64(Duration);
  63. }
  64. else // if(Version == 0)
  65. {
  66. stream.WriteBEUInt32(checked((uint)_CreationTime));
  67. stream.WriteBEUInt32(checked((uint)_ModificationTime));
  68. stream.WriteBEUInt32(TimeScale);
  69. stream.WriteBEUInt32(checked((uint)Duration));
  70. }
  71. stream.WriteBEInt32(_Rate);
  72. stream.WriteBEInt16(_Volume);
  73. stream.WriteBytes(Reserved);
  74. for (int i = 0; i < 9; i++) stream.WriteBEInt32(Matrix[i]);
  75. stream.WriteBytes(PreDefined);
  76. stream.WriteBEUInt32(NextTrackID);
  77. }
  78. private ulong _CreationTime;
  79. public DateTime CreationTime
  80. {
  81. get
  82. {
  83. return Convert1904Time(_CreationTime);
  84. }
  85. set
  86. {
  87. _CreationTime = Convert1904Time(value);
  88. }
  89. }
  90. private ulong _ModificationTime;
  91. public DateTime ModificationTime
  92. {
  93. get
  94. {
  95. return Convert1904Time(_ModificationTime);
  96. }
  97. set
  98. {
  99. _ModificationTime = Convert1904Time(value);
  100. }
  101. }
  102. public uint TimeScale { get; set; }
  103. public ulong Duration { get; set; }
  104. private int _Rate;
  105. public double Rate
  106. {
  107. get
  108. {
  109. return (double)_Rate / ((int)ushort.MaxValue + 1);
  110. }
  111. set
  112. {
  113. _Rate = checked((int)Math.Round(value * ((int)short.MaxValue + 1)));
  114. }
  115. }
  116. private short _Volume;
  117. public double Volume
  118. {
  119. get
  120. {
  121. return (double)_Volume / ((int)byte.MaxValue + 1);
  122. }
  123. set
  124. {
  125. _Volume = checked((short)Math.Round(value * ((int)byte.MaxValue + 1)));
  126. }
  127. }
  128. public byte[] Reserved { get; private set; }
  129. public int[] Matrix { get; private set; }
  130. public byte[] PreDefined { get; private set; }
  131. public uint NextTrackID { get; set; }
  132. internal static readonly DateTime _1904BaseTime = new DateTime(1904, 1, 1);
  133. internal static DateTime Convert1904Time(ulong secondsSince1904)
  134. {
  135. return _1904BaseTime + TimeSpan.FromSeconds(checked((double)secondsSince1904));
  136. }
  137. internal static ulong Convert1904Time(DateTime time)
  138. {
  139. return checked((ulong)Math.Round((time - _1904BaseTime).TotalSeconds));
  140. }
  141. }
  142. }