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}
diff --git a/talk/app/webrtc/java/jni/native_handle_impl.cc b/talk/app/webrtc/java/jni/native_handle_impl.cc
index bb31ba6..583a038 100644
--- a/talk/app/webrtc/java/jni/native_handle_impl.cc
+++ b/talk/app/webrtc/java/jni/native_handle_impl.cc
@@ -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 @@
   // 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
diff --git a/webrtc/base/callback_unittest.cc b/webrtc/base/callback_unittest.cc
index 66c9391..db294cd 100644
--- a/webrtc/base/callback_unittest.cc
+++ b/webrtc/base/callback_unittest.cc
@@ -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 @@
   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 @@
   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
diff --git a/webrtc/base/keep_ref_until_done.h b/webrtc/base/keep_ref_until_done.h
new file mode 100644
index 0000000..269e1c8
--- /dev/null
+++ b/webrtc/base/keep_ref_until_done.h
@@ -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_
diff --git a/webrtc/common_video/video_frame_buffer.cc b/webrtc/common_video/video_frame_buffer.cc
index fff90de..492bc49 100644
--- a/webrtc/common_video/video_frame_buffer.cc
+++ b/webrtc/common_video/video_frame_buffer.cc
@@ -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 @@
       y_plane, buffer->stride(kYPlane),
       u_plane, buffer->stride(kUPlane),
       v_plane, buffer->stride(kVPlane),
-      rtc::Bind(&NoLongerUsedCallback, buffer));
+      rtc::KeepRefUntilDone(buffer));
 }
 
 }  // namespace webrtc
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
index eba8dfb..6fdd676 100644
--- a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -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 @@
   }
 
   // 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 @@
           // 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);