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
Notes: sideshowbarker 2024-07-17 04:06:54 +09:00
13 changed files with 56 additions and 58 deletions

View file

@ -4,12 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibVideo/MatroskaReader.h>
#include <LibVideo/Containers/Matroska/Reader.h>
#include <stddef.h>
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)
return -1;
return 0;

View file

@ -6,14 +6,14 @@
#include <LibTest/TestCase.h>
#include <LibVideo/MatroskaReader.h>
#include <LibVideo/Containers/Matroska/Reader.h>
#include <LibVideo/VP9/Decoder.h>
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);
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());
auto video_track_entry = video_track_optional.value();

View file

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

View file

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

View file

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

View file

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

View file

@ -6,12 +6,12 @@
#include "MatroskaDemuxer.h"
namespace Video {
namespace Video::Matroska {
DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(StringView filename)
{
// 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)
return DecoderError::format(DecoderErrorCategory::IO, "Failed to open matroska from file '{}'", filename);
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)
{
// 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)
return DecoderError::format(DecoderErrorCategory::IO, "Failed to open matroska from data");
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)
{
Video::TrackEntry::TrackType matroska_track_type;
TrackEntry::TrackType matroska_track_type;
switch (type) {
case TrackType::Video:
matroska_track_type = Video::TrackEntry::TrackType::Video;
matroska_track_type = TrackEntry::TrackType::Video;
break;
case TrackType::Audio:
matroska_track_type = Video::TrackEntry::TrackType::Audio;
matroska_track_type = TrackEntry::TrackType::Audio;
break;
case TrackType::Subtitles:
matroska_track_type = Video::TrackEntry::TrackType::Subtitle;
matroska_track_type = TrackEntry::TrackType::Subtitle;
break;
}

View file

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

View file

@ -4,13 +4,14 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "MatroskaReader.h"
#include <AK/Function.h>
#include <AK/Optional.h>
#include <AK/Utf8View.h>
#include <LibCore/MappedFile.h>
namespace Video {
#include "Reader.h"
namespace Video::Matroska {
#define CHECK_HAS_VALUE(x) \
if (!(x).has_value()) \
@ -55,7 +56,7 @@ constexpr u32 BIT_DEPTH_ID = 0x6264;
constexpr u32 SIMPLE_BLOCK_ID = 0xA3;
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);
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());
}
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();
}
OwnPtr<MatroskaDocument> MatroskaReader::parse()
OwnPtr<MatroskaDocument> Reader::parse()
{
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());
@ -97,7 +98,7 @@ OwnPtr<MatroskaDocument> MatroskaReader::parse()
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();
CHECK_HAS_VALUE(element_data_size);
@ -124,7 +125,7 @@ bool MatroskaReader::parse_master_element([[maybe_unused]] StringView element_na
return true;
}
Optional<EBMLHeader> MatroskaReader::parse_ebml_header()
Optional<EBMLHeader> Reader::parse_ebml_header()
{
EBMLHeader header;
auto success = parse_master_element("Header"sv, [&](u64 element_id) {
@ -150,7 +151,7 @@ Optional<EBMLHeader> MatroskaReader::parse_ebml_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");
auto success = parse_master_element("Segment"sv, [&](u64 element_id) {
@ -177,7 +178,7 @@ bool MatroskaReader::parse_segment_elements(MatroskaDocument& matroska_document)
return success;
}
OwnPtr<SegmentInformation> MatroskaReader::parse_information()
OwnPtr<SegmentInformation> Reader::parse_information()
{
auto segment_information = make<SegmentInformation>();
auto success = parse_master_element("Segment Information"sv, [&](u64 element_id) {
@ -213,7 +214,7 @@ OwnPtr<SegmentInformation> MatroskaReader::parse_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) {
if (element_id == TRACK_ENTRY_ID) {
@ -234,7 +235,7 @@ bool MatroskaReader::parse_tracks(MatroskaDocument& matroska_document)
return success;
}
OwnPtr<TrackEntry> MatroskaReader::parse_track_entry()
OwnPtr<TrackEntry> Reader::parse_track_entry()
{
auto track_entry = make<TrackEntry>();
auto success = parse_master_element("Track"sv, [&](u64 element_id) {
@ -283,7 +284,7 @@ OwnPtr<TrackEntry> MatroskaReader::parse_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 {};
@ -328,7 +329,7 @@ Optional<TrackEntry::ColorFormat> MatroskaReader::parse_video_color_information(
return color_format;
}
Optional<TrackEntry::VideoTrack> MatroskaReader::parse_video_track_information()
Optional<TrackEntry::VideoTrack> Reader::parse_video_track_information()
{
TrackEntry::VideoTrack video_track {};
@ -359,7 +360,7 @@ Optional<TrackEntry::VideoTrack> MatroskaReader::parse_video_track_information()
return video_track;
}
Optional<TrackEntry::AudioTrack> MatroskaReader::parse_audio_track_information()
Optional<TrackEntry::AudioTrack> Reader::parse_audio_track_information()
{
TrackEntry::AudioTrack audio_track {};
@ -386,7 +387,7 @@ Optional<TrackEntry::AudioTrack> MatroskaReader::parse_audio_track_information()
return audio_track;
}
OwnPtr<Cluster> MatroskaReader::parse_cluster()
OwnPtr<Cluster> Reader::parse_cluster()
{
auto cluster = make<Cluster>();
@ -415,7 +416,7 @@ OwnPtr<Cluster> MatroskaReader::parse_cluster()
return cluster;
}
OwnPtr<Block> MatroskaReader::parse_simple_block()
OwnPtr<Block> Reader::parse_simple_block()
{
auto block = make<Block>();
@ -498,7 +499,7 @@ OwnPtr<Block> MatroskaReader::parse_simple_block()
return block;
}
Optional<String> MatroskaReader::read_string_element()
Optional<String> Reader::read_string_element()
{
auto string_length = m_streamer.read_variable_size_integer();
if (!string_length.has_value() || m_streamer.remaining() < string_length.value())
@ -508,7 +509,7 @@ Optional<String> MatroskaReader::read_string_element()
return string_value;
}
Optional<u64> MatroskaReader::read_u64_element()
Optional<u64> Reader::read_u64_element()
{
auto integer_length = m_streamer.read_variable_size_integer();
if (!integer_length.has_value() || m_streamer.remaining() < integer_length.value())
@ -522,7 +523,7 @@ Optional<u64> MatroskaReader::read_u64_element()
return result;
}
Optional<double> MatroskaReader::read_float_element()
Optional<double> Reader::read_float_element()
{
auto length = m_streamer.read_variable_size_integer();
if (!length.has_value() || m_streamer.remaining() < length.value())
@ -546,7 +547,7 @@ Optional<double> MatroskaReader::read_float_element()
return read_data.double_value;
}
bool MatroskaReader::read_unknown_element()
bool Reader::read_unknown_element()
{
auto element_length = m_streamer.read_variable_size_integer();
if (!element_length.has_value() || m_streamer.remaining() < element_length.value())

View file

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

View file

@ -6,17 +6,16 @@
#include <AK/Format.h>
#include <LibCore/Timer.h>
#include <LibVideo/MatroskaReader.h>
#include <LibVideo/Containers/Matroska/MatroskaDemuxer.h>
#include <LibVideo/VP9/Decoder.h>
#include "MatroskaDemuxer.h"
#include "PlaybackManager.h"
namespace Video {
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);
if (video_tracks.is_empty())
return DecoderError::with_description(DecoderErrorCategory::Invalid, "No video track is present"sv);

View file

@ -17,9 +17,9 @@
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.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"
namespace Video {

View file

@ -1,15 +1,16 @@
/*
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibMain/Main.h>
#include <LibVideo/MatroskaReader.h>
#include <LibVideo/Containers/Matroska/Reader.h>
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) {
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 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();
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();
outln("\t\tAudio has {} channels with a bit depth of {}", audio_track.channels, audio_track.bit_depth);
}