Changeset 270290 in webkit


Ignore:
Timestamp:
Dec 1, 2020 1:43:00 AM (20 months ago)
Author:
youenn@apple.com
Message:

Add support for readable/writable to RTCRtpSFrameTransform
https://bugs.webkit.org/show_bug.cgi?id=219298

Reviewed by Eric Carlson.

Source/WebCore:

Add support for locking WritableStream and checking locked state.
Add readable/writable getters so that RTCRtpSFrameTransform can be used as a TransformStream.
Make a refactoring to allow reuse of SimpleReadableStreamSource and SimpleWritableStreamSink.

In case of encryption/decryption error, we do not error the transform as this is final.
Instead, we output empty buffers.
In case of trying to encrypt unexpected objects, we error the transform.

Move RTCRtpTransformableFrame to be ref counted.
This allows to keep a RTCRtpTransformableFrame for each RTCEncodedFrame even though the underlying
webrtc frame (which is a unique ptr) is given back to the webrtc backend after processing.

Covered by updated test.

  • Modules/mediastream/RTCEncodedAudioFrame.cpp:

(WebCore::RTCEncodedAudioFrame::RTCEncodedAudioFrame):

  • Modules/mediastream/RTCEncodedAudioFrame.h:

(WebCore::RTCEncodedAudioFrame::create):

  • Modules/mediastream/RTCEncodedFrame.cpp:

(WebCore::RTCEncodedFrame::RTCEncodedFrame):

  • Modules/mediastream/RTCEncodedFrame.h:

(WebCore::RTCEncodedFrame::rtcFrame):

  • Modules/mediastream/RTCEncodedVideoFrame.cpp:

(WebCore::RTCEncodedVideoFrame::RTCEncodedVideoFrame):

  • Modules/mediastream/RTCEncodedVideoFrame.h:

(WebCore::RTCEncodedVideoFrame::create):

  • Modules/mediastream/RTCRtpSFrameTransform.cpp:

(WebCore::RTCRtpSFrameTransform::RTCRtpSFrameTransform):
(WebCore::RTCRtpSFrameTransform::isAttached const):
(WebCore::RTCRtpSFrameTransform::initializeTransformer):
(WebCore::RTCRtpSFrameTransform::willClearBackend):
(WebCore::transformFrame):
(WebCore::RTCRtpSFrameTransform::createStreams):
(WebCore::RTCRtpSFrameTransform::readable):
(WebCore::RTCRtpSFrameTransform::writable):

  • Modules/mediastream/RTCRtpSFrameTransform.h:

(WebCore::RTCRtpSFrameTransform::create):

  • Modules/mediastream/RTCRtpSFrameTransform.idl:
  • Modules/mediastream/RTCRtpSFrameTransformer.cpp:

(WebCore::RTCRtpSFrameTransformer::setEncryptionKey):
(WebCore::RTCRtpSFrameTransformer::decryptFrame):
(WebCore::RTCRtpSFrameTransformer::encryptFrame):
(WebCore::RTCRtpSFrameTransformer::transform):
(WebCore::RTCRtpSFrameTransformer::updateAuthenticationSize):

  • Modules/mediastream/RTCRtpSFrameTransformer.h:

(WebCore::RTCRtpSFrameTransformer::setIsEncrypting):
(WebCore::RTCRtpSFrameTransformer::setAuthenticationSize):

  • Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp:

(WebCore::RTCRtpSFrameTransformer::updateAuthenticationSize):

  • Modules/mediastream/RTCRtpScriptTransformer.cpp:

(WebCore::RTCRtpScriptTransformer::startStreams):

  • Modules/mediastream/RTCRtpScriptTransformer.h:
  • Modules/mediastream/RTCRtpTransformBackend.h:
  • Modules/mediastream/RTCRtpTransformableFrame.h:
  • Modules/mediastream/libwebrtc/LibWebRTCRtpSenderTransformBackend.cpp:
  • Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.cpp:

(WebCore::LibWebRTCRtpTransformBackend::processTransformedFrame):
(WebCore::LibWebRTCRtpTransformBackend::Transform):

  • Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.h:
  • Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.cpp: Added.
  • Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.h:
  • Modules/streams/ReadableStreamSource.h:

(WebCore::SimpleReadableStreamSource::create):
(WebCore::SimpleReadableStreamSource::close):
(WebCore::SimpleReadableStreamSource::enqueue):

  • Modules/streams/WritableStreamSink.h:

(WebCore::SimpleWritableStreamSink::create):
(WebCore::SimpleWritableStreamSink::SimpleWritableStreamSink):
(WebCore::SimpleWritableStreamSink::write):

  • bindings/js/WritableStream.cpp:

(WebCore::WritableStreamInternal::callFunction):
(WebCore::checkWritableStream):
(WebCore::WritableStream::lock):
(WebCore::WritableStream::isLocked const):

  • bindings/js/WritableStream.h:
  • bindings/scripts/CodeGeneratorJS.pm:

(AddToIncludesForIDLType):

Tools:

  • TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp:

(TestWebKitAPI::createVideoTransformer):

LayoutTests:

  • http/wpt/webrtc/sframe-transform-expected.txt:
  • http/wpt/webrtc/sframe-transform.html:
Location:
trunk
Files:
34 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r270289 r270290  
     12020-12-01  Youenn Fablet  <youenn@apple.com>
     2
     3        Add support for readable/writable to RTCRtpSFrameTransform
     4        https://bugs.webkit.org/show_bug.cgi?id=219298
     5
     6        Reviewed by Eric Carlson.
     7
     8        * http/wpt/webrtc/sframe-transform-expected.txt:
     9        * http/wpt/webrtc/sframe-transform.html:
     10
    1112020-12-01  Diego Pino Garcia  <dpino@igalia.com>
    212
  • trunk/LayoutTests/http/wpt/webrtc/sframe-transform-expected.txt

    r270107 r270290  
    11
    22PASS Cannot reuse attached transforms
     3PASS RTCRtpSFrameTransform exposes readable and writable
     4PASS readable/writable are locked when attached and after being attached
     5PASS SFrame with array buffer - authentication size 10
     6PASS SFrame decryption with array buffer that is too small
     7PASS SFrame transform gets errored if trying to process unexpected value types
    38
  • trunk/LayoutTests/http/wpt/webrtc/sframe-transform.html

    r270107 r270290  
    2929    receiver1.transform = null;
    3030}, "Cannot reuse attached transforms");
     31
     32test(() => {
     33    const senderTransform = new RTCRtpSFrameTransform();
     34
     35    assert_true(senderTransform.readable instanceof ReadableStream);
     36    assert_true(senderTransform.writable instanceof WritableStream);
     37}, "RTCRtpSFrameTransform exposes readable and writable");
     38
     39promise_test(async (test) => {
     40    const pc = new RTCPeerConnection();
     41    const senderTransform = new RTCRtpSFrameTransform();
     42    const receiverTransform = new RTCRtpSFrameTransform();
     43    const sender1 = pc.addTransceiver('audio').sender;
     44    const sender2 = pc.addTransceiver('video').sender;
     45    const receiver1 = pc.getReceivers()[0];
     46    const receiver2 = pc.getReceivers()[1];
     47
     48    assert_false(senderTransform.readable.locked, "sender readable before");
     49    assert_false(senderTransform.writable.locked, "sender writable before");
     50    assert_false(receiverTransform.readable.locked, "receiver readable before");
     51    assert_false(receiverTransform.writable.locked, "receiver writable before");
     52
     53    sender1.transform = senderTransform;
     54    receiver1.transform = receiverTransform;
     55
     56    assert_true(senderTransform.readable.locked, "sender readable during");
     57    assert_true(senderTransform.writable.locked, "sender writable during");
     58    assert_true(receiverTransform.readable.locked, "receiver readable during");
     59    assert_true(receiverTransform.writable.locked, "receiver writable during");
     60
     61    sender1.transform = null;
     62    receiver1.transform = null;
     63
     64    assert_true(senderTransform.readable.locked, "sender readable after");
     65    assert_true(senderTransform.writable.locked, "sender writable after");
     66    assert_true(receiverTransform.readable.locked, "receiver readable after");
     67    assert_true(receiverTransform.writable.locked, "receiver writable after");
     68}, "readable/writable are locked when attached and after being attached");
     69
     70promise_test(async (test) => {
     71    const key = await crypto.subtle.importKey("raw", new Uint8Array([143, 77, 43, 10, 72, 19, 37, 67, 236, 219, 24, 93, 26, 165, 91, 178]), "HKDF", false, ["deriveBits", "deriveKey"]);
     72
     73    const senderTransform = new RTCRtpSFrameTransform({ role : 'encrypt', authenticationSize: 10 });
     74    senderTransform.setEncryptionKey(key);
     75
     76    const receiverTransform = new RTCRtpSFrameTransform({ role : 'decrypt', authenticationSize: 10 });
     77    receiverTransform.setEncryptionKey(key);
     78
     79    const writer = senderTransform.writable.getWriter();
     80    const reader = receiverTransform.readable.getReader();
     81
     82    senderTransform.readable.pipeTo(receiverTransform.writable);
     83
     84    const sent = new ArrayBuffer(8);
     85    const view = new Int8Array(sent);
     86    for (let cptr = 0; cptr < sent.byteLength; ++cptr)
     87        view[cptr] = cptr;
     88
     89    writer.write(sent);
     90    const received = await reader.read();
     91
     92    assert_equals(received.value.byteLength, 8);
     93    const view2 = new Int8Array(received.value);
     94    for (let cptr = 0; cptr < sent.byteLength; ++cptr)
     95        assert_equals(view2[cptr], view[cptr]);
     96}, "SFrame with array buffer - authentication size 10");
     97
     98promise_test(async (test) => {
     99    const key = await crypto.subtle.importKey("raw", new Uint8Array([143, 77, 43, 10, 72, 19, 37, 67, 236, 219, 24, 93, 26, 165, 91, 178]), "HKDF", false, ["deriveBits", "deriveKey"]);
     100
     101    const senderTransform = new RTCRtpSFrameTransform({ role : 'encrypt', authenticationSize: 10 });
     102    const senderWriter = senderTransform.writable.getWriter();
     103    const senderReader = senderTransform.readable.getReader();
     104
     105    const receiverTransform = new RTCRtpSFrameTransform({ role : 'decrypt', authenticationSize: 10 });
     106    const receiverWriter = receiverTransform.writable.getWriter();
     107    const receiverReader = receiverTransform.readable.getReader();
     108
     109    senderTransform.setEncryptionKey(key);
     110    receiverTransform.setEncryptionKey(key);
     111
     112    const chunk = new ArrayBuffer(8);
     113
     114    // decryption should fail, leading to an empty array buffer.
     115    await receiverWriter.write(chunk);
     116    let received = await receiverReader.read();
     117    assert_equals(received.value.byteLength, 0);
     118
     119    // We write again but this time with a chunk we can decrypt.
     120    await senderWriter.write(chunk);
     121    const encrypted = await senderReader.read();
     122    await receiverWriter.write(encrypted.value);
     123    received = await receiverReader.read();
     124    assert_equals(received.value.byteLength, 8);
     125}, "SFrame decryption with array buffer that is too small");
     126
     127promise_test(async (test) => {
     128    const key = await crypto.subtle.importKey("raw", new Uint8Array([143, 77, 43, 10, 72, 19, 37, 67, 236, 219, 24, 93, 26, 165, 91, 178]), "HKDF", false, ["deriveBits", "deriveKey"]);
     129
     130    const receiverTransform = new RTCRtpSFrameTransform({ role : 'decrypt', authenticationSize: 10 });
     131    const receiverWriter = receiverTransform.writable.getWriter();
     132    receiverTransform.setEncryptionKey(key);
     133
     134    // decryption should fail, leading to erroring the transform.
     135    await promise_rejects_js(test, TypeError, receiverWriter.write({ }));
     136    await promise_rejects_js(test, TypeError, receiverWriter.closed);
     137}, "SFrame transform gets errored if trying to process unexpected value types");
     138
    31139        </script>
    32140    </body>
  • trunk/Source/WebCore/ChangeLog

    r270288 r270290  
     12020-12-01  Youenn Fablet  <youenn@apple.com>
     2
     3        Add support for readable/writable to RTCRtpSFrameTransform
     4        https://bugs.webkit.org/show_bug.cgi?id=219298
     5
     6        Reviewed by Eric Carlson.
     7
     8        Add support for locking WritableStream and checking locked state.
     9        Add readable/writable getters so that RTCRtpSFrameTransform can be used as a TransformStream.
     10        Make a refactoring to allow reuse of SimpleReadableStreamSource and SimpleWritableStreamSink.
     11
     12        In case of encryption/decryption error, we do not error the transform as this is final.
     13        Instead, we output empty buffers.
     14        In case of trying to encrypt unexpected objects, we error the transform.
     15
     16        Move RTCRtpTransformableFrame to be ref counted.
     17        This allows to keep a RTCRtpTransformableFrame for each RTCEncodedFrame even though the underlying
     18        webrtc frame (which is a unique ptr) is given back to the webrtc backend after processing.
     19
     20        Covered by updated test.
     21
     22        * Modules/mediastream/RTCEncodedAudioFrame.cpp:
     23        (WebCore::RTCEncodedAudioFrame::RTCEncodedAudioFrame):
     24        * Modules/mediastream/RTCEncodedAudioFrame.h:
     25        (WebCore::RTCEncodedAudioFrame::create):
     26        * Modules/mediastream/RTCEncodedFrame.cpp:
     27        (WebCore::RTCEncodedFrame::RTCEncodedFrame):
     28        * Modules/mediastream/RTCEncodedFrame.h:
     29        (WebCore::RTCEncodedFrame::rtcFrame):
     30        * Modules/mediastream/RTCEncodedVideoFrame.cpp:
     31        (WebCore::RTCEncodedVideoFrame::RTCEncodedVideoFrame):
     32        * Modules/mediastream/RTCEncodedVideoFrame.h:
     33        (WebCore::RTCEncodedVideoFrame::create):
     34        * Modules/mediastream/RTCRtpSFrameTransform.cpp:
     35        (WebCore::RTCRtpSFrameTransform::RTCRtpSFrameTransform):
     36        (WebCore::RTCRtpSFrameTransform::isAttached const):
     37        (WebCore::RTCRtpSFrameTransform::initializeTransformer):
     38        (WebCore::RTCRtpSFrameTransform::willClearBackend):
     39        (WebCore::transformFrame):
     40        (WebCore::RTCRtpSFrameTransform::createStreams):
     41        (WebCore::RTCRtpSFrameTransform::readable):
     42        (WebCore::RTCRtpSFrameTransform::writable):
     43        * Modules/mediastream/RTCRtpSFrameTransform.h:
     44        (WebCore::RTCRtpSFrameTransform::create):
     45        * Modules/mediastream/RTCRtpSFrameTransform.idl:
     46        * Modules/mediastream/RTCRtpSFrameTransformer.cpp:
     47        (WebCore::RTCRtpSFrameTransformer::setEncryptionKey):
     48        (WebCore::RTCRtpSFrameTransformer::decryptFrame):
     49        (WebCore::RTCRtpSFrameTransformer::encryptFrame):
     50        (WebCore::RTCRtpSFrameTransformer::transform):
     51        (WebCore::RTCRtpSFrameTransformer::updateAuthenticationSize):
     52        * Modules/mediastream/RTCRtpSFrameTransformer.h:
     53        (WebCore::RTCRtpSFrameTransformer::setIsEncrypting):
     54        (WebCore::RTCRtpSFrameTransformer::setAuthenticationSize):
     55        * Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp:
     56        (WebCore::RTCRtpSFrameTransformer::updateAuthenticationSize):
     57        * Modules/mediastream/RTCRtpScriptTransformer.cpp:
     58        (WebCore::RTCRtpScriptTransformer::startStreams):
     59        * Modules/mediastream/RTCRtpScriptTransformer.h:
     60        * Modules/mediastream/RTCRtpTransformBackend.h:
     61        * Modules/mediastream/RTCRtpTransformableFrame.h:
     62        * Modules/mediastream/libwebrtc/LibWebRTCRtpSenderTransformBackend.cpp:
     63        * Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.cpp:
     64        (WebCore::LibWebRTCRtpTransformBackend::processTransformedFrame):
     65        (WebCore::LibWebRTCRtpTransformBackend::Transform):
     66        * Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.h:
     67        * Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.cpp: Added.
     68        * Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.h:
     69        * Modules/streams/ReadableStreamSource.h:
     70        (WebCore::SimpleReadableStreamSource::create):
     71        (WebCore::SimpleReadableStreamSource::close):
     72        (WebCore::SimpleReadableStreamSource::enqueue):
     73        * Modules/streams/WritableStreamSink.h:
     74        (WebCore::SimpleWritableStreamSink::create):
     75        (WebCore::SimpleWritableStreamSink::SimpleWritableStreamSink):
     76        (WebCore::SimpleWritableStreamSink::write):
     77        * bindings/js/WritableStream.cpp:
     78        (WebCore::WritableStreamInternal::callFunction):
     79        (WebCore::checkWritableStream):
     80        (WebCore::WritableStream::lock):
     81        (WebCore::WritableStream::isLocked const):
     82        * bindings/js/WritableStream.h:
     83        * bindings/scripts/CodeGeneratorJS.pm:
     84        (AddToIncludesForIDLType):
     85
    1862020-12-01  Sergio Villar Senin  <svillar@igalia.com>
    287
  • trunk/Source/WebCore/Modules/mediastream/RTCEncodedAudioFrame.cpp

    r270107 r270290  
    3131namespace WebCore {
    3232
    33 RTCEncodedAudioFrame::RTCEncodedAudioFrame(UniqueRef<RTCRtpTransformableFrame>&& frame)
     33RTCEncodedAudioFrame::RTCEncodedAudioFrame(Ref<RTCRtpTransformableFrame>&& frame)
    3434    : RTCEncodedFrame(WTFMove(frame))
    3535{
  • trunk/Source/WebCore/Modules/mediastream/RTCEncodedAudioFrame.h

    r270107 r270290  
    3434class RTCEncodedAudioFrame : public RTCEncodedFrame {
    3535public:
    36     static Ref<RTCEncodedAudioFrame> create(UniqueRef<RTCRtpTransformableFrame>&& frame) { return adoptRef(*new RTCEncodedAudioFrame(WTFMove(frame))); }
     36    static Ref<RTCEncodedAudioFrame> create(Ref<RTCRtpTransformableFrame>&& frame) { return adoptRef(*new RTCEncodedAudioFrame(WTFMove(frame))); }
    3737    ~RTCEncodedAudioFrame();
    3838
    3939private:
    40     explicit RTCEncodedAudioFrame(UniqueRef<RTCRtpTransformableFrame>&&);
     40    explicit RTCEncodedAudioFrame(Ref<RTCRtpTransformableFrame>&&);
    4141};
    4242
  • trunk/Source/WebCore/Modules/mediastream/RTCEncodedFrame.cpp

    r270107 r270290  
    3434namespace WebCore {
    3535
    36 RTCEncodedFrame::RTCEncodedFrame(UniqueRef<RTCRtpTransformableFrame>&& frame)
     36RTCEncodedFrame::RTCEncodedFrame(Ref<RTCRtpTransformableFrame>&& frame)
    3737    : m_frame(WTFMove(frame))
    3838{
  • trunk/Source/WebCore/Modules/mediastream/RTCEncodedFrame.h

    r270107 r270290  
    4444    void setData(JSC::ArrayBuffer&);
    4545
    46     UniqueRef<RTCRtpTransformableFrame> takeRTCFrame() { return WTFMove(m_frame); }
     46    RTCRtpTransformableFrame& rtcFrame() { return m_frame.get(); }
    4747
    4848protected:
    49     explicit RTCEncodedFrame(UniqueRef<RTCRtpTransformableFrame>&&);
     49    explicit RTCEncodedFrame(Ref<RTCRtpTransformableFrame>&&);
    5050
    51     UniqueRef<RTCRtpTransformableFrame> m_frame;
     51    Ref<RTCRtpTransformableFrame> m_frame;
    5252};
    5353
  • trunk/Source/WebCore/Modules/mediastream/RTCEncodedVideoFrame.cpp

    r270107 r270290  
    3131namespace WebCore {
    3232
    33 RTCEncodedVideoFrame::RTCEncodedVideoFrame(UniqueRef<RTCRtpTransformableFrame>&& frame)
     33RTCEncodedVideoFrame::RTCEncodedVideoFrame(Ref<RTCRtpTransformableFrame>&& frame)
    3434    : RTCEncodedFrame(WTFMove(frame))
    3535{
  • trunk/Source/WebCore/Modules/mediastream/RTCEncodedVideoFrame.h

    r270107 r270290  
    3434class RTCEncodedVideoFrame : public RTCEncodedFrame {
    3535public:
    36     static Ref<RTCEncodedVideoFrame> create(UniqueRef<RTCRtpTransformableFrame>&& frame) { return adoptRef(*new RTCEncodedVideoFrame(WTFMove(frame))); }
     36    static Ref<RTCEncodedVideoFrame> create(Ref<RTCRtpTransformableFrame>&& frame) { return adoptRef(*new RTCEncodedVideoFrame(WTFMove(frame))); }
    3737    ~RTCEncodedVideoFrame();
    3838
    3939private:
    40     explicit RTCEncodedVideoFrame(UniqueRef<RTCRtpTransformableFrame>&&);
     40    explicit RTCEncodedVideoFrame(Ref<RTCRtpTransformableFrame>&&);
    4141};
    4242
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp

    r270107 r270290  
    3030
    3131#include "CryptoKeyRaw.h"
     32#include "JSDOMConvertBufferSource.h"
    3233#include "Logging.h"
     34#include "RTCEncodedAudioFrame.h"
     35#include "RTCEncodedVideoFrame.h"
    3336#include "RTCRtpSFrameTransformer.h"
    3437#include "RTCRtpTransformBackend.h"
    3538#include "RTCRtpTransformableFrame.h"
     39#include "ReadableStream.h"
     40#include "ReadableStreamSource.h"
     41#include "SharedBuffer.h"
     42#include "WritableStream.h"
     43#include "WritableStreamSink.h"
    3644
    3745namespace WebCore {
    3846
    39 RTCRtpSFrameTransform::RTCRtpSFrameTransform()
    40     : m_transformer(RTCRtpSFrameTransformer::create())
    41 {
     47RTCRtpSFrameTransform::RTCRtpSFrameTransform(ScriptExecutionContext& context, Options options)
     48    : ContextDestructionObserver(&context)
     49    , m_transformer(RTCRtpSFrameTransformer::create())
     50{
     51    m_transformer->setIsEncrypting(options.role == Role::Encrypt);
     52    m_transformer->setAuthenticationSize(options.authenticationSize);
    4253}
    4354
     
    6879}
    6980
     81bool RTCRtpSFrameTransform::isAttached() const
     82{
     83    return m_isAttached || (m_readable && m_readable->isLocked()) || (m_writable && m_writable->isLocked());
     84}
     85
    7086void RTCRtpSFrameTransform::initializeTransformer(RTCRtpTransformBackend& backend, Side side)
    7187{
     88    ASSERT(!isAttached());
     89
    7290    m_isAttached = true;
    73     m_transformer->setIsSending(side == Side::Sender);
    74     m_transformer->setIsProcessingAudio(backend.mediaType() == RTCRtpTransformBackend::MediaType::Audio);
     91    if (m_readable)
     92        m_readable->lock();
     93    if (m_writable)
     94        m_writable->lock();
     95
     96    m_transformer->setIsEncrypting(side == Side::Sender);
     97    m_transformer->setAuthenticationSize(backend.mediaType() == RTCRtpTransformBackend::MediaType::Audio ? 4 : 10);
    7598
    7699    backend.setTransformableFrameCallback([transformer = m_transformer, backend = makeRef(backend)](auto&& frame) {
     
    85108        frame->setData({ result.returnValue().data(), result.returnValue().size() });
    86109
    87         backend->processTransformedFrame(WTFMove(frame.get()));
     110        backend->processTransformedFrame(frame.get());
    88111    });
    89112}
    90113
    91 
    92114void RTCRtpSFrameTransform::initializeBackendForReceiver(RTCRtpTransformBackend& backend)
    93115{
     
    103125{
    104126    backend.clearTransformableFrameCallback();
    105     m_isAttached = false;
     127}
     128
     129template<typename Frame>
     130void transformFrame(Frame& frame, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source)
     131{
     132    auto chunk = frame.rtcFrame().data();
     133    auto result = transformer.transform(chunk.data, chunk.size);
     134    RELEASE_LOG_ERROR_IF(result.hasException(), WebRTC, "RTCRtpSFrameTransform failed transforming a frame");
     135
     136    RTCRtpTransformableFrame::Data transformedChunk;
     137    // In case of error, we just pass along the frame with empty data.
     138    if (!result.hasException())
     139        transformedChunk = { result.returnValue().data(), result.returnValue().size() };
     140
     141    frame.rtcFrame().setData(transformedChunk);
     142    source.enqueue(toJS(&globalObject, &globalObject, frame));
     143}
     144
     145template<>
     146void transformFrame(JSC::ArrayBuffer& value, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source)
     147{
     148    auto result = transformer.transform(static_cast<const uint8_t*>(value.data()), value.byteLength());
     149    RELEASE_LOG_ERROR_IF(result.hasException(), WebRTC, "RTCRtpSFrameTransform failed transforming a frame");
     150
     151    auto buffer = result.hasException() ? SharedBuffer::create() : SharedBuffer::create(result.returnValue().data(), result.returnValue().size());
     152    source.enqueue(toJS(&globalObject, &globalObject, buffer->tryCreateArrayBuffer().get()));
     153}
     154
     155void RTCRtpSFrameTransform::createStreams()
     156{
     157    auto& globalObject = *scriptExecutionContext()->globalObject();
     158
     159    m_readableStreamSource = SimpleReadableStreamSource::create();
     160    auto readable = ReadableStream::create(globalObject, m_readableStreamSource.copyRef());
     161    if (readable.hasException())
     162        return;
     163
     164    auto writable = WritableStream::create(globalObject, SimpleWritableStreamSink::create([transformer = m_transformer, readableStreamSource = m_readableStreamSource](auto& context, auto value) -> ExceptionOr<void> {
     165        auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(context.globalObject());
     166        auto scope = DECLARE_THROW_SCOPE(globalObject.vm());
     167
     168        auto frame = convert<IDLUnion<IDLArrayBuffer, IDLInterface<RTCEncodedAudioFrame>, IDLInterface<RTCEncodedVideoFrame>>>(globalObject, value);
     169        if (scope.exception())
     170            return Exception { ExistingExceptionError };
     171
     172        // We do not want to throw any exception in the transform to make sure we do not error the transform.
     173        WTF::switchOn(frame, [&](RefPtr<RTCEncodedAudioFrame>& value) {
     174            transformFrame(*value, globalObject, transformer.get(), *readableStreamSource);
     175        }, [&](RefPtr<RTCEncodedVideoFrame>& value) {
     176            transformFrame(*value, globalObject, transformer.get(), *readableStreamSource);
     177        }, [&](RefPtr<ArrayBuffer>& value) {
     178            transformFrame(*value, globalObject, transformer.get(), *readableStreamSource);
     179        });
     180        return { };
     181    }));
     182    if (writable.hasException())
     183        return;
     184
     185    m_readable = readable.releaseReturnValue();
     186    m_writable = writable.releaseReturnValue();
     187    if (m_isAttached) {
     188        m_readable->lock();
     189        m_writable->lock();
     190    }
     191}
     192
     193ExceptionOr<RefPtr<ReadableStream>> RTCRtpSFrameTransform::readable()
     194{
     195    auto* context = scriptExecutionContext();
     196    if (!context)
     197        return Exception { InvalidStateError };
     198
     199    if (!m_readable)
     200        createStreams();
     201
     202    return m_readable.copyRef();
     203}
     204
     205ExceptionOr<RefPtr<WritableStream>> RTCRtpSFrameTransform::writable()
     206{
     207    auto* context = scriptExecutionContext();
     208    if (!context)
     209        return Exception { InvalidStateError };
     210
     211    if (!m_writable)
     212        createStreams();
     213
     214    return m_writable.copyRef();
    106215}
    107216
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h

    r270107 r270290  
    2828#if ENABLE(WEB_RTC)
    2929
     30#include "ContextDestructionObserver.h"
    3031#include "JSDOMPromiseDeferred.h"
    3132
     
    3536class RTCRtpSFrameTransformer;
    3637class RTCRtpTransformBackend;
     38class ReadableStream;
     39class SimpleReadableStreamSource;
     40class WritableStream;
    3741
    38 class RTCRtpSFrameTransform : public RefCounted<RTCRtpSFrameTransform> {
     42class RTCRtpSFrameTransform : public RefCounted<RTCRtpSFrameTransform>, private ContextDestructionObserver {
    3943public:
    40     static Ref<RTCRtpSFrameTransform> create() { return adoptRef(*new RTCRtpSFrameTransform); }
     44    enum class Role { Encrypt, Decrypt };
     45    struct Options {
     46        Role role { Role::Encrypt };
     47        uint64_t authenticationSize { 10 };
     48    };
     49
     50    static Ref<RTCRtpSFrameTransform> create(ScriptExecutionContext& context, Options options) { return adoptRef(*new RTCRtpSFrameTransform(context, options)); }
    4151    ~RTCRtpSFrameTransform();
    4252
    4353    void setEncryptionKey(CryptoKey&, Optional<uint64_t>, DOMPromiseDeferred<void>&&);
    4454
    45     bool isAttached() const { return m_isAttached; }
     55    bool isAttached() const;
    4656    void initializeBackendForReceiver(RTCRtpTransformBackend&);
    4757    void initializeBackendForSender(RTCRtpTransformBackend&);
     
    5060    WEBCORE_EXPORT uint64_t counterForTesting() const;
    5161
     62    ExceptionOr<RefPtr<ReadableStream>> readable();
     63    ExceptionOr<RefPtr<WritableStream>> writable();
     64
    5265private:
    53     RTCRtpSFrameTransform();
     66    RTCRtpSFrameTransform(ScriptExecutionContext&, Options);
    5467
    5568    enum class Side { Sender, Receiver };
    5669    void initializeTransformer(RTCRtpTransformBackend&, Side);
     70    void createStreams();
    5771
    5872    bool m_isAttached { false };
    5973    Ref<RTCRtpSFrameTransformer> m_transformer;
     74    RefPtr<ReadableStream> m_readable;
     75    RefPtr<WritableStream> m_writable;
     76    RefPtr<SimpleReadableStreamSource> m_readableStreamSource;
    6077};
    6178
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl

    r270107 r270290  
    2424 */
    2525
     26enum RTCRtpSFrameTransformRole {
     27    "encrypt",
     28    "decrypt"
     29};
     30
     31dictionary RTCRtpSFrameTransformOptions {
     32    RTCRtpSFrameTransformRole role = "encrypt";
     33    unsigned long authenticationSize = 10;
     34};
     35
    2636[
    2737    Conditional=WEB_RTC,
     
    2939    ExportMacro=WEBCORE_EXPORT,
    3040    Exposed=Window,
    31     ImplementationLacksVTable,
    3241    JSGenerateToNativeObject,
    3342] interface RTCRtpSFrameTransform {
    34     constructor();
     43    [CallWith=ScriptExecutionContext] constructor(optional RTCRtpSFrameTransformOptions options);
    3544
    3645    Promise<undefined> setEncryptionKey(CryptoKey key, optional unsigned long long keyID);
     
    3847    // Promise<undefined> ratchetEncryptionKey();
    3948    // Promise<undefined> setSigningKey(CryptoKey key);
     49
     50    [MayThrowException] readonly attribute ReadableStream readable;
     51    [MayThrowException] readonly attribute WritableStream writable;
    4052};
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp

    r269830 r270290  
    168168        m_keyId = *keyId;
    169169
     170    updateAuthenticationSize();
    170171    m_hasKey = true;
     172
    171173    return { };
    172174}
     
    174176ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::decryptFrame(const uint8_t* frameData, size_t frameSize)
    175177{
    176     // FIXME: Support signature.
    177 
    178178    auto locker = holdLock(m_keyLock);
    179179
     
    191191        return Exception { NotSupportedError };
    192192    }
     193
     194    if (frameSize < (header->size + m_authenticationSize))
     195        return Exception { DataError, "Chunk is too small for authentication size" };
    193196
    194197    // Compute signature
     
    215218ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::encryptFrame(const uint8_t* frameData, size_t frameSize)
    216219{
    217     // FIXME: Support signature.
    218 
    219220    static const unsigned MaxHeaderSize = 17;
    220221
     
    260261{
    261262    if (!m_hasKey)
    262         return Exception { InvalidStateError };
    263 
    264     return m_isSending ? encryptFrame(data, size) : decryptFrame(data, size);
     263        return Exception { InvalidStateError, "Key is not initialized"_s };
     264
     265    return m_isEncrypting ? encryptFrame(data, size) : decryptFrame(data, size);
    265266}
    266267
     
    295296    return { };
    296297}
     298
     299void RTCRtpSFrameTransformer::updateAuthenticationSize()
     300{
     301}
    297302#endif // !PLATFORM(COCOA)
    298303
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h

    r269830 r270290  
    4141    WEBCORE_EXPORT ~RTCRtpSFrameTransformer();
    4242
    43     void setIsSending(bool);
    44     void setIsProcessingAudio(bool);
     43    void setIsEncrypting(bool);
     44    void setAuthenticationSize(uint64_t);
    4545
    4646    WEBCORE_EXPORT ExceptionOr<void> setEncryptionKey(const Vector<uint8_t>& rawKey, Optional<uint64_t>);
     
    6767    ExceptionOr<Vector<uint8_t>> decryptData(const uint8_t*, size_t, const Vector<uint8_t>& iv, const Vector<uint8_t>& key);
    6868    Vector<uint8_t> computeEncryptedDataSignature(const uint8_t*, size_t, const Vector<uint8_t>& key);
     69    void updateAuthenticationSize();
    6970
    7071    Lock m_keyLock;
     
    7475    Vector<uint8_t> m_saltKey;
    7576
    76     bool m_isSending { false };
     77    bool m_isEncrypting { false };
    7778    uint64_t m_authenticationSize { 10 };
    7879    uint64_t m_keyId { 0 };
     
    8081};
    8182
    82 inline void RTCRtpSFrameTransformer::setIsSending(bool isSending)
     83inline void RTCRtpSFrameTransformer::setIsEncrypting(bool isEncrypting)
    8384{
    84     m_isSending = isSending;
     85    m_isEncrypting = isEncrypting;
    8586}
    8687
    87 inline void RTCRtpSFrameTransformer::setIsProcessingAudio(bool isProcessingAudio)
     88inline void RTCRtpSFrameTransformer::setAuthenticationSize(uint64_t size)
    8889{
    89     m_authenticationSize = isProcessingAudio ? 4 : 10;
     90    m_authenticationSize = size;
    9091}
    9192
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp

    r269830 r270290  
    6969}
    7070
     71void RTCRtpSFrameTransformer::updateAuthenticationSize()
     72{
     73    if (m_authenticationSize > CC_SHA256_DIGEST_LENGTH)
     74        m_authenticationSize = CC_SHA256_DIGEST_LENGTH;
     75}
     76
    7177} // namespace WebCore
    7278
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpScriptTransformer.cpp

    r270107 r270290  
    4141namespace WebCore {
    4242
    43 class RTCRtpReadableStreamSource
    44     : public ReadableStreamSource
    45     , public CanMakeWeakPtr<RTCRtpReadableStreamSource> {
    46 public:
    47     static Ref<RTCRtpReadableStreamSource> create() { return adoptRef(*new RTCRtpReadableStreamSource); }
    48 
    49     void close() { controller().close(); }
    50     void enqueue(JSC::JSValue value) { controller().enqueue(value); }
    51 
    52 private:
    53     RTCRtpReadableStreamSource() = default;
    54 
    55     // ReadableStreamSource
    56     void setActive() final { }
    57     void setInactive() final { }
    58     void doStart() final { }
    59     void doPull() final { }
    60     void doCancel() final { }
    61 };
    62 
    63 class RTCRtpWritableStreamSink : public WritableStreamSink {
    64 public:
    65     static Ref<RTCRtpWritableStreamSink> create(Function<void(UniqueRef<RTCRtpTransformableFrame>&&)>&& enqueueFunction) { return adoptRef(*new RTCRtpWritableStreamSink(WTFMove(enqueueFunction))); }
    66 
    67 private:
    68     explicit RTCRtpWritableStreamSink(Function<void(UniqueRef<RTCRtpTransformableFrame>&&)>&& enqueueFunction)
    69         : m_enqueueFunction(WTFMove(enqueueFunction))
    70     {
    71     }
    72 
    73     void write(ScriptExecutionContext& context, JSC::JSValue value, DOMPromiseDeferred<void>&& promise)
    74     {
    75         auto& globalObject = *context.globalObject();
    76 
    77         auto scope = DECLARE_THROW_SCOPE(globalObject.vm());
    78         auto frame = convert<IDLUnion<IDLInterface<RTCEncodedAudioFrame>, IDLInterface<RTCEncodedVideoFrame>>>(globalObject, value);
    79 
    80         if (scope.exception()) {
    81             promise.reject(Exception { ExistingExceptionError }, RejectAsHandled::Yes);
    82             return;
    83         }
    84 
    85         WTF::switchOn(frame, [&](RefPtr<RTCEncodedAudioFrame>& value) {
    86             m_enqueueFunction(value->takeRTCFrame());
    87         }, [&](RefPtr<RTCEncodedVideoFrame>& value) {
    88             m_enqueueFunction(value->takeRTCFrame());
    89         });
    90         promise.resolve();
    91     }
    92 
    93     // FIXME: Decide whether clearing all pending frames.
    94     void close() final { }
    95     void error(String&&) final { }
    96 
    97     Function<void(UniqueRef<RTCRtpTransformableFrame>&&)> m_enqueueFunction;
    98 };
    99 
    10043ExceptionOr<Ref<RTCRtpScriptTransformer>> RTCRtpScriptTransformer::create(ScriptExecutionContext& context)
    10144{
     
    11962}
    12063
    121 RefPtr<RTCRtpReadableStreamSource> RTCRtpScriptTransformer::startStreams(RTCRtpTransformBackend& backend)
     64RefPtr<SimpleReadableStreamSource> RTCRtpScriptTransformer::startStreams(RTCRtpTransformBackend& backend)
    12265{
    12366    auto callback = WTFMove(m_callback);
     
    13174    JSC::JSLockHolder lock(vm);
    13275
    133     auto readableStreamSource = RTCRtpReadableStreamSource::create();
     76    auto readableStreamSource = SimpleReadableStreamSource::create();
    13477    auto readableStream = ReadableStream::create(globalObject, readableStreamSource.copyRef());
    13578    if (readableStream.hasException())
    13679        return nullptr;
    13780
    138     auto writableStream = WritableStream::create(globalObject, RTCRtpWritableStreamSink::create([backend = makeRef(backend)](auto&& frame) {
    139         backend->processTransformedFrame(WTFMove(frame.get()));
     81    auto writableStream = WritableStream::create(globalObject, SimpleWritableStreamSink::create([backend = makeRef(backend)](auto& context, auto value) -> ExceptionOr<void> {
     82        auto& globalObject = *context.globalObject();
     83
     84        auto scope = DECLARE_THROW_SCOPE(globalObject.vm());
     85        auto frame = convert<IDLUnion<IDLInterface<RTCEncodedAudioFrame>, IDLInterface<RTCEncodedVideoFrame>>>(globalObject, value);
     86
     87        if (scope.exception())
     88            return Exception { ExistingExceptionError };
     89
     90        auto rtcFrame = WTF::switchOn(frame, [&](RefPtr<RTCEncodedAudioFrame>& value) {
     91            return makeRef(value->rtcFrame());
     92        }, [&](RefPtr<RTCEncodedVideoFrame>& value) {
     93            return makeRef(value->rtcFrame());
     94        });
     95        backend->processTransformedFrame(rtcFrame.get());
     96        return { };
    14097    }));
    14198    if (writableStream.hasException())
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpScriptTransformer.h

    r270107 r270290  
    3939class ScriptExecutionContext;
    4040class RTCRtpTransformBackend;
    41 class RTCRtpReadableStreamSource;
     41class SimpleReadableStreamSource;
    4242
    4343class RTCRtpScriptTransformer
     
    6060    RTCRtpScriptTransformer(ScriptExecutionContext&, Ref<MessagePort>&&);
    6161
    62     RefPtr<RTCRtpReadableStreamSource> startStreams(RTCRtpTransformBackend&);
     62    RefPtr<SimpleReadableStreamSource> startStreams(RTCRtpTransformBackend&);
    6363
    6464    // ActiveDOMObject
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpTransformBackend.h

    r270107 r270290  
    3737    virtual ~RTCRtpTransformBackend() = default;
    3838
    39     using Callback = Function<void(UniqueRef<RTCRtpTransformableFrame>&&)>;
     39    using Callback = Function<void(Ref<RTCRtpTransformableFrame>&&)>;
    4040    virtual void setTransformableFrameCallback(Callback&&) = 0;
    4141    virtual void clearTransformableFrameCallback() = 0;
    42     virtual void processTransformedFrame(RTCRtpTransformableFrame&&) = 0;
     42    virtual void processTransformedFrame(RTCRtpTransformableFrame&) = 0;
    4343
    4444    enum class MediaType { Audio, Video };
    4545    virtual MediaType mediaType() const = 0;
    4646
    47     enum class Side { Sender, Receiver };
     47    enum class Side { Receiver, Sender };
    4848    virtual Side side() const = 0;
    4949};
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpTransformableFrame.h

    r270107 r270290  
    2727#if ENABLE(WEB_RTC)
    2828
     29#include <wtf/RefCounted.h>
     30
    2931namespace WebCore {
    3032
    31 class RTCRtpTransformableFrame {
    32     WTF_MAKE_FAST_ALLOCATED;
     33class RTCRtpTransformableFrame : public RefCounted<RTCRtpTransformableFrame> {
    3334public:
    3435    virtual ~RTCRtpTransformableFrame() = default;
    3536
    3637    struct Data {
    37         const uint8_t* data;
    38         size_t size;
     38        const uint8_t* data { nullptr };
     39        size_t size { 0 };
    3940    };
    4041    virtual Data data() const = 0;
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpSenderTransformBackend.cpp

    r269764 r270290  
    5353}
    5454
    55 
    5655} // namespace WebCore
    5756
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.cpp

    r270107 r270290  
    2929
    3030#include "LibWebRTCRtpTransformableFrame.h"
    31 #include <wtf/UniqueRef.h>
    3231
    3332namespace WebCore {
     
    5049}
    5150
    52 void LibWebRTCRtpTransformBackend::processTransformedFrame(RTCRtpTransformableFrame&& frame)
     51void LibWebRTCRtpTransformBackend::processTransformedFrame(RTCRtpTransformableFrame& frame)
    5352{
    5453    auto locker = holdLock(m_outputCallbackLock);
    5554    if (m_outputCallback)
    56         m_outputCallback->OnTransformedFrame(LibWebRTCRtpTransformableFrame::toRTCFrame(WTFMove(static_cast<LibWebRTCRtpTransformableFrame&>(frame))));
     55        m_outputCallback->OnTransformedFrame(static_cast<LibWebRTCRtpTransformableFrame&>(frame).takeRTCFrame());
    5756}
    5857
     
    6261        auto locker = holdLock(m_inputCallbackLock);
    6362        if (m_inputCallback) {
    64             m_inputCallback(makeUniqueRef<LibWebRTCRtpTransformableFrame>(WTFMove(rtcFrame)));
     63            m_inputCallback(LibWebRTCRtpTransformableFrame::create(WTFMove(rtcFrame)));
    6564            return;
    6665        }
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.h

    r269764 r270290  
    4747    void setInputCallback(Callback&&);
    4848
     49protected:
     50    MediaType mediaType() const final { return m_mediaType; }
     51
    4952private:
    5053    void setOutputCallback(rtc::scoped_refptr<webrtc::TransformedFrameCallback>&&);
    5154
    5255    // RTCRtpTransformBackend
    53     void processTransformedFrame(RTCRtpTransformableFrame&&) final;
     56    void processTransformedFrame(RTCRtpTransformableFrame&) final;
    5457    void clearTransformableFrameCallback() final;
    55     MediaType mediaType() const final { return m_mediaType; }
    5658    Side side() const final { return m_side; }
    5759
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.cpp

    r270289 r270290  
    2424
    2525#include "config.h"
    26 #include "LibWebRTCRtpSenderTransformBackend.h"
     26#include "LibWebRTCRtpTransformableFrame.h"
    2727
    2828#if ENABLE(WEB_RTC) && USE(LIBWEBRTC)
    2929
    30 #include "LibWebRTCRtpTransformableFrame.h"
     30ALLOW_UNUSED_PARAMETERS_BEGIN
     31ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     32
     33#include <webrtc/api/frame_transformer_interface.h>
     34
     35ALLOW_DEPRECATED_DECLARATIONS_END
     36ALLOW_UNUSED_PARAMETERS_END
    3137
    3238namespace WebCore {
    3339
    34 static inline LibWebRTCRtpSenderTransformBackend::MediaType mediaTypeFromSender(const webrtc::RtpSenderInterface& sender)
    35 {
    36     return sender.media_type() == cricket::MEDIA_TYPE_AUDIO ? RTCRtpTransformBackend::MediaType::Audio : RTCRtpTransformBackend::MediaType::Video;
    37 }
    38 
    39 LibWebRTCRtpSenderTransformBackend::LibWebRTCRtpSenderTransformBackend(rtc::scoped_refptr<webrtc::RtpSenderInterface> rtcSender)
    40     : LibWebRTCRtpTransformBackend(mediaTypeFromSender(*rtcSender), Side::Sender)
    41     , m_rtcSender(WTFMove(rtcSender))
     40LibWebRTCRtpTransformableFrame::LibWebRTCRtpTransformableFrame(std::unique_ptr<webrtc::TransformableFrameInterface>&& frame)
     41    : m_rtcFrame(WTFMove(frame))
    4242{
    4343}
    4444
    45 LibWebRTCRtpSenderTransformBackend::~LibWebRTCRtpSenderTransformBackend()
     45LibWebRTCRtpTransformableFrame::~LibWebRTCRtpTransformableFrame()
    4646{
    4747}
    4848
    49 void LibWebRTCRtpSenderTransformBackend::setTransformableFrameCallback(Callback&& callback)
     49std::unique_ptr<webrtc::TransformableFrameInterface> LibWebRTCRtpTransformableFrame::takeRTCFrame()
    5050{
    51     setInputCallback(WTFMove(callback));
    52     m_rtcSender->SetEncoderToPacketizerFrameTransformer(this);
     51    return WTFMove(m_rtcFrame);
    5352}
    5453
     54RTCRtpTransformableFrame::Data LibWebRTCRtpTransformableFrame::data() const
     55{
     56    if (!m_rtcFrame)
     57        return { nullptr, 0 };
     58    auto data = m_rtcFrame->GetData();
     59    return { data.begin(), data.size() };
     60}
     61
     62void LibWebRTCRtpTransformableFrame::setData(Data data)
     63{
     64    if (m_rtcFrame)
     65        m_rtcFrame->SetData({ data.data, data.size });
     66}
    5567
    5668} // namespace WebCore
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.h

    r269764 r270290  
    2828
    2929#include "RTCRtpTransformableFrame.h"
     30#include <wtf/Ref.h>
     31
     32namespace webrtc {
     33class TransformableFrameInterface;
     34}
    3035
    3136namespace WebCore {
     
    3439    WTF_MAKE_FAST_ALLOCATED;
    3540public:
    36     explicit LibWebRTCRtpTransformableFrame(std::unique_ptr<webrtc::TransformableFrameInterface>&&);
    37     virtual ~LibWebRTCRtpTransformableFrame() = default;
     41    static Ref<LibWebRTCRtpTransformableFrame> create(std::unique_ptr<webrtc::TransformableFrameInterface>&& frame) { return adoptRef(*new LibWebRTCRtpTransformableFrame(WTFMove(frame))); }
     42    ~LibWebRTCRtpTransformableFrame();
    3843
    39     static std::unique_ptr<webrtc::TransformableFrameInterface> toRTCFrame(LibWebRTCRtpTransformableFrame&&);
     44    std::unique_ptr<webrtc::TransformableFrameInterface> takeRTCFrame();
    4045
    4146private:
     47    explicit LibWebRTCRtpTransformableFrame(std::unique_ptr<webrtc::TransformableFrameInterface>&&);
     48
    4249    Data data() const final;
    43     void setData(Data data) final { m_rtcFrame->SetData({ data.data, data.size }); }
     50    void setData(Data) final;
    4451
    4552    std::unique_ptr<webrtc::TransformableFrameInterface> m_rtcFrame;
    4653};
    4754
    48 inline LibWebRTCRtpTransformableFrame::LibWebRTCRtpTransformableFrame(std::unique_ptr<webrtc::TransformableFrameInterface>&& frame)
    49     : m_rtcFrame(WTFMove(frame))
    50 {
    51 }
    52 
    53 inline std::unique_ptr<webrtc::TransformableFrameInterface> LibWebRTCRtpTransformableFrame::toRTCFrame(LibWebRTCRtpTransformableFrame&& frame)
    54 {
    55     return WTFMove(frame.m_rtcFrame);
    56 }
    57 
    58 inline RTCRtpTransformableFrame::Data LibWebRTCRtpTransformableFrame::data() const
    59 {
    60     auto data = m_rtcFrame->GetData();
    61     return { data.begin(), data.size() };
    62 }
    63 
    6455} // namespace WebCore
    6556
  • trunk/Source/WebCore/Modules/streams/ReadableStreamSource.cpp

    r263700 r270290  
    2727#include "config.h"
    2828#include "ReadableStreamSource.h"
    29 
    30 #include "JSDOMPromiseDeferred.h"
    3129
    3230namespace WebCore {
  • trunk/Source/WebCore/Modules/streams/ReadableStreamSource.h

    r263700 r270290  
    2929#pragma once
    3030
     31#include "JSDOMPromiseDeferred.h"
    3132#include "ReadableStreamDefaultController.h"
    3233#include <wtf/Optional.h>
     34#include <wtf/WeakPtr.h>
    3335
    3436namespace WebCore {
    35 
    36 template<typename IDLType> class DOMPromiseDeferred;
    3737
    3838class ReadableStreamSource : public RefCounted<ReadableStreamSource> {
     
    6767};
    6868
     69class SimpleReadableStreamSource
     70    : public ReadableStreamSource
     71    , public CanMakeWeakPtr<SimpleReadableStreamSource> {
     72public:
     73    static Ref<SimpleReadableStreamSource> create() { return adoptRef(*new SimpleReadableStreamSource); }
     74
     75    void close() { controller().close(); }
     76    void enqueue(JSC::JSValue value) { controller().enqueue(value); }
     77
     78private:
     79    SimpleReadableStreamSource() = default;
     80
     81    // ReadableStreamSource
     82    void setActive() final { }
     83    void setInactive() final { }
     84    void doStart() final { }
     85    void doPull() final { }
     86    void doCancel() final { }
     87};
     88
    6989} // namespace WebCore
  • trunk/Source/WebCore/Modules/streams/WritableStreamSink.h

    r270107 r270290  
    4646};
    4747
     48class SimpleWritableStreamSink : public WritableStreamSink {
     49public:
     50    using WriteCallback = Function<ExceptionOr<void>(ScriptExecutionContext&, JSC::JSValue)>;
     51    static Ref<SimpleWritableStreamSink> create(WriteCallback&& writeCallback) { return adoptRef(*new SimpleWritableStreamSink(WTFMove(writeCallback))); }
     52
     53private:
     54    explicit SimpleWritableStreamSink(WriteCallback&&);
     55
     56    void write(ScriptExecutionContext&, JSC::JSValue, DOMPromiseDeferred<void>&&) final;
     57    void close() final { }
     58    void error(String&&) final { }
     59
     60    WriteCallback m_writeCallback;
     61};
     62
     63inline SimpleWritableStreamSink::SimpleWritableStreamSink(WriteCallback&& writeCallback)
     64    : m_writeCallback(WTFMove(writeCallback))
     65{
     66}
     67
     68inline void SimpleWritableStreamSink::write(ScriptExecutionContext& context, JSC::JSValue value, DOMPromiseDeferred<void>&& promise)
     69{
     70    promise.settle(m_writeCallback(context, value));
     71}
     72
    4873} // namespace WebCore
  • trunk/Source/WebCore/Sources.txt

    r270257 r270290  
    183183Modules/mediastream/libwebrtc/LibWebRTCRtpSenderTransformBackend.cpp
    184184Modules/mediastream/libwebrtc/LibWebRTCRtpTransformBackend.cpp
     185Modules/mediastream/libwebrtc/LibWebRTCRtpTransformableFrame.cpp
    185186Modules/model-element/HTMLModelElement.cpp
    186187Modules/notifications/Notification.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r270257 r270290  
    75387538                410A8EF924F8F47B004F9070 /* TextEncoderStreamEncoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextEncoderStreamEncoder.h; sourceTree = "<group>"; };
    75397539                410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMessageEventCustom.cpp; sourceTree = "<group>"; };
     7540                410BA1312570FE57002E2F8A /* LibWebRTCRtpTransformableFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCRtpTransformableFrame.cpp; path = libwebrtc/LibWebRTCRtpTransformableFrame.cpp; sourceTree = "<group>"; };
    75407541                410E445F234373AD000173D4 /* LibWebRTCSocketIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCSocketIdentifier.h; path = libwebrtc/LibWebRTCSocketIdentifier.h; sourceTree = "<group>"; };
    75417542                410F565524FCF70500A2E50C /* RTCSessionDescriptionInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCSessionDescriptionInit.idl; sourceTree = "<group>"; };
     
    1928619287                                4186BD4D2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp */,
    1928719288                                4186BD4B2140A8050001826F /* LibWebRTCRtpTransceiverBackend.h */,
     19289                                410BA1312570FE57002E2F8A /* LibWebRTCRtpTransformableFrame.cpp */,
    1928819290                                4181C5CC2555836800AEB0FF /* LibWebRTCRtpTransformableFrame.h */,
    1928919291                                4181C5CE2555895500AEB0FF /* LibWebRTCRtpTransformBackend.cpp */,
  • trunk/Source/WebCore/bindings/js/WritableStream.cpp

    r270107 r270290  
    3737using namespace JSC;
    3838
     39namespace WritableStreamInternal {
     40static inline JSC::JSValue callFunction(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue jsFunction, JSC::JSValue thisValue, const JSC::ArgList& arguments)
     41{
     42    VM& vm = lexicalGlobalObject.vm();
     43    auto scope = DECLARE_CATCH_SCOPE(vm);
     44    auto callData = JSC::getCallData(vm, jsFunction);
     45    ASSERT(callData.type != JSC::CallData::Type::None);
     46    auto result = call(&lexicalGlobalObject, jsFunction, callData, thisValue, arguments);
     47    scope.assertNoException();
     48    return result;
     49}
     50}
     51
     52static inline bool checkWritableStream(JSDOMGlobalObject& globalObject, JSWritableStream* writableStream, JSC::JSValue function)
     53{
     54    auto& lexicalGlobalObject = globalObject;
     55
     56    ASSERT(function);
     57    JSC::MarkedArgumentBuffer arguments;
     58    arguments.append(writableStream);
     59    ASSERT(!arguments.hasOverflowed());
     60    return WritableStreamInternal::callFunction(lexicalGlobalObject, function, JSC::jsUndefined(), arguments).isTrue();
     61}
     62
    3963ExceptionOr<Ref<WritableStream>> WritableStream::create(JSC::JSGlobalObject& lexicalGlobalObject, RefPtr<WritableStreamSink>&& sink)
    4064{
     
    6185}
    6286
     87void WritableStream::lock()
     88{
     89    auto& lexicalGlobalObject = *m_globalObject;
     90    VM& vm = lexicalGlobalObject.vm();
     91    auto scope = DECLARE_CATCH_SCOPE(vm);
     92
     93    auto& clientData = *static_cast<JSVMClientData*>(vm.clientData);
     94
     95    auto* constructor = JSC::asObject(m_globalObject->get(&lexicalGlobalObject, clientData.builtinNames().WritableStreamDefaultWriterPrivateName()));
     96
     97    auto constructData = getConstructData(vm, constructor);
     98    ASSERT(constructData.type != CallData::Type::None);
     99
     100    MarkedArgumentBuffer args;
     101    args.append(writableStream());
     102    ASSERT(!args.hasOverflowed());
     103
     104    JSC::construct(&lexicalGlobalObject, constructor, constructData, args);
     105    scope.assertNoException();
    63106}
     107
     108bool WritableStream::isLocked() const
     109{
     110    return checkWritableStream(*globalObject(), writableStream(), globalObject()->builtinInternalFunctions().writableStreamInternals().m_isWritableStreamLockedFunction.get());
     111}
     112
     113}
  • trunk/Source/WebCore/bindings/js/WritableStream.h

    r270107 r270290  
    4343    JSWritableStream* writableStream() const { return guarded(); }
    4444
     45    void lock();
     46    bool isLocked() const;
     47
    4548private:
    4649    WritableStream(JSDOMGlobalObject&, JSWritableStream&);
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r270115 r270290  
    636636    if ($type->name eq "ReadableStream") {
    637637        AddToIncludes("ReadableStream.h", $includesRef, $conditional);
     638        return;
     639    }
     640
     641    if ($type->name eq "WritableStream") {
     642        AddToIncludes("WritableStream.h", $includesRef, $conditional);
    638643        return;
    639644    }
  • trunk/Tools/ChangeLog

    r270282 r270290  
     12020-12-01  Youenn Fablet  <youenn@apple.com>
     2
     3        Add support for readable/writable to RTCRtpSFrameTransform
     4        https://bugs.webkit.org/show_bug.cgi?id=219298
     5
     6        Reviewed by Eric Carlson.
     7
     8        * TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp:
     9        (TestWebKitAPI::createVideoTransformer):
     10
    1112020-11-30  Wenson Hsieh  <wenson_hsieh@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp

    r269830 r270290  
    7171}
    7272
    73 static Ref<WebCore::RTCRtpSFrameTransformer> createVideoTransformer(bool isSending = true)
     73static Ref<WebCore::RTCRtpSFrameTransformer> createVideoTransformer(bool isEncrypting = true)
    7474{
    7575    auto transformer = WebCore::RTCRtpSFrameTransformer::create();
    76     transformer->setIsSending(isSending);
    77     transformer->setIsProcessingAudio(false);
     76    transformer->setIsEncrypting(isEncrypting);
     77    transformer->setAuthenticationSize(10);
    7878
    7979    auto keyId = Vector<uint8_t>::from(198, 31, 251, 197, 48, 139, 91, 51);
Note: See TracChangeset for help on using the changeset viewer.