- Revision
- 258503
- Author
- [email protected]
- Date
- 2020-03-16 09:36:37 -0700 (Mon, 16 Mar 2020)
Log Message
Audio is not played from an audio element when the srcObject object has unstarted video tracks
https://bugs.webkit.org/show_bug.cgi?id=207041
<rdar://problem/59084745>
Reviewed by Eric Carlson.
Source/WebCore:
In case MediaPlayer is an audio element, we should just make it as if there is no video track in the stream.
Test: imported/w3c/web-platform-tests/webrtc/audio-video-element-playing.html
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::activeVideoTrack const):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::didPassCORSAccessCheck const):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode const):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::checkSelectedVideoTrack):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateTracks):
LayoutTests:
* webrtc/audio-video-element-playing-expected.txt: Added.
* webrtc/audio-video-element-playing.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (258502 => 258503)
--- trunk/LayoutTests/ChangeLog 2020-03-16 16:34:57 UTC (rev 258502)
+++ trunk/LayoutTests/ChangeLog 2020-03-16 16:36:37 UTC (rev 258503)
@@ -1,3 +1,14 @@
+2020-03-16 youenn fablet <[email protected]>
+
+ Audio is not played from an audio element when the srcObject object has unstarted video tracks
+ https://bugs.webkit.org/show_bug.cgi?id=207041
+ <rdar://problem/59084745>
+
+ Reviewed by Eric Carlson.
+
+ * webrtc/audio-video-element-playing-expected.txt: Added.
+ * webrtc/audio-video-element-playing.html: Added.
+
2020-03-16 Truitt Savell <[email protected]>
[ Mac wk2 ] (r258249) fast/scrolling/mac/absolute-in-overflow-scroll-dynamic.html is a flaky failure (209052)
Added: trunk/LayoutTests/webrtc/audio-video-element-playing-expected.txt (0 => 258503)
--- trunk/LayoutTests/webrtc/audio-video-element-playing-expected.txt (rev 0)
+++ trunk/LayoutTests/webrtc/audio-video-element-playing-expected.txt 2020-03-16 16:36:37 UTC (rev 258503)
@@ -0,0 +1,4 @@
+
+
+PASS Verify that, contrary to video elements, audio elements are playing even if video tracks have not started generated any video frame
+
Added: trunk/LayoutTests/webrtc/audio-video-element-playing.html (0 => 258503)
--- trunk/LayoutTests/webrtc/audio-video-element-playing.html (rev 0)
+++ trunk/LayoutTests/webrtc/audio-video-element-playing.html 2020-03-16 16:36:37 UTC (rev 258503)
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Testing audio/video element playing</title>
+ <script src=""
+ <script src=""
+ </head>
+ <body>
+ <audio id="audio" controls autoplay=""></audio>
+ <video id="video" controls autoplay=""></video>
+ <script>
+promise_test(async (t) => {
+ const pc1 = new RTCPeerConnection();
+ const pc2 = new RTCPeerConnection();
+ t.add_cleanup(() => {
+ pc1.close();
+ pc2.close();
+ });
+
+ const localStream = await navigator.mediaDevices.getUserMedia({ audio : true });
+ pc1.addTrack(localStream.getAudioTracks()[0], localStream);
+ pc1.addTransceiver("video", { streams : [localStream] });
+
+ let promise = new Promise(resolve => pc2._ontrack_ = resolve);
+
+ const offer = await pc1.createOffer();
+ await pc1.setLocalDescription(offer);
+
+ await pc2.setRemoteDescription(offer);
+ const answer = await pc2.createAnswer();
+ await pc2.setLocalDescription(answer);
+
+ await pc1.setRemoteDescription(answer);
+
+ // We do not pass any ICE candidate
+ let remoteTrackEvent = await promise;
+
+ let remoteStream = new MediaStream([remoteTrackEvent.streams[0].getVideoTracks()[0], localStream.getAudioTracks()[0]]);
+ audio.srcObject = remoteStream;
+ video.srcObject = remoteStream;
+
+ audio.play();
+ video.play();
+
+ let counter = 0;
+ do {
+ await new Promise(resolve => t.step_timeout(resolve, 100));
+ } while (audio.currentTime === 0 && ++counter < 20)
+
+ assert_not_equals(audio.currentTime, 0);
+ assert_equals(video.currentTime, 0);
+}, "Verify that, contrary to video elements, audio elements are playing even if video tracks have not started generated any video frame");
+ </script>
+ </body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (258502 => 258503)
--- trunk/Source/WebCore/ChangeLog 2020-03-16 16:34:57 UTC (rev 258502)
+++ trunk/Source/WebCore/ChangeLog 2020-03-16 16:36:37 UTC (rev 258503)
@@ -1,5 +1,28 @@
2020-03-16 youenn fablet <[email protected]>
+ Audio is not played from an audio element when the srcObject object has unstarted video tracks
+ https://bugs.webkit.org/show_bug.cgi?id=207041
+ <rdar://problem/59084745>
+
+ Reviewed by Eric Carlson.
+
+ In case MediaPlayer is an audio element, we should just make it as if there is no video track in the stream.
+
+ Test: imported/w3c/web-platform-tests/webrtc/audio-video-element-playing.html
+
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayers):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::activeVideoTrack const):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::didPassCORSAccessCheck const):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode const):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::checkSelectedVideoTrack):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateTracks):
+
+2020-03-16 youenn fablet <[email protected]>
+
RTCRtpSender of kind video should have a null dtmf attribute
https://bugs.webkit.org/show_bug.cgi?id=209135
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h (258502 => 258503)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h 2020-03-16 16:34:57 UTC (rev 258502)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h 2020-03-16 16:36:37 UTC (rev 258503)
@@ -209,8 +209,10 @@
void applicationDidBecomeActive() final;
- bool hideRootLayer() const { return (!m_activeVideoTrack || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
+ bool hideRootLayer() const { return (!activeVideoTrack() || m_waitingForFirstImage) && m_displayMode != PaintItBlack; }
+ MediaStreamTrackPrivate* activeVideoTrack() const;
+
MediaPlayer* m_player { nullptr };
RefPtr<MediaStreamPrivate> m_mediaStreamPrivate;
RefPtr<MediaStreamTrackPrivate> m_activeVideoTrack;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (258502 => 258503)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm 2020-03-16 16:34:57 UTC (rev 258502)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm 2020-03-16 16:36:37 UTC (rev 258503)
@@ -278,7 +278,7 @@
void MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample(MediaStreamTrackPrivate& track, MediaSample& sample)
{
- if (&track != m_mediaStreamPrivate->activeVideoTrack())
+ if (&track != activeVideoTrack())
return;
if (!m_imagePainter.mediaSample || m_displayMode != PausedImage) {
@@ -360,7 +360,8 @@
if (m_sampleBufferDisplayLayer)
return;
- if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->activeVideoTrack() || !m_mediaStreamPrivate->activeVideoTrack()->enabled())
+ auto* activeVideoTrack = this->activeVideoTrack();
+ if (!activeVideoTrack || !activeVideoTrack->enabled())
return;
m_sampleBufferDisplayLayer = SampleBufferDisplayLayer::create(*this);
@@ -432,11 +433,16 @@
});
}
+MediaStreamTrackPrivate* MediaPlayerPrivateMediaStreamAVFObjC::activeVideoTrack() const
+{
+ return (m_mediaStreamPrivate && m_player->isVideoPlayer()) ? m_mediaStreamPrivate->activeVideoTrack() : nullptr;
+}
+
bool MediaPlayerPrivateMediaStreamAVFObjC::didPassCORSAccessCheck() const
{
// We are only doing a check on the active video track since the sole consumer of this API is canvas.
// FIXME: We should change the name of didPassCORSAccessCheck if it is expected to stay like this.
- const auto* track = m_mediaStreamPrivate->activeVideoTrack();
+ const auto* track = activeVideoTrack();
return !track || !track->isIsolated();
}
@@ -465,7 +471,7 @@
if (m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
return None;
- if (auto* track = m_mediaStreamPrivate->activeVideoTrack()) {
+ if (auto* track = activeVideoTrack()) {
if (!track->enabled() || track->muted() || track->ended())
return PaintItBlack;
}
@@ -627,7 +633,7 @@
if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->active() || !m_mediaStreamPrivate->hasTracks())
return MediaPlayer::ReadyState::HaveNothing;
- bool waitingForImage = m_mediaStreamPrivate->activeVideoTrack() && !m_imagePainter.mediaSample;
+ bool waitingForImage = activeVideoTrack() && !m_imagePainter.mediaSample;
if (waitingForImage && (!m_haveSeenMetadata || m_waitingForFirstImage))
return MediaPlayer::ReadyState::HaveNothing;
@@ -843,10 +849,10 @@
auto oldVideoTrack = m_activeVideoTrack;
bool hideVideoLayer = true;
m_activeVideoTrack = nullptr;
- if (m_mediaStreamPrivate->activeVideoTrack()) {
+ if (auto* activeVideoTrack = this->activeVideoTrack()) {
for (const auto& track : m_videoTrackMap.values()) {
- if (&track->streamTrack() == m_mediaStreamPrivate->activeVideoTrack()) {
- m_activeVideoTrack = m_mediaStreamPrivate->activeVideoTrack();
+ if (&track->streamTrack() == activeVideoTrack) {
+ m_activeVideoTrack = activeVideoTrack;
if (track->selected())
hideVideoLayer = false;
break;
@@ -896,6 +902,9 @@
};
updateTracksOfType(m_audioTrackMap, RealtimeMediaSource::Type::Audio, currentTracks, &AudioTrackPrivateMediaStream::create, WTFMove(setAudioTrackState));
+ if (!m_player->isVideoPlayer())
+ return;
+
auto setVideoTrackState = [this](VideoTrackPrivateMediaStream& track, int index, TrackState state)
{
switch (state) {
@@ -910,7 +919,7 @@
break;
case TrackState::Configure:
track.setTrackIndex(index);
- bool selected = &track.streamTrack() == m_mediaStreamPrivate->activeVideoTrack();
+ bool selected = &track.streamTrack() == activeVideoTrack();
track.setSelected(selected);
checkSelectedVideoTrack();
break;