Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MockSourceBufferPrivate should only process samples once init segment has been processed. #11599

Conversation

jyavenard
Copy link
Member

@jyavenard jyavenard commented Mar 16, 2023

30fd635

MockSourceBufferPrivate should only process samples once init segment has been processed.
https://bugs.webkit.org/show_bug.cgi?id=253997
rdar://106784564

Reviewed by Youenn Fablet.

The ability of a SourceBufferPrivate to run in the GPU process required
some steps to be done asynchronously.
In particular no demuxed media segments should be processed until all
track buffers had been created as they would otherwise be dropped.
Currently, only the SourceBufferPrivateAVFObjC implementation had been
modified to run asynchronously and contained very specific handlings to
do so.

We move the responsibility of queuing samples for until the init segment
has been fully processed to the base SourceBufferPrivate class.
We allows the ability for any SourceBufferPrivate implementation to be
wrapped in a SourceBufferPrivateRemote and be platform agnostic, including
the MockMediaSource.

Fly-by changes:
- Rename ReceiveResult::RecieveSucceeded to ReceiveResult::Succeeded (and fix typo)
- Rename AppendResult::AppendSucceeded to AppendResult::Succeeded
- By spec, the Reset Parser State should process any frames left in the
  input buffer.

* Source/WebCore/Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::appendBufferTimerFired):
(WebCore::SourceBuffer::sourceBufferPrivateAppendComplete):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment):
* Source/WebCore/platform/graphics/SourceBufferPrivate.cpp:
(WebCore::SourceBufferPrivate::appendCompleted):
(WebCore::SourceBufferPrivate::didReceiveInitializationSegment):
(WebCore::SourceBufferPrivate::didReceiveSampleForTrackId):
(WebCore::SourceBufferPrivate::didReceiveSample):
(WebCore::SourceBufferPrivate::processPendingSamples):
(WebCore::SourceBufferPrivate::resetParserState): Make default implementation.
* Source/WebCore/platform/graphics/SourceBufferPrivate.h:
(WebCore::SourceBufferPrivate::appendCompleted):
* Source/WebCore/platform/graphics/SourceBufferPrivateClient.cpp:
(WebCore::convertEnumerationToString):
* Source/WebCore/platform/graphics/SourceBufferPrivateClient.h: Rename enum as name already contained in type.
* Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
* Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
* Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(WebCore::SourceBufferPrivateAVFObjC::didParseInitializationData):
(WebCore::SourceBufferPrivateAVFObjC::didProvideMediaDataForTrackId):
(WebCore::SourceBufferPrivateAVFObjC::processPendingTrackChangeTasks):
(WebCore::SourceBufferPrivateAVFObjC::didReceiveSampleForTrackId):
(WebCore::SourceBufferPrivateAVFObjC::append):
(WebCore::SourceBufferPrivateAVFObjC::appendCompleted):
(WebCore::SourceBufferPrivateAVFObjC::resetParserState):
* Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp:
(WebCore::SourceBufferPrivateGStreamer::resetParserState):
* Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp: Remove unnecessary method.
(WebCore::MockSourceBufferPrivate::resetParserState): Deleted.
* Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h: Remove unnecessary method.

Canonical link: https://commits.webkit.org/261799@main

d1f4a65

Misc iOS, tvOS & watchOS macOS Linux Windows
βœ… πŸ§ͺ style   πŸ›  ios   πŸ›  mac   πŸ›  wpe   πŸ›  wincairo
  πŸ§ͺ bindings   πŸ›  ios-sim   πŸ›  mac-AS-debug   πŸ§ͺ wpe-wk2
βœ… πŸ§ͺ webkitperl   πŸ§ͺ ios-wk2   πŸ§ͺ api-mac βœ… πŸ›  gtk
  πŸ§ͺ api-ios   πŸ§ͺ mac-wk1   πŸ§ͺ gtk-wk2
  πŸ›  tv   πŸ§ͺ mac-wk2 ⏳ πŸ§ͺ api-gtk
  πŸ›  tv-sim   πŸ§ͺ mac-AS-debug-wk2
  πŸ›  watch   πŸ§ͺ mac-wk2-stress
βœ… πŸ›  πŸ§ͺ merge βœ… πŸ›  watch-sim

@jyavenard jyavenard requested a review from philn as a code owner March 16, 2023 09:27
@jyavenard jyavenard self-assigned this Mar 16, 2023
@jyavenard jyavenard added the Media Bugs related to the HTML 5 Media elements. label Mar 16, 2023
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Mar 16, 2023
@jyavenard jyavenard removed the merging-blocked Applied to prevent a change from being merged label Mar 16, 2023
@jyavenard jyavenard force-pushed the eng/MockSourceBufferPrivate-should-only-process-samples-once-init-segment-has-been-processed- branch from 4ba99ec to 33bc608 Compare March 16, 2023 10:17
@philn philn requested a review from ntrrgc March 16, 2023 11:46
@@ -151,10 +152,17 @@ void SourceBufferPrivate::updateBufferedFromTrackBuffers(bool sourceIsEnded)
setBufferedRanges(intersectionRanges);
}

void SourceBufferPrivate::appendCompleted(bool parsingSucceeded, bool isEnded)
void SourceBufferPrivate::appendCompleted(bool parsingSucceeded, bool isEnded, Function<void()>&& preAppendCompletedTask)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be a CompletionHandler?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. As it may not always be run (such as if abort() is called in between or if an error occurred.


if (m_processingInitializationSegment) {
DEBUG_LOG(LOGIDENTIFIER, originalSample.get());
// TODO: MediaSample should use uint64_t for trackID.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectIdentifier?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TrackID is used everywhere, and it's either an int or a uint everywhere but with MediaSample. so we have to keep doing string conversion back and forth


WeakPtr<SourceBufferPrivateClient> m_client;

bool m_processingInitializationSegment { false };
Vector<std::pair<uint64_t, Ref<MediaSample>>> m_pendingMediaSamples;
bool m_hasPendingAppendCompleted { false };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make these private instead?
m_processingInitializationSegment is accessed, how about just adding a protected getter but no setter for instance?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -171,6 +179,14 @@ class SourceBufferPrivate
void trySignalAllSamplesInTrackEnqueued(TrackBuffer&, const AtomString& trackID);
MediaTime findPreviousSyncSamplePresentationTime(const MediaTime&);
bool evictFrames(uint64_t newDataSize, uint64_t maximumBufferSize, const MediaTime& currentTime, bool isEnded);
void processPendingSamples();

struct appendCompletedArguments {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/appendCompletedArguments/AppendCompletedArguments

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

{
DEBUG_LOG(LOGIDENTIFIER);

if (m_processingInitializationSegment) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ASSERT(!m_appendCompletedPending); ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, there could be two init segment appended with a media segment.
like so:
init_segment | media_segment | init_segment

Actually, I think our handling of such scenario is problematic and would result in an undefined behaviour , in particular in regards to track ID ; it is possible for track id to change in between run, even get swapped between audio and video (we even have a test about it: as it used to cause a crash).

However, the behaviour following these changes is identical to what we had before

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we file a bug and add a comment here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the issue I described isn't happening here. appendCompleted() can be called whenever the SourceBufferParser has finished demuxing all data but the init segment is yet to be processed by the SourceBuffer in the content process.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_processingInitializationSegment = false;
// 4.5.2 Reset Parser State
// 1. If the [[append state]] equals PARSING_MEDIA_SEGMENT and the [[input buffer]] contains some complete coded frames, then run the coded frame processing algorithm until all of these complete coded frames have been processed.
processPendingSamples();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about m_appendCompletedPending, should we reset it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so yes. good spotting

@@ -207,10 +208,8 @@ class SourceBufferPrivateAVFObjC final
WeakPtrFactory<SourceBufferPrivateAVFObjC> m_appendWeakFactory;

Ref<SourceBufferParser> m_parser;
bool m_processingInitializationSegment { false };
bool m_hasPendingAppendCompletedCallback { false };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it still needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no

Comment on lines +571 to +572
m_processingInitializationSegment = false;
processPendingSamples();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You always clear m_processingInitializationSegment before calling processPendingSamples, maybe do it in processPendingSamples instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would allow for unwanted side effects if it was to handle the case I described earlier (two init segments appended consecutively). So I prefer not to and leave this utility methods to do just what the name states.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there ever a case where m_processingInitializationSegment is true in processPendingSamples()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes there is. It can be called when the first didReceivedInitializatingSegment completion handler is run, but in between we received a new init segment.

See bug https://bugs.webkit.org/show_bug.cgi?id=254079

@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Mar 16, 2023
@jyavenard jyavenard removed the merging-blocked Applied to prevent a change from being merged label Mar 17, 2023
@jyavenard jyavenard force-pushed the eng/MockSourceBufferPrivate-should-only-process-samples-once-init-segment-has-been-processed- branch from 33bc608 to d1f4a65 Compare March 17, 2023 16:33
@jyavenard jyavenard added the merge-queue Applied to send a pull request to merge-queue label Mar 17, 2023
… has been processed.

https://bugs.webkit.org/show_bug.cgi?id=253997
rdar://106784564

Reviewed by Youenn Fablet.

The ability of a SourceBufferPrivate to run in the GPU process required
some steps to be done asynchronously.
In particular no demuxed media segments should be processed until all
track buffers had been created as they would otherwise be dropped.
Currently, only the SourceBufferPrivateAVFObjC implementation had been
modified to run asynchronously and contained very specific handlings to
do so.

We move the responsibility of queuing samples for until the init segment
has been fully processed to the base SourceBufferPrivate class.
We allows the ability for any SourceBufferPrivate implementation to be
wrapped in a SourceBufferPrivateRemote and be platform agnostic, including
the MockMediaSource.

Fly-by changes:
- Rename ReceiveResult::RecieveSucceeded to ReceiveResult::Succeeded (and fix typo)
- Rename AppendResult::AppendSucceeded to AppendResult::Succeeded
- By spec, the Reset Parser State should process any frames left in the
  input buffer.

* Source/WebCore/Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::appendBufferTimerFired):
(WebCore::SourceBuffer::sourceBufferPrivateAppendComplete):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment):
* Source/WebCore/platform/graphics/SourceBufferPrivate.cpp:
(WebCore::SourceBufferPrivate::appendCompleted):
(WebCore::SourceBufferPrivate::didReceiveInitializationSegment):
(WebCore::SourceBufferPrivate::didReceiveSampleForTrackId):
(WebCore::SourceBufferPrivate::didReceiveSample):
(WebCore::SourceBufferPrivate::processPendingSamples):
(WebCore::SourceBufferPrivate::resetParserState): Make default implementation.
* Source/WebCore/platform/graphics/SourceBufferPrivate.h:
(WebCore::SourceBufferPrivate::appendCompleted):
* Source/WebCore/platform/graphics/SourceBufferPrivateClient.cpp:
(WebCore::convertEnumerationToString):
* Source/WebCore/platform/graphics/SourceBufferPrivateClient.h: Rename enum as name already contained in type.
* Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
* Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
* Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(WebCore::SourceBufferPrivateAVFObjC::didParseInitializationData):
(WebCore::SourceBufferPrivateAVFObjC::didProvideMediaDataForTrackId):
(WebCore::SourceBufferPrivateAVFObjC::processPendingTrackChangeTasks):
(WebCore::SourceBufferPrivateAVFObjC::didReceiveSampleForTrackId):
(WebCore::SourceBufferPrivateAVFObjC::append):
(WebCore::SourceBufferPrivateAVFObjC::appendCompleted):
(WebCore::SourceBufferPrivateAVFObjC::resetParserState):
* Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp:
(WebCore::SourceBufferPrivateGStreamer::resetParserState):
* Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp: Remove unnecessary method.
(WebCore::MockSourceBufferPrivate::resetParserState): Deleted.
* Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h: Remove unnecessary method.

Canonical link: https://commits.webkit.org/261799@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/MockSourceBufferPrivate-should-only-process-samples-once-init-segment-has-been-processed- branch from d1f4a65 to 30fd635 Compare March 17, 2023 17:42
@webkit-commit-queue webkit-commit-queue merged commit 30fd635 into WebKit:main Mar 17, 2023
@webkit-commit-queue
Copy link
Collaborator

Committed 261799@main (30fd635): https://commits.webkit.org/261799@main

Reviewed commits have been landed. Closing PR #11599 and removing active labels.

@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Mar 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Media Bugs related to the HTML 5 Media elements.
Projects
None yet
6 participants