|
@@ -6,6 +6,7 @@
|
|
|
*/
|
|
|
|
|
|
#include <AK/Function.h>
|
|
|
+#include <LibCore/ArgsParser.h>
|
|
|
#include <LibMain/Main.h>
|
|
|
#include <LibVideo/Containers/Matroska/Reader.h>
|
|
|
|
|
@@ -19,9 +20,19 @@
|
|
|
_temporary_result.release_value(); \
|
|
|
})
|
|
|
|
|
|
-ErrorOr<int> serenity_main(Main::Arguments)
|
|
|
+ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
|
{
|
|
|
- auto reader = TRY_PARSE(Video::Matroska::Reader::from_file("/home/anon/Videos/test-webm.webm"sv));
|
|
|
+ StringView filename;
|
|
|
+ bool blocks = false;
|
|
|
+ u64 track_number = 0;
|
|
|
+
|
|
|
+ Core::ArgsParser args_parser;
|
|
|
+ args_parser.add_option(blocks, "Print blocks for each track.", "blocks", 'b');
|
|
|
+ args_parser.add_option<u64>(track_number, "Specify a track number to print info for, omit to print all of them.", "track", 't', "tracknumber");
|
|
|
+ args_parser.add_positional_argument(filename, "The video file to display.", "filename", Core::ArgsParser::Required::Yes);
|
|
|
+ args_parser.parse(arguments);
|
|
|
+
|
|
|
+ auto reader = TRY_PARSE(Video::Matroska::Reader::from_file(filename));
|
|
|
|
|
|
outln("DocType is {}", reader.header().doc_type.characters());
|
|
|
outln("DocTypeVersion is {}", reader.header().doc_type_version);
|
|
@@ -32,6 +43,9 @@ ErrorOr<int> serenity_main(Main::Arguments)
|
|
|
|
|
|
outln("Document has {} tracks", TRY_PARSE(reader.track_count()));
|
|
|
TRY_PARSE(reader.for_each_track([&](Video::Matroska::TrackEntry const& track_entry) -> Video::DecoderErrorOr<IterationDecision> {
|
|
|
+ if (track_number != 0 && track_entry.track_number() != track_number)
|
|
|
+ return IterationDecision::Continue;
|
|
|
+
|
|
|
outln("\tTrack #{} with TrackID {}", track_entry.track_number(), track_entry.track_uid());
|
|
|
outln("\tTrack has TrackType {}", static_cast<u8>(track_entry.track_type()));
|
|
|
outln("\tTrack has Language \"{}\"", track_entry.language().characters());
|
|
@@ -47,22 +61,29 @@ ErrorOr<int> serenity_main(Main::Arguments)
|
|
|
outln("\t\tAudio has {} channels with a bit depth of {}", audio_track.channels, audio_track.bit_depth);
|
|
|
}
|
|
|
|
|
|
- outln("\tBlocks:");
|
|
|
- auto iterator = TRY(reader.create_sample_iterator(track_entry.track_number()));
|
|
|
+ if (blocks) {
|
|
|
+ outln("\tBlocks:");
|
|
|
+ auto iterator = TRY(reader.create_sample_iterator(track_entry.track_number()));
|
|
|
|
|
|
- while (true) {
|
|
|
- auto block_result = iterator.next_block();
|
|
|
- if (block_result.is_error()) {
|
|
|
- if (block_result.error().category() == Video::DecoderErrorCategory::EndOfStream)
|
|
|
- break;
|
|
|
- return block_result.release_error();
|
|
|
+ while (true) {
|
|
|
+ auto block_result = iterator.next_block();
|
|
|
+ if (block_result.is_error()) {
|
|
|
+ if (block_result.error().category() == Video::DecoderErrorCategory::EndOfStream)
|
|
|
+ break;
|
|
|
+ return block_result.release_error();
|
|
|
+ }
|
|
|
+ auto block = block_result.release_value();
|
|
|
+ outln("\t\tBlock at timestamp {}ms:", block.timestamp().to_milliseconds());
|
|
|
+ if (block.only_keyframes())
|
|
|
+ outln("\t\t\tThis block contains only keyframes");
|
|
|
+ outln("\t\t\tContains {} frames", block.frame_count());
|
|
|
+ outln("\t\t\tLacing is {}", static_cast<u8>(block.lacing()));
|
|
|
}
|
|
|
- auto block = block_result.release_value();
|
|
|
- outln("\t\tBlock at timestamp {}ms:", block.timestamp().to_milliseconds());
|
|
|
- outln("\t\t\tContains {} frames", block.frame_count());
|
|
|
- outln("\t\t\tLacing is {}", static_cast<u8>(block.lacing()));
|
|
|
}
|
|
|
|
|
|
+ if (track_number != 0)
|
|
|
+ return IterationDecision::Break;
|
|
|
+
|
|
|
return IterationDecision::Continue;
|
|
|
}));
|
|
|
|