Boxes.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (c) 2023, Gregory Bertilson <Zaggy1024@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Boxes.h"
  7. #include "Reader.h"
  8. #include <AK/Function.h>
  9. namespace Gfx::ISOBMFF {
  10. ErrorOr<BoxHeader> read_box_header(BoxStream& stream)
  11. {
  12. BoxHeader header;
  13. u64 total_size = TRY(stream.read_value<BigEndian<u32>>());
  14. header.type = TRY(stream.read_value<BigEndian<BoxType>>());
  15. u64 data_size_read = sizeof(u32) + sizeof(BoxType);
  16. if (total_size == 0) {
  17. header.contents_size = stream.remaining();
  18. } else {
  19. if (total_size == 1) {
  20. total_size = TRY(stream.read_value<BigEndian<u64>>());
  21. data_size_read += sizeof(u64);
  22. }
  23. header.contents_size = total_size - data_size_read;
  24. }
  25. return header;
  26. }
  27. void Box::dump(String const& prepend) const
  28. {
  29. outln("{}{}", prepend, box_type());
  30. }
  31. ErrorOr<void> FullBox::read_from_stream(BoxStream& stream)
  32. {
  33. u32 data = TRY(stream.read_value<BigEndian<u32>>());
  34. // unsigned int(8) version
  35. version = static_cast<u8>(data >> 24);
  36. // unsigned int(24) flags
  37. flags = data & 0xFFF;
  38. return {};
  39. }
  40. void FullBox::dump(String const& prepend) const
  41. {
  42. outln("{}{} (version = {}, flags = {:#x})", prepend, box_type(), version, flags);
  43. }
  44. static String add_indent(String const& string)
  45. {
  46. return MUST(String::formatted("{} ", string));
  47. }
  48. ErrorOr<void> UnknownBox::read_from_stream(BoxStream& stream)
  49. {
  50. m_contents_size = stream.remaining();
  51. TRY(stream.discard_remaining());
  52. return {};
  53. }
  54. void UnknownBox::dump(String const& prepend) const
  55. {
  56. Box::dump(prepend);
  57. auto indented_prepend = add_indent(prepend);
  58. outln("{}[ {} bytes ]", prepend, m_contents_size);
  59. }
  60. ErrorOr<void> FileTypeBox::read_from_stream(BoxStream& stream)
  61. {
  62. // unsigned int(32) major_brand;
  63. major_brand = TRY(stream.read_value<BigEndian<BrandIdentifier>>());
  64. // unsigned int(32) minor_version;
  65. minor_version = TRY(stream.read_value<BigEndian<u32>>());
  66. // unsigned int(32) compatible_brands[]; // to end of the box
  67. if (stream.remaining() % sizeof(BrandIdentifier) != 0)
  68. return Error::from_string_literal("FileTypeBox compatible_brands contains a partial brand");
  69. for (auto minor_brand_count = stream.remaining() / sizeof(BrandIdentifier); minor_brand_count > 0; minor_brand_count--)
  70. TRY(compatible_brands.try_append(TRY(stream.read_value<BigEndian<BrandIdentifier>>())));
  71. return {};
  72. }
  73. void FileTypeBox::dump(String const& prepend) const
  74. {
  75. Box::dump(prepend);
  76. auto indented_prepend = add_indent(prepend);
  77. outln("{}- major_brand = {}", prepend, major_brand);
  78. outln("{}- minor_version = {}", prepend, minor_version);
  79. StringBuilder compatible_brands_string;
  80. compatible_brands_string.append("- compatible_brands = { "sv);
  81. for (size_t i = 0; i < compatible_brands.size() - 1; i++)
  82. compatible_brands_string.appendff("{}, ", compatible_brands[i]);
  83. compatible_brands_string.appendff("{} }}", compatible_brands[compatible_brands.size() - 1]);
  84. outln("{}{}", prepend, compatible_brands_string.string_view());
  85. }
  86. ErrorOr<void> SuperBox::read_from_stream(BoxStream& stream, BoxCallback box_factory)
  87. {
  88. auto reader = TRY(Gfx::ISOBMFF::Reader::create(MaybeOwned { stream }));
  89. m_child_boxes = TRY(reader.read_entire_file(move(box_factory)));
  90. return {};
  91. }
  92. void SuperBox::dump(String const& prepend) const
  93. {
  94. Box::dump(prepend);
  95. auto indented_prepend = add_indent(prepend);
  96. for (auto const& child_box : m_child_boxes)
  97. child_box->dump(indented_prepend);
  98. }
  99. ErrorOr<void> UserExtensionBox::read_from_stream(BoxStream& stream)
  100. {
  101. // unsigned int(8)[16] uuid;
  102. TRY(stream.read_until_filled(uuid));
  103. // unsigned int(8) data[];
  104. data = TRY(ByteBuffer::create_uninitialized(stream.remaining()));
  105. TRY(stream.read_until_filled(data));
  106. return {};
  107. }
  108. void UserExtensionBox::dump(String const& prepend) const
  109. {
  110. Box::dump(prepend);
  111. auto indented_prepend = add_indent(prepend);
  112. out("{}- uuid = ", prepend);
  113. for (auto byte : uuid)
  114. out("{:02x}"sv, byte);
  115. outln();
  116. outln("{}- data = [ {} bytes ]", prepend, data.size());
  117. }
  118. }