Skip to content

Commit

Permalink
WebM file with Vorbis track plays in burst
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=273866
rdar://124880261

Reviewed by Eric Carlson.

Add support for Block containing multiple frames. Previously we would create as many CMSampleBuffer
as found in the block, but all those samples would have the timestamp of the Block.
We now accrue the duration of each frame and properly increment the sample's timestamp accordingly.

Manually verified that file plays okay

* Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp:
(WebCore::WebMParser::OnSimpleBlockBegin):
(WebCore::WebMParser::OnSimpleBlockEnd):
(WebCore::WebMParser::OnFrame):
(WebCore::WebMParser::VideoTrackData::consumeFrameData):
(WebCore::WebMParser::AudioTrackData::consumeFrameData):
* Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h:
(WebCore::WebMParser::TrackData::consumeFrameData):

Canonical link: https://commits.webkit.org/278665@main
  • Loading branch information
jyavenard committed May 12, 2024
1 parent eb34966 commit 6a9c5f8
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 7 deletions.
14 changes: 10 additions & 4 deletions Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ webm::Status WebMParser::OnSimpleBlockBegin(const ElementMetadata&, const Simple
*action = Action::kRead;

m_currentBlock = std::make_optional<BlockVariant>(SimpleBlock(block));
m_currentDuration = MediaTime::zeroTime();

return Status(Status::kOkCompleted);
}
Expand All @@ -934,6 +935,7 @@ webm::Status WebMParser::OnSimpleBlockEnd(const ElementMetadata&, const SimpleBl
INFO_LOG_IF_POSSIBLE(LOGIDENTIFIER);

m_currentBlock = std::nullopt;
m_currentDuration = MediaTime::zeroTime();

return Status(Status::kOkCompleted);
}
Expand Down Expand Up @@ -1003,7 +1005,11 @@ webm::Status WebMParser::OnFrame(const FrameMetadata& metadata, Reader* reader,
return Skip(reader, bytesRemaining);
}

return trackData->consumeFrameData(*reader, metadata, bytesRemaining, MediaTime(block->timecode + m_currentTimecode, m_timescale));
auto result = trackData->consumeFrameData(*reader, metadata, bytesRemaining, MediaTime(block->timecode + m_currentTimecode, m_timescale) + m_currentDuration);
if (std::holds_alternative<webm::Status>(result))
return std::get<webm::Status>(result);
m_currentDuration += std::get<MediaTime>(result);
return Status(Status::kOkCompleted);
}


Expand Down Expand Up @@ -1067,7 +1073,7 @@ void WebMParser::VideoTrackData::resetCompletedFramesState()
TrackData::resetCompletedFramesState();
}

webm::Status WebMParser::VideoTrackData::consumeFrameData(webm::Reader& reader, const FrameMetadata& metadata, uint64_t* bytesRemaining, const MediaTime& presentationTime)
WebMParser::ConsumeFrameDataResult WebMParser::VideoTrackData::consumeFrameData(webm::Reader& reader, const FrameMetadata& metadata, uint64_t* bytesRemaining, const MediaTime& presentationTime)
{
#if ENABLE(VP9)
auto status = readFrameData(reader, metadata, bytesRemaining);
Expand Down Expand Up @@ -1203,7 +1209,7 @@ void WebMParser::AudioTrackData::resetCompletedFramesState()
TrackData::resetCompletedFramesState();
}

webm::Status WebMParser::AudioTrackData::consumeFrameData(webm::Reader& reader, const FrameMetadata& metadata, uint64_t* bytesRemaining, const MediaTime& presentationTime)
WebMParser::ConsumeFrameDataResult WebMParser::AudioTrackData::consumeFrameData(webm::Reader& reader, const FrameMetadata& metadata, uint64_t* bytesRemaining, const MediaTime& presentationTime)
{
auto status = readFrameData(reader, metadata, bytesRemaining);
if (!status.completed_ok())
Expand Down Expand Up @@ -1329,7 +1335,7 @@ webm::Status WebMParser::AudioTrackData::consumeFrameData(webm::Reader& reader,
drainPendingSamples();

ASSERT(!*bytesRemaining);
return webm::Status(webm::Status::kOkCompleted);
return packetDuration;
}


Expand Down
10 changes: 7 additions & 3 deletions Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class WebMParser
Opus,
};

using ConsumeFrameDataResult = std::variant<MediaTime, webm::Status>;

class TrackData {
WTF_MAKE_FAST_ALLOCATED;
public:
Expand Down Expand Up @@ -154,7 +156,8 @@ class WebMParser

WebMParser& parser() const { return m_parser; }

virtual webm::Status consumeFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t*, const MediaTime&)
using ConsumeFrameDataResult = WebMParser::ConsumeFrameDataResult;
virtual ConsumeFrameDataResult consumeFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t*, const MediaTime&)
{
ASSERT_NOT_REACHED();
return webm::Status(webm::Status::kInvalidElementId);
Expand Down Expand Up @@ -221,7 +224,7 @@ class WebMParser

private:
ASCIILiteral logClassName() const { return "VideoTrackData"_s; }
webm::Status consumeFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t*, const MediaTime&) final;
ConsumeFrameDataResult consumeFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t*, const MediaTime&) final;
void resetCompletedFramesState() final;
void processPendingMediaSamples(const MediaTime&);
WTF::Deque<MediaSamplesBlock::MediaSampleItem> m_pendingMediaSamples;
Expand All @@ -244,7 +247,7 @@ class WebMParser
~AudioTrackData();

private:
webm::Status consumeFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t*, const MediaTime&) final;
ConsumeFrameDataResult consumeFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t*, const MediaTime&) final;
void resetCompletedFramesState() final;
ASCIILiteral logClassName() const { return "AudioTrackData"_s; }

Expand Down Expand Up @@ -296,6 +299,7 @@ class WebMParser
bool m_initializationSegmentProcessed { false };
uint32_t m_timescale { 1000 };
uint64_t m_currentTimecode { 0 };
MediaTime m_currentDuration;

State m_state { State::None };

Expand Down

0 comments on commit 6a9c5f8

Please sign in to comment.