1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 11:07:35 +00:00

LibVideo: Reorganize demuxer file hierarchy and rename Matroska files

As new demuxers are added, this will get quite full of files, so it'll
be good to have a separate folder for these.

To avoid too many chained namespaces, the Containers subdirectory is
not also a namespace, but the Matroska folder is for the sake of
separating the multiple classes for parsed information entering the
Video namespace.
This commit is contained in:
Zaggy1024 2022-11-09 19:47:56 -06:00 committed by Andreas Kling
parent edec6bdc32
commit 9cf7e8c5aa
13 changed files with 56 additions and 58 deletions

View file

@ -4,12 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibVideo/MatroskaReader.h> #include <LibVideo/Containers/Matroska/Reader.h>
#include <stddef.h> #include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(u8 const* data, size_t size) extern "C" int LLVMFuzzerTestOneInput(u8 const* data, size_t size)
{ {
auto matroska_document = Video::MatroskaReader::parse_matroska_from_data(data, size); auto matroska_document = Video::Matroska::Reader::parse_matroska_from_data(data, size);
if (!matroska_document) if (!matroska_document)
return -1; return -1;
return 0; return 0;

View file

@ -6,14 +6,14 @@
#include <LibTest/TestCase.h> #include <LibTest/TestCase.h>
#include <LibVideo/MatroskaReader.h> #include <LibVideo/Containers/Matroska/Reader.h>
#include <LibVideo/VP9/Decoder.h> #include <LibVideo/VP9/Decoder.h>
static void decode_video(StringView path, size_t expected_frame_count) static void decode_video(StringView path, size_t expected_frame_count)
{ {
auto matroska_document = Video::MatroskaReader::MatroskaReader::parse_matroska_from_file(path); auto matroska_document = Video::Matroska::Reader::parse_matroska_from_file(path);
VERIFY(matroska_document); VERIFY(matroska_document);
auto video_track_optional = matroska_document->track_for_track_type(Video::TrackEntry::TrackType::Video); auto video_track_optional = matroska_document->track_for_track_type(Video::Matroska::TrackEntry::TrackType::Video);
VERIFY(video_track_optional.has_value()); VERIFY(video_track_optional.has_value());
auto video_track_entry = video_track_optional.value(); auto video_track_entry = video_track_optional.value();

View file

@ -4,8 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include "LibVideo/Color/CodingIndependentCodePoints.h"
#include "LibVideo/MatroskaDemuxer.h"
#include <LibCore/ArgsParser.h> #include <LibCore/ArgsParser.h>
#include <LibGUI/Application.h> #include <LibGUI/Application.h>
#include <LibGUI/Icon.h> #include <LibGUI/Icon.h>

View file

@ -2,8 +2,8 @@ set(SOURCES
Color/ColorConverter.cpp Color/ColorConverter.cpp
Color/ColorPrimaries.cpp Color/ColorPrimaries.cpp
Color/TransferCharacteristics.cpp Color/TransferCharacteristics.cpp
MatroskaDemuxer.cpp Containers/Matroska/MatroskaDemuxer.cpp
MatroskaReader.cpp Containers/Matroska/Reader.cpp
PlaybackManager.cpp PlaybackManager.cpp
VideoFrame.cpp VideoFrame.cpp
VP9/BitStream.cpp VP9/BitStream.cpp

View file

@ -8,10 +8,9 @@
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <LibCore/Object.h> #include <LibCore/Object.h>
#include <LibVideo/DecoderError.h>
#include "DecoderError.h" #include <LibVideo/Sample.h>
#include "Sample.h" #include <LibVideo/Track.h>
#include "Track.h"
namespace Video { namespace Video {

View file

@ -15,7 +15,7 @@
#include <AK/Utf8View.h> #include <AK/Utf8View.h>
#include <LibVideo/Color/CodingIndependentCodePoints.h> #include <LibVideo/Color/CodingIndependentCodePoints.h>
namespace Video { namespace Video::Matroska {
struct EBMLHeader { struct EBMLHeader {
String doc_type; String doc_type;

View file

@ -6,12 +6,12 @@
#include "MatroskaDemuxer.h" #include "MatroskaDemuxer.h"
namespace Video { namespace Video::Matroska {
DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(StringView filename) DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(StringView filename)
{ {
// FIXME: MatroskaReader should return errors. // FIXME: MatroskaReader should return errors.
auto nullable_document = MatroskaReader::parse_matroska_from_file(filename); auto nullable_document = Reader::parse_matroska_from_file(filename);
if (!nullable_document) if (!nullable_document)
return DecoderError::format(DecoderErrorCategory::IO, "Failed to open matroska from file '{}'", filename); return DecoderError::format(DecoderErrorCategory::IO, "Failed to open matroska from file '{}'", filename);
auto document = nullable_document.release_nonnull(); auto document = nullable_document.release_nonnull();
@ -21,7 +21,7 @@ DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(String
DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_data(ReadonlyBytes data) DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_data(ReadonlyBytes data)
{ {
// FIXME: MatroskaReader should return errors. // FIXME: MatroskaReader should return errors.
auto nullable_document = MatroskaReader::parse_matroska_from_data(data.data(), data.size()); auto nullable_document = Reader::parse_matroska_from_data(data.data(), data.size());
if (!nullable_document) if (!nullable_document)
return DecoderError::format(DecoderErrorCategory::IO, "Failed to open matroska from data"); return DecoderError::format(DecoderErrorCategory::IO, "Failed to open matroska from data");
auto document = nullable_document.release_nonnull(); auto document = nullable_document.release_nonnull();
@ -30,17 +30,17 @@ DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_data(Readon
Vector<Track> MatroskaDemuxer::get_tracks_for_type(TrackType type) Vector<Track> MatroskaDemuxer::get_tracks_for_type(TrackType type)
{ {
Video::TrackEntry::TrackType matroska_track_type; TrackEntry::TrackType matroska_track_type;
switch (type) { switch (type) {
case TrackType::Video: case TrackType::Video:
matroska_track_type = Video::TrackEntry::TrackType::Video; matroska_track_type = TrackEntry::TrackType::Video;
break; break;
case TrackType::Audio: case TrackType::Audio:
matroska_track_type = Video::TrackEntry::TrackType::Audio; matroska_track_type = TrackEntry::TrackType::Audio;
break; break;
case TrackType::Subtitles: case TrackType::Subtitles:
matroska_track_type = Video::TrackEntry::TrackType::Subtitle; matroska_track_type = TrackEntry::TrackType::Subtitle;
break; break;
} }

View file

@ -7,11 +7,11 @@
#pragma once #pragma once
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <LibVideo/Containers/Demuxer.h>
#include "Demuxer.h" #include "Reader.h"
#include "MatroskaReader.h"
namespace Video { namespace Video::Matroska {
class MatroskaDemuxer final : public Demuxer { class MatroskaDemuxer final : public Demuxer {
public: public:

View file

@ -4,13 +4,14 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include "MatroskaReader.h"
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <AK/Utf8View.h> #include <AK/Utf8View.h>
#include <LibCore/MappedFile.h> #include <LibCore/MappedFile.h>
namespace Video { #include "Reader.h"
namespace Video::Matroska {
#define CHECK_HAS_VALUE(x) \ #define CHECK_HAS_VALUE(x) \
if (!(x).has_value()) \ if (!(x).has_value()) \
@ -55,7 +56,7 @@ constexpr u32 BIT_DEPTH_ID = 0x6264;
constexpr u32 SIMPLE_BLOCK_ID = 0xA3; constexpr u32 SIMPLE_BLOCK_ID = 0xA3;
constexpr u32 TIMESTAMP_ID = 0xE7; constexpr u32 TIMESTAMP_ID = 0xE7;
OwnPtr<MatroskaDocument> MatroskaReader::parse_matroska_from_file(StringView path) OwnPtr<MatroskaDocument> Reader::parse_matroska_from_file(StringView path)
{ {
auto mapped_file_result = Core::MappedFile::map(path); auto mapped_file_result = Core::MappedFile::map(path);
if (mapped_file_result.is_error()) if (mapped_file_result.is_error())
@ -65,13 +66,13 @@ OwnPtr<MatroskaDocument> MatroskaReader::parse_matroska_from_file(StringView pat
return parse_matroska_from_data((u8*)mapped_file->data(), mapped_file->size()); return parse_matroska_from_data((u8*)mapped_file->data(), mapped_file->size());
} }
OwnPtr<MatroskaDocument> MatroskaReader::parse_matroska_from_data(u8 const* data, size_t size) OwnPtr<MatroskaDocument> Reader::parse_matroska_from_data(u8 const* data, size_t size)
{ {
MatroskaReader reader(data, size); Reader reader(data, size);
return reader.parse(); return reader.parse();
} }
OwnPtr<MatroskaDocument> MatroskaReader::parse() OwnPtr<MatroskaDocument> Reader::parse()
{ {
auto first_element_id = m_streamer.read_variable_size_integer(false); auto first_element_id = m_streamer.read_variable_size_integer(false);
dbgln_if(MATROSKA_TRACE_DEBUG, "First element ID is {:#010x}\n", first_element_id.value()); dbgln_if(MATROSKA_TRACE_DEBUG, "First element ID is {:#010x}\n", first_element_id.value());
@ -97,7 +98,7 @@ OwnPtr<MatroskaDocument> MatroskaReader::parse()
return matroska_document; return matroska_document;
} }
bool MatroskaReader::parse_master_element([[maybe_unused]] StringView element_name, Function<bool(u64)> element_consumer) bool Reader::parse_master_element([[maybe_unused]] StringView element_name, Function<bool(u64)> element_consumer)
{ {
auto element_data_size = m_streamer.read_variable_size_integer(); auto element_data_size = m_streamer.read_variable_size_integer();
CHECK_HAS_VALUE(element_data_size); CHECK_HAS_VALUE(element_data_size);
@ -124,7 +125,7 @@ bool MatroskaReader::parse_master_element([[maybe_unused]] StringView element_na
return true; return true;
} }
Optional<EBMLHeader> MatroskaReader::parse_ebml_header() Optional<EBMLHeader> Reader::parse_ebml_header()
{ {
EBMLHeader header; EBMLHeader header;
auto success = parse_master_element("Header"sv, [&](u64 element_id) { auto success = parse_master_element("Header"sv, [&](u64 element_id) {
@ -150,7 +151,7 @@ Optional<EBMLHeader> MatroskaReader::parse_ebml_header()
return header; return header;
} }
bool MatroskaReader::parse_segment_elements(MatroskaDocument& matroska_document) bool Reader::parse_segment_elements(MatroskaDocument& matroska_document)
{ {
dbgln_if(MATROSKA_DEBUG, "Parsing segment elements"); dbgln_if(MATROSKA_DEBUG, "Parsing segment elements");
auto success = parse_master_element("Segment"sv, [&](u64 element_id) { auto success = parse_master_element("Segment"sv, [&](u64 element_id) {
@ -177,7 +178,7 @@ bool MatroskaReader::parse_segment_elements(MatroskaDocument& matroska_document)
return success; return success;
} }
OwnPtr<SegmentInformation> MatroskaReader::parse_information() OwnPtr<SegmentInformation> Reader::parse_information()
{ {
auto segment_information = make<SegmentInformation>(); auto segment_information = make<SegmentInformation>();
auto success = parse_master_element("Segment Information"sv, [&](u64 element_id) { auto success = parse_master_element("Segment Information"sv, [&](u64 element_id) {
@ -213,7 +214,7 @@ OwnPtr<SegmentInformation> MatroskaReader::parse_information()
return segment_information; return segment_information;
} }
bool MatroskaReader::parse_tracks(MatroskaDocument& matroska_document) bool Reader::parse_tracks(MatroskaDocument& matroska_document)
{ {
auto success = parse_master_element("Tracks"sv, [&](u64 element_id) { auto success = parse_master_element("Tracks"sv, [&](u64 element_id) {
if (element_id == TRACK_ENTRY_ID) { if (element_id == TRACK_ENTRY_ID) {
@ -234,7 +235,7 @@ bool MatroskaReader::parse_tracks(MatroskaDocument& matroska_document)
return success; return success;
} }
OwnPtr<TrackEntry> MatroskaReader::parse_track_entry() OwnPtr<TrackEntry> Reader::parse_track_entry()
{ {
auto track_entry = make<TrackEntry>(); auto track_entry = make<TrackEntry>();
auto success = parse_master_element("Track"sv, [&](u64 element_id) { auto success = parse_master_element("Track"sv, [&](u64 element_id) {
@ -283,7 +284,7 @@ OwnPtr<TrackEntry> MatroskaReader::parse_track_entry()
return track_entry; return track_entry;
} }
Optional<TrackEntry::ColorFormat> MatroskaReader::parse_video_color_information() Optional<TrackEntry::ColorFormat> Reader::parse_video_color_information()
{ {
TrackEntry::ColorFormat color_format {}; TrackEntry::ColorFormat color_format {};
@ -328,7 +329,7 @@ Optional<TrackEntry::ColorFormat> MatroskaReader::parse_video_color_information(
return color_format; return color_format;
} }
Optional<TrackEntry::VideoTrack> MatroskaReader::parse_video_track_information() Optional<TrackEntry::VideoTrack> Reader::parse_video_track_information()
{ {
TrackEntry::VideoTrack video_track {}; TrackEntry::VideoTrack video_track {};
@ -359,7 +360,7 @@ Optional<TrackEntry::VideoTrack> MatroskaReader::parse_video_track_information()
return video_track; return video_track;
} }
Optional<TrackEntry::AudioTrack> MatroskaReader::parse_audio_track_information() Optional<TrackEntry::AudioTrack> Reader::parse_audio_track_information()
{ {
TrackEntry::AudioTrack audio_track {}; TrackEntry::AudioTrack audio_track {};
@ -386,7 +387,7 @@ Optional<TrackEntry::AudioTrack> MatroskaReader::parse_audio_track_information()
return audio_track; return audio_track;
} }
OwnPtr<Cluster> MatroskaReader::parse_cluster() OwnPtr<Cluster> Reader::parse_cluster()
{ {
auto cluster = make<Cluster>(); auto cluster = make<Cluster>();
@ -415,7 +416,7 @@ OwnPtr<Cluster> MatroskaReader::parse_cluster()
return cluster; return cluster;
} }
OwnPtr<Block> MatroskaReader::parse_simple_block() OwnPtr<Block> Reader::parse_simple_block()
{ {
auto block = make<Block>(); auto block = make<Block>();
@ -498,7 +499,7 @@ OwnPtr<Block> MatroskaReader::parse_simple_block()
return block; return block;
} }
Optional<String> MatroskaReader::read_string_element() Optional<String> Reader::read_string_element()
{ {
auto string_length = m_streamer.read_variable_size_integer(); auto string_length = m_streamer.read_variable_size_integer();
if (!string_length.has_value() || m_streamer.remaining() < string_length.value()) if (!string_length.has_value() || m_streamer.remaining() < string_length.value())
@ -508,7 +509,7 @@ Optional<String> MatroskaReader::read_string_element()
return string_value; return string_value;
} }
Optional<u64> MatroskaReader::read_u64_element() Optional<u64> Reader::read_u64_element()
{ {
auto integer_length = m_streamer.read_variable_size_integer(); auto integer_length = m_streamer.read_variable_size_integer();
if (!integer_length.has_value() || m_streamer.remaining() < integer_length.value()) if (!integer_length.has_value() || m_streamer.remaining() < integer_length.value())
@ -522,7 +523,7 @@ Optional<u64> MatroskaReader::read_u64_element()
return result; return result;
} }
Optional<double> MatroskaReader::read_float_element() Optional<double> Reader::read_float_element()
{ {
auto length = m_streamer.read_variable_size_integer(); auto length = m_streamer.read_variable_size_integer();
if (!length.has_value() || m_streamer.remaining() < length.value()) if (!length.has_value() || m_streamer.remaining() < length.value())
@ -546,7 +547,7 @@ Optional<double> MatroskaReader::read_float_element()
return read_data.double_value; return read_data.double_value;
} }
bool MatroskaReader::read_unknown_element() bool Reader::read_unknown_element()
{ {
auto element_length = m_streamer.read_variable_size_integer(); auto element_length = m_streamer.read_variable_size_integer();
if (!element_length.has_value() || m_streamer.remaining() < element_length.value()) if (!element_length.has_value() || m_streamer.remaining() < element_length.value())

View file

@ -6,18 +6,18 @@
#pragma once #pragma once
#include "MatroskaDocument.h" #include "Document.h"
#include <AK/Debug.h> #include <AK/Debug.h>
#include <AK/IntegralMath.h> #include <AK/IntegralMath.h>
#include <AK/NonnullOwnPtrVector.h> #include <AK/NonnullOwnPtrVector.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
namespace Video { namespace Video::Matroska {
class MatroskaReader { class Reader {
public: public:
MatroskaReader(u8 const* data, size_t size) Reader(u8 const* data, size_t size)
: m_streamer(data, size) : m_streamer(data, size)
{ {
} }

View file

@ -6,17 +6,16 @@
#include <AK/Format.h> #include <AK/Format.h>
#include <LibCore/Timer.h> #include <LibCore/Timer.h>
#include <LibVideo/MatroskaReader.h> #include <LibVideo/Containers/Matroska/MatroskaDemuxer.h>
#include <LibVideo/VP9/Decoder.h> #include <LibVideo/VP9/Decoder.h>
#include "MatroskaDemuxer.h"
#include "PlaybackManager.h" #include "PlaybackManager.h"
namespace Video { namespace Video {
DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::from_file(Core::Object& event_handler, StringView filename) DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::from_file(Core::Object& event_handler, StringView filename)
{ {
NonnullOwnPtr<Demuxer> demuxer = TRY(MatroskaDemuxer::from_file(filename)); NonnullOwnPtr<Demuxer> demuxer = TRY(Matroska::MatroskaDemuxer::from_file(filename));
auto video_tracks = demuxer->get_tracks_for_type(TrackType::Video); auto video_tracks = demuxer->get_tracks_for_type(TrackType::Video);
if (video_tracks.is_empty()) if (video_tracks.is_empty())
return DecoderError::with_description(DecoderErrorCategory::Invalid, "No video track is present"sv); return DecoderError::with_description(DecoderErrorCategory::Invalid, "No video track is present"sv);

View file

@ -17,9 +17,9 @@
#include <LibThreading/ConditionVariable.h> #include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h> #include <LibThreading/Mutex.h>
#include <LibThreading/Thread.h> #include <LibThreading/Thread.h>
#include <LibVideo/Containers/Demuxer.h>
#include <LibVideo/Containers/Matroska/Document.h>
#include "Demuxer.h"
#include "MatroskaDocument.h"
#include "VideoDecoder.h" #include "VideoDecoder.h"
namespace Video { namespace Video {

View file

@ -1,15 +1,16 @@
/* /*
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com> * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibMain/Main.h> #include <LibMain/Main.h>
#include <LibVideo/MatroskaReader.h> #include <LibVideo/Containers/Matroska/Reader.h>
ErrorOr<int> serenity_main(Main::Arguments) ErrorOr<int> serenity_main(Main::Arguments)
{ {
auto document = Video::MatroskaReader::parse_matroska_from_file("/home/anon/Videos/test-webm.webm"sv); auto document = Video::Matroska::Reader::parse_matroska_from_file("/home/anon/Videos/test-webm.webm"sv);
if (!document) { if (!document) {
return Error::from_string_literal("Failed to parse :("); return Error::from_string_literal("Failed to parse :(");
} }
@ -30,10 +31,10 @@ ErrorOr<int> serenity_main(Main::Arguments)
outln("\tTrack has Language \"{}\"", track.language().characters()); outln("\tTrack has Language \"{}\"", track.language().characters());
outln("\tTrack has CodecID \"{}\"", track.codec_id().characters()); outln("\tTrack has CodecID \"{}\"", track.codec_id().characters());
if (track.track_type() == Video::TrackEntry::TrackType::Video) { if (track.track_type() == Video::Matroska::TrackEntry::TrackType::Video) {
auto const video_track = track.video_track().value(); auto const video_track = track.video_track().value();
outln("\t\tVideo is {} pixels wide by {} pixels tall", video_track.pixel_width, video_track.pixel_height); outln("\t\tVideo is {} pixels wide by {} pixels tall", video_track.pixel_width, video_track.pixel_height);
} else if (track.track_type() == Video::TrackEntry::TrackType::Audio) { } else if (track.track_type() == Video::Matroska::TrackEntry::TrackType::Audio) {
auto const audio_track = track.audio_track().value(); auto const audio_track = track.audio_track().value();
outln("\t\tAudio has {} channels with a bit depth of {}", audio_track.channels, audio_track.bit_depth); outln("\t\tAudio has {} channels with a bit depth of {}", audio_track.channels, audio_track.bit_depth);
} }