Title: [275300] trunk
Revision
275300
Author
you...@apple.com
Date
2021-03-31 12:25:22 -0700 (Wed, 31 Mar 2021)

Log Message

In case WebRTC VTB decoder returns a null frame, mark the decoder as failing
https://bugs.webkit.org/show_bug.cgi?id=223993
<rdar://problem/76049206>

Reviewed by Eric Carlson.

Source/ThirdParty/libwebrtc:

In case VTB does not return any pixel buffer, consider decoding is failing.
Set the error so that we we will send the error on the next frame we try to decode.

* Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH264.mm:
(decompressionOutputCallback):
* Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH265.mm:
(h265DecompressionOutputCallback):
(-[RTCVideoDecoderH265 setError:]):
* Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderVTBVP9.mm:
(vp9DecompressionOutputCallback):

LayoutTests:

* http/wpt/webrtc/webrtc-late-transform-expected.txt: Added.
* http/wpt/webrtc/webrtc-late-transform.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (275299 => 275300)


--- trunk/LayoutTests/ChangeLog	2021-03-31 18:45:36 UTC (rev 275299)
+++ trunk/LayoutTests/ChangeLog	2021-03-31 19:25:22 UTC (rev 275300)
@@ -1,3 +1,14 @@
+2021-03-31  Youenn Fablet  <you...@apple.com>
+
+        In case WebRTC VTB decoder returns a null frame, mark the decoder as failing
+        https://bugs.webkit.org/show_bug.cgi?id=223993
+        <rdar://problem/76049206>
+
+        Reviewed by Eric Carlson.
+
+        * http/wpt/webrtc/webrtc-late-transform-expected.txt: Added.
+        * http/wpt/webrtc/webrtc-late-transform.html: Added.
+
 2021-03-31  Chris Gambrell  <cgambr...@apple.com>
 
         [LayoutTests] Convert http/tests/download convert PHP to Python

Added: trunk/LayoutTests/http/wpt/webrtc/webrtc-late-transform-expected.txt (0 => 275300)


--- trunk/LayoutTests/http/wpt/webrtc/webrtc-late-transform-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/webrtc/webrtc-late-transform-expected.txt	2021-03-31 19:25:22 UTC (rev 275300)
@@ -0,0 +1,4 @@
+
+
+PASS video exchange with late receiver transform
+

Added: trunk/LayoutTests/http/wpt/webrtc/webrtc-late-transform.html (0 => 275300)


--- trunk/LayoutTests/http/wpt/webrtc/webrtc-late-transform.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/webrtc/webrtc-late-transform.html	2021-03-31 19:25:22 UTC (rev 275300)
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <video controls id="video" autoplay></video>
+        <canvas id="canvas" width="640" height="480"></canvas>
+        <script src =""
+        <script>
+function grabFrameData(x, y, w, h)
+{
+    canvas.width = video.videoWidth;
+    canvas.height = video.videoHeight;
+
+    canvas.getContext('2d').drawImage(video, x, y, w, h, x, y, w, h);
+    return canvas.getContext('2d').getImageData(x, y, w, h).data;
+}
+
+function getCircleImageData()
+{
+    return grabFrameData(450, 100, 150, 100);
+}
+
+async function checkVideoIsUpdated(shouldBeUpdated, count, referenceData)
+{
+    if (count === undefined)
+        count = 0;
+    else if (count >= 20)
+        return Promise.reject("checkVideoIsUpdated timed out :" + shouldBeUpdated + " " + count);
+
+    if (referenceData === undefined)
+        referenceData = getCircleImageData();
+
+    await waitFor(200);
+    const newData = getCircleImageData();
+
+    if (shouldBeUpdated === (JSON.stringify(referenceData) !== JSON.stringify(newData)))
+        return;
+
+    await checkVideoIsUpdated(shouldBeUpdated, ++count, newData);
+}
+
+promise_test(async (test) => {
+    const localStream = await navigator.mediaDevices.getUserMedia({video: true});
+    const senderTransform = new SFrameTransform({ compatibilityMode: "H264" });
+    const receiverTransform = new SFrameTransform({ compatibilityMode: "H264" });
+    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"]).then(key => {
+       senderTransform.setEncryptionKey(key);
+       receiverTransform.setEncryptionKey(key);
+    });
+
+    let sender, receiver;
+    const stream = await new Promise((resolve, reject) => {
+        createConnections((firstConnection) => {
+            pc1 = firstConnection;
+            sender = firstConnection.addTrack(localStream.getVideoTracks()[0], localStream);
+            sender.transform = senderTransform;
+        }, (secondConnection) => {
+            pc2 = secondConnection;
+            secondConnection._ontrack_ = (trackEvent) => {
+                receiver = trackEvent.receiver;
+                // we do not set the receiver transform here;
+                resolve(trackEvent.streams[0]);
+            };
+        }, {
+            observeOffer : (offer) => {
+                const lines = offer.sdp.split('\r\n');
+                const h264Lines = lines.filter(line => line.indexOf("a=fmtp") === 0 && line.indexOf("42e01f") !== -1);
+                const baselineNumber = h264Lines[0].substring(6).split(' ')[0];
+                offer.sdp = lines.filter(line => {
+                    return (line.indexOf('a=fmtp') === -1 && line.indexOf('a=rtcp-fb') === -1 && line.indexOf('a=rtpmap') === -1) || line.indexOf(baselineNumber) !== -1;
+                }).join('\r\n');
+            }
+        });
+        setTimeout(() => reject("Test timed out"), 5000);
+    });
+
+    video.srcObject = stream;
+    video.play();
+
+    // We set the receiver transform here so that the decoder probably tried to decode sframe content.
+    setTimeout(() => receiver.transform = receiverTransform, 50);
+    await checkVideoIsUpdated(true);
+}, "video exchange with late receiver transform");
+        </script>
+    </body>
+</html>

Modified: trunk/Source/ThirdParty/libwebrtc/ChangeLog (275299 => 275300)


--- trunk/Source/ThirdParty/libwebrtc/ChangeLog	2021-03-31 18:45:36 UTC (rev 275299)
+++ trunk/Source/ThirdParty/libwebrtc/ChangeLog	2021-03-31 19:25:22 UTC (rev 275300)
@@ -1,3 +1,22 @@
+2021-03-31  Youenn Fablet  <you...@apple.com>
+
+        In case WebRTC VTB decoder returns a null frame, mark the decoder as failing
+        https://bugs.webkit.org/show_bug.cgi?id=223993
+        <rdar://problem/76049206>
+
+        Reviewed by Eric Carlson.
+
+        In case VTB does not return any pixel buffer, consider decoding is failing.
+        Set the error so that we we will send the error on the next frame we try to decode.
+
+        * Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH264.mm:
+        (decompressionOutputCallback):
+        * Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH265.mm:
+        (h265DecompressionOutputCallback):
+        (-[RTCVideoDecoderH265 setError:]):
+        * Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderVTBVP9.mm:
+        (vp9DecompressionOutputCallback):
+
 2021-03-31  Thibault Saunier  <tsaun...@igalia.com> and Philippe Normand  <pnorm...@igalia.com>
 
         [WebRTC][GStreamer] Build and use the openh264 based encoder if present on the system

Modified: trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH264.mm (275299 => 275300)


--- trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH264.mm	2021-03-31 18:45:36 UTC (rev 275299)
+++ trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH264.mm	2021-03-31 19:25:22 UTC (rev 275300)
@@ -50,14 +50,14 @@
                                  CVImageBufferRef imageBuffer,
                                  CMTime timestamp,
                                  CMTime duration) {
-  std::unique_ptr<RTCFrameDecodeParams> decodeParams(
-      reinterpret_cast<RTCFrameDecodeParams *>(params));
-  if (status != noErr) {
+  if (status != noErr || !imageBuffer) {
     RTCVideoDecoderH264 *decoder = (__bridge RTCVideoDecoderH264 *)decoderRef;
-    [decoder setError:status];
+    [decoder setError:status != noErr ? status : 1];
     RTC_LOG(LS_ERROR) << "Failed to decode frame. Status: " << status;
     return;
   }
+
+  std::unique_ptr<RTCFrameDecodeParams> decodeParams(reinterpret_cast<RTCFrameDecodeParams *>(params));
   // TODO(tkchin): Handle CVO properly.
   RTCCVPixelBuffer *frameBuffer = [[RTCCVPixelBuffer alloc] initWithPixelBuffer:imageBuffer];
   RTCVideoFrame *decodedFrame =

Modified: trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH265.mm (275299 => 275300)


--- trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH265.mm	2021-03-31 18:45:36 UTC (rev 275299)
+++ trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH265.mm	2021-03-31 19:25:22 UTC (rev 275300)
@@ -34,9 +34,13 @@
   int64_t timestamp;
 };
 
+@interface RTCVideoDecoderH265 ()
+- (void)setError:(OSStatus)error;
+@end
+
 // This is the callback function that VideoToolbox calls when decode is
 // complete.
-void h265DecompressionOutputCallback(void* decoder,
+void h265DecompressionOutputCallback(void* decoderRef,
                                      void* params,
                                      OSStatus status,
                                      VTDecodeInfoFlags infoFlags,
@@ -43,12 +47,14 @@
                                      CVImageBufferRef imageBuffer,
                                      CMTime timestamp,
                                      CMTime duration) {
-  std::unique_ptr<RTCH265FrameDecodeParams> decodeParams(
-      reinterpret_cast<RTCH265FrameDecodeParams*>(params));
-  if (status != noErr) {
+  if (status != noErr || !imageBuffer) {
+    RTCVideoDecoderH265 *decoder = (__bridge RTCVideoDecoderH265 *)decoderRef;
+    [decoder setError:status != noErr ? status : 1];
     RTC_LOG(LS_ERROR) << "Failed to decode frame. Status: " << status;
     return;
   }
+
+  std::unique_ptr<RTCH265FrameDecodeParams> decodeParams(reinterpret_cast<RTCH265FrameDecodeParams*>(params));
   // TODO(tkchin): Handle CVO properly.
   RTCCVPixelBuffer* frameBuffer =
       [[RTCCVPixelBuffer alloc] initWithPixelBuffer:imageBuffer];
@@ -166,6 +172,10 @@
   _callback = callback;
 }
 
+- (void)setError:(OSStatus)error {
+  _error = error;
+}
+
 - (NSInteger)releaseDecoder {
   // Need to invalidate the session so that callbacks no longer occur and it
   // is safe to null out the callback.

Modified: trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderVTBVP9.mm (275299 => 275300)


--- trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderVTBVP9.mm	2021-03-31 18:45:36 UTC (rev 275299)
+++ trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderVTBVP9.mm	2021-03-31 19:25:22 UTC (rev 275300)
@@ -146,14 +146,14 @@
                                  CVImageBufferRef imageBuffer,
                                  CMTime timestamp,
                                  CMTime duration) {
-  std::unique_ptr<RTCFrameDecodeParams> decodeParams(
-      reinterpret_cast<RTCFrameDecodeParams *>(params));
-  if (status != noErr) {
-      RTCVideoDecoderVTBVP9 *decoder = (__bridge RTCVideoDecoderVTBVP9 *)decoderRef;
-    [decoder setError:status];
+  if (status != noErr || !imageBuffer) {
+    RTCVideoDecoderVTBVP9 *decoder = (__bridge RTCVideoDecoderVTBVP9 *)decoderRef;
+    [decoder setError:status != noErr ? status : 1];
     RTC_LOG(LS_ERROR) << "Failed to decode frame. Status: " << status;
     return;
   }
+
+  std::unique_ptr<RTCFrameDecodeParams> decodeParams(reinterpret_cast<RTCFrameDecodeParams *>(params));
   RTCCVPixelBuffer *frameBuffer = [[RTCCVPixelBuffer alloc] initWithPixelBuffer:imageBuffer];
   RTCVideoFrame *decodedFrame =
       [[RTCVideoFrame alloc] initWithBuffer:frameBuffer
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to