WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
231162
ObjectiveC WebRTC frame buffers are autoreleased late, especially on Debug builds
https://bugs.webkit.org/show_bug.cgi?id=231162
Summary
ObjectiveC WebRTC frame buffers are autoreleased late, especially on Debug bu...
youenn fablet
Reported
2021-10-04 03:03:48 PDT
ObjectiveC WebRTC frame buffers are autoreleased late, especially on Debug builds. On debug builds, running
https://webrtc.github.io/samples/src/content/peerconnection/change-codecs/
with VP8 and mock capture source (click start, then call) will see memory increases a lot, up to more than 1 GB. When clicking hang up, all this memory got autoreleased but we would hope it would be released sooner. On debug builds, running
https://webrtc.github.io/samples/src/content/peerconnection/pc1/
with the real camera fails after a few frames being encoded (click start, then call). The camera CVPixelBuffers are only released after clicking hang up, which makes the camera stopping to emit frames.
Attachments
Explicit close approach
(7.38 KB, patch)
2021-10-04 03:19 PDT
,
youenn fablet
no flags
Details
Formatted Diff
Diff
Patch for landing
(7.54 KB, patch)
2021-10-06 00:28 PDT
,
youenn fablet
no flags
Details
Formatted Diff
Diff
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
youenn fablet
Comment 1
2021-10-04 03:19:24 PDT
Created
attachment 440047
[details]
Explicit close approach
youenn fablet
Comment 2
2021-10-04 03:36:12 PDT
For the real camera case, RTCCVPixelBuffer are sometimes deallocated too late, and deallocation triggers releasing the wrapped CVPixelBuffer. For the VP8 case, CVPixelBuffers are converted in I420 webrtc internal buffers, which are kept alive until RTCI420Buffer are deallocated. I feel like we might be able to do better (@autoreleasepool maybe?) but I am not familiar with how to do it. Advices most welcome.
youenn fablet
Comment 3
2021-10-04 03:36:43 PDT
I wonder whether this might explain
rdar://83435926
.
youenn fablet
Comment 4
2021-10-04 05:27:02 PDT
Also not sure why the issue occurs now.
David Kilzer (:ddkilzer)
Comment 5
2021-10-04 17:53:51 PDT
Comment on
attachment 440047
[details]
Explicit close approach View in context:
https://bugs.webkit.org/attachment.cgi?id=440047&action=review
> Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.mm:374 > - auto *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:ToObjCVideoFrameBuffer(pixelBufferToFrame(pixelBuffer)) rotation:RTCVideoRotation(rotation) timeStampNs:timeStampNs]; > + auto videoFrameBuffer = pixelBufferToFrame(pixelBuffer); > + auto *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:ToObjCVideoFrameBuffer(videoFrameBuffer) rotation:RTCVideoRotation(rotation) timeStampNs:timeStampNs];
This change is likely what fixes the autoreleased objects. I'd have to look at generated code to be sure (which I'm not very good at), but this change probably allows the compiler to avoid autoreleasing the result of ToObjCVideoFrameBuffer() somehow, which is where these objects come from. Under ARC, any method that returns an Objective-C object (that's not marked NS_RETURNS_RETAINED) will return a +1 autoreleased object unless the caller is also compiled with ARC and the result is stored in some kind of a (temp) variable, which allows the +1 autoreleased object to become a +1 retained object using a special optimization trick. I would have said that this change would be a "safer" bet to eliminate the autoreleased object because it provides a local variable for the Objective-C object that was formerly autoreleased: auto videoFrameBuffer = ToObjCVideoFrameBuffer(pixelBufferToFrame(pixelBuffer)); // Obj-C object is now +1 retained instead of +1 autoreleased auto *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:videoFrameBuffer rotation:RTCVideoRotation(rotation) timeStampNs:timeStampNs]; Having said that, changing ToObjCVideoFrameBuffer() into an inline method (moving it from objc_frame_buffer.mm to objc_frame_buffer.h) might also allow the optimization to occur (without changes to this caller), but I'm not 100% sure about that. (If ToObjCVideoFrameBuffer() is used in more than one place, this might eliminate other places where videoFrameBuffer objects are autoreleased as well.) (I used to have a blog article that I linked to where I learned about the optimization, but I can't find it now.)
David Kilzer (:ddkilzer)
Comment 6
2021-10-04 17:58:08 PDT
Ah, here's the article where I read about this: <
https://mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html
>
David Kilzer (:ddkilzer)
Comment 7
2021-10-04 18:06:01 PDT
(In reply to David Kilzer (:ddkilzer) from
comment #6
)
> Ah, here's the article where I read about this: > <
https://mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference
- > counting.html>
See the sections about objc_retainAutoreleaseReturnValue().
Radar WebKit Bug Importer
Comment 8
2021-10-05 01:24:05 PDT
<
rdar://problem/83876310
>
youenn fablet
Comment 9
2021-10-05 03:43:26 PDT
Comment on
attachment 440047
[details]
Explicit close approach View in context:
https://bugs.webkit.org/attachment.cgi?id=440047&action=review
>> Source/ThirdParty/libwebrtc/Source/webrtc/sdk/WebKit/WebKitEncoder.mm:374 >> + auto *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:ToObjCVideoFrameBuffer(videoFrameBuffer) rotation:RTCVideoRotation(rotation) timeStampNs:timeStampNs]; > > This change is likely what fixes the autoreleased objects. > > I'd have to look at generated code to be sure (which I'm not very good at), but this change probably allows the compiler to avoid autoreleasing the result of ToObjCVideoFrameBuffer() somehow, which is where these objects come from. > > Under ARC, any method that returns an Objective-C object (that's not marked NS_RETURNS_RETAINED) will return a +1 autoreleased object unless the caller is also compiled with ARC and the result is stored in some kind of a (temp) variable, which allows the +1 autoreleased object to become a +1 retained object using a special optimization trick. > > I would have said that this change would be a "safer" bet to eliminate the autoreleased object because it provides a local variable for the Objective-C object that was formerly autoreleased: > > auto videoFrameBuffer = ToObjCVideoFrameBuffer(pixelBufferToFrame(pixelBuffer)); // Obj-C object is now +1 retained instead of +1 autoreleased > auto *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:videoFrameBuffer rotation:RTCVideoRotation(rotation) timeStampNs:timeStampNs]; > > Having said that, changing ToObjCVideoFrameBuffer() into an inline method (moving it from objc_frame_buffer.mm to objc_frame_buffer.h) might also allow the optimization to occur (without changes to this caller), but I'm not 100% sure about that. (If ToObjCVideoFrameBuffer() is used in more than one place, this might eliminate other places where videoFrameBuffer objects are autoreleased as well.) > > (I used to have a blog article that I linked to where I learned about the optimization, but I can't find it now.)
I tried that but it does not seem to work for me.
youenn fablet
Comment 10
2021-10-06 00:22:35 PDT
Thanks for the r+, I will add some WEBRTC_WEBKIT_BUILD to keep track of the changes.
youenn fablet
Comment 11
2021-10-06 00:28:55 PDT
Created
attachment 440340
[details]
Patch for landing
EWS
Comment 12
2021-10-06 03:13:22 PDT
Committed
r283610
(
242562@main
): <
https://commits.webkit.org/242562@main
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 440340
[details]
.
youenn fablet
Comment 13
2021-10-06 05:20:33 PDT
<
rdar://83435926
>
youenn fablet
Comment 14
2021-10-06 05:20:59 PDT
<
rdar://problem/83876310
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug