forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Boxes.cpp
123 lines (99 loc) Β· 3.53 KB
/
Boxes.cpp
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
/*
* Copyright (c) 2023, Gregory Bertilson <Zaggy1024@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "Boxes.h"
#include "Reader.h"
#include <AK/Function.h>
namespace Gfx::ISOBMFF {
ErrorOr<BoxHeader> read_box_header(BoxStream& stream)
{
BoxHeader header;
u64 total_size = TRY(stream.read_value<BigEndian<u32>>());
header.type = TRY(stream.read_value<BigEndian<BoxType>>());
u64 data_size_read = sizeof(u32) + sizeof(BoxType);
if (total_size == 0) {
header.contents_size = stream.remaining();
} else {
if (total_size == 1) {
total_size = TRY(stream.read_value<BigEndian<u64>>());
data_size_read += sizeof(u64);
}
header.contents_size = total_size - data_size_read;
}
return header;
}
void Box::dump(String const& prepend) const
{
outln("{}{}", prepend, box_type());
}
ErrorOr<void> FullBox::read_from_stream(BoxStream& stream)
{
u32 data = TRY(stream.read_value<BigEndian<u32>>());
// unsigned int(8) version
version = static_cast<u8>(data >> 24);
// unsigned int(24) flags
flags = data & 0xFFF;
return {};
}
void FullBox::dump(String const& prepend) const
{
outln("{}{} (version = {}, flags = {:#x})", prepend, box_type(), version, flags);
}
static String add_indent(String const& string)
{
return MUST(String::formatted("{} ", string));
}
ErrorOr<void> UnknownBox::read_from_stream(BoxStream& stream)
{
m_contents_size = stream.remaining();
TRY(stream.discard_remaining());
return {};
}
void UnknownBox::dump(String const& prepend) const
{
Box::dump(prepend);
auto indented_prepend = add_indent(prepend);
outln("{}[ {} bytes ]", prepend, m_contents_size);
}
ErrorOr<void> FileTypeBox::read_from_stream(BoxStream& stream)
{
// unsigned int(32) major_brand;
major_brand = TRY(stream.read_value<BigEndian<BrandIdentifier>>());
// unsigned int(32) minor_version;
minor_version = TRY(stream.read_value<BigEndian<u32>>());
// unsigned int(32) compatible_brands[]; // to end of the box
if (stream.remaining() % sizeof(BrandIdentifier) != 0)
return Error::from_string_literal("FileTypeBox compatible_brands contains a partial brand");
for (auto minor_brand_count = stream.remaining() / sizeof(BrandIdentifier); minor_brand_count > 0; minor_brand_count--)
TRY(compatible_brands.try_append(TRY(stream.read_value<BigEndian<BrandIdentifier>>())));
return {};
}
void FileTypeBox::dump(String const& prepend) const
{
Box::dump(prepend);
auto indented_prepend = add_indent(prepend);
outln("{}- major_brand = {}", prepend, major_brand);
outln("{}- minor_version = {}", prepend, minor_version);
StringBuilder compatible_brands_string;
compatible_brands_string.append("- compatible_brands = { "sv);
for (size_t i = 0; i < compatible_brands.size() - 1; i++)
compatible_brands_string.appendff("{}, ", compatible_brands[i]);
compatible_brands_string.appendff("{} }}", compatible_brands[compatible_brands.size() - 1]);
outln("{}{}", prepend, compatible_brands_string.string_view());
}
ErrorOr<void> SuperBox::read_from_stream(BoxStream& stream, BoxCallback box_factory)
{
auto reader = TRY(Gfx::ISOBMFF::Reader::create(MaybeOwned { stream }));
m_child_boxes = TRY(reader.read_entire_file(move(box_factory)));
return {};
}
void SuperBox::dump(String const& prepend) const
{
Box::dump(prepend);
auto indented_prepend = add_indent(prepend);
for (auto const& child_box : m_child_boxes)
child_box->dump(indented_prepend);
}
}