| Index: talk/app/webrtc/androidvideocapturer.cc
|
| diff --git a/talk/app/webrtc/androidvideocapturer.cc b/talk/app/webrtc/androidvideocapturer.cc
|
| index 8901188492166fd66a6e7f5b5dab721802a4bba1..e2270228227750027ab5e59e3438a63af786c795 100644
|
| --- a/talk/app/webrtc/androidvideocapturer.cc
|
| +++ b/talk/app/webrtc/androidvideocapturer.cc
|
| @@ -27,69 +27,50 @@
|
| #include "talk/app/webrtc/androidvideocapturer.h"
|
|
|
| #include "talk/media/webrtc/webrtcvideoframe.h"
|
| -#include "webrtc/base/bind.h"
|
| -#include "webrtc/base/callback.h"
|
| #include "webrtc/base/common.h"
|
| #include "webrtc/base/json.h"
|
| #include "webrtc/base/timeutils.h"
|
| -#include "webrtc/base/thread.h"
|
| -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
|
|
| namespace webrtc {
|
|
|
| -using cricket::WebRtcVideoFrame;
|
| -using rtc::scoped_ptr;
|
| -using rtc::scoped_refptr;
|
| -
|
| -// An implementation of cricket::VideoFrameFactory for frames that are not
|
| -// guaranteed to outlive the created cricket::VideoFrame.
|
| -// A frame is injected using UpdateCapturedFrame, and converted into a
|
| -// cricket::VideoFrame with
|
| -// CreateAliasedFrame. UpdateCapturedFrame should be called before
|
| -// CreateAliasedFrame for every frame.
|
| +// A hack for avoiding deep frame copies in
|
| +// cricket::VideoCapturer.SignalFrameCaptured() using a custom FrameFactory.
|
| +// A frame is injected using UpdateCapturedFrame(), and converted into a
|
| +// cricket::VideoFrame with CreateAliasedFrame(). UpdateCapturedFrame() should
|
| +// be called before CreateAliasedFrame() for every frame.
|
| +// TODO(magjed): Add an interface cricket::VideoCapturer::OnFrameCaptured()
|
| +// for ref counted I420 frames instead of this hack.
|
| class AndroidVideoCapturer::FrameFactory : public cricket::VideoFrameFactory {
|
| public:
|
| - FrameFactory(int width,
|
| - int height,
|
| - const scoped_refptr<AndroidVideoCapturerDelegate>& delegate)
|
| - : start_time_(rtc::TimeNanos()), delegate_(delegate) {
|
| + FrameFactory(const rtc::scoped_refptr<AndroidVideoCapturerDelegate>& delegate)
|
| + : start_time_(rtc::TimeNanos()), delegate_(delegate) {
|
| // Create a CapturedFrame that only contains header information, not the
|
| // actual pixel data.
|
| - captured_frame_.width = width;
|
| - captured_frame_.height = height;
|
| captured_frame_.pixel_height = 1;
|
| captured_frame_.pixel_width = 1;
|
| - captured_frame_.rotation = 0;
|
| - captured_frame_.data = NULL;
|
| + captured_frame_.data = nullptr;
|
| captured_frame_.data_size = cricket::CapturedFrame::kUnknownDataSize;
|
| captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_ANY);
|
| }
|
|
|
| - void UpdateCapturedFrame(void* frame_data,
|
| - int length,
|
| - int width,
|
| - int height,
|
| - int rotation,
|
| - int64 time_stamp_in_ns) {
|
| - // Make sure we don't overwrite the previous frame.
|
| - CHECK(captured_frame_.data == nullptr);
|
| - captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_YV12);
|
| - captured_frame_.data = frame_data;
|
| - captured_frame_.width = width;
|
| - captured_frame_.height = height;
|
| + void UpdateCapturedFrame(
|
| + const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
|
| + int rotation,
|
| + int64 time_stamp_in_ns) {
|
| + buffer_ = buffer;
|
| + captured_frame_.width = buffer->width();
|
| + captured_frame_.height = buffer->height();
|
| captured_frame_.elapsed_time = rtc::TimeNanos() - start_time_;
|
| captured_frame_.time_stamp = time_stamp_in_ns;
|
| captured_frame_.rotation = rotation;
|
| - captured_frame_.data_size = length;
|
| }
|
|
|
| - void ClearCapturedFrame() const {
|
| - captured_frame_.data = nullptr;
|
| + void ClearCapturedFrame() {
|
| + buffer_ = nullptr;
|
| captured_frame_.width = 0;
|
| captured_frame_.height = 0;
|
| captured_frame_.elapsed_time = 0;
|
| captured_frame_.time_stamp = 0;
|
| - captured_frame_.data_size = 0;
|
| }
|
|
|
| const cricket::CapturedFrame* GetCapturedFrame() const {
|
| @@ -100,64 +81,23 @@ class AndroidVideoCapturer::FrameFactory : public cricket::VideoFrameFactory {
|
| const cricket::CapturedFrame* captured_frame,
|
| int dst_width,
|
| int dst_height) const override {
|
| - // This override of CreateAliasedFrame creates a copy of the frame since
|
| - // |captured_frame_.data| is only guaranteed to be valid during the scope
|
| - // of |AndroidVideoCapturer::OnIncomingFrame_w|.
|
| // Check that captured_frame is actually our frame.
|
| CHECK(captured_frame == &captured_frame_);
|
| - CHECK(captured_frame->data != nullptr);
|
| -
|
| - if (!apply_rotation_ || captured_frame->rotation == kVideoRotation_0) {
|
| - CHECK(captured_frame->fourcc == cricket::FOURCC_YV12);
|
| - const uint8_t* y_plane = static_cast<uint8_t*>(captured_frame_.data);
|
| -
|
| - // Android guarantees that the stride is a multiple of 16.
|
| - // http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29
|
| - int y_stride;
|
| - int uv_stride;
|
| - webrtc::Calc16ByteAlignedStride(captured_frame->width, &y_stride,
|
| - &uv_stride);
|
| - const uint8_t* v_plane = y_plane + y_stride * captured_frame->height;
|
| - const uint8_t* u_plane =
|
| - v_plane + uv_stride * webrtc::AlignInt(captured_frame->height, 2) / 2;
|
| -
|
| - // Create a WrappedI420Buffer and bind the |no_longer_used| callback
|
| - // to the static method ReturnFrame. The |delegate_| is bound as an
|
| - // argument which means that the callback will hold a reference to
|
| - // |delegate_|.
|
| - rtc::scoped_refptr<WrappedI420Buffer> buffer(
|
| - new rtc::RefCountedObject<webrtc::WrappedI420Buffer>(
|
| - dst_width, dst_height, captured_frame->width,
|
| - captured_frame->height, y_plane, y_stride, u_plane, uv_stride,
|
| - v_plane, uv_stride,
|
| - rtc::Bind(&AndroidVideoCapturer::FrameFactory::ReturnFrame,
|
| - delegate_,
|
| - captured_frame->time_stamp)));
|
| - cricket::VideoFrame* cricket_frame = new WebRtcVideoFrame(
|
| - buffer, captured_frame->elapsed_time,
|
| - captured_frame->time_stamp, captured_frame->GetRotation());
|
| - // |cricket_frame| is now responsible for returning the frame. Clear
|
| - // |captured_frame_| so the frame isn't returned twice.
|
| - ClearCapturedFrame();
|
| - return cricket_frame;
|
| - }
|
| -
|
| - scoped_ptr<WebRtcVideoFrame> frame(new WebRtcVideoFrame());
|
| - frame->Init(captured_frame, dst_width, dst_height, apply_rotation_);
|
| - return frame.release();
|
| - }
|
| -
|
| - static void ReturnFrame(scoped_refptr<AndroidVideoCapturerDelegate> delegate,
|
| - int64 time_stamp) {
|
| - delegate->ReturnBuffer(time_stamp);
|
| + rtc::scoped_ptr<cricket::VideoFrame> frame(new cricket::WebRtcVideoFrame(
|
| + ShallowCenterCrop(buffer_, dst_width, dst_height),
|
| + captured_frame->elapsed_time, captured_frame->time_stamp,
|
| + captured_frame->GetRotation()));
|
| + // Caller takes ownership.
|
| + // TODO(magjed): Change CreateAliasedFrame() to return a rtc::scoped_ptr.
|
| + return apply_rotation_ ? frame->GetCopyWithRotationApplied()->Copy()
|
| + : frame.release();
|
| }
|
|
|
| private:
|
| uint64 start_time_;
|
| - // |captured_frame_| is mutable as a hacky way to modify it inside
|
| - // CreateAliasedframe().
|
| - mutable cricket::CapturedFrame captured_frame_;
|
| - scoped_refptr<AndroidVideoCapturerDelegate> delegate_;
|
| + rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer_;
|
| + cricket::CapturedFrame captured_frame_;
|
| + rtc::scoped_refptr<AndroidVideoCapturerDelegate> delegate_;
|
| };
|
|
|
| AndroidVideoCapturer::AndroidVideoCapturer(
|
| @@ -202,8 +142,7 @@ cricket::CaptureState AndroidVideoCapturer::Start(
|
| CHECK(thread_checker_.CalledOnValidThread());
|
| CHECK(!running_);
|
|
|
| - frame_factory_ = new AndroidVideoCapturer::FrameFactory(
|
| - capture_format.width, capture_format.height, delegate_.get());
|
| + frame_factory_ = new AndroidVideoCapturer::FrameFactory(delegate_.get());
|
| set_frame_factory(frame_factory_);
|
|
|
| running_ = true;
|
| @@ -252,24 +191,14 @@ void AndroidVideoCapturer::OnCapturerStarted(bool success) {
|
| SignalStateChange(this, new_state);
|
| }
|
|
|
| -void AndroidVideoCapturer::OnIncomingFrame(void* frame_data,
|
| - int length,
|
| - int width,
|
| - int height,
|
| - int rotation,
|
| - int64 time_stamp) {
|
| +void AndroidVideoCapturer::OnIncomingFrame(
|
| + rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer,
|
| + int rotation,
|
| + int64 time_stamp) {
|
| CHECK(thread_checker_.CalledOnValidThread());
|
| - frame_factory_->UpdateCapturedFrame(frame_data, length, width, height,
|
| - rotation, time_stamp);
|
| + frame_factory_->UpdateCapturedFrame(buffer, rotation, time_stamp);
|
| SignalFrameCaptured(this, frame_factory_->GetCapturedFrame());
|
| - if (frame_factory_->GetCapturedFrame()->data == nullptr) {
|
| - // Ownership has been passed to a WrappedI420Buffer. Do nothing.
|
| - } else {
|
| - // |captured_frame_| has either been copied or dropped, return it
|
| - // immediately.
|
| - delegate_->ReturnBuffer(time_stamp);
|
| - frame_factory_->ClearCapturedFrame();
|
| - }
|
| + frame_factory_->ClearCapturedFrame();
|
| }
|
|
|
| void AndroidVideoCapturer::OnOutputFormatRequest(
|
|
|