Title: [231167] trunk/Source/ThirdParty/libwebrtc
Revision
231167
Author
you...@apple.com
Date
2018-04-30 13:28:22 -0700 (Mon, 30 Apr 2018)

Log Message

Mandate H264 hardware encoder for Mac in libwebrtc
https://bugs.webkit.org/show_bug.cgi?id=184835

Reviewed by Eric Carlson.

Tested manually through console traces that hardware VCP encoder code path is actually used instead of software VCP encoder code path.

* Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm:
(-[RTCVideoEncoderH264 resetCompressionSessionWithPixelFormat:]):
* WebKit/0001-Update-RTCVideoEncoderH264.mm-for-WebKit.patch: Added to cover this change and changes made in bug 184668 and 183961.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/ThirdParty/libwebrtc/ChangeLog (231166 => 231167)


--- trunk/Source/ThirdParty/libwebrtc/ChangeLog	2018-04-30 20:22:08 UTC (rev 231166)
+++ trunk/Source/ThirdParty/libwebrtc/ChangeLog	2018-04-30 20:28:22 UTC (rev 231167)
@@ -1,3 +1,16 @@
+2018-04-30  Youenn Fablet  <you...@apple.com>
+
+        Mandate H264 hardware encoder for Mac in libwebrtc
+        https://bugs.webkit.org/show_bug.cgi?id=184835
+
+        Reviewed by Eric Carlson.
+
+        Tested manually through console traces that hardware VCP encoder code path is actually used instead of software VCP encoder code path.
+
+        * Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm:
+        (-[RTCVideoEncoderH264 resetCompressionSessionWithPixelFormat:]):
+        * WebKit/0001-Update-RTCVideoEncoderH264.mm-for-WebKit.patch: Added to cover this change and changes made in bug 184668 and 183961.
+
 2018-04-20  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, rolling out r230862.

Modified: trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm (231166 => 231167)


--- trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm	2018-04-30 20:22:08 UTC (rev 231166)
+++ trunk/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm	2018-04-30 20:28:22 UTC (rev 231167)
@@ -607,15 +607,14 @@
     CFRelease(pixelFormat);
     pixelFormat = nullptr;
   }
-  CFMutableDictionaryRef encoder_specs = nullptr;
+  CFDictionaryRef encoderSpecs = nullptr;
 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
+  auto useHardwareEncoder = webrtc::isH264HardwareEncoderAllowed() ? kCFBooleanTrue : kCFBooleanFalse;
   // Currently hw accl is supported above 360p on mac, below 360p
   // the compression session will be created with hw accl disabled.
-  encoder_specs = CFDictionaryCreateMutable(
-      nullptr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-  CFDictionarySetValue(encoder_specs,
-                       kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
-                       webrtc::isH264HardwareEncoderAllowed() ? kCFBooleanTrue : kCFBooleanFalse);
+  CFTypeRef sessionKeys[] = {kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, kVTCompressionPropertyKey_RealTime };
+  CFTypeRef sessionValues[] = {  useHardwareEncoder, useHardwareEncoder, kCFBooleanTrue };
+  encoderSpecs = CFDictionaryCreate(kCFAllocatorDefault, sessionKeys, sessionValues, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 #endif
   OSStatus status =
       CompressionSessionCreate(nullptr,  // use default allocator
@@ -622,7 +621,7 @@
                                  _width,
                                  _height,
                                  kCodecTypeH264,
-                                 encoder_specs,  // use hardware accelerated encoder if available
+                                 encoderSpecs,  // use hardware accelerated encoder if available
                                  sourceAttributes,
                                  nullptr,  // use default compressed data allocator
                                  compressionOutputCallback,
@@ -632,20 +631,25 @@
     CFRelease(sourceAttributes);
     sourceAttributes = nullptr;
   }
-  if (encoder_specs) {
-    CFRelease(encoder_specs);
-    encoder_specs = nullptr;
+  if (encoderSpecs) {
+    CFRelease(encoderSpecs);
+    encoderSpecs = nullptr;
   }
+
+#if ENABLE_VCP_ENCODER || defined(WEBRTC_IOS)
   if (status != noErr) {
     RTC_LOG(LS_ERROR) << "Failed to create compression session: " << status;
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
+#endif
 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
   CFBooleanRef hwaccl_enabled = nullptr;
-  status = VTSessionCopyProperty(_compressionSession,
+  if (status == noErr) {
+    status = VTSessionCopyProperty(_compressionSession,
                                  kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder,
                                  nullptr,
                                  &hwaccl_enabled);
+  }
   if (status == noErr && (CFBooleanGetValue(hwaccl_enabled))) {
     RTC_LOG(LS_INFO) << "Compression session created with hw accl enabled";
   } else {
@@ -714,9 +718,9 @@
       CFRelease(sourceAttributes);
       sourceAttributes = nullptr;
     }
-    if (encoder_specs) {
-      CFRelease(encoder_specs);
-      encoder_specs = nullptr;
+    if (encoderSpecs) {
+      CFRelease(encoderSpecs);
+      encoderSpecs = nullptr;
     }
     if (status != noErr) {
       return WEBRTC_VIDEO_CODEC_ERROR;

Added: trunk/Source/ThirdParty/libwebrtc/WebKit/0001-Update-RTCVideoEncoderH264.mm-for-WebKit.patch (0 => 231167)


--- trunk/Source/ThirdParty/libwebrtc/WebKit/0001-Update-RTCVideoEncoderH264.mm-for-WebKit.patch	                        (rev 0)
+++ trunk/Source/ThirdParty/libwebrtc/WebKit/0001-Update-RTCVideoEncoderH264.mm-for-WebKit.patch	2018-04-30 20:28:22 UTC (rev 231167)
@@ -0,0 +1,274 @@
+From 6526d1daf054748cd0983f994ec0f988df235dc1 Mon Sep 17 00:00:00 2001
+From: Youenn Fablet <you...@apple.com>
+Date: Mon, 30 Apr 2018 11:26:26 -0700
+Subject: [PATCH] Update RTCVideoEncoderH264 for WebKit
+
+---
+ .../Classes/VideoToolbox/RTCVideoEncoderH264.mm    | 159 ++++++++++++++++++---
+ 1 file changed, 140 insertions(+), 19 deletions(-)
+
+diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm
+index a818c27d1e6..68118f8f56a 100644
+--- a/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm
++++ b/Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm
+@@ -35,6 +35,43 @@
+ #include "system_wrappers/include/clock.h"
+ #include "third_party/libyuv/include/libyuv/convert_from.h"
+ 
++#include "sdk/WebKit/EncoderUtilities.h"
++#include "sdk/WebKit/WebKitUtilities.h"
++
++#import <dlfcn.h>
++#import <objc/runtime.h>
++
++SOFT_LINK_FRAMEWORK_OPTIONAL(VideoToolBox)
++SOFT_LINK_POINTER_OPTIONAL(VideoToolBox, kVTVideoEncoderSpecification_Usage, NSString *)
++
++#if !ENABLE_VCP_ENCODER && !defined(WEBRTC_IOS)
++static inline bool isStandardFrameSize(int32_t width, int32_t height)
++{
++    // FIXME: Envision relaxing this rule, something like width and height dividable by 4 or 8 should be good enough.
++    if (width == 1280)
++        return height == 720;
++    if (width == 720)
++        return height == 1280;
++    if (width == 960)
++        return height == 540;
++    if (width == 540)
++        return height == 960;
++    if (width == 640)
++        return height == 480;
++    if (width == 480)
++        return height == 640;
++    if (width == 288)
++        return height == 352;
++    if (width == 352)
++        return height == 288;
++    if (width == 320)
++        return height == 240;
++    if (width == 240)
++        return height == 320;
++    return false;
++}
++#endif
++
+ @interface RTCVideoEncoderH264 ()
+ 
+ - (void)frameWasEncoded:(OSStatus)status
+@@ -285,7 +322,7 @@ @implementation RTCVideoEncoderH264 {
+   RTCVideoEncoderCallback _callback;
+   int32_t _width;
+   int32_t _height;
+-  VTCompressionSessionRef _compressionSession;
++  CompressionSessionRef _compressionSession;
+   RTCVideoCodecMode _mode;
+ 
+   webrtc::H264BitstreamParser _h264BitstreamParser;
+@@ -318,6 +355,10 @@ - (instancetype)initWithCodecInfo:(RTCVideoCodecInfo *)codecInfo {
+ 
+ - (void)dealloc {
+   [self destroyCompressionSession];
++  if (_callback) {
++    Block_release(_callback);
++  }
++  [super dealloc];
+ }
+ 
+ - (NSInteger)startEncodeWithSettings:(RTCVideoEncoderSettings *)settings
+@@ -358,9 +399,9 @@ - (NSInteger)encode:(RTCVideoFrame *)frame
+ 
+   // Get a pixel buffer from the pool and copy frame data over.
+   CVPixelBufferPoolRef pixelBufferPool =
+-      VTCompressionSessionGetPixelBufferPool(_compressionSession);
++      CompressionSessionGetPixelBufferPool(_compressionSession);
+   if ([self resetCompressionSessionIfNeededForPool:pixelBufferPool withFrame:frame]) {
+-    pixelBufferPool = VTCompressionSessionGetPixelBufferPool(_compressionSession);
++    pixelBufferPool = CompressionSessionGetPixelBufferPool(_compressionSession);
+     isKeyframeRequired = YES;
+   }
+ 
+@@ -442,7 +483,7 @@ - (NSInteger)encode:(RTCVideoFrame *)frame
+   // Update the bitrate if needed.
+   [self setBitrateBps:_bitrateAdjuster->GetAdjustedBitrateBps()];
+ 
+-  OSStatus status = VTCompressionSessionEncodeFrame(_compressionSession,
++  OSStatus status = CompressionSessionEncodeFrame(_compressionSession,
+                                                     pixelBuffer,
+                                                     presentationTimeStamp,
+                                                     kCMTimeInvalid,
+@@ -463,7 +504,7 @@ - (NSInteger)encode:(RTCVideoFrame *)frame
+ }
+ 
+ - (void)setCallback:(RTCVideoEncoderCallback)callback {
+-  _callback = callback;
++  _callback = Block_copy(callback);
+ }
+ 
+ - (int)setBitrate:(uint32_t)bitrateKbit framerate:(uint32_t)framerate {
+@@ -480,6 +521,7 @@ - (NSInteger)releaseEncoder {
+   // callback anymore. Do not remove callback until the session is invalidated
+   // since async encoder callbacks can occur until invalidation.
+   [self destroyCompressionSession];
++  Block_release(_callback);
+   _callback = nullptr;
+   return WEBRTC_VIDEO_CODEC_OK;
+ }
+@@ -565,22 +607,21 @@ - (int)resetCompressionSessionWithPixelFormat:(OSType)framePixelFormat {
+     CFRelease(pixelFormat);
+     pixelFormat = nullptr;
+   }
+-  CFMutableDictionaryRef encoder_specs = nullptr;
++  CFDictionaryRef encoderSpecs = nullptr;
+ #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
++  auto useHardwareEncoder = webrtc::isH264HardwareEncoderAllowed() ? kCFBooleanTrue : kCFBooleanFalse;
+   // Currently hw accl is supported above 360p on mac, below 360p
+   // the compression session will be created with hw accl disabled.
+-  encoder_specs = CFDictionaryCreateMutable(
+-      nullptr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+-  CFDictionarySetValue(encoder_specs,
+-                       kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
+-                       kCFBooleanTrue);
++  CFTypeRef sessionKeys[] = {kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, kVTCompressionPropertyKey_RealTime };
++  CFTypeRef sessionValues[] = {  useHardwareEncoder, useHardwareEncoder, kCFBooleanTrue };
++  encoderSpecs = CFDictionaryCreate(kCFAllocatorDefault, sessionKeys, sessionValues, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ #endif
+   OSStatus status =
+-      VTCompressionSessionCreate(nullptr,  // use default allocator
++      CompressionSessionCreate(nullptr,  // use default allocator
+                                  _width,
+                                  _height,
+-                                 kCMVideoCodecType_H264,
+-                                 encoder_specs,  // use hardware accelerated encoder if available
++                                 kCodecTypeH264,
++                                 encoderSpecs,  // use hardware accelerated encoder if available
+                                  sourceAttributes,
+                                  nullptr,  // use default compressed data allocator
+                                  compressionOutputCallback,
+@@ -590,24 +631,101 @@ - (int)resetCompressionSessionWithPixelFormat:(OSType)framePixelFormat {
+     CFRelease(sourceAttributes);
+     sourceAttributes = nullptr;
+   }
+-  if (encoder_specs) {
+-    CFRelease(encoder_specs);
+-    encoder_specs = nullptr;
++  if (encoderSpecs) {
++    CFRelease(encoderSpecs);
++    encoderSpecs = nullptr;
+   }
++
++#if ENABLE_VCP_ENCODER || defined(WEBRTC_IOS)
+   if (status != noErr) {
+     RTC_LOG(LS_ERROR) << "Failed to create compression session: " << status;
+     return WEBRTC_VIDEO_CODEC_ERROR;
+   }
++#endif
+ #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
+   CFBooleanRef hwaccl_enabled = nullptr;
+-  status = VTSessionCopyProperty(_compressionSession,
++  if (status == noErr) {
++    status = VTSessionCopyProperty(_compressionSession,
+                                  kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder,
+                                  nullptr,
+                                  &hwaccl_enabled);
++  }
+   if (status == noErr && (CFBooleanGetValue(hwaccl_enabled))) {
+     RTC_LOG(LS_INFO) << "Compression session created with hw accl enabled";
+   } else {
+     RTC_LOG(LS_INFO) << "Compression session created with hw accl disabled";
++
++#if !ENABLE_VCP_ENCODER && !defined(WEBRTC_IOS)
++    if (!isStandardFrameSize(_width, _height)) {
++      RTC_LOG(LS_ERROR) << "Using H264 software encoder with non standard size is not supported";
++      return WEBRTC_VIDEO_CODEC_ERROR;
++    }
++
++    if (!getkVTVideoEncoderSpecification_Usage()) {
++      RTC_LOG(LS_ERROR) << "RTCVideoEncoderH264 cannot create a H264 software encoder";
++      return WEBRTC_VIDEO_CODEC_ERROR;
++    }
++
++    CFDictionaryRef ioSurfaceValue = CreateCFTypeDictionary(nullptr, nullptr, 0);
++    int64_t pixelFormatType = framePixelFormat;
++    CFNumberRef pixelFormat = CFNumberCreate(nullptr, kCFNumberLongType, &pixelFormatType);
++
++    const size_t attributesSize = 3;
++    CFTypeRef keys[attributesSize] = {
++      kCVPixelBufferOpenGLCompatibilityKey,
++      kCVPixelBufferIOSurfacePropertiesKey,
++      kCVPixelBufferPixelFormatTypeKey
++    };
++    CFTypeRef values[attributesSize] = {
++      kCFBooleanTrue,
++      ioSurfaceValue,
++      pixelFormat};
++    CFDictionaryRef sourceAttributes = CreateCFTypeDictionary(keys, values, attributesSize);
++
++    if (ioSurfaceValue) {
++      CFRelease(ioSurfaceValue);
++      ioSurfaceValue = nullptr;
++    }
++    if (pixelFormat) {
++      CFRelease(pixelFormat);
++      pixelFormat = nullptr;
++    }
++
++    CFMutableDictionaryRef encoderSpecs = CFDictionaryCreateMutable(nullptr, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
++    CFDictionarySetValue(encoderSpecs, kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, kCFBooleanFalse);
++    int usageValue = 1;
++    CFNumberRef usage = CFNumberCreate(nullptr, kCFNumberIntType, &usageValue);
++    CFDictionarySetValue(encoderSpecs, getkVTVideoEncoderSpecification_Usage(), usage);
++    if (usage) {
++      CFRelease(usage);
++      usage = nullptr;
++    }
++
++    [self destroyCompressionSession];
++
++    OSStatus status =
++      CompressionSessionCreate(nullptr,  // use default allocator
++                                 _width,
++                                 _height,
++                                 kCodecTypeH264,
++                                 encoderSpecs,
++                                 sourceAttributes,
++                                 nullptr,  // use default compressed data allocator
++                                 compressionOutputCallback,
++                                 nullptr,
++                                 &_compressionSession);
++    if (sourceAttributes) {
++      CFRelease(sourceAttributes);
++      sourceAttributes = nullptr;
++    }
++    if (encoderSpecs) {
++      CFRelease(encoderSpecs);
++      encoderSpecs = nullptr;
++    }
++    if (status != noErr) {
++      return WEBRTC_VIDEO_CODEC_ERROR;
++    }
++#endif
+   }
+ #endif
+   [self configureCompressionSession];
+@@ -619,6 +737,9 @@ - (void)configureCompressionSession {
+   SetVTSessionProperty(_compressionSession, kVTCompressionPropertyKey_RealTime, true);
+   SetVTSessionProperty(_compressionSession, kVTCompressionPropertyKey_ProfileLevel, _profile);
+   SetVTSessionProperty(_compressionSession, kVTCompressionPropertyKey_AllowFrameReordering, false);
++#if ENABLE_VCP_ENCODER
++  SetVTSessionProperty(_compressionSession, (__bridge CFStringRef)getkVTVideoEncoderSpecification_Usage(), 1);
++#endif
+   [self setEncoderBitrateBps:_targetBitrateBps];
+   // TODO(tkchin): Look at entropy mode and colorspace matrices.
+   // TODO(tkchin): Investigate to see if there's any way to make this work.
+@@ -636,7 +757,7 @@ - (void)configureCompressionSession {
+ 
+ - (void)destroyCompressionSession {
+   if (_compressionSession) {
+-    VTCompressionSessionInvalidate(_compressionSession);
++    CompressionSessionInvalidate(_compressionSession);
+     CFRelease(_compressionSession);
+     _compressionSession = nullptr;
+   }
+-- 
+2.16.1 (Apple Git-102)
+
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to