Files
platform-external-webrtc/sdk/android/src/java/org/webrtc/RefCountDelegate.java
Sami Kalliomäki 0f6bcd18b2 Hold a reference to AndroidVideoTrackSource while calling onFrameCaptured.
This makes it safe to deliver frames to the sink from VideoProcessor
even after setSink has been called with null reference without danger
of use after free.

Bug: b/148063550
Change-Id: Ib78f75ac49fc6117f744c55da1a4e671bbdcdf22
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168160
Reviewed-by: Paulina Hensman <phensman@webrtc.org>
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30455}
2020-02-04 15:00:05 +00:00

64 lines
2.0 KiB
Java

/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
import android.support.annotation.Nullable;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Implementation of RefCounted that executes a Runnable once the ref count reaches zero.
*/
class RefCountDelegate implements RefCounted {
private final AtomicInteger refCount = new AtomicInteger(1);
private final @Nullable Runnable releaseCallback;
/**
* @param releaseCallback Callback that will be executed once the ref count reaches zero.
*/
public RefCountDelegate(@Nullable Runnable releaseCallback) {
this.releaseCallback = releaseCallback;
}
@Override
public void retain() {
int updated_count = refCount.incrementAndGet();
if (updated_count < 2) {
throw new IllegalStateException("retain() called on an object with refcount < 1");
}
}
@Override
public void release() {
int updated_count = refCount.decrementAndGet();
if (updated_count < 0) {
throw new IllegalStateException("release() called on an object with refcount < 1");
}
if (updated_count == 0 && releaseCallback != null) {
releaseCallback.run();
}
}
/**
* Tries to retain the object. Can be used in scenarios where it is unknown if the object has
* already been released. Returns true if successful or false if the object was already released.
*/
boolean safeRetain() {
int currentRefCount = refCount.get();
while (currentRefCount != 0) {
if (refCount.weakCompareAndSet(currentRefCount, currentRefCount + 1)) {
return true;
}
currentRefCount = refCount.get();
}
return false;
}
}