Diff
Modified: trunk/Source/WebCore/ChangeLog (208850 => 208851)
--- trunk/Source/WebCore/ChangeLog 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/ChangeLog 2016-11-17 18:43:40 UTC (rev 208851)
@@ -1,3 +1,109 @@
+2016-11-17 Eric Carlson <[email protected]>
+
+ [MediaStream][Mac] Use AVCapturePreview object for camera/microphone rendering
+ https://bugs.webkit.org/show_bug.cgi?id=164837
+ <rdar://problem/29297727>
+
+ Reviewed by Jer Noble.
+
+ No new tests, the real capture devices can not be used in layout tests.
+
+ * WebCore.xcodeproj/project.pbxproj:
+
+ Drive-by fix: clear m_settingMediaStreamSrcObject when the media player is destroyed unless
+ that happens as a side effect of setting video.srcObject.
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::setSrcObject):
+ (WebCore::HTMLMediaElement::clearMediaPlayer):
+ * html/HTMLMediaElement.h:
+
+ Add support for realtime media source that vend a preview interface, while keeping support
+ for those that do not (e.g. the mock capture devices).
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::isAvailable):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::prepareVideoSampleBufferFromTrack):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::platformLayer):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::play):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::pause):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::internalSetVolume):
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::updateTracks):
+
+ * platform/mediastream/MediaStreamPrivate.cpp:
+ (WebCore::MediaStreamPrivate::platformLayer): Deleted, no longer used.
+ * platform/mediastream/MediaStreamPrivate.h:
+
+ Enable/disable the preview when available.
+ * platform/mediastream/MediaStreamTrackPrivate.cpp:
+ (WebCore::MediaStreamTrackPrivate::setEnabled):
+ (WebCore::MediaStreamTrackPrivate::endTrack):
+ (WebCore::MediaStreamTrackPrivate::preview):
+ * platform/mediastream/MediaStreamTrackPrivate.h:
+
+ * platform/mediastream/RealtimeMediaSource.h:
+ (WebCore::RealtimeMediaSource::preview):
+ (WebCore::RealtimeMediaSource::createWeakPtr):
+ (WebCore::RealtimeMediaSource::platformLayer): Deleted.
+
+ Define a realtime media source preview interface.
+ * platform/mediastream/RealtimeMediaSourcePreview.h: Added.
+ (WebCore::RealtimeMediaSourcePreview::~RealtimeMediaSourcePreview):
+ (WebCore::RealtimeMediaSourcePreview::invalidate):
+ (WebCore::RealtimeMediaSourcePreview::createWeakPtr):
+ (WebCore::RealtimeMediaSourcePreview::RealtimeMediaSourcePreview):
+
+ Implement the preview interface.
+ * platform/mediastream/mac/AVAudioCaptureSource.h:
+ * platform/mediastream/mac/AVAudioCaptureSource.mm:
+ (WebCore::AVAudioSourcePreview::create):
+ (WebCore::AVAudioSourcePreview::AVAudioSourcePreview):
+ (WebCore::AVAudioSourcePreview::invalidate):
+ (WebCore::AVAudioSourcePreview::play):
+ (WebCore::AVAudioSourcePreview::pause):
+ (WebCore::AVAudioSourcePreview::setEnabled):
+ (WebCore::AVAudioSourcePreview::setVolume):
+ (WebCore::AVAudioSourcePreview::updateState):
+ (WebCore::AVAudioCaptureSource::createPreview):
+ * platform/mediastream/mac/AVMediaCaptureSource.h:
+ (WebCore::AVMediaCaptureSource::createWeakPtr):
+ * platform/mediastream/mac/AVMediaCaptureSource.mm:
+ (WebCore::AVMediaCaptureSource::AVMediaCaptureSource):
+ (WebCore::AVMediaCaptureSource::reset):
+ (WebCore::AVMediaCaptureSource::preview):
+ (WebCore::AVMediaCaptureSource::removePreview):
+ (WebCore::AVMediaSourcePreview::AVMediaSourcePreview):
+ (WebCore::AVMediaSourcePreview::~AVMediaSourcePreview):
+ (WebCore::AVMediaSourcePreview::invalidate):
+ * platform/mediastream/mac/AVVideoCaptureSource.h:
+ * platform/mediastream/mac/AVVideoCaptureSource.mm:
+ (WebCore::AVVideoSourcePreview::create):
+ (WebCore::AVVideoSourcePreview::AVVideoSourcePreview):
+ (WebCore::AVVideoSourcePreview::invalidate):
+ (WebCore::AVVideoSourcePreview::play):
+ (WebCore::AVVideoSourcePreview::pause):
+ (WebCore::AVVideoSourcePreview::setPaused):
+ (WebCore::AVVideoSourcePreview::setEnabled):
+ (WebCore::AVVideoCaptureSource::shutdownCaptureSession):
+ (WebCore::AVVideoCaptureSource::processNewFrame):
+ (WebCore::AVVideoCaptureSource::createPreview):
+ (WebCore::AVVideoCaptureSource::platformLayer): Deleted.
+
+ * platform/mediastream/mac/MockRealtimeVideoSourceMac.h:
+ * platform/mediastream/mac/MockRealtimeVideoSourceMac.mm:
+ (WebCore::MockRealtimeVideoSourceMac::platformLayer): Deleted.
+ (WebCore::MockRealtimeVideoSourceMac::updatePlatformLayer): Deleted.
+ * platform/mock/MockRealtimeVideoSource.cpp:
+ (WebCore::MockRealtimeVideoSource::applyFrameRate):
+ (WebCore::MockRealtimeVideoSource::applySize):
+ (WebCore::MockRealtimeVideoSource::generateFrame):
+ * platform/mock/MockRealtimeVideoSource.h:
+ (WebCore::MockRealtimeVideoSource::updatePlatformLayer): Deleted.
+
2016-11-17 Chris Dumez <[email protected]>
Unreviewed, fix build after r208839.
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (208850 => 208851)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-11-17 18:43:40 UTC (rev 208851)
@@ -305,6 +305,7 @@
07C59B6917F784BA000FBCBB /* MediaSourceSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C59B6617F784BA000FBCBB /* MediaSourceSettings.h */; };
07C59B6E17F794F6000FBCBB /* JSMediaStreamTrackCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C59B6D17F794F6000FBCBB /* JSMediaStreamTrackCustom.cpp */; };
07CE77D516712A6A00C55A47 /* InbandTextTrackPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 07D1503B1DDB6965008F7598 /* RealtimeMediaSourcePreview.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */; settings = {ATTRIBUTES = (Private, ); }; };
07D637401BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */; };
07D637411BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */; };
07D6A4EF1BECF2D200174146 /* MockRealtimeMediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */; };
@@ -7262,6 +7263,7 @@
07C8AD111D073D630087C5CE /* AVFoundationMIMETypeCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AVFoundationMIMETypeCache.mm; sourceTree = "<group>"; };
07C8AD121D073D630087C5CE /* AVFoundationMIMETypeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVFoundationMIMETypeCache.h; sourceTree = "<group>"; };
07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateClient.h; sourceTree = "<group>"; };
+ 07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeMediaSourcePreview.h; sourceTree = "<group>"; };
07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAudioSourceProviderAVFObjC.h; sourceTree = "<group>"; };
07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAudioSourceProviderAVFObjC.mm; sourceTree = "<group>"; };
07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockRealtimeMediaSource.cpp; sourceTree = "<group>"; };
@@ -15104,6 +15106,7 @@
07221B9217CF0AD400848E51 /* mediastream */ = {
isa = PBXGroup;
children = (
+ 07D1503A1DDB6688008F7598 /* RealtimeMediaSourcePreview.h */,
0729B14D17CFCCA0004F1D60 /* mac */,
07D6A4F61BF2307D00174146 /* AudioTrackPrivateMediaStream.h */,
07B7116A1D899E63009F0FFB /* CaptureDevice.h */,
@@ -28149,6 +28152,7 @@
1411DCB1164C39A800D49BC1 /* WidthCache.h in Headers */,
939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */,
0F15ED5C1B7EC7C500EDDFEB /* WillChangeData.h in Headers */,
+ 07D1503B1DDB6965008F7598 /* RealtimeMediaSourcePreview.h in Headers */,
BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */,
7E99AF530B13846468FB01A5 /* WindowFocusAllowedIndicator.h in Headers */,
E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */,
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (208850 => 208851)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2016-11-17 18:43:40 UTC (rev 208851)
@@ -1048,8 +1048,11 @@
// https://bugs.webkit.org/show_bug.cgi?id=124896
m_mediaStreamSrcObject = mediaStream;
- if (mediaStream)
+ if (mediaStream) {
+ m_settingMediaStreamSrcObject = true;
setSrc(DOMURL::createPublicURL(context, *mediaStream));
+ m_settingMediaStreamSrcObject = false;
+ }
}
#endif
@@ -4983,6 +4986,11 @@
{
LOG(Media, "HTMLMediaElement::clearMediaPlayer(%p) - flags = %s", this, actionName(flags).utf8().data());
+#if ENABLE(MEDIA_STREAM)
+ if (!m_settingMediaStreamSrcObject)
+ m_mediaStreamSrcObject = nullptr;
+#endif
+
#if ENABLE(MEDIA_SOURCE)
detachMediaSource();
#endif
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (208850 => 208851)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -1023,6 +1023,7 @@
#if ENABLE(MEDIA_STREAM)
RefPtr<MediaStream> m_mediaStreamSrcObject;
+ bool m_settingMediaStreamSrcObject { false };
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h (208850 => 208851)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -186,11 +186,19 @@
void setVideoFullscreenFrame(FloatRect) override;
#endif
+ bool haveVideoLayer() const { return m_sampleBufferDisplayLayer || m_videoPreviewPlayer; }
+
MediaPlayer* m_player { nullptr };
WeakPtrFactory<MediaPlayerPrivateMediaStreamAVFObjC> m_weakPtrFactory;
RefPtr<MediaStreamPrivate> m_mediaStreamPrivate;
+
+ RefPtr<RealtimeMediaSourcePreview> m_videoPreviewPlayer;
+ RefPtr<MediaStreamTrackPrivate> m_videoTrack;
+
RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
+#if PLATFORM(MAC)
RetainPtr<AVSampleBufferRenderSynchronizer> m_synchronizer;
+#endif
RetainPtr<CGImageRef> m_pausedImage;
double m_pausedTime { 0 };
std::unique_ptr<Clock> m_clock;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (208850 => 208851)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm 2016-11-17 18:43:40 UTC (rev 208851)
@@ -28,9 +28,7 @@
#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
-#import "AVAudioCaptureSource.h"
#import "AVFoundationSPI.h"
-#import "AVVideoCaptureSource.h"
#import "AudioTrackPrivateMediaStream.h"
#import "Clock.h"
#import "GraphicsContext.h"
@@ -66,7 +64,6 @@
MediaPlayerPrivateMediaStreamAVFObjC::MediaPlayerPrivateMediaStreamAVFObjC(MediaPlayer* player)
: m_player(player)
, m_weakPtrFactory(this)
- , m_synchronizer(adoptNS([allocAVSampleBufferRenderSynchronizerInstance() init]))
, m_clock(Clock::create())
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
, m_videoFullscreenLayerManager(VideoFullscreenLayerManager::create())
@@ -103,7 +100,15 @@
bool MediaPlayerPrivateMediaStreamAVFObjC::isAvailable()
{
- return AVFoundationLibrary() && isCoreMediaFrameworkAvailable() && getAVSampleBufferDisplayLayerClass() && getAVSampleBufferRenderSynchronizerClass();
+ if (!AVFoundationLibrary() || !isCoreMediaFrameworkAvailable() || !getAVSampleBufferDisplayLayerClass())
+ return false;
+
+#if PLATFORM(MAC)
+ if (!getAVSampleBufferRenderSynchronizerClass())
+ return false;
+#endif
+
+ return true;
}
void MediaPlayerPrivateMediaStreamAVFObjC::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
@@ -147,11 +152,17 @@
void MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSampleBuffer(MediaSample& sample)
{
- ASSERT([m_sampleBufferDisplayLayer isReadyForMoreMediaData]);
+ if (m_sampleBufferDisplayLayer) {
+ if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+ m_sampleQueue.append(sample);
+ requestNotificationWhenReadyForMediaData();
+ return;
+ }
- [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+ [m_sampleBufferDisplayLayer enqueueSampleBuffer:sample.platformSample().sample.cmSampleBuffer];
+ }
+
m_isFrameDisplayed = true;
-
if (!m_hasEverEnqueuedVideoFrame) {
m_hasEverEnqueuedVideoFrame = true;
m_player->firstVideoFrameAvailable();
@@ -164,12 +175,6 @@
if (&track != m_mediaStreamPrivate->activeVideoTrack() || !shouldEnqueueVideoSampleBuffer())
return;
- if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
- m_sampleQueue.append(sample);
- requestNotificationWhenReadyForMediaData();
- return;
- }
-
enqueueVideoSampleBuffer(sample);
}
@@ -192,37 +197,56 @@
void MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer()
{
- if (m_sampleBufferDisplayLayer)
+ if (haveVideoLayer())
return;
-
- m_sampleBufferDisplayLayer = adoptNS([allocAVSampleBufferDisplayLayerInstance() init]);
+
+ CALayer *videoLayer = nil;
+ if (m_mediaStreamPrivate->activeVideoTrack()) {
+ m_videoPreviewPlayer = m_mediaStreamPrivate->activeVideoTrack()->preview();
+ if (m_videoPreviewPlayer)
+ videoLayer = m_videoPreviewPlayer->platformLayer();
+ }
+
+ if (!videoLayer) {
+ m_sampleBufferDisplayLayer = adoptNS([allocAVSampleBufferDisplayLayerInstance() init]);
+ videoLayer = m_sampleBufferDisplayLayer.get();
#ifndef NDEBUG
- [m_sampleBufferDisplayLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer"];
+ [m_sampleBufferDisplayLayer setName:@"MediaPlayerPrivateMediaStreamAVFObjC AVSampleBufferDisplayLayer"];
#endif
- m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
+ m_sampleBufferDisplayLayer.get().backgroundColor = cachedCGColor(Color::black);
- [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
+#if PLATFORM(MAC)
+ m_synchronizer = adoptNS([allocAVSampleBufferRenderSynchronizerInstance() init]);
+ [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
+#endif
+ }
renderingModeChanged();
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
- m_videoFullscreenLayerManager->setVideoLayer(m_sampleBufferDisplayLayer.get(), snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
+ m_videoFullscreenLayerManager->setVideoLayer(videoLayer, snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
#endif
}
void MediaPlayerPrivateMediaStreamAVFObjC::destroyLayer()
{
- if (!m_sampleBufferDisplayLayer)
+ if (!haveVideoLayer())
return;
-
- [m_sampleBufferDisplayLayer stopRequestingMediaData];
- [m_sampleBufferDisplayLayer flush];
- CMTime currentTime = CMTimebaseGetTime([m_synchronizer timebase]);
- [m_synchronizer removeRenderer:m_sampleBufferDisplayLayer.get() atTime:currentTime withCompletionHandler:^(BOOL){
- // No-op.
- }];
- m_sampleBufferDisplayLayer = nullptr;
+ m_videoPreviewPlayer = nullptr;
+
+ if (m_sampleBufferDisplayLayer) {
+ [m_sampleBufferDisplayLayer stopRequestingMediaData];
+ [m_sampleBufferDisplayLayer flush];
+#if PLATFORM(MAC)
+ CMTime currentTime = CMTimebaseGetTime([m_synchronizer timebase]);
+ [m_synchronizer removeRenderer:m_sampleBufferDisplayLayer.get() atTime:currentTime withCompletionHandler:^(BOOL) {
+ // No-op.
+ }];
+ m_sampleBufferDisplayLayer = nullptr;
+#endif
+ }
+
renderingModeChanged();
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
@@ -282,12 +306,15 @@
PlatformLayer* MediaPlayerPrivateMediaStreamAVFObjC::platformLayer() const
{
- if (!m_sampleBufferDisplayLayer || m_displayMode == None)
+ if (!haveVideoLayer() || m_displayMode == None)
return nullptr;
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
return m_videoFullscreenLayerManager->videoInlineLayer();
#else
+ if (m_videoPreviewPlayer)
+ return m_videoPreviewPlayer->platformLayer();
+
return m_sampleBufferDisplayLayer.get();
#endif
}
@@ -294,7 +321,7 @@
MediaPlayerPrivateMediaStreamAVFObjC::DisplayMode MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode() const
{
- if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
+ if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !haveVideoLayer())
return None;
if (m_mediaStreamPrivate->activeVideoTrack() && !m_mediaStreamPrivate->activeVideoTrack()->enabled())
@@ -344,7 +371,21 @@
m_clock->start();
m_playing = true;
- [m_synchronizer setRate:1];
+
+ if (m_videoPreviewPlayer)
+ m_videoPreviewPlayer->play();
+#if PLATFORM(MAC)
+ else
+ [m_synchronizer setRate:1];
+#endif
+
+ for (const auto& track : m_audioTrackMap.values()) {
+ if (!track->enabled() || !track->streamTrack()->preview())
+ continue;
+
+ track->streamTrack()->preview()->play();
+ }
+
m_haveEverPlayed = true;
scheduleDeferredTask([this] {
updateDisplayMode();
@@ -361,7 +402,21 @@
m_pausedTime = m_clock->currentTime();
m_playing = false;
- [m_synchronizer setRate:0];
+
+ if (m_videoPreviewPlayer)
+ m_videoPreviewPlayer->pause();
+#if PLATFORM(MAC)
+ else
+ [m_synchronizer setRate:0];
+#endif
+
+ for (const auto& track : m_audioTrackMap.values()) {
+ if (!track->enabled() || !track->streamTrack()->preview())
+ continue;
+
+ track->streamTrack()->preview()->pause();
+ }
+
updateDisplayMode();
updatePausedImage();
}
@@ -379,7 +434,12 @@
if (!metaDataAvailable())
return;
- // FIXME: Set volume once we actually play audio.
+ for (const auto& track : m_audioTrackMap.values()) {
+ if (!track->enabled() || !track->streamTrack()->preview())
+ continue;
+
+ track->streamTrack()->preview()->setVolume(volume);
+ }
}
void MediaPlayerPrivateMediaStreamAVFObjC::setVolume(float volume)
@@ -627,9 +687,10 @@
std::function<void(RefPtr<VideoTrackPrivateMediaStream>, int)> enableVideoTrack = [this](auto track, int index)
{
track->setTrackIndex(index);
- track->setSelected(track->streamTrack() == m_mediaStreamPrivate->activeVideoTrack());
+ bool selected = track->streamTrack() == m_mediaStreamPrivate->activeVideoTrack();
+ track->setSelected(selected);
- if (track->selected())
+ if (selected)
ensureLayer();
};
updateTracksOfType(m_videoTrackMap, RealtimeMediaSource::Video, currentTracks, &VideoTrackPrivateMediaStream::create, m_player, &MediaPlayer::removeVideoTrack, &MediaPlayer::addVideoTrack, enableVideoTrack, (MediaStreamTrackPrivate::Observer*) this);
Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp 2016-11-17 18:43:40 UTC (rev 208851)
@@ -239,14 +239,6 @@
return size;
}
-PlatformLayer* MediaStreamPrivate::platformLayer() const
-{
- if (!m_activeVideoTrack)
- return nullptr;
-
- return m_activeVideoTrack->source().platformLayer();
-}
-
void MediaStreamPrivate::paintCurrentFrameInContext(GraphicsContext& context, const FloatRect& rect)
{
if (context.paintingDisabled())
Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -93,7 +93,6 @@
void stopProducingData();
bool isProducingData() const;
- PlatformLayer* platformLayer() const;
RefPtr<Image> currentFrameImage();
void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&);
Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp 2016-11-17 18:43:40 UTC (rev 208851)
@@ -101,6 +101,9 @@
// Always update the enabled state regardless of the track being ended.
m_isEnabled = enabled;
+ if (m_preview)
+ m_preview->setEnabled(enabled);
+
for (auto& observer : m_observers)
observer->trackEnabledChanged(*this);
}
@@ -115,6 +118,7 @@
// trackEnded method once.
m_isEnded = true;
+ m_preview = nullptr;
m_source->requestStop(this);
for (auto& observer : m_observers)
@@ -166,6 +170,15 @@
}
}
+RealtimeMediaSourcePreview* MediaStreamTrackPrivate::preview()
+{
+ if (m_preview)
+ return m_preview.get();
+
+ m_preview = m_source->preview();
+ return m_preview.get();
+}
+
void MediaStreamTrackPrivate::applyConstraints(const MediaConstraints& constraints, RealtimeMediaSource::SuccessHandler successHandler, RealtimeMediaSource::FailureHandler failureHandler)
{
m_source->applyConstraints(constraints, successHandler, failureHandler);
Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -96,6 +96,7 @@
AudioSourceProvider* audioSourceProvider();
void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&);
+ RealtimeMediaSourcePreview* preview();
private:
MediaStreamTrackPrivate(Ref<RealtimeMediaSource>&&, String&& id);
@@ -110,6 +111,7 @@
Vector<Observer*> m_observers;
Ref<RealtimeMediaSource> m_source;
RefPtr<MediaConstraints> m_constraints;
+ RefPtr<RealtimeMediaSourcePreview> m_preview;
String m_id;
bool m_isEnabled;
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -42,6 +42,7 @@
#include "MediaSample.h"
#include "PlatformLayer.h"
#include "RealtimeMediaSourceCapabilities.h"
+#include "RealtimeMediaSourcePreview.h"
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
#include <wtf/WeakPtr.h>
@@ -126,9 +127,9 @@
virtual AudioSourceProvider* audioSourceProvider() { return nullptr; }
- virtual PlatformLayer* platformLayer() const { return nullptr; }
virtual RefPtr<Image> currentFrameImage() { return nullptr; }
virtual void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) { }
+ virtual RefPtr<RealtimeMediaSourcePreview> preview() { return nullptr; }
void setWidth(int);
void setHeight(int);
Copied: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h (from rev 208850, trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h) (0 => 208851)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourcePreview.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "PlatformLayer.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class RealtimeMediaSourcePreview : public RefCounted<RealtimeMediaSourcePreview> {
+public:
+ virtual ~RealtimeMediaSourcePreview() { }
+
+ virtual void play() const = 0;
+ virtual void pause() const = 0;
+ virtual void setEnabled(bool) = 0;
+
+ virtual PlatformLayer* platformLayer() const = 0;
+ virtual void setVolume(double) const = 0;
+
+ virtual void invalidate() { m_weakPtrFactory.revokeAll(); }
+
+ WeakPtr<RealtimeMediaSourcePreview> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
+protected:
+ RealtimeMediaSourcePreview()
+ : m_weakPtrFactory(this)
+ {
+ }
+
+private:
+ WeakPtrFactory<RealtimeMediaSourcePreview> m_weakPtrFactory;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -67,6 +67,7 @@
void shutdownCaptureSession() override;
void updateSettings(RealtimeMediaSourceSettings&) override;
AudioSourceProvider* audioSourceProvider() override;
+ RefPtr<AVMediaSourcePreview> createPreview() final;
RetainPtr<AVCaptureConnection> m_audioConnection;
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm 2016-11-17 18:43:40 UTC (rev 208851)
@@ -47,15 +47,31 @@
typedef AVCaptureDeviceInput AVCaptureDeviceInputType;
typedef AVCaptureOutput AVCaptureOutputType;
+#if !PLATFORM(IOS)
+typedef AVCaptureAudioPreviewOutput AVCaptureAudioPreviewOutputType;
+#endif
+
SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioChannel)
SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioDataOutput)
+SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioPreviewOutput)
SOFT_LINK_CLASS(AVFoundation, AVCaptureConnection)
SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice)
SOFT_LINK_CLASS(AVFoundation, AVCaptureDeviceInput)
SOFT_LINK_CLASS(AVFoundation, AVCaptureOutput)
+#define AVCaptureAudioPreviewOutput getAVCaptureAudioPreviewOutputClass()
+
+#define AVCaptureAudioChannel getAVCaptureAudioChannelClass()
+#define AVCaptureAudioDataOutput getAVCaptureAudioDataOutputClass()
+#define AVCaptureConnection getAVCaptureConnectionClass()
+#define AVCaptureDevice getAVCaptureDeviceClass()
+#define AVCaptureDeviceFormat getAVCaptureDeviceFormatClass()
+#define AVCaptureDeviceInput getAVCaptureDeviceInputClass()
+#define AVCaptureOutput getAVCaptureOutputClass()
+#define AVFrameRateRange getAVFrameRateRangeClass()
+
SOFT_LINK_POINTER(AVFoundation, AVMediaTypeAudio, NSString *)
#define AVMediaTypeAudio getAVMediaTypeAudio()
@@ -62,6 +78,79 @@
namespace WebCore {
+#if !PLATFORM(IOS)
+class AVAudioSourcePreview: public AVMediaSourcePreview {
+public:
+ static RefPtr<AVMediaSourcePreview> create(AVCaptureSession *, AVAudioCaptureSource*);
+
+private:
+ AVAudioSourcePreview(AVCaptureSession *, AVAudioCaptureSource*);
+
+ void invalidate() final;
+
+ void play() const final;
+ void pause() const final;
+ void setVolume(double) const final;
+ void setEnabled(bool) final;
+ PlatformLayer* platformLayer() const final { return nullptr; }
+
+ void updateState() const;
+
+ RetainPtr<AVCaptureAudioPreviewOutputType> m_audioPreviewOutput;
+ mutable double m_volume { 1 };
+ mutable bool m_paused { false };
+ mutable bool m_enabled { true };
+};
+
+RefPtr<AVMediaSourcePreview> AVAudioSourcePreview::create(AVCaptureSession *session, AVAudioCaptureSource* parent)
+{
+ return adoptRef(new AVAudioSourcePreview(session, parent));
+}
+
+AVAudioSourcePreview::AVAudioSourcePreview(AVCaptureSession *session, AVAudioCaptureSource* parent)
+ : AVMediaSourcePreview(parent)
+{
+ m_audioPreviewOutput = adoptNS([allocAVCaptureAudioPreviewOutputInstance() init]);
+ setVolume(1);
+ [session addOutput:m_audioPreviewOutput.get()];
+}
+
+void AVAudioSourcePreview::invalidate()
+{
+ m_audioPreviewOutput = nullptr;
+ AVMediaSourcePreview::invalidate();
+}
+
+void AVAudioSourcePreview::play() const
+{
+ m_paused = false;
+ updateState();
+}
+
+void AVAudioSourcePreview::pause() const
+{
+ m_paused = true;
+ updateState();
+}
+
+void AVAudioSourcePreview::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+ updateState();
+}
+
+void AVAudioSourcePreview::setVolume(double volume) const
+{
+ m_volume = volume;
+ m_audioPreviewOutput.get().volume = volume;
+}
+
+void AVAudioSourcePreview::updateState() const
+{
+ m_audioPreviewOutput.get().volume = (!m_enabled || m_paused) ? 0 : m_volume;
+}
+#endif
+
RefPtr<AVMediaCaptureSource> AVAudioCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString& id, const MediaConstraints* constraints, String& invalidConstraint)
{
auto source = adoptRef(new AVAudioCaptureSource(device, id));
@@ -213,6 +302,15 @@
return m_audioSourceProvider.get();
}
+RefPtr<AVMediaSourcePreview> AVAudioCaptureSource::createPreview()
+{
+#if !PLATFORM(IOS)
+ return AVAudioSourcePreview::create(session(), this);
+#else
+ return nullptr;
+#endif
+}
+
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -32,7 +32,6 @@
#include "RealtimeMediaSource.h"
#include "Timer.h"
#include <wtf/Function.h>
-#include <wtf/RetainPtr.h>
OBJC_CLASS AVCaptureAudioDataOutput;
OBJC_CLASS AVCaptureConnection;
@@ -46,6 +45,21 @@
namespace WebCore {
+class AVMediaCaptureSource;
+
+class AVMediaSourcePreview: public RealtimeMediaSourcePreview {
+public:
+ virtual ~AVMediaSourcePreview();
+
+ void invalidate() override;
+
+protected:
+ AVMediaSourcePreview(AVMediaCaptureSource*);
+
+private:
+ WeakPtr<AVMediaCaptureSource> m_parent;
+};
+
class AVMediaCaptureSource : public RealtimeMediaSource {
public:
virtual ~AVMediaCaptureSource();
@@ -62,6 +76,10 @@
void stopProducingData() final;
bool isProducingData() const final { return m_isRunning; }
+ RefPtr<RealtimeMediaSourcePreview> preview() final;
+ void removePreview(AVMediaSourcePreview*);
+ WeakPtr<AVMediaCaptureSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
protected:
AVMediaCaptureSource(AVCaptureDevice*, const AtomicString&, RealtimeMediaSource::Type);
@@ -81,6 +99,8 @@
void setVideoSampleBufferDelegate(AVCaptureVideoDataOutput*);
void setAudioSampleBufferDelegate(AVCaptureAudioDataOutput*);
+ virtual RefPtr<AVMediaSourcePreview> createPreview() = 0;
+
private:
void setupSession();
void reset() final;
@@ -97,6 +117,8 @@
RefPtr<RealtimeMediaSourceCapabilities> m_capabilities;
RetainPtr<AVCaptureSession> m_session;
RetainPtr<AVCaptureDevice> m_device;
+ Vector<WeakPtr<RealtimeMediaSourcePreview>> m_previews;
+ WeakPtrFactory<AVMediaCaptureSource> m_weakPtrFactory;
bool m_isRunning { false};
};
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2016-11-17 18:43:40 UTC (rev 208851)
@@ -126,6 +126,7 @@
: RealtimeMediaSource(id, type, emptyString())
, m_objcObserver(adoptNS([[WebCoreAVMediaCaptureSourceObserver alloc] initWithCallback:this]))
, m_device(device)
+ , m_weakPtrFactory(this)
{
setName(device.localizedName);
setPersistentID(device.uniqueID);
@@ -235,6 +236,13 @@
m_isRunning = false;
for (NSString *keyName in sessionKVOProperties())
[m_session removeObserver:m_objcObserver.get() forKeyPath:keyName];
+
+ for (const auto& preview : m_previews) {
+ if (preview)
+ preview->invalidate();
+ }
+ m_previews.clear();
+
shutdownCaptureSession();
m_session = nullptr;
}
@@ -266,6 +274,45 @@
return nullptr;
}
+RefPtr<RealtimeMediaSourcePreview> AVMediaCaptureSource::preview()
+{
+ RefPtr<AVMediaSourcePreview> preview = createPreview();
+ if (!preview)
+ return nullptr;
+
+ m_previews.append(preview->createWeakPtr());
+ return preview.leakRef();
+}
+
+void AVMediaCaptureSource::removePreview(AVMediaSourcePreview* preview)
+{
+ size_t index;
+ for (index = 0; index < m_previews.size(); ++index) {
+ if (m_previews[index].get() == preview)
+ break;
+ }
+
+ if (index < m_previews.size())
+ m_previews.remove(index);
+}
+
+AVMediaSourcePreview::AVMediaSourcePreview(AVMediaCaptureSource* parent)
+ : m_parent(parent->createWeakPtr())
+{
+}
+
+AVMediaSourcePreview::~AVMediaSourcePreview()
+{
+ if (m_parent)
+ m_parent->removePreview(this);
+}
+
+void AVMediaSourcePreview::invalidate()
+{
+ m_parent = nullptr;
+ RealtimeMediaSourcePreview::invalidate();
+}
+
NSArray* sessionKVOProperties()
{
static NSArray* keys = [@[@"running"] retain];
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -41,6 +41,7 @@
class FloatRect;
class GraphicsContext;
+class AVVideoSourcePreview;
class AVVideoCaptureSource : public AVMediaCaptureSource {
public:
@@ -77,8 +78,8 @@
void processNewFrame(RetainPtr<CMSampleBufferRef>);
void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) final;
- PlatformLayer* platformLayer() const final;
+ RefPtr<AVMediaSourcePreview> createPreview() final;
RetainPtr<CGImageRef> currentFrameCGImage();
RefPtr<Image> currentFrameImage() final;
@@ -85,8 +86,8 @@
RetainPtr<NSString> m_pendingPreset;
RetainPtr<CMSampleBufferRef> m_buffer;
RetainPtr<CGImageRef> m_lastImage;
+
Vector<Float64> m_videoFrameTimeStamps;
- mutable RetainPtr<PlatformLayer> m_videoPreviewLayer;
Float64 m_frameRate { 0 };
int32_t m_width { 0 };
int32_t m_height { 0 };
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm 2016-11-17 18:43:40 UTC (rev 208851)
@@ -38,6 +38,7 @@
#import "NotImplemented.h"
#import "PlatformLayer.h"
#import "RealtimeMediaSourceCenter.h"
+#import "RealtimeMediaSourcePreview.h"
#import "RealtimeMediaSourceSettings.h"
#import <AVFoundation/AVFoundation.h>
#import <objc/runtime.h>
@@ -90,6 +91,90 @@
namespace WebCore {
+class AVVideoSourcePreview: public AVMediaSourcePreview {
+public:
+ static RefPtr<AVMediaSourcePreview> create(AVCaptureSession *, AVCaptureDeviceTypedef *, AVVideoCaptureSource*);
+
+private:
+ AVVideoSourcePreview(AVCaptureSession *, AVCaptureDeviceTypedef *, AVVideoCaptureSource*);
+
+ void invalidate() final;
+
+ void play() const final;
+ void pause() const final;
+ void setVolume(double) const final { };
+ void setEnabled(bool) final;
+ PlatformLayer* platformLayer() const final { return m_previewBackgroundLayer.get(); }
+
+ void setPaused(bool) const;
+
+ RetainPtr<AVCaptureVideoPreviewLayerType> m_previewLayer;
+ RetainPtr<PlatformLayer> m_previewBackgroundLayer;
+ RetainPtr<AVCaptureDeviceTypedef> m_device;
+};
+
+RefPtr<AVMediaSourcePreview> AVVideoSourcePreview::create(AVCaptureSession *session, AVCaptureDeviceTypedef* device, AVVideoCaptureSource* parent)
+{
+ return adoptRef(new AVVideoSourcePreview(session, device, parent));
+}
+
+AVVideoSourcePreview::AVVideoSourcePreview(AVCaptureSession *session, AVCaptureDeviceTypedef* device, AVVideoCaptureSource* parent)
+ : AVMediaSourcePreview(parent)
+{
+ m_device = device;
+ m_previewLayer = adoptNS([allocAVCaptureVideoPreviewLayerInstance() initWithSession:session]);
+#ifndef NDEBUG
+ m_previewLayer.get().name = @"AVVideoCaptureSource preview layer";
+#endif
+
+ m_previewLayer.get().contentsGravity = kCAGravityResize;
+ m_previewLayer.get().anchorPoint = CGPointZero;
+#if !PLATFORM(IOS)
+ m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+
+ m_previewBackgroundLayer = adoptNS([[CALayer alloc] init]);
+ m_previewBackgroundLayer.get().name = @"AVVideoSourcePreview parent layer";
+ m_previewBackgroundLayer.get().contentsGravity = kCAGravityResizeAspect;
+ m_previewBackgroundLayer.get().anchorPoint = CGPointZero;
+ m_previewBackgroundLayer.get().needsDisplayOnBoundsChange = YES;
+#if !PLATFORM(IOS)
+ m_previewBackgroundLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+#endif
+
+ [m_previewBackgroundLayer addSublayer:m_previewLayer.get()];
+}
+
+void AVVideoSourcePreview::invalidate()
+{
+ m_previewLayer = nullptr;
+ m_previewBackgroundLayer = nullptr;
+ m_device = nullptr;
+ AVMediaSourcePreview::invalidate();
+}
+
+void AVVideoSourcePreview::play() const
+{
+ setPaused(false);
+}
+
+void AVVideoSourcePreview::pause() const
+{
+ setPaused(true);
+}
+
+void AVVideoSourcePreview::setPaused(bool paused) const
+{
+ [m_device lockForConfiguration:nil];
+ m_previewLayer.get().connection.enabled = !paused;
+ [m_device unlockForConfiguration];
+}
+
+void AVVideoSourcePreview::setEnabled(bool enabled)
+{
+ m_previewLayer.get().hidden = !enabled;
+}
+
const OSType videoCaptureFormat = kCVPixelFormatType_32BGRA;
RefPtr<AVMediaCaptureSource> AVVideoCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString& id, const MediaConstraints* constraints, String& invalidConstraint)
@@ -215,7 +300,7 @@
{
NSString *preset = bestSessionPresetForVideoDimensions(size.width(), size.height());
if (!preset || ![session() canSetSessionPreset:preset]) {
- LOG(Media, "AVVideoCaptureSource::applySize%p), unable find or set preset for width: %i, height: %i", this, size.width(), size.height());
+ LOG(Media, "AVVideoCaptureSource::applySize(%p), unable find or set preset for width: %i, height: %i", this, size.width(), size.height());
return false;
}
@@ -318,7 +403,6 @@
void AVVideoCaptureSource::shutdownCaptureSession()
{
- m_videoPreviewLayer = nullptr;
m_buffer = nullptr;
m_lastImage = nullptr;
m_videoFrameTimeStamps.clear();
@@ -365,12 +449,14 @@
ASSERT(newSampleBuffer);
CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(newSampleBuffer, true);
- for (CFIndex i = 0; i < CFArrayGetCount(attachmentsArray); ++i) {
- CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
- CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
+ if (attachmentsArray) {
+ for (CFIndex i = 0; i < CFArrayGetCount(attachmentsArray); ++i) {
+ CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
+ CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
+ }
}
- m_buffer = newSampleBuffer;
+ m_buffer = adoptCF(newSampleBuffer);
m_lastImage = nullptr;
bool settingsChanged = false;
@@ -450,17 +536,9 @@
CGContextDrawImage(context.platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), m_lastImage.get());
}
-PlatformLayer* AVVideoCaptureSource::platformLayer() const
+RefPtr<AVMediaSourcePreview> AVVideoCaptureSource::createPreview()
{
- if (m_videoPreviewLayer)
- return m_videoPreviewLayer.get();
-
- m_videoPreviewLayer = adoptNS([allocAVCaptureVideoPreviewLayerInstance() initWithSession:session()]);
-#ifndef NDEBUG
- m_videoPreviewLayer.get().name = @"AVVideoCaptureSource preview layer";
-#endif
-
- return m_videoPreviewLayer.get();
+ return AVVideoSourcePreview::create(session(), device(), this);
}
NSString *AVVideoCaptureSource::bestSessionPresetForVideoDimensions(Optional<int> width, Optional<int> height) const
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -54,8 +54,7 @@
RetainPtr<CMSampleBufferRef> CMSampleBufferFromPixelBuffer(CVPixelBufferRef);
RetainPtr<CVPixelBufferRef> pixelBufferFromCGImage(CGImageRef) const;
- PlatformLayer* platformLayer() const override;
- void updatePlatformLayer() const override;
+ PlatformLayer* platformLayer() const;
void updateSampleBuffer() override;
mutable RetainPtr<CGImageRef> m_previewImage;
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm (208850 => 208851)
--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm 2016-11-17 18:43:40 UTC (rev 208851)
@@ -120,49 +120,6 @@
return adoptCF(pixelBuffer);
}
-PlatformLayer* MockRealtimeVideoSourceMac::platformLayer() const
-{
- if (m_previewLayer)
- return m_previewLayer.get();
-
- m_previewLayer = adoptNS([[CALayer alloc] init]);
- m_previewLayer.get().name = @"MockRealtimeVideoSourceMac preview layer";
- m_previewLayer.get().contentsGravity = kCAGravityResizeAspect;
- m_previewLayer.get().anchorPoint = CGPointZero;
- m_previewLayer.get().needsDisplayOnBoundsChange = YES;
-#if !PLATFORM(IOS)
- m_previewLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
-#endif
-
- updatePlatformLayer();
-
- return m_previewLayer.get();
-}
-
-void MockRealtimeVideoSourceMac::updatePlatformLayer() const
-{
- if (!m_previewLayer)
- return;
-
- [CATransaction begin];
- [CATransaction setAnimationDuration:0];
- [CATransaction setDisableActions:YES];
-
- do {
- RefPtr<Image> image = imageBuffer()->copyImage();
- if (!image)
- break;
-
- m_previewImage = image->nativeImage();
- if (!m_previewImage)
- break;
-
- m_previewLayer.get().contents = (NSObject*)(m_previewImage.get());
- } while (0);
-
- [CATransaction commit];
-}
-
void MockRealtimeVideoSourceMac::updateSampleBuffer()
{
auto pixelBuffer = pixelBufferFromCGImage(imageBuffer()->copyImage()->nativeImage().get());
Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (208850 => 208851)
--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp 2016-11-17 18:43:40 UTC (rev 208851)
@@ -138,7 +138,6 @@
if (m_timer.isActive())
m_timer.startRepeating(std::chrono::milliseconds(lround(1000 / rate)));
- updatePlatformLayer();
updateSampleBuffer();
return true;
}
@@ -168,7 +167,6 @@
m_statsFont.update(nullptr);
m_imageBuffer = nullptr;
- updatePlatformLayer();
return true;
}
@@ -339,7 +337,6 @@
drawAnimation(context);
drawBoxes(context);
- updatePlatformLayer();
updateSampleBuffer();
}
Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (208850 => 208851)
--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h 2016-11-17 18:19:55 UTC (rev 208850)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h 2016-11-17 18:43:40 UTC (rev 208851)
@@ -53,7 +53,6 @@
protected:
MockRealtimeVideoSource(const String&);
- virtual void updatePlatformLayer() const { }
virtual void updateSampleBuffer() { }
ImageBuffer* imageBuffer() const;
@@ -77,7 +76,6 @@
bool applyFacingMode(RealtimeMediaSourceSettings::VideoFacingMode) override { return true; }
bool applyAspectRatio(double) override { return true; }
- PlatformLayer* platformLayer() const override { return nullptr; }
RefPtr<Image> currentFrameImage() override;
void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) override;