Title: [291033] trunk
Revision
291033
Author
j...@apple.com
Date
2022-03-08 23:38:58 -0800 (Tue, 08 Mar 2022)

Log Message

Have MediaFormatReader plugin use WebMParser directly
https://bugs.webkit.org/show_bug.cgi?id=237594
rdar://89960307

Reviewed by Eric Carlson.

Source/WebCore:

Covered by existing tests.

* platform/MediaSample.h:
(WebCore::MediaSample::byteRange const): Have default implementation.
* platform/VideoFrame.cpp:
* platform/VideoFrame.h:
* platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm:
(WebCore::ImageDecoderAVFObjCSample::byteRangeForAttachment const):
* platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm:
* platform/graphics/cocoa/CMUtilities.h: Export symbols.
* platform/graphics/cocoa/SourceBufferParserWebM.cpp:
(WebCore::WebMParser::createByteRangeSamples):
(WebCore::WebMParser::OnTrackEntry):
(WebCore::WebMParser::VideoTrackData::consumeFrameData):
(WebCore::WebMParser::AudioTrackData::consumeFrameData):
(WebCore::WebMParser::provideMediaData):
(WebCore::SourceBufferParserWebM::parsedMediaData):
(WebCore::SourceBufferParserWebM::returnSamples):
(WebCore::SourceBufferParserWebM::flushPendingAudioSamples):
* platform/graphics/cocoa/SourceBufferParserWebM.h:
(WebCore::WebMParser::TrackData::createByteRangeSamples):
(WebCore::WebMParser::TrackData::drainPendingSamples):
* platform/graphics/gstreamer/MediaSampleGStreamer.h:
* platform/mock/mediasource/MockSourceBufferPrivate.cpp:

Source/WebKit:

Directly build the sample tables from the sample's offset/size without
first build MediaSampleAVFObjC objects.
The MTPluginByteSourceRef interface unfortunately doesn't allow to skip a
given number of bytes, and you must read the content into a buffer to be
able to continue reading the resource.
As such, we continue to have to create SharedBuffer objects for each sample.
However, those objects are now much shorter lived and not dispatched to
other work queues. So the peak memory usage when playing a webm is
significantly reduced: a 50% memory reduction (from 440MB to 202MB with a sample video)

* Shared/mac/MediaFormatReader/MediaFormatReader.cpp:
(WebKit::MediaFormatReader::parseByteSource):
(WebKit::MediaFormatReader::parsedInitializationData):
(WebKit::MediaFormatReader::parsedMediaData):
(WebKit::MediaFormatReader::didProvideMediaData):
(WebKit::MediaFormatReader::finishParsing):
* Shared/mac/MediaFormatReader/MediaFormatReader.h:
* Shared/mac/MediaFormatReader/MediaSampleByteRange.cpp:
(WebKit::MediaSampleByteRange::MediaSampleByteRange):
(WebKit::MediaSampleByteRange::trackID const):
(WebKit::MediaSampleByteRange::platformSample const):
(WebKit::MediaSampleByteRange::presentationTime const):
(WebKit::MediaSampleByteRange::decodeTime const):
(WebKit::MediaSampleByteRange::duration const):
(WebKit::MediaSampleByteRange::sizeInBytes const):
(WebKit::MediaSampleByteRange::presentationSize const):
(WebKit::MediaSampleByteRange::flags const):
(WebKit::MediaSampleByteRange::byteRange const):
(WebKit::MediaSampleByteRange::offsetTimestampsBy):
(WebKit::MediaSampleByteRange::setTimestamps):
* Shared/mac/MediaFormatReader/MediaSampleByteRange.h:
* Shared/mac/MediaFormatReader/MediaSampleCursor.cpp:
(WebKit::MediaSampleCursor::copyFormatDescription const):
* Shared/mac/MediaFormatReader/MediaTrackReader.cpp:
(WebKit::MediaTrackReader::addSample):
(WebKit::MediaTrackReader::copyProperty):
* Shared/mac/MediaFormatReader/MediaTrackReader.h:

Tools:

* TestWebKitAPI/Tests/WebCore/SampleMap.cpp:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (291032 => 291033)


--- trunk/Source/WebCore/ChangeLog	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/ChangeLog	2022-03-09 07:38:58 UTC (rev 291033)
@@ -1,3 +1,37 @@
+2022-03-08  Jean-Yves Avenard  <j...@apple.com>
+
+        Have MediaFormatReader plugin use WebMParser directly
+        https://bugs.webkit.org/show_bug.cgi?id=237594
+        rdar://89960307
+
+        Reviewed by Eric Carlson.
+
+        Covered by existing tests.
+
+        * platform/MediaSample.h:
+        (WebCore::MediaSample::byteRange const): Have default implementation.
+        * platform/VideoFrame.cpp:
+        * platform/VideoFrame.h:
+        * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm:
+        (WebCore::ImageDecoderAVFObjCSample::byteRangeForAttachment const):
+        * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm:
+        * platform/graphics/cocoa/CMUtilities.h: Export symbols.
+        * platform/graphics/cocoa/SourceBufferParserWebM.cpp:
+        (WebCore::WebMParser::createByteRangeSamples):
+        (WebCore::WebMParser::OnTrackEntry):
+        (WebCore::WebMParser::VideoTrackData::consumeFrameData):
+        (WebCore::WebMParser::AudioTrackData::consumeFrameData):
+        (WebCore::WebMParser::provideMediaData):
+        (WebCore::SourceBufferParserWebM::parsedMediaData):
+        (WebCore::SourceBufferParserWebM::returnSamples):
+        (WebCore::SourceBufferParserWebM::flushPendingAudioSamples):
+        * platform/graphics/cocoa/SourceBufferParserWebM.h:
+        (WebCore::WebMParser::TrackData::createByteRangeSamples):
+        (WebCore::WebMParser::TrackData::drainPendingSamples):
+        * platform/graphics/gstreamer/MediaSampleGStreamer.h:
+        * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+
 2022-03-08  Chris Dumez  <cdu...@apple.com>
 
         IntersectionObserver is causing massive document leaks on haaretz.co.il

Modified: trunk/Source/WebCore/platform/MediaSample.h (291032 => 291033)


--- trunk/Source/WebCore/platform/MediaSample.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/MediaSample.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -30,6 +30,7 @@
 #include "PlatformVideoColorSpace.h"
 #include "SharedBuffer.h"
 #include <_javascript_Core/TypedArrays.h>
+#include <functional>
 #include <wtf/EnumTraits.h>
 #include <wtf/MediaTime.h>
 #include <wtf/ThreadSafeRefCounted.h>
@@ -47,6 +48,7 @@
 class MockSampleBox;
 class ProcessIdentity;
 class SharedBuffer;
+struct TrackInfo;
 
 struct PlatformSample {
     enum Type {
@@ -61,7 +63,7 @@
         const MockSampleBox* mockSampleBox;
         CMSampleBufferRef cmSampleBuffer;
         GstSample* gstSample;
-        std::pair<MTPluginByteSourceRef, CMFormatDescriptionRef> byteRangeSample;
+        std::pair<MTPluginByteSourceRef, std::reference_wrapper<const TrackInfo>> byteRangeSample;
     } sample;
 };
 
@@ -107,7 +109,7 @@
         size_t byteOffset { 0 };
         size_t byteLength { 0 };
     };
-    virtual std::optional<ByteRange> byteRange() const = 0;
+    virtual std::optional<ByteRange> byteRange() const { return std::nullopt; }
 
     enum class VideoRotation {
         None = 0,
@@ -227,11 +229,13 @@
 
 class MediaSamplesBlock {
 public:
+    using MediaSampleDataType = std::variant<MediaSample::ByteRange, Ref<const FragmentedSharedBuffer>>;
     struct MediaSampleItem {
+        using MediaSampleDataType = MediaSamplesBlock::MediaSampleDataType;
         MediaTime presentationTime;
         MediaTime decodeTime;
         MediaTime duration;
-        std::variant<MediaSample::ByteRange, Ref<const FragmentedSharedBuffer>> data;
+        MediaSampleDataType data;
         MediaSample::SampleFlags flags;
     };
 

Modified: trunk/Source/WebCore/platform/VideoFrame.cpp (291032 => 291033)


--- trunk/Source/WebCore/platform/VideoFrame.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/VideoFrame.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -108,13 +108,6 @@
     return MediaSample::SampleFlags::None;
 }
 
-std::optional<MediaSample::ByteRange> VideoFrame::byteRange() const
-{
-    // FIXME: Remove from the base class.
-    ASSERT_NOT_REACHED();
-    return std::nullopt;
-}
-
 void VideoFrame::dump(PrintStream&) const
 {
 }

Modified: trunk/Source/WebCore/platform/VideoFrame.h (291032 => 291033)


--- trunk/Source/WebCore/platform/VideoFrame.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/VideoFrame.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -74,7 +74,6 @@
     WEBCORE_EXPORT void setTimestamps(const MediaTime&, const MediaTime&) final;
     WEBCORE_EXPORT Ref<WebCore::MediaSample> createNonDisplayingCopy() const final;
     WEBCORE_EXPORT SampleFlags flags() const final;
-    WEBCORE_EXPORT std::optional<ByteRange> byteRange() const final;
     WEBCORE_EXPORT void dump(PrintStream&) const final;
 };
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm	2022-03-09 07:38:58 UTC (rev 291033)
@@ -53,6 +53,7 @@
 #import <wtf/MediaTime.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/Vector.h>
+#import <wtf/cf/TypeCastsCF.h>
 
 #import "CoreVideoSoftLink.h"
 #import "VideoToolboxSoftLink.h"
@@ -272,6 +273,26 @@
     {
     }
 
+    std::optional<ByteRange> byteRangeForAttachment(CFStringRef key) const
+    {
+        auto byteOffsetCF = dynamic_cf_cast<CFNumberRef>(PAL::CMGetAttachment(m_sample.get(), key, nullptr));
+        if (!byteOffsetCF)
+            return std::nullopt;
+
+        int64_t byteOffset = 0;
+        if (!CFNumberGetValue(byteOffsetCF, kCFNumberSInt64Type, &byteOffset))
+            return std::nullopt;
+
+        CMItemCount sizeArrayEntries = 0;
+        PAL::CMSampleBufferGetSampleSizeArray(m_sample.get(), 0, nullptr, &sizeArrayEntries);
+        if (sizeArrayEntries != 1)
+            return std::nullopt;
+
+        size_t singleSizeEntry = 0;
+        PAL::CMSampleBufferGetSampleSizeArray(m_sample.get(), 1, &singleSizeEntry, nullptr);
+        return { { CheckedSize(byteOffset), singleSizeEntry } };
+    }
+
     RetainPtr<CGImageRef> m_image;
     bool m_hasAlpha { false };
 };

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -64,7 +64,6 @@
     SampleFlags flags() const override;
     PlatformSample platformSample() const override;
     PlatformSample::Type platformSampleType() const override { return PlatformSample::CMSampleBufferType; }
-    std::optional<ByteRange> byteRange() const override;
     void offsetTimestampsBy(const MediaTime&) override;
     void setTimestamps(const MediaTime&, const MediaTime&) override;
     WEBCORE_EXPORT bool isDivisable() const override;
@@ -82,8 +81,6 @@
     bool isHomogeneous() const;
     Vector<Ref<MediaSampleAVFObjC>> divideIntoHomogeneousSamples();
 
-    void setByteRangeOffset(size_t);
-
 #if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
     using KeyIDs = Vector<Ref<FragmentedSharedBuffer>>;
     void setKeyIDs(KeyIDs&& keyIDs) { m_keyIDs = WTFMove(keyIDs); }
@@ -101,8 +98,6 @@
     WEBCORE_EXPORT MediaSampleAVFObjC(CMSampleBufferRef, VideoRotation, bool mirrored);
     WEBCORE_EXPORT virtual ~MediaSampleAVFObjC();
 
-    std::optional<MediaSample::ByteRange> byteRangeForAttachment(CFStringRef key) const;
-
     RetainPtr<CMSampleBufferRef> m_sample;
     AtomString m_id;
     VideoRotation m_rotation { VideoRotation::None };

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm	2022-03-09 07:38:58 UTC (rev 291033)
@@ -505,44 +505,6 @@
     return adoptCF(newSampleBuffer);
 }
 
-static CFStringRef byteRangeOffsetAttachmentKey()
-{
-    static CFStringRef key = CFSTR("WebKitMediaSampleByteRangeOffset");
-    return key;
-}
-
-std::optional<MediaSample::ByteRange> MediaSampleAVFObjC::byteRange() const
-{
-    return byteRangeForAttachment(byteRangeOffsetAttachmentKey());
-}
-
-void MediaSampleAVFObjC::setByteRangeOffset(size_t byteOffset)
-{
-    int64_t checkedOffset = CheckedInt64(byteOffset);
-    auto offsetNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &checkedOffset));
-    PAL::CMSetAttachment(m_sample.get(), byteRangeOffsetAttachmentKey(), offsetNumber.get(), kCMAttachmentMode_ShouldPropagate);
-}
-
-std::optional<MediaSample::ByteRange> MediaSampleAVFObjC::byteRangeForAttachment(CFStringRef key) const
-{
-    auto byteOffsetCF = dynamic_cf_cast<CFNumberRef>(PAL::CMGetAttachment(m_sample.get(), key, nullptr));
-    if (!byteOffsetCF)
-        return std::nullopt;
-
-    int64_t byteOffset = 0;
-    if (!CFNumberGetValue(byteOffsetCF, kCFNumberSInt64Type, &byteOffset))
-        return std::nullopt;
-
-    CMItemCount sizeArrayEntries = 0;
-    PAL::CMSampleBufferGetSampleSizeArray(m_sample.get(), 0, nullptr, &sizeArrayEntries);
-    if (sizeArrayEntries != 1)
-        return std::nullopt;
-
-    size_t singleSizeEntry = 0;
-    PAL::CMSampleBufferGetSampleSizeArray(m_sample.get(), 1, &singleSizeEntry, nullptr);
-    return { { CheckedSize(byteOffset), singleSizeEntry } };
-}
-
 CVPixelBufferRef MediaSampleAVFObjC::pixelBuffer() const
 {
     return static_cast<CVPixelBufferRef>(PAL::CMSampleBufferGetImageBuffer(m_sample.get()));

Modified: trunk/Source/WebCore/platform/graphics/cocoa/CMUtilities.h (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/cocoa/CMUtilities.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/cocoa/CMUtilities.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -41,7 +41,7 @@
 WEBCORE_EXPORT RetainPtr<CMFormatDescriptionRef> createFormatDescriptionFromTrackInfo(const TrackInfo&);
 // Convert MediaSamplesBlock to the equivalent CMSampleBufferRef. If CMFormatDescriptionRef
 // is set it will be used, otherwise it will be created from the MediaSamplesBlock's TrackInfo.
-WEBCORE_EXPORT Expected<RetainPtr<CMSampleBufferRef>, CString> toCMSampleBuffer(MediaSamplesBlock&&, CMFormatDescriptionRef);
+WEBCORE_EXPORT Expected<RetainPtr<CMSampleBufferRef>, CString> toCMSampleBuffer(MediaSamplesBlock&&, CMFormatDescriptionRef = nullptr);
 
 }
 

Modified: trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -536,9 +536,7 @@
 {
 }
 
-WebMParser::~WebMParser()
-{
-}
+WebMParser::~WebMParser() = default;
 
 void WebMParser::resetState()
 {
@@ -560,6 +558,13 @@
     m_parser->DidSeek();
 }
 
+void WebMParser::createByteRangeSamples()
+{
+    for (auto& track : m_tracks)
+        track->createByteRangeSamples();
+    m_createByteRangeSamples = true;
+}
+
 ExceptionOr<int> WebMParser::parse(SourceBufferParser::Segment&& segment)
 {
     if (!m_parser)
@@ -851,32 +856,30 @@
     }
 
     StringView codecString { trackEntry.codec_id.value().data(), (unsigned)trackEntry.codec_id.value().length() };
+    auto track = [&]() -> UniqueRef<TrackData> {
 #if ENABLE(VP9)
-    if (codecString == "V_VP9" && isVP9DecoderAvailable()) {
-        m_tracks.append(VideoTrackData::create(CodecType::VP9, trackEntry, *this));
-        return Status(Status::kOkCompleted);
-    }
-    if (codecString == "V_VP8" && isVP8DecoderAvailable()) {
-        m_tracks.append(VideoTrackData::create(CodecType::VP8, trackEntry, *this));
-        return Status(Status::kOkCompleted);
-    }
+        if (codecString == "V_VP9" && isVP9DecoderAvailable())
+            return VideoTrackData::create(CodecType::VP9, trackEntry, *this);
+        if (codecString == "V_VP8" && isVP8DecoderAvailable())
+            return VideoTrackData::create(CodecType::VP8, trackEntry, *this);
 #endif
 
 #if ENABLE(VORBIS)
-    if (codecString == "A_VORBIS" && isVorbisDecoderAvailable()) {
-        m_tracks.append(AudioTrackData::create(CodecType::Vorbis, trackEntry, *this));
-        return Status(Status::kOkCompleted);
-    }
+        if (codecString == "A_VORBIS" && isVorbisDecoderAvailable())
+            return AudioTrackData::create(CodecType::Vorbis, trackEntry, *this);
 #endif
 
 #if ENABLE(OPUS)
-    if (codecString == "A_OPUS" && isOpusDecoderAvailable()) {
-        m_tracks.append(AudioTrackData::create(CodecType::Opus, trackEntry, *this));
-        return Status(Status::kOkCompleted);
-    }
+        if (codecString == "A_OPUS" && isOpusDecoderAvailable())
+            return AudioTrackData::create(CodecType::Opus, trackEntry, *this);
 #endif
+        return TrackData::create(CodecType::Unsupported, trackEntry, *this);
+    }();
 
-    m_tracks.append(TrackData::create(CodecType::Unsupported, trackEntry, *this));
+    if (m_createByteRangeSamples)
+        track->createByteRangeSamples();
+
+    m_tracks.append(WTFMove(track));
     return Status(Status::kOkCompleted);
 }
 
@@ -1032,6 +1035,11 @@
         return webm::Status(webm::Status::kOkPartial);
 
     m_completeBlockBuffer = m_currentBlockBuffer.take();
+    if (m_useByteRange)
+        m_completeFrameData = MediaSample::ByteRange { metadata.position, metadata.size };
+    else
+        m_completeFrameData = Ref { *m_completeBlockBuffer };
+
     m_completePacketSize = std::nullopt;
     m_partialBytesRead = 0;
 
@@ -1051,10 +1059,8 @@
     if (!status.completed_ok())
         return status;
 
-    m_lastPosition = metadata.position;
-
     constexpr size_t maxHeaderSize = 32; // The maximum length of a VP9 uncompressed header is 144 bits and 11 bytes for VP8. Round high.
-    size_t segmentHeaderLength = std::min(maxHeaderSize, m_completeBlockBuffer->size());
+    size_t segmentHeaderLength = std::min<size_t>(maxHeaderSize, metadata.size);
     auto contiguousBuffer = contiguousCompleteBlockBuffer(0, segmentHeaderLength);
     if (!contiguousBuffer) {
         PARSER_LOG_ERROR_IF_POSSIBLE("VideoTrackData::consumeFrameData failed to create contiguous data block");
@@ -1090,7 +1096,7 @@
     if (track.default_duration.is_present())
         duration = track.default_duration.value() * presentationTime.timeScale() / k_us_in_seconds;
 
-    m_completeMediaSamples.append({ presentationTime, presentationTime, MediaTime(duration, presentationTime.timeScale()), m_completeBlockBuffer.releaseNonNull(), isKey ? MediaSample::SampleFlags::IsSync : MediaSample::SampleFlags::None });
+    m_completeMediaSamples.append({ presentationTime, presentationTime, MediaTime(duration, presentationTime.timeScale()), WTFMove(m_completeFrameData), isKey ? MediaSample::SampleFlags::IsSync : MediaSample::SampleFlags::None });
 
     drainPendingSamples();
 
@@ -1116,8 +1122,6 @@
     if (!status.completed_ok())
         return status;
 
-    m_lastPosition = metadata.position;
-
     if (!formatDescription()) {
         if (!track().codec_private.is_present()) {
             PARSER_LOG_ERROR_IF_POSSIBLE("Audio track missing magic cookie");
@@ -1180,7 +1184,7 @@
     else if (formatDescription() && *formatDescription() != *m_completeMediaSamples.info())
         drainPendingSamples();
 
-    m_completeMediaSamples.append({ presentationTime, MediaTime::invalidTime(), m_packetDuration, m_completeBlockBuffer.releaseNonNull(), MediaSample::SampleFlags::IsSync });
+    m_completeMediaSamples.append({ presentationTime, MediaTime::invalidTime(), m_packetDuration, WTFMove(m_completeFrameData), MediaSample::SampleFlags::IsSync });
 
     drainPendingSamples();
 
@@ -1299,9 +1303,9 @@
     return nullptr;
 }
 
-void WebMParser::provideMediaData(MediaSamplesBlock&& samples, uint64_t position)
+void WebMParser::provideMediaData(MediaSamplesBlock&& samples)
 {
-    m_callback.parsedMediaData(WTFMove(samples), position);
+    m_callback.parsedMediaData(WTFMove(samples));
 }
 
 void SourceBufferParserWebM::parsedInitializationData(InitializationSegment&& initializationSegment)
@@ -1312,7 +1316,7 @@
     });
 }
 
-void SourceBufferParserWebM::parsedMediaData(MediaSamplesBlock&& samplesBlock, uint64_t position)
+void SourceBufferParserWebM::parsedMediaData(MediaSamplesBlock&& samplesBlock)
 {
     if (!samplesBlock.info()) {
         ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "No TrackInfo set");
@@ -1336,7 +1340,7 @@
     }
 
     if (samplesBlock.isVideo()) {
-        returnSamples(WTFMove(samplesBlock), m_videoFormatDescription.get(), position);
+        returnSamples(WTFMove(samplesBlock), m_videoFormatDescription.get());
         return;
     }
 
@@ -1344,7 +1348,7 @@
     if (m_queuedAudioSamples.size()) {
         auto& lastSample = m_queuedAudioSamples.last();
         if (lastSample.duration + lastSample.presentationTime != samplesBlock.first().presentationTime)
-            flushPendingAudioSamples(position);
+            flushPendingAudioSamples();
     }
     for (auto& sample : samplesBlock)
         m_queuedAudioDuration += sample.duration;
@@ -1351,10 +1355,10 @@
     m_queuedAudioSamples.append(WTFMove(samplesBlock));
     if (m_queuedAudioDuration < m_minimumAudioSampleDuration)
         return;
-    flushPendingAudioSamples(position);
+    flushPendingAudioSamples();
 }
 
-void SourceBufferParserWebM::returnSamples(MediaSamplesBlock&& block, CMFormatDescriptionRef description, std::optional<uint64_t> position)
+void SourceBufferParserWebM::returnSamples(MediaSamplesBlock&& block, CMFormatDescriptionRef description)
 {
     if (block.isEmpty())
         return;
@@ -1365,13 +1369,11 @@
         return;
     }
 
-    m_callOnClientThreadCallback([this, protectedThis = Ref { *this }, trackID = block.info()->trackID, sampleBuffer = WTFMove(expectedBuffer.value()), position] () mutable {
+    m_callOnClientThreadCallback([this, protectedThis = Ref { *this }, trackID = block.info()->trackID, sampleBuffer = WTFMove(expectedBuffer.value())] () mutable {
         if (!m_didProvideMediaDataCallback)
             return;
 
         auto mediaSample = MediaSampleAVFObjC::create(sampleBuffer.get(), trackID);
-        if (position)
-            mediaSample->setByteRangeOffset(*position);
 
         m_didProvideMediaDataCallback(WTFMove(mediaSample), trackID, emptyString());
     });
@@ -1391,13 +1393,13 @@
         m_didProvideContentKeyRequestInitializationDataForTrackIDCallback(WTFMove(keyID), trackID);
 }
 
-void SourceBufferParserWebM::flushPendingAudioSamples(std::optional<uint64_t> position)
+void SourceBufferParserWebM::flushPendingAudioSamples()
 {
     if (!m_audioFormatDescription)
         return;
     ASSERT(m_audioInfo);
     m_queuedAudioSamples.setInfo(m_audioInfo.copyRef());
-    returnSamples(WTFMove(m_queuedAudioSamples), m_audioFormatDescription.get(), position);
+    returnSamples(WTFMove(m_queuedAudioSamples), m_audioFormatDescription.get());
 
     m_queuedAudioSamples = { };
     m_queuedAudioDuration = { };

Modified: trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -28,6 +28,7 @@
 #if ENABLE(MEDIA_SOURCE)
 
 #include "ExceptionOr.h"
+#include "MediaSample.h"
 #include "SharedBuffer.h"
 #include "SourceBufferParser.h"
 #include <CoreAudio/CoreAudioTypes.h>
@@ -52,30 +53,30 @@
     WTF_MAKE_FAST_ALLOCATED;
 public:
     class Callback {
-        WTF_MAKE_FAST_ALLOCATED;
     public:
         virtual void parsedTrimmingData(uint64_t, const MediaTime&) { }
         virtual void parsedInitializationData(SourceBufferParser::InitializationSegment&&) = 0;
-        virtual void parsedMediaData(MediaSamplesBlock&&, uint64_t) = 0;
+        virtual void parsedMediaData(MediaSamplesBlock&&) = 0;
         virtual bool canDecrypt() const { return false; }
         virtual void contentKeyRequestInitializationDataForTrackID(Ref<SharedBuffer>&&, uint64_t) { }
         virtual ~Callback() = default;
     };
 
-    WebMParser(Callback&);
-    ~WebMParser();
+    WEBCORE_EXPORT WebMParser(Callback&);
+    WEBCORE_EXPORT ~WebMParser();
 
     class SegmentReader;
 
-    ExceptionOr<int> parse(SourceBufferParser::Segment&&);
-    void resetState();
-    void reset();
-    void invalidate();
+    WEBCORE_EXPORT void createByteRangeSamples();
+    WEBCORE_EXPORT ExceptionOr<int> parse(SourceBufferParser::Segment&&);
+    WEBCORE_EXPORT void resetState();
+    WEBCORE_EXPORT void reset();
+    WEBCORE_EXPORT void invalidate();
     const webm::Status& status() const { return m_status; }
 
-    void provideMediaData(MediaSamplesBlock&&, uint64_t);
+    void provideMediaData(MediaSamplesBlock&&);
 
-    void setLogger(const Logger&, const void* identifier);
+    WEBCORE_EXPORT void setLogger(const Logger&, const void* identifier);
     const Logger* loggerPtr() const { return m_logger.get(); }
     const void* logIdentifier() const { return m_logIdentifier; }
 
@@ -134,6 +135,8 @@
         webm::TrackEntry& track() { return m_track; }
         TrackInfo::TrackType trackType() const { return m_trackType; }
 
+        void createByteRangeSamples() { m_useByteRange = true; }
+
         RefPtr<TrackInfo> formatDescription() const { return m_formatDescription.copyRef(); }
         void setFormatDescription(Ref<TrackInfo>&& description)
         {
@@ -167,7 +170,7 @@
         {
             if (!m_completeMediaSamples.size())
                 return;
-            m_parser.provideMediaData(WTFMove(m_completeMediaSamples), m_lastPosition);
+            m_parser.provideMediaData(WTFMove(m_completeMediaSamples));
             resetCompletedFramesState();
         }
 
@@ -174,9 +177,9 @@
     protected:
         RefPtr<SharedBuffer> contiguousCompleteBlockBuffer(size_t offset, size_t length) const;
         webm::Status readFrameData(webm::Reader&, const webm::FrameMetadata&, uint64_t* bytesRemaining);
-        RefPtr<FragmentedSharedBuffer> m_completeBlockBuffer;
         MediaSamplesBlock m_completeMediaSamples;
-        uint64_t m_lastPosition { 0 };
+        bool m_useByteRange { false };
+        MediaSamplesBlock::MediaSampleDataType m_completeFrameData;
 
     private:
         CodecType m_codec;
@@ -184,6 +187,7 @@
         const TrackInfo::TrackType m_trackType;
         RefPtr<TrackInfo> m_formatDescription;
         SharedBufferBuilder m_currentBlockBuffer;
+        RefPtr<const FragmentedSharedBuffer> m_completeBlockBuffer;
         WebMParser& m_parser;
         std::optional<size_t> m_completePacketSize;
         // Size of the currently incomplete parsed packet.
@@ -279,6 +283,7 @@
     const void* m_logIdentifier { nullptr };
     uint64_t m_nextChildIdentifier { 0 };
     Callback& m_callback;
+    bool m_createByteRangeSamples { false };
 };
 
 class SourceBufferParserWebM : public SourceBufferParser, WebMParser::Callback {
@@ -308,7 +313,7 @@
         m_didParseTrimmingDataCallback = WTFMove(callback);
     }
 
-    void flushPendingAudioSamples(std::optional<uint64_t> = std::nullopt);
+    void flushPendingAudioSamples();
     void setMinimumAudioSampleDuration(float);
     
     WEBCORE_EXPORT void setLogger(const Logger&, const void* identifier) final;
@@ -318,13 +323,13 @@
 private:
     // WebMParser::Callback
     void parsedInitializationData(SourceBufferParser::InitializationSegment&&) final;
-    void parsedMediaData(MediaSamplesBlock&&, uint64_t) final;
+    void parsedMediaData(MediaSamplesBlock&&) final;
     bool canDecrypt() const final { return !!m_didProvideContentKeyRequestInitializationDataForTrackIDCallback; }
     void contentKeyRequestInitializationDataForTrackID(Ref<SharedBuffer>&&, uint64_t) final;
     void parsedTrimmingData(uint64_t, const MediaTime&) final;
-    
-    void returnSamples(MediaSamplesBlock&&, CMFormatDescriptionRef, std::optional<uint64_t>);
 
+    void returnSamples(MediaSamplesBlock&&, CMFormatDescriptionRef);
+
     DidParseTrimmingDataCallback m_didParseTrimmingDataCallback;
     WebMParser m_parser;
     RetainPtr<CMFormatDescriptionRef> m_audioFormatDescription;

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h (291032 => 291033)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -61,7 +61,6 @@
     SampleFlags flags() const override { return m_flags; }
     PlatformSample platformSample() const override;
     PlatformSample::Type platformSampleType() const override { return PlatformSample::GStreamerSampleType; }
-    std::optional<ByteRange> byteRange() const override { return std::nullopt; }
     void dump(PrintStream&) const override;
     RefPtr<JSC::Uint8ClampedArray> getRGBAImageData() const final;
     VideoRotation videoRotation() const override { return m_videoRotation; }

Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (291032 => 291033)


--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -62,7 +62,6 @@
     SampleFlags flags() const override;
     PlatformSample platformSample() const override;
     PlatformSample::Type platformSampleType() const override { return PlatformSample::MockSampleBoxType; }
-    std::optional<ByteRange> byteRange() const override { return std::nullopt; }
     FloatSize presentationSize() const override { return FloatSize(); }
     void dump(PrintStream&) const override;
     void offsetTimestampsBy(const MediaTime& offset) override { m_box.offsetTimestampsBy(offset); }

Modified: trunk/Source/WebKit/ChangeLog (291032 => 291033)


--- trunk/Source/WebKit/ChangeLog	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/ChangeLog	2022-03-09 07:38:58 UTC (rev 291033)
@@ -1,3 +1,49 @@
+2022-03-08  Jean-Yves Avenard  <j...@apple.com>
+
+        Have MediaFormatReader plugin use WebMParser directly
+        https://bugs.webkit.org/show_bug.cgi?id=237594
+        rdar://89960307
+
+        Reviewed by Eric Carlson.
+
+        Directly build the sample tables from the sample's offset/size without
+        first build MediaSampleAVFObjC objects.
+        The MTPluginByteSourceRef interface unfortunately doesn't allow to skip a
+        given number of bytes, and you must read the content into a buffer to be
+        able to continue reading the resource.
+        As such, we continue to have to create SharedBuffer objects for each sample.
+        However, those objects are now much shorter lived and not dispatched to
+        other work queues. So the peak memory usage when playing a webm is
+        significantly reduced: a 50% memory reduction (from 440MB to 202MB with a sample video)
+
+        * Shared/mac/MediaFormatReader/MediaFormatReader.cpp:
+        (WebKit::MediaFormatReader::parseByteSource):
+        (WebKit::MediaFormatReader::parsedInitializationData):
+        (WebKit::MediaFormatReader::parsedMediaData):
+        (WebKit::MediaFormatReader::didProvideMediaData):
+        (WebKit::MediaFormatReader::finishParsing):
+        * Shared/mac/MediaFormatReader/MediaFormatReader.h:
+        * Shared/mac/MediaFormatReader/MediaSampleByteRange.cpp:
+        (WebKit::MediaSampleByteRange::MediaSampleByteRange):
+        (WebKit::MediaSampleByteRange::trackID const):
+        (WebKit::MediaSampleByteRange::platformSample const):
+        (WebKit::MediaSampleByteRange::presentationTime const):
+        (WebKit::MediaSampleByteRange::decodeTime const):
+        (WebKit::MediaSampleByteRange::duration const):
+        (WebKit::MediaSampleByteRange::sizeInBytes const):
+        (WebKit::MediaSampleByteRange::presentationSize const):
+        (WebKit::MediaSampleByteRange::flags const):
+        (WebKit::MediaSampleByteRange::byteRange const):
+        (WebKit::MediaSampleByteRange::offsetTimestampsBy):
+        (WebKit::MediaSampleByteRange::setTimestamps):
+        * Shared/mac/MediaFormatReader/MediaSampleByteRange.h:
+        * Shared/mac/MediaFormatReader/MediaSampleCursor.cpp:
+        (WebKit::MediaSampleCursor::copyFormatDescription const):
+        * Shared/mac/MediaFormatReader/MediaTrackReader.cpp:
+        (WebKit::MediaTrackReader::addSample):
+        (WebKit::MediaTrackReader::copyProperty):
+        * Shared/mac/MediaFormatReader/MediaTrackReader.h:
+
 2022-03-08  John Cunningham  <johncunning...@apple.com>
 
         RemoteGraphicsContextGL ReadPixels does not preserve contents for area that is not part of the Framebuffer

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -132,14 +132,6 @@
 {
     ASSERT(isMainRunLoop());
 
-    static NeverDestroyed<ContentType> contentType("video/webm"_s);
-    auto parser = SourceBufferParserWebM::create(contentType);
-    if (!parser) {
-        Locker locker { m_parseTracksLock };
-        m_parseTracksStatus = kMTPluginFormatReaderError_AllocationFailure;
-        return;
-    }
-
     if (!m_logger) {
         m_logger = &Document::sharedLogger();
         m_logIdentifier = nextLogIdentifier();
@@ -146,27 +138,7 @@
     }
 
     ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER);
-    parser->setLogger(*m_logger, m_logIdentifier);
 
-    // Set a minimum audio sample duration of 0 so the parser creates indivisible samples with byte source ranges.
-    parser->setMinimumAudioSampleDuration(0);
-
-    parser->setCallOnClientThreadCallback([](Function<void()>&& function) {
-        MediaTrackReader::storageQueue().dispatch(WTFMove(function));
-    });
-
-    parser->setDidParseInitializationDataCallback([this, protectedThis = Ref { *this }](SourceBufferParser::InitializationSegment&& initializationSegment) {
-        didParseTracks(WTFMove(initializationSegment), noErr);
-    });
-
-    parser->setDidEncounterErrorDuringParsingCallback([this, protectedThis = Ref { *this }](uint64_t errorCode) {
-        didParseTracks({ }, errorCode);
-    });
-
-    parser->setDidProvideMediaDataCallback([this, protectedThis = Ref { *this }](Ref<MediaSampleAVFObjC>&& mediaSample, uint64_t trackID, const String& mediaType) {
-        didProvideMediaData(WTFMove(mediaSample), trackID, mediaType);
-    });
-
     Locker locker { m_parseTracksLock };
     m_byteSource = WTFMove(byteSource);
     m_parseTracksStatus = std::nullopt;
@@ -173,14 +145,34 @@
     m_duration = MediaTime::invalidTime();
     m_trackReaders.clear();
 
-    readerQueue().dispatch([this, protectedThis = Ref { *this }, byteSource = m_byteSource, parser = parser.releaseNonNull()]() mutable {
-        parser->appendData(WTFMove(byteSource));
-        MediaTrackReader::storageQueue().dispatch([this, protectedThis = Ref { *this }, parser = WTFMove(parser)]() mutable {
-            finishParsing(WTFMove(parser));
+    // FIXME: why do we need a storage queue different to reader's queue?
+    readerQueue().dispatch([this, protectedThis = Ref { *this }, byteSource = m_byteSource]() mutable {
+        WebMParser parser(*this);
+        parser.setLogger(*m_logger, m_logIdentifier);
+        parser.createByteRangeSamples();
+        auto result = parser.parse(WTFMove(byteSource));
+        MediaTrackReader::storageQueue().dispatch([this, protectedThis = Ref { *this }, result] () mutable {
+            if (!result.hasException() && result.returnValue())
+                didParseTracks({ }, result.returnValue());
+            finishParsing();
         });
     });
 }
 
+void MediaFormatReader::parsedInitializationData(SourceBufferParser::InitializationSegment&& initializationSegment)
+{
+    MediaTrackReader::storageQueue().dispatch([this, protectedThis = Ref { *this }, initializationSegment = WTFMove(initializationSegment)] () mutable {
+        didParseTracks(WTFMove(initializationSegment), noErr);
+    });
+}
+
+void MediaFormatReader::parsedMediaData(MediaSamplesBlock&& mediaSamples)
+{
+    MediaTrackReader::storageQueue().dispatch([this, protectedThis = Ref { *this }, mediaSamples = WTFMove(mediaSamples)] () mutable {
+        didProvideMediaData(WTFMove(mediaSamples));
+    });
+}
+
 void MediaFormatReader::didParseTracks(SourceBufferPrivateClient::InitializationSegment&& segment, uint64_t errorCode)
 {
     ASSERT(!isMainRunLoop());
@@ -225,20 +217,20 @@
     m_init = true;
 }
 
-void MediaFormatReader::didProvideMediaData(Ref<MediaSampleAVFObjC>&& mediaSample, uint64_t trackID, const String&)
+void MediaFormatReader::didProvideMediaData(MediaSamplesBlock&& mediaSamples)
 {
     ASSERT(!isMainRunLoop());
 
     Locker locker { m_parseTracksLock };
     auto trackIndex = m_trackReaders.findIf([&](auto& track) {
-        return track->trackID() == trackID;
+        return track->trackID() == mediaSamples.info()->trackID;
     });
 
     if (trackIndex != notFound)
-        m_trackReaders[trackIndex]->addSample(WTFMove(mediaSample), m_byteSource.get());
+        m_trackReaders[trackIndex]->addSample(WTFMove(mediaSamples), m_byteSource.get());
 }
 
-void MediaFormatReader::finishParsing(Ref<SourceBufferParser>&& parser)
+void MediaFormatReader::finishParsing()
 {
     ASSERT(!isMainRunLoop());
     ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER);
@@ -258,11 +250,6 @@
         if (greatestPresentationTime.isValid())
             m_duration = greatestPresentationTime;
     }
-
-    parser->setDidParseInitializationDataCallback(nullptr);
-    parser->setDidEncounterErrorDuringParsingCallback(nullptr);
-    parser->setDidProvideMediaDataCallback(nullptr);
-    parser->resetParserState();
 }
 
 OSStatus MediaFormatReader::copyProperty(CFStringRef key, CFAllocatorRef allocator, void* valueCopy)

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.h (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -28,6 +28,7 @@
 #if ENABLE(WEBM_FORMAT_READER)
 
 #include "CoreMediaWrapped.h"
+#include <WebCore/SourceBufferParserWebM.h>
 #include <WebCore/SourceBufferPrivateClient.h>
 #include <wtf/Condition.h>
 #include <wtf/Lock.h>
@@ -36,8 +37,8 @@
 DECLARE_CORE_MEDIA_TRAITS(FormatReader);
 
 namespace WebCore {
-class MediaSampleAVFObjC;
-class SourceBufferParser;
+class MediaSamplesBlock;
+class WebMParser;
 }
 
 namespace WebKit {
@@ -44,7 +45,7 @@
 
 class MediaTrackReader;
 
-class MediaFormatReader final : public CoreMediaWrapped<MediaFormatReader> {
+class MediaFormatReader final : public CoreMediaWrapped<MediaFormatReader> , public WebCore::WebMParser::Callback {
 public:
     using CoreMediaWrapped<MediaFormatReader>::unwrap;
 
@@ -64,12 +65,16 @@
 private:
     explicit MediaFormatReader(Allocator&&);
 
+    // WebMParser::Callback
+    void parsedInitializationData(WebCore::SourceBufferParser::InitializationSegment&&) final;
+    void parsedMediaData(WebCore::MediaSamplesBlock&&) final;
+
     void parseByteSource(RetainPtr<MTPluginByteSourceRef>&&);
     void didParseTracks(WebCore::SourceBufferPrivateClient::InitializationSegment&&, uint64_t errorCode);
     void didSelectVideoTrack(WebCore::VideoTrackPrivate&, bool) { }
     void didEnableAudioTrack(WebCore::AudioTrackPrivate&, bool) { }
-    void didProvideMediaData(Ref<WebCore::MediaSampleAVFObjC>&&, uint64_t, const String&);
-    void finishParsing(Ref<WebCore::SourceBufferParser>&&);
+    void didProvideMediaData(WebCore::MediaSamplesBlock&&);
+    void finishParsing();
 
     // CMBaseClass
     String debugDescription() const final { return "WebKit::MediaFormatReader"_s; }

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.cpp (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -33,57 +33,75 @@
 
 using namespace WebCore;
 
-MediaSampleByteRange::MediaSampleByteRange(MediaSample& sample, MTPluginByteSourceRef byteSource, uint64_t trackID)
-    : m_presentationTime(sample.presentationTime())
-    , m_decodeTime(sample.decodeTime())
-    , m_duration(sample.duration())
-    , m_byteRange(*sample.byteRange())
-    , m_trackID(trackID)
-    , m_sizeInBytes(sample.sizeInBytes())
-    , m_presentationSize(sample.presentationSize())
+MediaSampleByteRange::MediaSampleByteRange(MediaSamplesBlock&& sample, MTPluginByteSourceRef byteSource)
+    : m_block(WTFMove(sample))
     , m_byteSource(byteSource)
-    , m_flags(sample.flags())
 {
-    ASSERT(!isMainRunLoop());
-    ASSERT(m_decodeTime == m_presentationTime || m_decodeTime == MediaTime::invalidTime());
-    auto platformSample = sample.platformSample();
-    switch (platformSample.type) {
-    case PlatformSample::CMSampleBufferType:
-        m_formatDescription = PAL::CMSampleBufferGetFormatDescription(platformSample.sample.cmSampleBuffer);
-        break;
-    case PlatformSample::ByteRangeSampleType:
-        m_formatDescription = platformSample.sample.byteRangeSample.second;
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-        break;
-    }
+    ASSERT(!m_block.isEmpty());
+    ASSERT(std::holds_alternative<MediaSample::ByteRange>(m_block.last().data));
 }
 
 AtomString MediaSampleByteRange::trackID() const
 {
-    return AtomString::number(m_trackID);
+    return AtomString::number(m_block.info()->trackID);
 }
 
 PlatformSample MediaSampleByteRange::platformSample() const
 {
+    ASSERT(m_block.info());
     return {
         PlatformSample::ByteRangeSampleType,
-        { .byteRangeSample = std::make_pair(m_byteSource.get(), m_formatDescription.get()) },
+        { .byteRangeSample = std::make_pair(m_byteSource.get(), std::reference_wrapper(*m_block.info())) },
     };
 }
 
-void MediaSampleByteRange::offsetTimestampsBy(const MediaTime& offset)
+MediaTime MediaSampleByteRange::presentationTime() const
 {
-    setTimestamps(presentationTime() + offset, decodeTime() + offset);
+    return m_block.last().presentationTime;
 }
 
-void MediaSampleByteRange::setTimestamps(const MediaTime& presentationTime, const MediaTime& decodeTime)
+MediaTime MediaSampleByteRange::decodeTime() const
 {
-    m_presentationTime = presentationTime;
-    m_decodeTime = decodeTime;
+    return m_block.last().decodeTime;
 }
 
+MediaTime MediaSampleByteRange::duration() const
+{
+    return m_block.last().duration;
+}
+
+size_t MediaSampleByteRange::sizeInBytes() const
+{
+    return std::get<MediaSample::ByteRange>(m_block.last().data).byteLength;
+}
+
+WebCore::FloatSize MediaSampleByteRange::presentationSize() const
+{
+    if (m_block.isVideo())
+        return downcast<const VideoInfo>(m_block.info())->displaySize;
+    return { };
+}
+
+MediaSampleByteRange::SampleFlags MediaSampleByteRange::flags() const
+{
+    return m_block.last().flags;
+}
+
+std::optional<MediaSampleByteRange::ByteRange> MediaSampleByteRange::byteRange() const
+{
+    return std::get<MediaSample::ByteRange>(m_block.last().data);
+}
+
+void MediaSampleByteRange::offsetTimestampsBy(const MediaTime&)
+{
+    ASSERT_NOT_REACHED();
+}
+
+void MediaSampleByteRange::setTimestamps(const MediaTime&, const MediaTime&)
+{
+    ASSERT_NOT_REACHED();
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEBM_FORMAT_READER)

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.h (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -27,27 +27,24 @@
 
 #if ENABLE(WEBM_FORMAT_READER)
 
-#include <WebCore/MediaSampleAVFObjC.h>
-#include <pal/spi/cocoa/MediaToolboxSPI.h>
-#include <wtf/MediaTime.h>
-#include <wtf/RetainPtr.h>
+#include <WebCore/MediaSample.h>
 
 namespace WebKit {
 
 class MediaSampleByteRange final : public WebCore::MediaSample {
 public:
-    static Ref<MediaSampleByteRange> create(WebCore::MediaSample& sample, MTPluginByteSourceRef byteSource, uint64_t trackID)
+    static Ref<MediaSampleByteRange> create(WebCore::MediaSamplesBlock&& sample, MTPluginByteSourceRef byteSource)
     {
-        return adoptRef(*new MediaSampleByteRange(sample, byteSource, trackID));
+        return adoptRef(*new MediaSampleByteRange(WTFMove(sample), byteSource));
     }
 
-    MediaTime presentationTime() const final { return m_presentationTime; }
-    MediaTime decodeTime() const final { return m_decodeTime; }
-    MediaTime duration() const final { return m_duration; }
-    size_t sizeInBytes() const final { return m_sizeInBytes; }
-    WebCore::FloatSize presentationSize() const final { return m_presentationSize; }
-    SampleFlags flags() const final { return m_flags; }
-    std::optional<ByteRange> byteRange() const final { return m_byteRange; }
+    MediaTime presentationTime() const final;
+    MediaTime decodeTime() const final;
+    MediaTime duration() const final;
+    size_t sizeInBytes() const final;
+    WebCore::FloatSize presentationSize() const final;
+    SampleFlags flags() const final;
+    std::optional<ByteRange> byteRange() const final;
 
     AtomString trackID() const final;
     WebCore::PlatformSample platformSample() const final;
@@ -54,21 +51,13 @@
     WebCore::PlatformSample::Type platformSampleType() const final { return WebCore::PlatformSample::ByteRangeSampleType; }
     void offsetTimestampsBy(const MediaTime&) final;
     void setTimestamps(const MediaTime&, const MediaTime&) final;
-    Ref<MediaSample> createNonDisplayingCopy() const { return *const_cast<MediaSampleByteRange*>(this); }
+    Ref<MediaSample> createNonDisplayingCopy() const final { return *const_cast<MediaSampleByteRange*>(this); }
 
 private:
-    MediaSampleByteRange(MediaSample&, MTPluginByteSourceRef, uint64_t trackID);
+    MediaSampleByteRange(WebCore::MediaSamplesBlock&&, MTPluginByteSourceRef);
 
-    MediaTime m_presentationTime;
-    MediaTime m_decodeTime;
-    MediaTime m_duration;
-    ByteRange m_byteRange;
-    uint64_t m_trackID;
-    size_t m_sizeInBytes;
-    WebCore::FloatSize m_presentationSize;
+    const WebCore::MediaSamplesBlock m_block;
     RetainPtr<MTPluginByteSourceRef> m_byteSource;
-    RetainPtr<CMFormatDescriptionRef> m_formatDescription;
-    SampleFlags m_flags;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleCursor.cpp (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleCursor.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleCursor.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -30,6 +30,7 @@
 
 #include "Logging.h"
 #include "MediaTrackReader.h"
+#include <WebCore/CMUtilities.h>
 #include <WebCore/MediaSample.h>
 #include <WebCore/SampleMap.h>
 #include <pal/avfoundation/MediaTimeAVFoundation.h>
@@ -348,19 +349,11 @@
 
 OSStatus MediaSampleCursor::getSyncInfo(MTPluginSampleCursorSyncInfo* syncInfo) const
 {
-    OSStatus syncInfoStatus = noErr;
-    auto getSampleStatus = getMediaSample([&](MediaSample& sample) {
-        if (sample.hasSyncInfo()) {
-            *syncInfo = {
-                .fullSync = sample.isSync()
-            };
-            return;
-        }
-        syncInfoStatus = kCMBaseObjectError_ValueNotAvailable;
+    return getMediaSample([&](MediaSample& sample) {
+        *syncInfo = {
+            .fullSync = sample.isSync()
+        };
     });
-    if (syncInfoStatus != noErr)
-        return syncInfoStatus;
-    return getSampleStatus;
 }
 
 OSStatus MediaSampleCursor::copyFormatDescription(CMFormatDescriptionRef* formatDescriptionOut) const
@@ -367,7 +360,7 @@
 {
     return getMediaSample([&](MediaSample& sample) {
         RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(sample.platformSample().type == PlatformSample::ByteRangeSampleType);
-        *formatDescriptionOut = retainPtr(sample.platformSample().sample.byteRangeSample.second).leakRef();
+        *formatDescriptionOut = createFormatDescriptionFromTrackInfo(sample.platformSample().sample.byteRangeSample.second).leakRef();
     });
 }
 

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaTrackReader.cpp (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaTrackReader.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaTrackReader.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -33,6 +33,7 @@
 #include "MediaSampleByteRange.h"
 #include "MediaSampleCursor.h"
 #include <WebCore/AudioTrackPrivate.h>
+#include <WebCore/CMUtilities.h>
 #include <WebCore/InbandTextTrackPrivate.h>
 #include <WebCore/MediaDescription.h>
 #include <WebCore/SampleMap.h>
@@ -97,7 +98,7 @@
     return lastSample.presentationTime() + lastSample.duration();
 }
 
-void MediaTrackReader::addSample(Ref<MediaSample>&& sample, MTPluginByteSourceRef byteSource)
+void MediaTrackReader::addSample(MediaSamplesBlock&& sample, MTPluginByteSourceRef byteSource)
 {
     ASSERT(!isMainRunLoop());
     Locker locker { m_sampleStorageLock };
@@ -104,9 +105,11 @@
     if (!m_sampleStorage)
         m_sampleStorage = makeUnique<SampleStorage>();
 
-    ASSERT(!sample->isDivisable() && sample->byteRange());
-    auto sampleToAdd = MediaSampleByteRange::create(sample.get(), byteSource, m_trackID);
+    ASSERT(!sample.isEmpty());
+    ASSERT(std::holds_alternative<MediaSample::ByteRange>(sample.last().data));
 
+    auto sampleToAdd = MediaSampleByteRange::create(WTFMove(sample), byteSource);
+
     // FIXME: Even though WebM muxer guidelines say this must not happen, some video tracks have two
     // consecutive frames with the same presentation time. SampleMap will not store the second frame
     // in these cases, corrupting all subsequent non-key frames. Find a way to store frames with
@@ -185,7 +188,15 @@
 
     if (CFEqual(key, PAL::get_MediaToolbox_kMTPluginTrackReaderProperty_FormatDescriptionArray())) {
         RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(lastSample.platformSample().type == PlatformSample::ByteRangeSampleType);
-        const void* descriptions[1] = { lastSample.platformSample().sample.byteRangeSample.second };
+        const TrackInfo& trackInfo = lastSample.platformSample().sample.byteRangeSample.second;
+        if (!m_trackInfo) {
+            m_trackInfo = &lastSample.platformSample().sample.byteRangeSample.second.get();
+            m_formatDescription = WebCore::createFormatDescriptionFromTrackInfo(*m_trackInfo);
+        } else if (*m_trackInfo != trackInfo) {
+            m_trackInfo = &trackInfo;
+            m_formatDescription = WebCore::createFormatDescriptionFromTrackInfo(*m_trackInfo);
+        }
+        const void* descriptions[1] = { m_formatDescription.get() };
         *reinterpret_cast<CFArrayRef*>(copiedValue) = adoptCF(CFArrayCreate(allocator, descriptions, 1, &kCFTypeArrayCallBacks)).leakRef();
         return noErr;
     }

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaTrackReader.h (291032 => 291033)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaTrackReader.h	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaTrackReader.h	2022-03-09 07:38:58 UTC (rev 291033)
@@ -41,7 +41,7 @@
 namespace WebCore {
 class AudioTrackPrivate;
 class InbandTextTrackPrivate;
-class MediaSample;
+class MediaSamplesBlock;
 class TrackPrivateBase;
 class VideoTrackPrivate;
 }
@@ -65,7 +65,7 @@
     MediaTime greatestPresentationTime() const;
 
     void setEnabled(bool enabled) { m_isEnabled = enabled ? Enabled::True : Enabled::False; }
-    void addSample(Ref<WebCore::MediaSample>&&, MTPluginByteSourceRef);
+    void addSample(WebCore::MediaSamplesBlock&&, MTPluginByteSourceRef);
     void waitForSample(Function<bool(WebCore::SampleMap&, bool)>&&) const;
     void finishParsing();
 
@@ -111,6 +111,8 @@
     mutable std::unique_ptr<SampleStorage> m_sampleStorage WTF_GUARDED_BY_LOCK(m_sampleStorageLock);
     Ref<const Logger> m_logger;
     const void* m_logIdentifier;
+    RetainPtr<CMFormatDescriptionRef> m_formatDescription;
+    RefPtr<const WebCore::TrackInfo> m_trackInfo;
 };
 
 constexpr MediaTrackReader::WrapperClass MediaTrackReader::wrapperClass()

Modified: trunk/Tools/ChangeLog (291032 => 291033)


--- trunk/Tools/ChangeLog	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Tools/ChangeLog	2022-03-09 07:38:58 UTC (rev 291033)
@@ -1,3 +1,13 @@
+2022-03-08  Jean-Yves Avenard  <j...@apple.com>
+
+        Have MediaFormatReader plugin use WebMParser directly
+        https://bugs.webkit.org/show_bug.cgi?id=237594
+        rdar://89960307
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/Tests/WebCore/SampleMap.cpp:
+
 2022-03-08  John Cunningham  <johncunning...@apple.com>
 
         RemoteGraphicsContextGL ReadPixels does not preserve contents for area that is not part of the Framebuffer

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp (291032 => 291033)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp	2022-03-09 06:49:50 UTC (rev 291032)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp	2022-03-09 07:38:58 UTC (rev 291033)
@@ -70,7 +70,6 @@
     SampleFlags flags() const final { return m_flags; }
     PlatformSample platformSample() const final { return { PlatformSample::None, { nullptr } }; }
     PlatformSample::Type platformSampleType() const final { return PlatformSample::None; }
-    std::optional<ByteRange> byteRange() const final { return std::nullopt; }
 
     void dump(PrintStream&) const final { }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to