mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:47:35 +00:00
LibVideo: Make Matroska Block and Cluster timestamps absolute
This commit is contained in:
parent
5c2cede2c9
commit
9040194d54
4 changed files with 15 additions and 16 deletions
|
@ -12,6 +12,7 @@
|
||||||
#include <AK/NonnullOwnPtrVector.h>
|
#include <AK/NonnullOwnPtrVector.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
#include <AK/Time.h>
|
||||||
#include <AK/Utf8View.h>
|
#include <AK/Utf8View.h>
|
||||||
#include <LibVideo/Color/CodingIndependentCodePoints.h>
|
#include <LibVideo/Color/CodingIndependentCodePoints.h>
|
||||||
|
|
||||||
|
@ -152,8 +153,8 @@ public:
|
||||||
|
|
||||||
u64 track_number() const { return m_track_number; }
|
u64 track_number() const { return m_track_number; }
|
||||||
void set_track_number(u64 track_number) { m_track_number = track_number; }
|
void set_track_number(u64 track_number) { m_track_number = track_number; }
|
||||||
i16 timestamp() const { return m_timestamp; }
|
Time timestamp() const { return m_timestamp; }
|
||||||
void set_timestamp(i16 timestamp) { m_timestamp = timestamp; }
|
void set_timestamp(Time timestamp) { m_timestamp = timestamp; }
|
||||||
bool only_keyframes() const { return m_only_keyframes; }
|
bool only_keyframes() const { return m_only_keyframes; }
|
||||||
void set_only_keyframes(bool only_keyframes) { m_only_keyframes = only_keyframes; }
|
void set_only_keyframes(bool only_keyframes) { m_only_keyframes = only_keyframes; }
|
||||||
bool invisible() const { return m_invisible; }
|
bool invisible() const { return m_invisible; }
|
||||||
|
@ -170,7 +171,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 m_track_number { 0 };
|
u64 m_track_number { 0 };
|
||||||
i16 m_timestamp { 0 };
|
Time m_timestamp { Time::zero() };
|
||||||
bool m_only_keyframes { false };
|
bool m_only_keyframes { false };
|
||||||
bool m_invisible { false };
|
bool m_invisible { false };
|
||||||
Lacing m_lacing { None };
|
Lacing m_lacing { None };
|
||||||
|
@ -180,11 +181,11 @@ private:
|
||||||
|
|
||||||
class Cluster {
|
class Cluster {
|
||||||
public:
|
public:
|
||||||
u64 timestamp() const { return m_timestamp; }
|
Time timestamp() const { return m_timestamp; }
|
||||||
void set_timestamp(u64 timestamp) { m_timestamp = timestamp; }
|
void set_timestamp(Time timestamp) { m_timestamp = timestamp; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 m_timestamp;
|
Time m_timestamp { Time::zero() };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,10 +72,8 @@ DecoderErrorOr<NonnullOwnPtr<Sample>> MatroskaDemuxer::get_next_sample_for_track
|
||||||
status.block = TRY(status.iterator.next_block());
|
status.block = TRY(status.iterator.next_block());
|
||||||
status.frame_index = 0;
|
status.frame_index = 0;
|
||||||
}
|
}
|
||||||
auto const& cluster = status.iterator.current_cluster();
|
|
||||||
Time timestamp = Time::from_nanoseconds((cluster.timestamp() + status.block->timestamp()) * TRY(m_reader.segment_information()).timestamp_scale());
|
|
||||||
auto cicp = TRY(m_reader.track_for_track_number(track.identifier())).video_track()->color_format.to_cicp();
|
auto cicp = TRY(m_reader.track_for_track_number(track.identifier())).video_track()->color_format.to_cicp();
|
||||||
return make<VideoSample>(status.block->frame(status.frame_index++), cicp, timestamp);
|
return make<VideoSample>(status.block->frame(status.frame_index++), cicp, status.block->timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
DecoderErrorOr<Time> MatroskaDemuxer::duration()
|
DecoderErrorOr<Time> MatroskaDemuxer::duration()
|
||||||
|
|
|
@ -487,7 +487,7 @@ constexpr size_t get_element_id_size(u32 element_id)
|
||||||
return sizeof(element_id) - (count_leading_zeroes(element_id) / 8);
|
return sizeof(element_id) - (count_leading_zeroes(element_id) / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DecoderErrorOr<Cluster> parse_cluster(Streamer& streamer)
|
static DecoderErrorOr<Cluster> parse_cluster(Streamer& streamer, u64 timestamp_scale)
|
||||||
{
|
{
|
||||||
Optional<u64> timestamp;
|
Optional<u64> timestamp;
|
||||||
size_t first_element_position = 0;
|
size_t first_element_position = 0;
|
||||||
|
@ -516,11 +516,11 @@ static DecoderErrorOr<Cluster> parse_cluster(Streamer& streamer)
|
||||||
TRY_READ(streamer.seek_to_position(first_element_position));
|
TRY_READ(streamer.seek_to_position(first_element_position));
|
||||||
|
|
||||||
Cluster cluster;
|
Cluster cluster;
|
||||||
cluster.set_timestamp(timestamp.release_value());
|
cluster.set_timestamp(Time::from_nanoseconds(timestamp.release_value() * timestamp_scale));
|
||||||
return cluster;
|
return cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DecoderErrorOr<Block> parse_simple_block(Streamer& streamer)
|
static DecoderErrorOr<Block> parse_simple_block(Streamer& streamer, Time cluster_timestamp, u64 timestamp_scale)
|
||||||
{
|
{
|
||||||
Block block;
|
Block block;
|
||||||
|
|
||||||
|
@ -529,7 +529,7 @@ static DecoderErrorOr<Block> parse_simple_block(Streamer& streamer)
|
||||||
auto position_before_track_number = streamer.position();
|
auto position_before_track_number = streamer.position();
|
||||||
block.set_track_number(TRY_READ(streamer.read_variable_size_integer()));
|
block.set_track_number(TRY_READ(streamer.read_variable_size_integer()));
|
||||||
|
|
||||||
block.set_timestamp(TRY_READ(streamer.read_i16()));
|
block.set_timestamp(cluster_timestamp + Time::from_nanoseconds(TRY_READ(streamer.read_i16()) * timestamp_scale));
|
||||||
|
|
||||||
auto flags = TRY_READ(streamer.read_octet());
|
auto flags = TRY_READ(streamer.read_octet());
|
||||||
block.set_only_keyframes((flags & (1u << 7u)) != 0);
|
block.set_only_keyframes((flags & (1u << 7u)) != 0);
|
||||||
|
@ -627,10 +627,10 @@ DecoderErrorOr<Block> SampleIterator::next_block()
|
||||||
|
|
||||||
if (element_id == CLUSTER_ELEMENT_ID) {
|
if (element_id == CLUSTER_ELEMENT_ID) {
|
||||||
dbgln_if(MATROSKA_DEBUG, " Iterator is parsing new cluster.");
|
dbgln_if(MATROSKA_DEBUG, " Iterator is parsing new cluster.");
|
||||||
m_current_cluster = TRY(parse_cluster(streamer));
|
m_current_cluster = TRY(parse_cluster(streamer, m_timestamp_scale));
|
||||||
} else if (element_id == SIMPLE_BLOCK_ID) {
|
} else if (element_id == SIMPLE_BLOCK_ID) {
|
||||||
dbgln_if(MATROSKA_TRACE_DEBUG, " Iterator is parsing new block.");
|
dbgln_if(MATROSKA_TRACE_DEBUG, " Iterator is parsing new block.");
|
||||||
auto candidate_block = TRY(parse_simple_block(streamer));
|
auto candidate_block = TRY(parse_simple_block(streamer, m_current_cluster->timestamp(), m_timestamp_scale));
|
||||||
if (candidate_block.track_number() == m_track_id)
|
if (candidate_block.track_number() == m_track_id)
|
||||||
block = move(candidate_block);
|
block = move(candidate_block);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -56,7 +56,7 @@ ErrorOr<int> serenity_main(Main::Arguments)
|
||||||
return block_result.release_error();
|
return block_result.release_error();
|
||||||
}
|
}
|
||||||
auto block = block_result.release_value();
|
auto block = block_result.release_value();
|
||||||
outln("\t\tBlock at timestamp {}:", iterator.current_cluster().timestamp() + block.timestamp());
|
outln("\t\tBlock at timestamp {}ms:", block.timestamp().to_milliseconds());
|
||||||
outln("\t\t\tContains {} frames", block.frame_count());
|
outln("\t\t\tContains {} frames", block.frame_count());
|
||||||
outln("\t\t\tLacing is {}", static_cast<u8>(block.lacing()));
|
outln("\t\t\tLacing is {}", static_cast<u8>(block.lacing()));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue