LibGfx/ISOBMFF: Give Reader::read_entire_file() a factory callback

This will allow creating different child boxes in different containers.
This commit is contained in:
Nico Weber 2024-03-22 14:26:56 -04:00 committed by Tim Schumacher
parent b7a120c47e
commit 78deac3dca
Notes: sideshowbarker 2024-07-17 03:14:39 +09:00
5 changed files with 36 additions and 16 deletions

View file

@ -6,6 +6,7 @@
#include "Boxes.h"
#include "Reader.h"
#include <AK/Function.h>
namespace Gfx::ISOBMFF {
@ -104,10 +105,10 @@ void FileTypeBox::dump(String const& prepend) const
outln("{}{}", prepend, compatible_brands_string.string_view());
}
ErrorOr<void> SuperBox::read_from_stream(BoxStream& stream)
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());
m_child_boxes = TRY(reader.read_entire_file(move(box_factory)));
return {};
}

View file

@ -95,7 +95,9 @@ struct FileTypeBox final : public Box {
// A box that contains other boxes.
struct SuperBox : public Box {
SuperBox() = default;
ErrorOr<void> read_from_stream(BoxStream&);
using BoxCallback = Function<ErrorOr<Optional<NonnullOwnPtr<Box>>>(BoxType, BoxStream&)>;
ErrorOr<void> read_from_stream(BoxStream&, BoxCallback);
virtual void dump(String const& prepend = {}) const override;
private:

View file

@ -5,12 +5,17 @@
*/
#include "JPEG2000Boxes.h"
#include <AK/Function.h>
namespace Gfx::ISOBMFF {
ErrorOr<void> JPEG2000HeaderBox::read_from_stream(BoxStream& stream)
{
TRY(SuperBox::read_from_stream(stream));
auto make_subbox = [](BoxType, BoxStream&) -> ErrorOr<Optional<NonnullOwnPtr<Box>>> {
return OptionalNone {};
};
TRY(SuperBox::read_from_stream(stream, move(make_subbox)));
return {};
}

View file

@ -22,6 +22,23 @@ ErrorOr<Reader> Reader::create(MaybeOwned<BoxStream> stream)
}
ErrorOr<BoxList> Reader::read_entire_file()
{
auto make_top_level_box = [](BoxType type, BoxStream& stream) -> ErrorOr<Optional<NonnullOwnPtr<Box>>> {
switch (type) {
case BoxType::FileTypeBox:
return TRY(FileTypeBox::create_from_stream(stream));
case BoxType::JPEG2000HeaderBox:
return TRY(JPEG2000HeaderBox::create_from_stream(stream));
case BoxType::JPEG2000SignatureBox:
return TRY(JPEG2000SignatureBox::create_from_stream(stream));
default:
return OptionalNone {};
}
};
return read_entire_file((ErrorOr<Optional<NonnullOwnPtr<Box>>>(*)(BoxType, BoxStream&))(make_top_level_box));
}
ErrorOr<BoxList> Reader::read_entire_file(BoxCallback box_factory)
{
BoxList top_level_boxes;
@ -29,19 +46,11 @@ ErrorOr<BoxList> Reader::read_entire_file()
auto box_header = TRY(read_box_header(*m_box_stream));
BoxStream box_stream { MaybeOwned<Stream> { *m_box_stream }, static_cast<size_t>(box_header.contents_size) };
switch (box_header.type) {
case BoxType::FileTypeBox:
TRY(top_level_boxes.try_append(TRY(FileTypeBox::create_from_stream(box_stream))));
break;
case BoxType::JPEG2000HeaderBox:
TRY(top_level_boxes.try_append(TRY(JPEG2000HeaderBox::create_from_stream(box_stream))));
break;
case BoxType::JPEG2000SignatureBox:
TRY(top_level_boxes.try_append(TRY(JPEG2000SignatureBox::create_from_stream(box_stream))));
break;
default:
auto maybe_box = TRY(box_factory(box_header.type, box_stream));
if (maybe_box.has_value()) {
TRY(top_level_boxes.try_append(move(maybe_box.value())));
} else {
TRY(top_level_boxes.try_append(TRY(UnknownBox::create_from_stream(box_header.type, box_stream))));
break;
}
if (!box_stream.is_eof())

View file

@ -20,6 +20,9 @@ public:
ErrorOr<BoxList> read_entire_file();
using BoxCallback = Function<ErrorOr<Optional<NonnullOwnPtr<Box>>>(BoxType, BoxStream&)>;
ErrorOr<BoxList> read_entire_file(BoxCallback);
private:
Reader(MaybeOwned<BoxStream> stream)
: m_box_stream(move(stream))