MediaHeaderBox.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. /// Media Header Box ("mdhd")
  10. /// </summary>
  11. [Box("mdhd", "Media Header Box")]
  12. public class MediaHeaderBox : FullBox
  13. {
  14. public MediaHeaderBox() : base() { }
  15. public MediaHeaderBox(Stream stream) : base(stream) { }
  16. internal override ulong CalculateSize()
  17. {
  18. return base.CalculateSize() + (ulong)(Version == 1 ? 8 + 8 + 4 + 8 : 4 + 4 + 4 + 4) + 2 + 2;
  19. }
  20. protected override void LoadFromStream(Stream stream)
  21. {
  22. base.LoadFromStream(stream);
  23. if (Version == 1)
  24. {
  25. CreationTime = MovieHeaderBox.Convert1904Time(stream.ReadBEUInt64());
  26. ModificationTime = MovieHeaderBox.Convert1904Time(stream.ReadBEUInt64());
  27. TimeScale = stream.ReadBEUInt32();
  28. Duration = stream.ReadBEUInt64();
  29. }
  30. else // if (Version == 0)
  31. {
  32. CreationTime = MovieHeaderBox.Convert1904Time(stream.ReadBEUInt32());
  33. ModificationTime = MovieHeaderBox.Convert1904Time(stream.ReadBEUInt32());
  34. TimeScale = stream.ReadBEUInt32();
  35. Duration = stream.ReadBEUInt32();
  36. }
  37. Language = ConvertThreeLetterLanguageCode(stream.ReadBEUInt16());
  38. Predefined = stream.ReadBEUInt16();
  39. }
  40. protected override void SaveToStream(Stream stream)
  41. {
  42. base.SaveToStream(stream);
  43. if (Version == 1)
  44. {
  45. stream.WriteBEUInt64(MovieHeaderBox.Convert1904Time(CreationTime));
  46. stream.WriteBEUInt64(MovieHeaderBox.Convert1904Time(ModificationTime));
  47. stream.WriteBEUInt32(TimeScale);
  48. stream.WriteBEUInt64(Duration);
  49. }
  50. else // if (Version == 0)
  51. {
  52. stream.WriteBEUInt32((uint)MovieHeaderBox.Convert1904Time(CreationTime));
  53. stream.WriteBEUInt32((uint)MovieHeaderBox.Convert1904Time(ModificationTime));
  54. stream.WriteBEUInt32(TimeScale);
  55. stream.WriteBEUInt32((uint)Duration);
  56. }
  57. stream.WriteBEUInt16(ConvertThreeLetterLanguageCode(Language));
  58. stream.WriteBEUInt16(Predefined);
  59. }
  60. public DateTime CreationTime { get; set; }
  61. public DateTime ModificationTime { get; set; }
  62. public uint TimeScale { get; set; }
  63. public ulong Duration { get; set; }
  64. // TODO: Validate this on set.
  65. public string Language { get; set; }
  66. public ushort Predefined { get; set; }
  67. private const ushort CHARBASE = 0x0060;
  68. private const ushort CHARMASK1 = 0x7C00;
  69. private const ushort CHARMASK2 = 0x03E0;
  70. private const ushort CHARMASK3 = 0x001F;
  71. internal ushort ConvertThreeLetterLanguageCode(string language)
  72. {
  73. byte[] langBytes = Encoding.UTF8.GetBytes(language);
  74. if (langBytes.Length != 3) throw new ArgumentOutOfRangeException();
  75. return (ushort)((((langBytes[0]-CHARBASE) << 10) & CHARMASK1) | (((langBytes[1]-CHARBASE) << 5) & CHARMASK2) | (((langBytes[2]-CHARBASE) & CHARMASK3)));
  76. }
  77. internal string ConvertThreeLetterLanguageCode(ushort language)
  78. {
  79. byte[] langBytes = new byte[3];
  80. langBytes[0] = (byte)(((language & CHARMASK1) >> 10) + CHARBASE);
  81. langBytes[1] = (byte)(((language & CHARMASK2) >> 5) + CHARBASE);
  82. langBytes[2] = (byte)((language & CHARMASK3) + CHARBASE);
  83. return Encoding.UTF8.GetString(langBytes, 0, langBytes.Length);
  84. }
  85. }
  86. }