LibMedia: Retrieve codec initialization data from Matroska files

This is necessary to give H.264 decoders the data they need to
initialize, including frame size and profile.

(cherry picked from commit 457a69786b788d3158813156d11e70980f50f7b7)
This commit is contained in:
Zaggy1024 authored and Nico Weber committed 2024-07-04 22:09:32 +02:00
1 parent b2668c8c6c
commit f57d2acf05
5 files changed
+24

No files matched your search

@@ -8,6 +8,7 @@
#include <AK/ByteBuffer.h>
#include <AK/ByteString.h>
#include <AK/FixedArray.h>
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
@@ -119,6 +120,12 @@ public:
void set_language(FlyString const& language) { m_language = language; }
FlyString codec_id() const { return m_codec_id; }
void set_codec_id(FlyString const& codec_id) { m_codec_id = codec_id; }
ReadonlyBytes codec_private_data() const { return m_codec_private_data.span(); }
ErrorOr<void> set_codec_private_data(ReadonlyBytes codec_private_data)
{
m_codec_private_data = TRY(FixedArray<u8>::create(codec_private_data));
return {};
}
double timestamp_scale() const { return m_timestamp_scale; }
void set_timestamp_scale(double timestamp_scale) { m_timestamp_scale = timestamp_scale; }
u64 codec_delay() const { return m_codec_delay; }
@@ -146,6 +153,7 @@ private:
TrackType m_track_type { Invalid };
FlyString m_language = "eng"_fly_string;
FlyString m_codec_id;
FixedArray<u8> m_codec_private_data;
double m_timestamp_scale { 1 };
u64 m_codec_delay { 0 };
u64 m_timestamp_offset { 0 };
@@ -104,6 +104,11 @@ DecoderErrorOr<CodecID> MatroskaDemuxer::get_codec_id_for_track(Track track)
return get_codec_id_for_string(codec_id);
}
DecoderErrorOr<ReadonlyBytes> MatroskaDemuxer::get_codec_initialization_data_for_track(Track track)
{
return TRY(m_reader.track_for_track_number(track.identifier()))->codec_private_data();
}
DecoderErrorOr<Optional<Duration>> MatroskaDemuxer::seek_to_most_recent_keyframe(Track track, Duration timestamp, Optional<Duration> earliest_available_sample)
{
// Removing the track status will cause us to start from the beginning.
@@ -35,6 +35,8 @@ public:
DecoderErrorOr<CodecID> get_codec_id_for_track(Track track) override;
DecoderErrorOr<ReadonlyBytes> get_codec_initialization_data_for_track(Track track) override;
DecoderErrorOr<Sample> get_next_sample_for_track(Track track) override;
private:
@@ -50,6 +50,7 @@ constexpr u32 TRACK_UID_ID = 0x73C5;
constexpr u32 TRACK_TYPE_ID = 0x83;
constexpr u32 TRACK_LANGUAGE_ID = 0x22B59C;
constexpr u32 TRACK_CODEC_ID = 0x86;
constexpr u32 TRACK_CODEC_PRIVATE = 0x63A2;
constexpr u32 TRACK_TIMESTAMP_SCALE_ID = 0x23314F;
constexpr u32 TRACK_OFFSET_ID = 0x537F;
constexpr u32 TRACK_VIDEO_ID = 0xE0;
@@ -480,6 +481,12 @@ static DecoderErrorOr<NonnullRefPtr<TrackEntry>> parse_track_entry(Streamer& str
track_entry->set_codec_id(DECODER_TRY_ALLOC(String::from_byte_string(TRY_READ(streamer.read_string()))));
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Track's CodecID attribute: {}", track_entry->codec_id());
break;
case TRACK_CODEC_PRIVATE: {
auto codec_private_data = TRY_READ(streamer.read_raw_octets(TRY_READ(streamer.read_variable_size_integer())));
DECODER_TRY_ALLOC(track_entry->set_codec_private_data(codec_private_data));
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Track's CodecID attribute: {}", track_entry->codec_id());
break;
}
case TRACK_TIMESTAMP_SCALE_ID:
track_entry->set_timestamp_scale(TRY_READ(streamer.read_float()));
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Track's TrackTimestampScale attribute: {}", track_entry->timestamp_scale());
+2
View File
@@ -26,6 +26,8 @@ public:
virtual DecoderErrorOr<CodecID> get_codec_id_for_track(Track track) = 0;
virtual DecoderErrorOr<ReadonlyBytes> get_codec_initialization_data_for_track(Track track) = 0;
// Returns the timestamp of the keyframe that was seeked to.
// The value is `Optional` to allow the demuxer to decide not to seek so that it can keep its position
// in the case that the timestamp is closer to the current time than the nearest keyframe.