Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/webrtc_video_renderer_adapter.h" | 5 #include "remoting/protocol/webrtc_video_renderer_adapter.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/memory/ptr_util.h" | |
| 13 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 15 #include "base/task_runner_util.h" | |
| 14 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
| 17 #include "base/threading/worker_pool.h" | |
| 15 #include "remoting/protocol/frame_consumer.h" | 18 #include "remoting/protocol/frame_consumer.h" |
| 16 #include "third_party/libyuv/include/libyuv/video_common.h" | 19 #include "third_party/libyuv/include/libyuv/video_common.h" |
| 17 #include "third_party/webrtc/media/base/videoframe.h" | 20 #include "third_party/webrtc/media/base/videoframe.h" |
| 18 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 21 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 19 | 22 |
| 20 namespace remoting { | 23 namespace remoting { |
| 21 namespace protocol { | 24 namespace protocol { |
| 22 | 25 |
| 26 namespace { | |
| 27 | |
| 28 std::unique_ptr<webrtc::DesktopFrame> ConvertYuvToRgb( | |
| 29 std::unique_ptr<cricket::VideoFrame> yuv_frame, | |
| 30 std::unique_ptr<webrtc::DesktopFrame> rgb_frame, | |
| 31 uint32_t format) { | |
| 32 yuv_frame->ConvertToRgbBuffer( | |
| 33 format, rgb_frame->data(), | |
| 34 std::abs(rgb_frame->stride()) * rgb_frame->size().height(), | |
| 35 rgb_frame->stride()); | |
| 36 rgb_frame->mutable_updated_region()->AddRect( | |
| 37 webrtc::DesktopRect::MakeSize(rgb_frame->size())); | |
| 38 return rgb_frame; | |
| 39 } | |
| 40 | |
| 41 } // namespace | |
| 42 | |
| 23 WebrtcVideoRendererAdapter::WebrtcVideoRendererAdapter( | 43 WebrtcVideoRendererAdapter::WebrtcVideoRendererAdapter( |
| 24 scoped_refptr<webrtc::MediaStreamInterface> media_stream, | 44 scoped_refptr<webrtc::MediaStreamInterface> media_stream, |
| 25 FrameConsumer* frame_consumer) | 45 FrameConsumer* frame_consumer) |
| 26 : media_stream_(std::move(media_stream)), | 46 : media_stream_(std::move(media_stream)), |
| 27 frame_consumer_(frame_consumer), | 47 frame_consumer_(frame_consumer), |
| 28 output_format_fourcc_(frame_consumer_->GetPixelFormat() == | 48 output_format_fourcc_(frame_consumer_->GetPixelFormat() == |
| 29 FrameConsumer::FORMAT_BGRA | 49 FrameConsumer::FORMAT_BGRA |
| 30 ? libyuv::FOURCC_ARGB | 50 ? libyuv::FOURCC_ARGB |
| 31 : libyuv::FOURCC_ABGR), | 51 : libyuv::FOURCC_ABGR), |
| 32 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 52 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 46 | 66 |
| 47 WebrtcVideoRendererAdapter::~WebrtcVideoRendererAdapter() { | 67 WebrtcVideoRendererAdapter::~WebrtcVideoRendererAdapter() { |
| 48 DCHECK(task_runner_->BelongsToCurrentThread()); | 68 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 49 | 69 |
| 50 webrtc::VideoTrackVector video_tracks = media_stream_->GetVideoTracks(); | 70 webrtc::VideoTrackVector video_tracks = media_stream_->GetVideoTracks(); |
| 51 DCHECK(!video_tracks.empty()); | 71 DCHECK(!video_tracks.empty()); |
| 52 video_tracks[0]->RemoveSink(this); | 72 video_tracks[0]->RemoveSink(this); |
| 53 } | 73 } |
| 54 | 74 |
| 55 void WebrtcVideoRendererAdapter::OnFrame(const cricket::VideoFrame& frame) { | 75 void WebrtcVideoRendererAdapter::OnFrame(const cricket::VideoFrame& frame) { |
| 56 // TODO(sergeyu): WebRTC calls OnFrame on a separate thread it creates. | 76 task_runner_->PostTask( |
| 57 // FrameConsumer normally expects to be called on the network thread, so we | 77 FROM_HERE, |
| 58 // cannot call FrameConsumer::AllocateFrame() here and instead | 78 base::Bind(&WebrtcVideoRendererAdapter::HandleFrameOnMainThread, |
| 59 // BasicDesktopFrame is created directly. This will not work correctly with | 79 weak_factory_.GetWeakPtr(), |
| 60 // all FrameConsumer implementations. Fix this somehow. | 80 base::Passed(base::WrapUnique(frame.Copy())))); |
|
Jamie
2016/06/13 21:22:51
Is the cost of this copy significant?
Sergey Ulanov
2016/06/13 22:34:55
No. It doesn't copy the buffer.
nisse-chromium (ooo August 14)
2016/06/21 11:40:02
Hi, I'm trying to delete this Copy method (cl http
Sergey Ulanov
2016/06/21 17:38:22
Copy() isn't marked as deprecated, so I assumed it
| |
| 61 std::unique_ptr<webrtc::DesktopFrame> rgb_frame(new webrtc::BasicDesktopFrame( | 81 } |
| 62 webrtc::DesktopSize(frame.width(), frame.height()))); | |
| 63 | 82 |
| 64 base::TimeDelta render_delay = std::max( | 83 void WebrtcVideoRendererAdapter::HandleFrameOnMainThread( |
| 65 base::TimeDelta(), base::TimeDelta::FromMicroseconds(static_cast<float>( | 84 std::unique_ptr<cricket::VideoFrame> frame) { |
| 66 frame.timestamp_us() - rtc::TimeMicros()))); | 85 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 67 | 86 |
| 68 frame.ConvertToRgbBuffer( | 87 std::unique_ptr<webrtc::DesktopFrame> rgb_frame = |
| 69 output_format_fourcc_, rgb_frame->data(), | 88 frame_consumer_->AllocateFrame( |
| 70 std::abs(rgb_frame->stride()) * rgb_frame->size().height(), | 89 webrtc::DesktopSize(frame->width(), frame->height())); |
| 71 rgb_frame->stride()); | 90 |
| 72 rgb_frame->mutable_updated_region()->AddRect( | 91 if (static_cast<uint64_t>(frame->timestamp_us()) >= rtc::TimeMicros()) { |
| 73 webrtc::DesktopRect::MakeSize(rgb_frame->size())); | 92 // The host sets playout delay to 0, so all incoming frames are expected to |
| 74 task_runner_->PostDelayedTask( | 93 // be rendered as so as they are received. |
| 75 FROM_HERE, | 94 LOG(WARNING) << "Received frame with playout delay greater than 0."; |
|
Jamie
2016/06/13 21:22:51
If this is never expected to happen, maybe it shou
Sergey Ulanov
2016/06/13 22:34:55
It's not supposed to happen, but it depends on the
| |
| 95 } | |
| 96 | |
| 97 base::PostTaskAndReplyWithResult( | |
| 98 base::WorkerPool::GetTaskRunner(false).get(), FROM_HERE, | |
| 99 base::Bind(&ConvertYuvToRgb, base::Passed(&frame), | |
| 100 base::Passed(&rgb_frame), output_format_fourcc_), | |
| 76 base::Bind(&WebrtcVideoRendererAdapter::DrawFrame, | 101 base::Bind(&WebrtcVideoRendererAdapter::DrawFrame, |
| 77 weak_factory_.GetWeakPtr(), base::Passed(&rgb_frame)), | 102 weak_factory_.GetWeakPtr())); |
| 78 render_delay); | |
| 79 } | 103 } |
| 80 | 104 |
| 81 void WebrtcVideoRendererAdapter::DrawFrame( | 105 void WebrtcVideoRendererAdapter::DrawFrame( |
| 82 std::unique_ptr<webrtc::DesktopFrame> frame) { | 106 std::unique_ptr<webrtc::DesktopFrame> frame) { |
| 83 DCHECK(task_runner_->BelongsToCurrentThread()); | 107 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 84 frame_consumer_->DrawFrame(std::move(frame), base::Closure()); | 108 frame_consumer_->DrawFrame(std::move(frame), base::Closure()); |
| 85 } | 109 } |
| 86 | 110 |
| 87 } // namespace protocol | 111 } // namespace protocol |
| 88 } // namespace remoting | 112 } // namespace remoting |
| OLD | NEW |