⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 237642 in webkit


Ignore:
Timestamp:
Oct 31, 2018, 10:19:27 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
https://bugs.webkit.org/show_bug.cgi?id=190778

Patch by YUHAN WU <yuhan_wu@apple.com> on 2018-10-31
Reviewed by Youenn Fablet.

LayoutTests/imported/w3c:

  • web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt:
  • web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution-expected.txt: Added.
  • web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html: Added.
  • web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt:
  • web-platform-tests/mediacapture-record/MediaRecorder-stop.html:
  • web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html: Added.

Source/WebCore:

Implement JavaScript dispatch event dataavailable and JavaScript exposed method stop().
Implement a mock string as the output buffer of MediaRecorder.
Remove the declaration of timecode in BlobEvent since it has not been implemented in MediaRecorder and MediaRecorderPrivate.

Tests: http/wpt/mediarecorder/MediaRecorder-dataavailable.html

http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html
imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html
imported/w3c/web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html

  • CMakeLists.txt:
  • Modules/mediarecorder/BlobEvent.cpp: Added.

(WebCore::BlobEvent::create):
(WebCore::BlobEvent::BlobEvent):
(WebCore::BlobEvent::eventInterface const):

  • Modules/mediarecorder/BlobEvent.h:
  • Modules/mediarecorder/BlobEvent.idl:
  • Modules/mediarecorder/MediaRecorder.cpp:

(WebCore::MediaRecorder::MediaRecorder):
(WebCore::MediaRecorder::~MediaRecorder):
(WebCore::MediaRecorder::stop):
(WebCore::MediaRecorder::startRecording):
(WebCore::MediaRecorder::stopRecording):
(WebCore::MediaRecorder::stopRecordingInternal):
(WebCore::MediaRecorder::didAddOrRemoveTrack):
(WebCore::MediaRecorder::trackEnded):
(WebCore::MediaRecorder::sampleBufferUpdated):
(WebCore::MediaRecorder::audioSamplesAvailable):
(WebCore::MediaRecorder::scheduleDeferredTask):

  • Modules/mediarecorder/MediaRecorder.h:
  • Modules/mediarecorder/MediaRecorder.idl:
  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • dom/EventNames.h:
  • dom/EventNames.in:
  • platform/mediarecorder/MediaRecorderPrivate.h: Added.
  • platform/mediarecorder/MediaRecorderPrivateMock.cpp: Added.

(WebCore::MediaRecorderPrivateMock::sampleBufferUpdated):
(WebCore::MediaRecorderPrivateMock::audioSamplesAvailable):
(WebCore::MediaRecorderPrivateMock::generateMockString):
(WebCore::MediaRecorderPrivateMock::fetchData):

  • platform/mediarecorder/MediaRecorderPrivateMock.h: Added.

LayoutTests:

These tests are used to check if MediaRecorder can generate both video and audio buffers through mock source.

  • http/wpt/mediarecorder/MediaRecorder-dataavailable-expected.txt: Added.
  • http/wpt/mediarecorder/MediaRecorder-dataavailable.html: Added.
  • http/wpt/mediarecorder/MediaRecorder-mock-dataavailable-expected.txt: Added.
  • http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html: Added.
  • platform/win/TestExpectations:
Location:
trunk
Files:
10 added
17 edited
4 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r237639 r237642  
     12018-10-31  YUHAN WU  <yuhan_wu@apple.com>
     2
     3        MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
     4        https://bugs.webkit.org/show_bug.cgi?id=190778
     5
     6        Reviewed by Youenn Fablet.
     7
     8        These tests are used to check if MediaRecorder can generate both video and audio buffers through mock source.
     9
     10        * http/wpt/mediarecorder/MediaRecorder-dataavailable-expected.txt: Added.
     11        * http/wpt/mediarecorder/MediaRecorder-dataavailable.html: Added.
     12        * http/wpt/mediarecorder/MediaRecorder-mock-dataavailable-expected.txt: Added.
     13        * http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html: Added.
     14        * platform/win/TestExpectations:
     15
    1162018-10-31  Chris Dumez  <cdumez@apple.com>
    217
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r237618 r237642  
     12018-10-31  YUHAN WU  <yuhan_wu@apple.com>
     2
     3        MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
     4        https://bugs.webkit.org/show_bug.cgi?id=190778
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt:
     9        * web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution-expected.txt: Added.
     10        * web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html: Added.
     11        * web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt:
     12        * web-platform-tests/mediacapture-record/MediaRecorder-stop.html:
     13        * web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html: Added.
     14
    1152018-10-30  Chris Dumez  <cdumez@apple.com>
    216
  • trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt

    r236840 r237642  
    22PASS The BlobEventInit dictionary is required
    33PASS The BlobEventInit dictionary's data member is required.
    4 FAIL The BlobEvent instance's data attribute is set. assert_equals: expected (object) object "[object Blob]" but got (undefined) undefined
     4PASS The BlobEvent instance's data attribute is set.
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt

    r237311 r237642  
    11
    22PASS MediaRecorder will stop recording and fire a stop event when all tracks are ended
     3PASS MediaRecorder will stop recording and fire a stop event when stop() is called
    34
  • trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop.html

    r237311 r237642  
    3030        assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
    3131        video.getVideoTracks()[0].stop();
    32     }, "MediaRecorder will stop recording and fire a stop event when all tracks are ended", { timeout: 10000 });
     32    }, "MediaRecorder will stop recording and fire a stop event when all tracks are ended");
     33
     34    async_test(t => {
     35        let video = createVideoStream();
     36        let recorder = new MediaRecorder(video);
     37        recorder.onstop = t.step_func(errorEvent => {
     38            assert_equals(errorEvent.type, 'stop', 'the error type should be stop');
     39            assert_true(errorEvent.isTrusted, 'isTrusted should be true when the event is created by C++');
     40            assert_equals(recorder.state, "inactive", "MediaRecorder has been stopped when stop() is called");
     41            t.done();
     42        });
     43        recorder.start();
     44        assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
     45        recorder.stop();
     46        assert_equals(recorder.state, "recording", "State should remain the same until stop event is fired");
     47    }, "MediaRecorder will stop recording and fire a stop event when stop() is called");
    3348</script>
    3449</body>
  • trunk/LayoutTests/platform/win/TestExpectations

    r237279 r237642  
    42234223
    42244224# MediaRecorder is not enabled on Windows
    4225 imported/w3c/web-platform-tests/mediacapture-record/BlobEvent-constructor.html [ Skip ]
    4226 imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-constructor.html [ Skip ]
     4225imported/w3c/web-platform-tests/mediacapture-record [ Skip ]
    42274226fast/mediacapturefromelement/CanvasCaptureMediaStream-imagebitmaprenderingcontext.html [ Skip ]
     4227http/wpt/mediarecorder [ Skip ]
    42284228
    42294229webkit.org/b/190472 fast/forms/fieldset/fieldset-elements-htmlcollection.html [ Failure ]
  • trunk/Source/WebCore/CMakeLists.txt

    r237344 r237642  
    114114    "${WEBCORE_DIR}/platform/graphics/opentype"
    115115    "${WEBCORE_DIR}/platform/graphics/transforms"
     116    "${WEBCORE_DIR}/platform/mediarecorder"
    116117    "${WEBCORE_DIR}/platform/mediastream"
    117118    "${WEBCORE_DIR}/platform/mediastream/libwebrtc"
  • trunk/Source/WebCore/ChangeLog

    r237637 r237642  
     12018-10-31  YUHAN WU  <yuhan_wu@apple.com>
     2
     3        MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
     4        https://bugs.webkit.org/show_bug.cgi?id=190778
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Implement JavaScript dispatch event dataavailable and JavaScript exposed method stop().
     9        Implement a mock string as the output buffer of MediaRecorder.
     10        Remove the declaration of timecode in BlobEvent since it has not been implemented in MediaRecorder and MediaRecorderPrivate.
     11
     12        Tests: http/wpt/mediarecorder/MediaRecorder-dataavailable.html
     13               http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html
     14               imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html
     15               imported/w3c/web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html
     16
     17        * CMakeLists.txt:
     18        * Modules/mediarecorder/BlobEvent.cpp: Added.
     19        (WebCore::BlobEvent::create):
     20        (WebCore::BlobEvent::BlobEvent):
     21        (WebCore::BlobEvent::eventInterface const):
     22        * Modules/mediarecorder/BlobEvent.h:
     23        * Modules/mediarecorder/BlobEvent.idl:
     24        * Modules/mediarecorder/MediaRecorder.cpp:
     25        (WebCore::MediaRecorder::MediaRecorder):
     26        (WebCore::MediaRecorder::~MediaRecorder):
     27        (WebCore::MediaRecorder::stop):
     28        (WebCore::MediaRecorder::startRecording):
     29        (WebCore::MediaRecorder::stopRecording):
     30        (WebCore::MediaRecorder::stopRecordingInternal):
     31        (WebCore::MediaRecorder::didAddOrRemoveTrack):
     32        (WebCore::MediaRecorder::trackEnded):
     33        (WebCore::MediaRecorder::sampleBufferUpdated):
     34        (WebCore::MediaRecorder::audioSamplesAvailable):
     35        (WebCore::MediaRecorder::scheduleDeferredTask):
     36        * Modules/mediarecorder/MediaRecorder.h:
     37        * Modules/mediarecorder/MediaRecorder.idl:
     38        * Sources.txt:
     39        * WebCore.xcodeproj/project.pbxproj:
     40        * dom/EventNames.h:
     41        * dom/EventNames.in:
     42        * platform/mediarecorder/MediaRecorderPrivate.h: Added.
     43        * platform/mediarecorder/MediaRecorderPrivateMock.cpp: Added.
     44        (WebCore::MediaRecorderPrivateMock::sampleBufferUpdated):
     45        (WebCore::MediaRecorderPrivateMock::audioSamplesAvailable):
     46        (WebCore::MediaRecorderPrivateMock::generateMockString):
     47        (WebCore::MediaRecorderPrivateMock::fetchData):
     48        * platform/mediarecorder/MediaRecorderPrivateMock.h: Added.
     49
    1502018-10-31  Claudio Saavedra  <csaavedra@igalia.com>
    251
  • trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.cpp

    r237641 r237642  
    2323 */
    2424
    25 #pragma once
     25
     26#include "config.h"
     27#include "BlobEvent.h"
    2628
    2729#if ENABLE(MEDIA_STREAM)
    2830
    29 #include "Event.h"
     31#include "Blob.h"
    3032
    3133namespace WebCore {
     34
     35Ref<BlobEvent> BlobEvent::create(const AtomicString& type, Init&& init, IsTrusted isTrusted)
     36{
     37    return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
     38}
     39
     40Ref<BlobEvent> BlobEvent::create(const AtomicString& type, CanBubble canBubble, IsCancelable isCancelable, Ref<Blob>&& data)
     41{
     42    return adoptRef(*new BlobEvent(type, canBubble, isCancelable, WTFMove(data)));
     43}
     44
     45BlobEvent::BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
     46    : Event(type, init, isTrusted)
     47    , m_blob(init.data.releaseNonNull())
     48{
     49}
     50
     51BlobEvent::BlobEvent(const AtomicString& type, CanBubble canBubble, IsCancelable isCancelable, Ref<Blob>&& data)
     52    : Event(type, canBubble, isCancelable)
     53    , m_blob(WTFMove(data))
     54{
     55}
    3256   
    33 class Blob;
    34    
    35 class BlobEvent final : public Event {
    36 public:
    37     struct Init : EventInit {
    38         RefPtr<Blob> data;
    39         double timecode;
    40     };
    41    
    42     static Ref<BlobEvent> create(const AtomicString& type, Init&& init, IsTrusted isTrusted = IsTrusted::No)
    43     {
    44         return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
    45     }
     57EventInterface BlobEvent::eventInterface() const
     58{
     59    return BlobEventInterfaceType;
     60}
    4661
    47 private:
    48     BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
    49         : Event(type, WTFMove(init), isTrusted)
    50     {
    51     }
    52 };
    53    
    5462} // namespace WebCore
    5563
  • trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h

    r236840 r237642  
    4040    };
    4141   
    42     static Ref<BlobEvent> create(const AtomicString& type, Init&& init, IsTrusted isTrusted = IsTrusted::No)
    43     {
    44         return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
    45     }
     42    static Ref<BlobEvent> create(const AtomicString&, Init&&, IsTrusted = IsTrusted::No);
     43    static Ref<BlobEvent> create(const AtomicString&, CanBubble, IsCancelable, Ref<Blob>&&);
    4644
     45    Blob& data() const { return m_blob.get(); }
     46   
    4747private:
    48     BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
    49         : Event(type, WTFMove(init), isTrusted)
    50     {
    51     }
     48    BlobEvent(const AtomicString&, Init&&, IsTrusted);
     49    BlobEvent(const AtomicString&, CanBubble, IsCancelable, Ref<Blob>&&);
     50   
     51    // Event
     52    EventInterface eventInterface() const final;
     53   
     54    Ref<Blob> m_blob;
    5255};
    5356   
  • trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.idl

    r236840 r237642  
    3232]  interface BlobEvent : Event {
    3333    // FIXME: Implement these:
    34     // [SameObject] readonly attribute Blob data;
     34    [SameObject] readonly attribute Blob data;
    3535    // readonly attribute DOMHighResTimeStamp timecode;
    3636};
  • trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp

    r237311 r237642  
    2929#if ENABLE(MEDIA_STREAM)
    3030
     31#include "Blob.h"
     32#include "BlobEvent.h"
    3133#include "Document.h"
    3234#include "EventNames.h"
    3335#include "MediaRecorderErrorEvent.h"
     36#include "MediaRecorderPrivateMock.h"
    3437
    3538namespace WebCore {
     
    4649    , m_options(WTFMove(option))
    4750    , m_stream(WTFMove(stream))
     51    , m_private(makeUniqueRef<MediaRecorderPrivateMock>()) // FIXME: we will need to decide which MediaRecorderPrivate instance to create based on the mock enabled feature flag
    4852{
    49     m_tracks = WTF::map(m_stream->getTracks(), [this] (const auto& track) -> Ref<MediaStreamTrackPrivate> {
    50         auto& privateTrack = track->privateTrack();
    51         privateTrack.addObserver(*this);
    52         return privateTrack;
     53    m_tracks = WTF::map(m_stream->getTracks(), [] (auto&& track) -> Ref<MediaStreamTrackPrivate> {
     54        return track->privateTrack();
    5355    });
    5456    m_stream->addObserver(this);
     
    5860{
    5961    m_stream->removeObserver(this);
    60     for (auto& track : m_tracks)
    61         track->removeObserver(*this);
     62    stopRecordingInternal();
    6263}
    6364
     
    6566{
    6667    m_isActive = false;
     68    stopRecordingInternal();
    6769}
    6870
     
    7779}
    7880
    79 ExceptionOr<void> MediaRecorder::start(std::optional<int> timeslice)
     81ExceptionOr<void> MediaRecorder::startRecording(std::optional<int> timeslice)
    8082{
    8183    UNUSED_PARAM(timeslice);
     
    8385        return Exception { InvalidStateError, "The MediaRecorder's state must be inactive in order to start recording"_s };
    8486   
     87    for (auto& track : m_tracks)
     88        track->addObserver(*this);
     89
    8590    m_state = RecordingState::Recording;
    8691    return { };
     92}
     93
     94ExceptionOr<void> MediaRecorder::stopRecording()
     95{
     96    if (state() == RecordingState::Inactive)
     97        return Exception { InvalidStateError, "The MediaRecorder's state cannot be inactive"_s };
     98
     99    scheduleDeferredTask([this] {
     100        if (!m_isActive || state() == RecordingState::Inactive)
     101            return;
     102
     103        stopRecordingInternal();
     104        ASSERT(m_state == RecordingState::Inactive);
     105        dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, m_private->fetchData()));
     106        if (!m_isActive)
     107            return;
     108        dispatchEvent(Event::create(eventNames().stopEvent, Event::CanBubble::No, Event::IsCancelable::No));
     109    });
     110    return { };
     111}
     112
     113void MediaRecorder::stopRecordingInternal()
     114{
     115    if (state() != RecordingState::Recording)
     116        return;
     117
     118    for (auto& track : m_tracks)
     119        track->removeObserver(*this);
     120
     121    m_state = RecordingState::Inactive;
    87122}
    88123
     
    104139    if (position != notFound)
    105140        return;
    106     scheduleDeferredTask([this] {
    107         if (!m_isActive || state() == RecordingState::Inactive)
    108             return;
    109         // FIXME: Add a dataavailable event
    110         auto event = Event::create(eventNames().stopEvent, Event::CanBubble::No, Event::IsCancelable::No);
    111         setNewRecordingState(RecordingState::Inactive, WTFMove(event));
    112     });
     141
     142    stopRecording();
     143}
     144
     145void MediaRecorder::sampleBufferUpdated(MediaStreamTrackPrivate& track, MediaSample& mediaSample)
     146{
     147    m_private->sampleBufferUpdated(track, mediaSample);
     148}
     149
     150void MediaRecorder::audioSamplesAvailable(MediaStreamTrackPrivate& track, const MediaTime& mediaTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount)
     151{
     152    m_private->audioSamplesAvailable(track, mediaTime, audioData, description, sampleCount);
    113153}
    114154
     
    125165    if (!scriptExecutionContext)
    126166        return;
    127     scriptExecutionContext->postTask([weakThis = makeWeakPtr(*this), function = WTFMove(function)] (auto&) {
    128         if (!weakThis)
    129             return;
    130 
     167    scriptExecutionContext->postTask([protectedThis = makeRef(*this), function = WTFMove(function)] (auto&) {
    131168        function();
    132169    });
  • trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h

    r237311 r237642  
    2626
    2727#if ENABLE(MEDIA_STREAM)
     28
    2829#include "ActiveDOMObject.h"
    2930#include "EventTarget.h"
    3031#include "MediaStream.h"
    3132#include "MediaStreamTrackPrivate.h"
     33#include <wtf/UniqueRef.h>
    3234
    3335namespace WebCore {
    3436
    3537class Document;
     38class MediaRecorderPrivate;
    3639
    3740class MediaRecorder final
     
    6164    using RefCounted::deref;
    6265   
    63     ExceptionOr<void> start(std::optional<int>);
     66    ExceptionOr<void> startRecording(std::optional<int>);
     67    ExceptionOr<void> stopRecording();
    6468   
    6569private:
     
    7781    bool canSuspendForDocumentSuspension() const final;
    7882   
     83    void stopRecordingInternal();
     84   
    7985    // MediaStream::Observer
    8086    void didAddOrRemoveTrack() final;
     
    8591    void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
    8692    void trackEnabledChanged(MediaStreamTrackPrivate&) final { };
     93    void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final;
     94    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
    8795   
    8896    void scheduleDeferredTask(Function<void()>&&);
     
    9199    Options m_options;
    92100    Ref<MediaStream> m_stream;
     101    UniqueRef<MediaRecorderPrivate> m_private;
    93102    RecordingState m_state { RecordingState::Inactive };
    94103    Vector<Ref<MediaStreamTrackPrivate>> m_tracks;
  • trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl

    r237311 r237642  
    3939    // attribute EventHandler onstart;
    4040    attribute EventHandler onstop;
    41     // attribute EventHandler ondataavailable;
     41    attribute EventHandler ondataavailable;
    4242    // attribute EventHandler onpause;
    4343    // attribute EventHandler onresume;
     
    4646    // readonly attribute unsigned long audioBitsPerSecond;
    4747
    48     [MayThrowException] void start(optional long timeslice);
    49     // void stop();
     48    [MayThrowException, ImplementedAs=startRecording] void start(optional long timeslice);
     49    [ImplementedAs=stopRecording] void stop();
    5050    // void pause();
    5151    // void resume();
  • trunk/Source/WebCore/Sources.txt

    r237631 r237642  
    141141Modules/mediacontrols/MediaControlsHost.cpp
    142142
     143Modules/mediarecorder/BlobEvent.cpp
    143144Modules/mediarecorder/MediaRecorder.cpp
    144145Modules/mediarecorder/MediaRecorderErrorEvent.cpp
     
    17671768
    17681769platform/mediacapabilities/MediaEngineConfigurationFactory.cpp
     1770
     1771platform/mediarecorder/MediaRecorderPrivateMock.cpp
    17691772
    17701773platform/mediastream/CaptureDeviceManager.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r237636 r237642  
    13611361                4D3B00AB215D69A70076B983 /* MediaRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B00A9215D69A70076B983 /* MediaRecorder.h */; };
    13621362                4D3B00AF215D6A690076B983 /* BlobEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B00AD215D6A690076B983 /* BlobEvent.h */; };
     1363                4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */; };
    13631364                4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DB7130C216EC2BD0096A4DD /* MediaRecorderErrorEvent.h */; };
    13641365                4E1959220A39DABA00220FE5 /* MediaFeatureNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E1959200A39DABA00220FE5 /* MediaFeatureNames.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    79217922                4D3B00A9215D69A70076B983 /* MediaRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorder.h; sourceTree = "<group>"; };
    79227923                4D3B00AD215D6A690076B983 /* BlobEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobEvent.h; sourceTree = "<group>"; };
     7924                4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivate.h; sourceTree = "<group>"; };
     7925                4D7EB3F4217C6AE600D64888 /* BlobEvent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlobEvent.cpp; sourceTree = "<group>"; };
     7926                4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivateMock.h; sourceTree = "<group>"; };
     7927                4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderPrivateMock.cpp; sourceTree = "<group>"; };
    79237928                4DB7130A216EC2BC0096A4DD /* MediaRecorderErrorEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaRecorderErrorEvent.idl; sourceTree = "<group>"; };
    79247929                4DB7130C216EC2BD0096A4DD /* MediaRecorderErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorderErrorEvent.h; sourceTree = "<group>"; };
     
    1803818043                        isa = PBXGroup;
    1803918044                        children = (
     18045                                4D7EB3F4217C6AE600D64888 /* BlobEvent.cpp */,
    1804018046                                4D3B00AD215D6A690076B983 /* BlobEvent.h */,
    1804118047                                4D3B00A6215D645B0076B983 /* BlobEvent.idl */,
     
    1804618052                                4DB7130C216EC2BD0096A4DD /* MediaRecorderErrorEvent.h */,
    1804718053                                4DB7130A216EC2BC0096A4DD /* MediaRecorderErrorEvent.idl */,
     18054                        );
     18055                        path = mediarecorder;
     18056                        sourceTree = "<group>";
     18057                };
     18058                4D3B5012217E58A300665DB1 /* mediarecorder */ = {
     18059                        isa = PBXGroup;
     18060                        children = (
     18061                                4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */,
     18062                                4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */,
     18063                                4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */,
    1804818064                        );
    1804918065                        path = mediarecorder;
     
    2483224848                                6582A14809999D6C00BEEB6D /* mac */,
    2483324849                                9AC6F02021148F1E00CBDA06 /* mediacapabilities */,
     24850                                4D3B5012217E58A300665DB1 /* mediarecorder */,
    2483424851                                C96F5EBF1B5872260091EA9D /* mediasession */,
    2483524852                                07221B9217CF0AD400848E51 /* mediastream */,
     
    2994629963                                4D3B00AB215D69A70076B983 /* MediaRecorder.h in Headers */,
    2994729964                                4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */,
     29965                                4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */,
    2994829966                                C90843D01B18E47D00B68564 /* MediaRemoteControls.h in Headers */,
    2994929967                                CD8ACA8F1D23971900ECC59E /* MediaRemoteSoftLink.h in Headers */,
  • trunk/Source/WebCore/dom/EventNames.h

    r237311 r237642  
    102102    macro(cuechange) \
    103103    macro(cut) \
     104    macro(dataavailable) \
    104105    macro(datachannel) \
    105106    macro(dblclick) \
  • trunk/Source/WebCore/dom/EventNames.in

    r237106 r237642  
    4848ApplePayValidateMerchantEvent conditional=APPLE_PAY
    4949AudioProcessingEvent conditional=WEB_AUDIO
     50BlobEvent conditional=MEDIA_STREAM
    5051OfflineAudioCompletionEvent conditional=WEB_AUDIO
    5152MediaRecorderErrorEvent conditional=MEDIA_STREAM
  • trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h

    r237641 r237642  
    2727#if ENABLE(MEDIA_STREAM)
    2828
    29 #include "Event.h"
     29namespace WTF {
     30class MediaTime;
     31}
    3032
    3133namespace WebCore {
     34
     35class AudioStreamDescription;
     36class Blob;
     37class PlatformAudioData;
     38class MediaSample;
     39class MediaStreamTrackPrivate;
     40
     41class MediaRecorderPrivate {
     42public:
     43    virtual void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) = 0;
     44    virtual void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) = 0;
    3245   
    33 class Blob;
    34    
    35 class BlobEvent final : public Event {
    36 public:
    37     struct Init : EventInit {
    38         RefPtr<Blob> data;
    39         double timecode;
    40     };
    41    
    42     static Ref<BlobEvent> create(const AtomicString& type, Init&& init, IsTrusted isTrusted = IsTrusted::No)
    43     {
    44         return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
    45     }
    46 
    47 private:
    48     BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
    49         : Event(type, WTFMove(init), isTrusted)
    50     {
    51     }
     46    virtual Ref<Blob> fetchData() = 0;
     47    virtual ~MediaRecorderPrivate() = default;
    5248};
    5349   
  • trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp

    r237641 r237642  
    2323 */
    2424
    25 #pragma once
     25
     26#include "config.h"
     27#include "MediaRecorderPrivateMock.h"
    2628
    2729#if ENABLE(MEDIA_STREAM)
    2830
    29 #include "Event.h"
     31#include "Blob.h"
     32#include "MediaStreamTrackPrivate.h"
    3033
    3134namespace WebCore {
    32    
    33 class Blob;
    34    
    35 class BlobEvent final : public Event {
    36 public:
    37     struct Init : EventInit {
    38         RefPtr<Blob> data;
    39         double timecode;
    40     };
    41    
    42     static Ref<BlobEvent> create(const AtomicString& type, Init&& init, IsTrusted isTrusted = IsTrusted::No)
    43     {
    44         return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
    45     }
    4635
    47 private:
    48     BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
    49         : Event(type, WTFMove(init), isTrusted)
    50     {
    51     }
    52 };
    53    
     36void MediaRecorderPrivateMock::sampleBufferUpdated(MediaStreamTrackPrivate& track, MediaSample&)
     37{
     38    generateMockString(track);
     39}
     40
     41void MediaRecorderPrivateMock::audioSamplesAvailable(MediaStreamTrackPrivate& track, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t)
     42{
     43    generateMockString(track);
     44}
     45
     46void MediaRecorderPrivateMock::generateMockString(MediaStreamTrackPrivate& track)
     47{
     48    auto locker = holdLock(m_bufferLock);
     49    if (track.type() == RealtimeMediaSource::Type::Audio)
     50        m_buffer.append("Audio Track ID: ");
     51    else
     52        m_buffer.append("Video Track ID: ");
     53    m_buffer.append(track.id());
     54    m_buffer.append(" Counter: ");
     55    m_buffer.appendNumber(++m_counter);
     56    m_buffer.append("\r\n---------\r\n");
     57}
     58
     59Ref<Blob> MediaRecorderPrivateMock::fetchData()
     60{
     61    auto locker = holdLock(m_bufferLock);
     62    Vector<uint8_t> value(m_buffer.length());
     63    memcpy(value.data(), m_buffer.characters8(), m_buffer.length());
     64    m_buffer.clear();
     65    return Blob::create(WTFMove(value), "text/plain");
     66}
     67
    5468} // namespace WebCore
    5569
  • trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h

    r237641 r237642  
    2727#if ENABLE(MEDIA_STREAM)
    2828
    29 #include "Event.h"
     29#include "MediaRecorderPrivate.h"
     30#include <wtf/Lock.h>
     31#include <wtf/text/StringBuilder.h>
    3032
    3133namespace WebCore {
     34
     35class Blob;
     36class MediaStreamTrackPrivate;
     37
     38class MediaRecorderPrivateMock final : public MediaRecorderPrivate {
     39private:
     40    void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final;
     41    void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
     42    Ref<Blob> fetchData() final;
    3243   
    33 class Blob;
    34    
    35 class BlobEvent final : public Event {
    36 public:
    37     struct Init : EventInit {
    38         RefPtr<Blob> data;
    39         double timecode;
    40     };
    41    
    42     static Ref<BlobEvent> create(const AtomicString& type, Init&& init, IsTrusted isTrusted = IsTrusted::No)
    43     {
    44         return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
    45     }
     44    void generateMockString(MediaStreamTrackPrivate&);
    4645
    47 private:
    48     BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
    49         : Event(type, WTFMove(init), isTrusted)
    50     {
    51     }
     46    mutable Lock m_bufferLock;
     47    StringBuilder m_buffer;
     48    unsigned m_counter { 0 };
    5249};
    53    
     50
    5451} // namespace WebCore
    5552
Note: See TracChangeset for help on using the changeset viewer.