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 "Boxes.h"
#include "Reader.h" #include "Reader.h"
#include <AK/Function.h>
namespace Gfx::ISOBMFF { namespace Gfx::ISOBMFF {
@ -104,10 +105,10 @@ void FileTypeBox::dump(String const& prepend) const
outln("{}{}", prepend, compatible_brands_string.string_view()); 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 })); 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 {}; return {};
} }

View file

@ -95,7 +95,9 @@ struct FileTypeBox final : public Box {
// A box that contains other boxes. // A box that contains other boxes.
struct SuperBox : public Box { struct SuperBox : public Box {
SuperBox() = default; 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; virtual void dump(String const& prepend = {}) const override;
private: private:

View file

@ -5,12 +5,17 @@
*/ */
#include "JPEG2000Boxes.h" #include "JPEG2000Boxes.h"
#include <AK/Function.h>
namespace Gfx::ISOBMFF { namespace Gfx::ISOBMFF {
ErrorOr<void> JPEG2000HeaderBox::read_from_stream(BoxStream& stream) 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 {}; return {};
} }

View file

@ -22,6 +22,23 @@ ErrorOr<Reader> Reader::create(MaybeOwned<BoxStream> stream)
} }
ErrorOr<BoxList> Reader::read_entire_file() 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; BoxList top_level_boxes;
@ -29,19 +46,11 @@ ErrorOr<BoxList> Reader::read_entire_file()
auto box_header = TRY(read_box_header(*m_box_stream)); 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) }; BoxStream box_stream { MaybeOwned<Stream> { *m_box_stream }, static_cast<size_t>(box_header.contents_size) };
switch (box_header.type) { auto maybe_box = TRY(box_factory(box_header.type, box_stream));
case BoxType::FileTypeBox: if (maybe_box.has_value()) {
TRY(top_level_boxes.try_append(TRY(FileTypeBox::create_from_stream(box_stream)))); TRY(top_level_boxes.try_append(move(maybe_box.value())));
break; } else {
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:
TRY(top_level_boxes.try_append(TRY(UnknownBox::create_from_stream(box_header.type, box_stream)))); TRY(top_level_boxes.try_append(TRY(UnknownBox::create_from_stream(box_header.type, box_stream))));
break;
} }
if (!box_stream.is_eof()) if (!box_stream.is_eof())

View file

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