Merge to M87: Guard VideoCaptureDeviceAVFoundationFrameReceiver

The class VideoCaptureDeviceAVFoundationFrameReceiver cannot handle
concurrent calls. Make VideoCaptureDeviceAVFoundation guard all access
like VideoCaptureDeviceAVFoundationLegacy does.

[email protected]

(cherry picked from commit eafed0bb7242b0dd0cbc6e9b25807329fb81950a)

Bug: 1135246
Change-Id: I6ae5a810ed2df9af4de0b4412b3dfe906b666b41
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454426
Reviewed-by: Markus Handell <[email protected]>
Commit-Queue: ccameron <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#814884}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2479702
Reviewed-by: ccameron <[email protected]>
Commit-Queue: Markus Handell <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#463}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
index d152e19..a4e4315 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
@@ -42,8 +42,11 @@
   // The capture format that best matches the above attributes.
   base::scoped_nsobject<AVCaptureDeviceFormat> _bestCaptureFormat;
 
-  base::Lock _lock;  // Protects concurrent setting and using |frameReceiver_|.
-  media::VideoCaptureDeviceAVFoundationFrameReceiver* _frameReceiver;  // weak.
+  // Protects concurrent setting and using |frameReceiver_|. Note that the
+  // GUARDED_BY decoration below does not have any effect.
+  base::Lock _lock;
+  media::VideoCaptureDeviceAVFoundationFrameReceiver* _frameReceiver
+      GUARDED_BY(_lock);  // weak.
 
   base::scoped_nsobject<AVCaptureSession> _captureSession;
 
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
index 5ebc7073..d54d34b 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -553,6 +553,7 @@
   char* baseAddress = 0;
   size_t frameSize = 0;
   media::ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer);
+  _lock.AssertAcquired();
   _frameReceiver->ReceiveFrame(reinterpret_cast<const uint8_t*>(baseAddress),
                                frameSize, captureFormat, colorSpace, 0, 0,
                                timestamp);
@@ -588,6 +589,7 @@
   frameSize = CVPixelBufferGetDataSize(pixelBuffer);
   // Only contiguous buffers are supported.
   CHECK(frameSize);
+  _lock.AssertAcquired();
   _frameReceiver->ReceiveFrame(reinterpret_cast<const uint8_t*>(baseAddress),
                                frameSize, captureFormat, colorSpace, 0, 0,
                                timestamp);
@@ -608,6 +610,7 @@
   handle.mach_port.reset(IOSurfaceCreateMachPort(ioSurface));
   if (!handle.mach_port)
     return NO;
+  _lock.AssertAcquired();
   _frameReceiver->ReceiveExternalGpuMemoryBufferFrame(
       std::move(handle),
       std::make_unique<CMSampleBufferScopedAccessPermission>(sampleBuffer),
@@ -622,6 +625,13 @@
     didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
            fromConnection:(AVCaptureConnection*)connection {
   VLOG(3) << __func__;
+
+  // Concurrent calls into |_frameReceiver| are not supported, so take |_lock|
+  // before any of the subsequent paths.
+  base::AutoLock lock(_lock);
+  if (!_frameReceiver)
+    return;
+
   // We have certain format expectation for capture output:
   // For MJPEG, |sampleBuffer| is expected to always be a CVBlockBuffer.
   // For other formats, |sampleBuffer| may be either CVBlockBuffer or