BmffReader.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using MatrixIO.IO.Bmff;
  7. namespace MatrixIO.IO.Bmff
  8. {
  9. public class BmffReader : ISuperBox, IEnumerable<Box>
  10. {
  11. private readonly Stream _baseStream;
  12. public Stream BaseStream { get { return _baseStream; } }
  13. private IList<Box> _rootBoxes;
  14. public IList<Box> RootBoxes
  15. {
  16. get
  17. {
  18. #pragma warning disable 612,618
  19. if (_rootBoxes == null) return _rootBoxes = Portability.CreateList<Box>(GetBoxes());
  20. #pragma warning restore 612,618
  21. return _rootBoxes;
  22. }
  23. }
  24. public bool RandomAccess { get { return _baseStream.CanSeek; } }
  25. #region Navigation
  26. private readonly Stack<Box> _boxStack = new Stack<Box>();
  27. public int Depth
  28. {
  29. get
  30. {
  31. return _boxStack.Count;
  32. }
  33. }
  34. public Box CurrentBox
  35. {
  36. get
  37. {
  38. return _boxStack.Peek();
  39. }
  40. }
  41. public bool HasChildren
  42. {
  43. get
  44. {
  45. if (CurrentBox is ISuperBox) return true;
  46. else return false;
  47. }
  48. }
  49. #endregion
  50. public BmffReader(Stream stream)
  51. {
  52. if (stream.CanSeek && stream.Position!=0) stream.Seek(0, SeekOrigin.Begin);
  53. _baseStream = stream;
  54. }
  55. [Obsolete("Use the BaseMedia class instead.")]
  56. public void Scan()
  57. {
  58. GetBoxes();
  59. }
  60. /// <summary>
  61. /// Traverses the tree of Boxes in file order (depth-first)
  62. /// </summary>
  63. /// <returns>IEnumerable collection of Box types in file order.</returns>
  64. [Obsolete("Use the BaseMedia class instead.")]
  65. public IEnumerable<Box> GetBoxes()
  66. {
  67. Box box = null;
  68. do
  69. {
  70. box = Box.FromStream(_baseStream);
  71. if (box != null) yield return box;
  72. } while (box != null);
  73. }
  74. /// <summary>
  75. /// Seeks to the beginning of the file and reads the "ftyp" Box.
  76. /// </summary>
  77. /// <returns>FileTypeBox</returns>
  78. [Obsolete]
  79. public Boxes.FileTypeBox GetFileTypeBox()
  80. {
  81. if (_baseStream.CanSeek && _baseStream.Position!=0) _baseStream.Seek(0, SeekOrigin.Begin);
  82. // TODO: Support files where "ftyp" is not the first FourCC like JPEG2000.
  83. return Box.FromStream<Boxes.FileTypeBox>(_baseStream);
  84. }
  85. /// <summary>
  86. /// Seek to the end of the file and returns the "mfro" Box for a Microsoft Smooth Streaming PIFF format file that gives
  87. /// you the chunk offsets within the file.
  88. /// </summary>
  89. /// <returns>MovieFragmentRandomAccessBox</returns>
  90. // TODO: Move to a new MatrixIO.IO.Piff.??? class
  91. public Boxes.MovieFragmentRandomAccessBox GetMovieFragmentRandomAccessBox()
  92. {
  93. _baseStream.Seek(-24, SeekOrigin.End);
  94. byte[] mfrobuf = _baseStream.ReadBytes(24);
  95. uint mfraOffset;
  96. if (BitConverter.ToUInt32(mfrobuf, 12).NetworkToHostOrder() == 0x6d66726f ||
  97. BitConverter.ToUInt32(mfrobuf, 4).NetworkToHostOrder() == 0x6d66726f) // 'mfro'
  98. {
  99. mfraOffset = BitConverter.ToUInt32(mfrobuf, 20).NetworkToHostOrder();
  100. }
  101. else return null;
  102. _baseStream.Seek(-mfraOffset, SeekOrigin.End);
  103. return new Boxes.MovieFragmentRandomAccessBox(_baseStream);
  104. }
  105. [Obsolete("Use the BaseMedia class instead.")]
  106. IList<Box> ISuperBox.Children
  107. {
  108. get { return RootBoxes; }
  109. }
  110. [Obsolete("Use the BaseMedia class instead.")]
  111. IEnumerator<Box> IEnumerable<Box>.GetEnumerator()
  112. {
  113. return RootBoxes.GetEnumerator();
  114. }
  115. [Obsolete("Use the BaseMedia class instead.")]
  116. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  117. {
  118. return RootBoxes.GetEnumerator();
  119. }
  120. }
  121. }