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 |