Add helper KeepRefUntilDone.

The callback keeps a reference to an object until the callback goes out of scope.

Review URL: https://codereview.webrtc.org/1487493002

Cr-Commit-Position: refs/heads/master@{#10847}
This commit is contained in:
perkj 2015-11-30 22:15:45 -08:00 committed by Commit bot
parent ee69ed505b
commit 14f4144a82
5 changed files with 110 additions and 30 deletions

View File

@ -28,17 +28,13 @@
#include "talk/app/webrtc/java/jni/native_handle_impl.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/keep_ref_until_done.h"
#include "webrtc/base/scoped_ref_ptr.h"
using rtc::scoped_refptr;
using webrtc::NativeHandleBuffer;
namespace webrtc_jni {
namespace {
void ScaledFrameNotInUse(scoped_refptr<NativeHandleBuffer> original) {}
} // anonymous namespace
NativeHandleImpl::NativeHandleImpl(JNIEnv* jni,
jint j_oes_texture_id,
jfloatArray j_transform_matrix)
@ -87,7 +83,7 @@ rtc::scoped_refptr<AndroidTextureBuffer> AndroidTextureBuffer::CropAndScale(
// will be decreased by one.
return new rtc::RefCountedObject<AndroidTextureBuffer>(
dst_widht, dst_height, native_handle_,
rtc::Bind(&ScaledFrameNotInUse, this));
rtc::KeepRefUntilDone(this));
}
} // namespace webrtc_jni

View File

@ -11,6 +11,8 @@
#include "webrtc/base/bind.h"
#include "webrtc/base/callback.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/keep_ref_until_done.h"
#include "webrtc/base/refcount.h"
namespace rtc {
@ -26,6 +28,21 @@ struct BindTester {
int b(int x) const { return x * x; }
};
class RefCountedBindTester : public RefCountInterface {
public:
RefCountedBindTester() : count_(0) {}
int AddRef() const override {
return ++count_;
}
int Release() const {
return --count_;
}
int RefCount() const { return count_; }
private:
mutable int count_;
};
} // namespace
TEST(CallbackTest, VoidReturn) {
@ -78,4 +95,46 @@ TEST(CallbackTest, WithBind) {
EXPECT_EQ(25, cb1());
}
TEST(KeepRefUntilDoneTest, simple) {
RefCountedBindTester t;
EXPECT_EQ(0, t.RefCount());
{
Callback0<void> cb = KeepRefUntilDone(&t);
EXPECT_EQ(1, t.RefCount());
cb();
EXPECT_EQ(1, t.RefCount());
cb();
EXPECT_EQ(1, t.RefCount());
}
EXPECT_EQ(0, t.RefCount());
}
TEST(KeepRefUntilDoneTest, copy) {
RefCountedBindTester t;
EXPECT_EQ(0, t.RefCount());
Callback0<void> cb2;
{
Callback0<void> cb = KeepRefUntilDone(&t);
EXPECT_EQ(1, t.RefCount());
cb2 = cb;
}
EXPECT_EQ(1, t.RefCount());
cb2 = Callback0<void>();
EXPECT_EQ(0, t.RefCount());
}
TEST(KeepRefUntilDoneTest, scopedref) {
RefCountedBindTester t;
EXPECT_EQ(0, t.RefCount());
{
scoped_refptr<RefCountedBindTester> t_scoped_ref(&t);
Callback0<void> cb = KeepRefUntilDone(t_scoped_ref);
t_scoped_ref = nullptr;
EXPECT_EQ(1, t.RefCount());
cb();
EXPECT_EQ(1, t.RefCount());
}
EXPECT_EQ(0, t.RefCount());
}
} // namespace rtc

View File

@ -0,0 +1,43 @@
/*
* Copyright 2015 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.
*/
#ifndef WEBRTC_BASE_KEEP_REF_UNTIL_DONE_H_
#define WEBRTC_BASE_KEEP_REF_UNTIL_DONE_H_
#include "webrtc/base/bind.h"
#include "webrtc/base/callback.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h"
namespace rtc {
namespace impl {
template <class T>
static inline void DoNothing(const scoped_refptr<T>& object) {}
} // namespace impl
// KeepRefUntilDone keeps a reference to |object| until the returned
// callback goes out of scope. If the returned callback is copied, the
// reference will be released when the last callback goes out of scope.
template <class ObjectT>
static inline Callback0<void> KeepRefUntilDone(ObjectT* object) {
return rtc::Bind(&impl::DoNothing<ObjectT>, scoped_refptr<ObjectT>(object));
}
template <class ObjectT>
static inline Callback0<void> KeepRefUntilDone(
const scoped_refptr<ObjectT>& object) {
return rtc::Bind(&impl::DoNothing<ObjectT>, object);
}
} // namespace rtc
#endif // WEBRTC_BASE_KEEP_REF_UNTIL_DONE_H_

View File

@ -10,19 +10,13 @@
#include "webrtc/common_video/include/video_frame_buffer.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/keep_ref_until_done.h"
// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
static const int kBufferAlignment = 64;
namespace webrtc {
namespace {
// Used in rtc::Bind to keep a buffer alive until destructor is called.
static void NoLongerUsedCallback(rtc::scoped_refptr<VideoFrameBuffer> dummy) {}
} // anonymous namespace
uint8_t* VideoFrameBuffer::MutableData(PlaneType type) {
RTC_NOTREACHED();
@ -238,7 +232,7 @@ rtc::scoped_refptr<VideoFrameBuffer> ShallowCenterCrop(
y_plane, buffer->stride(kYPlane),
u_plane, buffer->stride(kUPlane),
v_plane, buffer->stride(kVPlane),
rtc::Bind(&NoLongerUsedCallback, buffer));
rtc::KeepRefUntilDone(buffer));
}
} // namespace webrtc

View File

@ -21,8 +21,8 @@
#include "vpx/vp8cx.h"
#include "vpx/vp8dx.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/keep_ref_until_done.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/trace_event.h"
#include "webrtc/common.h"
@ -31,16 +31,6 @@
#include "webrtc/modules/video_coding/codecs/vp9/screenshare_layers.h"
#include "webrtc/system_wrappers/include/tick_util.h"
namespace {
// VP9DecoderImpl::ReturnFrame helper function used with WrappedI420Buffer.
static void WrappedI420BufferNoLongerUsedCb(
webrtc::Vp9FrameBufferPool::Vp9FrameBuffer* img_buffer) {
img_buffer->Release();
}
} // anonymous namespace
namespace webrtc {
// Only positive speeds, range for real-time coding currently is: 5 - 8.
@ -933,12 +923,10 @@ int VP9DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) {
}
// This buffer contains all of |img|'s image data, a reference counted
// Vp9FrameBuffer. Performing AddRef/Release ensures it is not released and
// recycled during use (libvpx is done with the buffers after a few
// Vp9FrameBuffer. (libvpx is done with the buffers after a few
// vpx_codec_decode calls or vpx_codec_destroy).
Vp9FrameBufferPool::Vp9FrameBuffer* img_buffer =
static_cast<Vp9FrameBufferPool::Vp9FrameBuffer*>(img->fb_priv);
img_buffer->AddRef();
// The buffer can be used directly by the VideoFrame (without copy) by
// using a WrappedI420Buffer.
rtc::scoped_refptr<WrappedI420Buffer> img_wrapped_buffer(
@ -950,7 +938,7 @@ int VP9DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) {
// WrappedI420Buffer's mechanism for allowing the release of its frame
// buffer is through a callback function. This is where we should
// release |img_buffer|.
rtc::Bind(&WrappedI420BufferNoLongerUsedCb, img_buffer)));
rtc::KeepRefUntilDone(img_buffer)));
VideoFrame decoded_image;
decoded_image.set_video_frame_buffer(img_wrapped_buffer);