Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: remoting/test/test_video_renderer.cc

Issue 1214113009: Update TestVideoRenderer with video decoding capabilities (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/test/test_video_renderer.h" 5 #include "remoting/test/test_video_renderer.h"
6 6
7 #include "base/bind.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/synchronization/lock.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/thread.h"
12 #include "remoting/codec/video_decoder.h"
13 #include "remoting/codec/video_decoder_verbatim.h"
14 #include "remoting/codec/video_decoder_vpx.h"
8 #include "remoting/proto/video.pb.h" 15 #include "remoting/proto/video.pb.h"
16 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
17 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
9 18
10 namespace remoting { 19 namespace remoting {
11 namespace test { 20 namespace test {
12 21
13 TestVideoRenderer::TestVideoRenderer() : video_frames_processed_(0) { 22 // Implements video decoding functionality.
23 class TestVideoRenderer::Core {
24 public:
25 explicit Core(base::WeakPtr<TestVideoRenderer> renderer);
26 ~Core();
27
28 // Initializes the internal structures of the class.
29 void Initialize();
30
31 // Used to decode video packets.
32 void ProcessVideoPacket(scoped_ptr<VideoPacket> packet);
33
34 // Set negotiated Codec for decoder.
35 void SetDecoder(const protocol::ChannelConfig::Codec codec);
36
37 // Returns a copy of the current buffer.
38 scoped_ptr<webrtc::DesktopFrame> GetBufferForTest() const;
39
40 private:
41 // Used to ensure TestVideoRenderer::Core methods are called on the same
42 // thread.
43 base::ThreadChecker thread_checker_;
44
45 // Used to decode video packets.
46 scoped_ptr<VideoDecoder> decoder_;
47
48 // Updated region of the current desktop frame compared to previous one.
49 webrtc::DesktopRegion updated_region_;
50
51 // Screen size of the remote host.
52 webrtc::DesktopSize screen_size_;
53
54 // Holding a WeakPtr to the TestVideoRenderer
55 base::WeakPtr<TestVideoRenderer> renderer_;
56
57 // Used to post tasks back to main thread.
58 scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_;
joedow 2015/06/30 17:52:27 Can you rename 'renderer_task_runner_' to 'main_ta
liaoyuke 2015/06/30 19:34:59 Done.
59
60 // Used to store decoded video frame.
61 scoped_ptr<webrtc::DesktopFrame> buffer_;
62
63 // Protects access to |buffer_|.
64 mutable base::Lock lock_;
65
66 DISALLOW_COPY_AND_ASSIGN(Core);
67 };
68
69 TestVideoRenderer::Core::Core(base::WeakPtr<TestVideoRenderer> renderer)
70 : renderer_(renderer),
71 renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
72 thread_checker_.DetachFromThread();
73 }
74
75 TestVideoRenderer::Core::~Core() {
76 DCHECK(thread_checker_.CalledOnValidThread());
77 }
78
79 void TestVideoRenderer::Core::Initialize() {
80 DCHECK(thread_checker_.CalledOnValidThread());
81 }
82
83 void TestVideoRenderer::Core::SetDecoder(
84 const protocol::ChannelConfig::Codec codec) {
85 DCHECK(thread_checker_.CalledOnValidThread());
86
87 if (decoder_) {
88 LOG(WARNING) << "Decoder is set more than once";
89 }
90
91 switch (codec) {
92 case protocol::ChannelConfig::CODEC_VP8: {
93 DVLOG(2) << "Test Video Renderer will use VP8 decoder";
94 decoder_ = VideoDecoderVpx::CreateForVP8();
95 break;
96 }
97 case protocol::ChannelConfig::CODEC_VP9: {
98 DVLOG(2) << "Test Video Renderer will use VP9 decoder";
99 decoder_ = VideoDecoderVpx::CreateForVP9();
100 break;
101 }
102 case protocol::ChannelConfig::CODEC_VERBATIM: {
103 DVLOG(2) << "Test Video Renderer will use VERBATIM decoder";
104 decoder_.reset(new VideoDecoderVerbatim());
105 break;
106 }
107 default: {
108 NOTREACHED() << "Unsupported codec: " << codec;
109 }
110 }
111 }
112
113 scoped_ptr<webrtc::DesktopFrame>
114 TestVideoRenderer::Core::GetBufferForTest() const {
115 base::AutoLock auto_lock(lock_);
116 DCHECK(buffer_);
117 return make_scoped_ptr(webrtc::BasicDesktopFrame::CopyOf(*buffer_.get()));
118 }
119
120 void TestVideoRenderer::Core::ProcessVideoPacket(
121 scoped_ptr<VideoPacket> packet) {
122 DCHECK(thread_checker_.CalledOnValidThread());
123 DCHECK(decoder_);
124 DCHECK(packet);
125
126 DVLOG(2) << "TestVideoRenderer::Core::ProcessVideoPacket() Called";
127
128 // Screen size is attached on the first packet as well as when the
129 // host screen is resized.
130 if (packet->format().has_screen_width() &&
131 packet->format().has_screen_height()) {
132 webrtc::DesktopSize source_size(packet->format().screen_width(),
133 packet->format().screen_height());
134 if (!screen_size_.equals(source_size)) {
135 screen_size_ = source_size;
136 decoder_->Initialize(screen_size_);
137 buffer_.reset(new webrtc::BasicDesktopFrame(screen_size_));
138 }
139 }
140
141 // To make life easier, assume that the desktop shape is a single rectangle.
142 packet->clear_use_desktop_shape();
143 if (!decoder_->DecodePacket(*packet.get())) {
144 LOG(ERROR) << "Decoder::DecodePacket() failed.";
145 return;
146 }
147
148 {
149 base::AutoLock auto_lock(lock_);
150
151 // Render the decoded packet and write results to the buffer.
152 // Note that the |updated_region_| maintains the changed regions compared to
153 // previous video frame.
154 decoder_->RenderFrame(screen_size_,
155 webrtc::DesktopRect::MakeWH(screen_size_.width(),
156 screen_size_.height()), buffer_->data(),
157 buffer_->stride(), &updated_region_);
158 }
159
160 renderer_task_runner_->PostTask(
161 FROM_HERE, base::Bind(&TestVideoRenderer::OnPacketDone, renderer_));
joedow 2015/06/30 17:52:27 This would be a lot cleaner if we reuse the done c
liaoyuke 2015/06/30 19:34:59 Done.
162 }
163
164 TestVideoRenderer::TestVideoRenderer()
165 : video_decode_thread_(
166 new base::Thread("TestVideoRendererVideoDecodingThread")),
167 weak_factory_(this) {
168 DCHECK(thread_checker_.CalledOnValidThread());
169
170 core_.reset(new Core(weak_factory_.GetWeakPtr()));
171 if (!video_decode_thread_->Start()) {
172 LOG(ERROR) << "Cannot start TestVideoRenderer";
173 } else {
174 video_decode_task_runner_ = video_decode_thread_->task_runner();
175 video_decode_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Initialize,
176 base::Unretained(core_.get())));
177 }
14 } 178 }
15 179
16 TestVideoRenderer::~TestVideoRenderer() { 180 TestVideoRenderer::~TestVideoRenderer() {
181 DCHECK(thread_checker_.CalledOnValidThread());
182
183 video_decode_task_runner_->DeleteSoon(FROM_HERE, core_.release());
184
185 // The thread's message loop will run until it runs out of work.
186 video_decode_thread_->Stop();
17 } 187 }
18 188
19 void TestVideoRenderer::OnSessionConfig(const protocol::SessionConfig& config) { 189 void TestVideoRenderer::OnSessionConfig(const protocol::SessionConfig& config) {
190 DCHECK(thread_checker_.CalledOnValidThread());
191
20 DVLOG(2) << "TestVideoRenderer::OnSessionConfig() Called"; 192 DVLOG(2) << "TestVideoRenderer::OnSessionConfig() Called";
193 protocol::ChannelConfig::Codec codec = config.video_config().codec;
194 SetDecoder(codec);
21 } 195 }
22 196
23 ChromotingStats* TestVideoRenderer::GetStats() { 197 ChromotingStats* TestVideoRenderer::GetStats() {
198 DCHECK(thread_checker_.CalledOnValidThread());
199
24 DVLOG(2) << "TestVideoRenderer::GetStats() Called"; 200 DVLOG(2) << "TestVideoRenderer::GetStats() Called";
25 return nullptr; 201 return nullptr;
26 } 202 }
27 203
28 protocol::VideoStub* TestVideoRenderer::GetVideoStub() { 204 protocol::VideoStub* TestVideoRenderer::GetVideoStub() {
205 DCHECK(thread_checker_.CalledOnValidThread());
206
29 DVLOG(2) << "TestVideoRenderer::GetVideoStub() Called"; 207 DVLOG(2) << "TestVideoRenderer::GetVideoStub() Called";
30 return this; 208 return this;
31 } 209 }
32 210
33 void TestVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet, 211 void TestVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
34 const base::Closure& done) { 212 const base::Closure& done) {
35 if (!video_packet->data().empty()) { 213 DCHECK(thread_checker_.CalledOnValidThread());
36 // If the video frame was not a keep alive frame (i.e. not empty) then 214 DCHECK(video_decode_task_runner_) << "Failed to start video decode thread";
37 // count it. 215
38 DVLOG(2) << "Video Packet Processed, Total: " << ++video_frames_processed_; 216 if (video_packet->has_data() && video_packet->data().size() != 0) {
217 DVLOG(2) << "process video packet is called!";
218
219 // Post video process task to the video decode thread.
220 base::Closure process_video_task = base::Bind(
221 &TestVideoRenderer::Core::ProcessVideoPacket,
222 base::Unretained(core_.get()), base::Passed(&video_packet));
223 video_decode_task_runner_->PostTask(FROM_HERE, process_video_task);
39 } else { 224 } else {
40 // Log at a high verbosity level as we receive empty packets frequently and 225 // Log at a high verbosity level as we receive empty packets frequently and
41 // they can clutter up the debug output if the level is set too low. 226 // they can clutter up the debug output if the level is set too low.
42 DVLOG(3) << "Empty Video Packet received."; 227 DVLOG(3) << "Empty Video Packet received.";
43 } 228 }
44
45 done.Run(); 229 done.Run();
46 } 230 }
47 231
232 void TestVideoRenderer::SetDecoder(const protocol::ChannelConfig::Codec codec) {
233 DCHECK(thread_checker_.CalledOnValidThread());
234
235 DVLOG(2) << "TestVideoRenderer::SetDecoder() Called";
236 video_decode_task_runner_->PostTask(
237 FROM_HERE, base::Bind(&Core::SetDecoder, base::Unretained(core_.get()),
238 codec));
239 }
240
241 scoped_ptr<webrtc::DesktopFrame> TestVideoRenderer::GetBufferForTest() const {
242 DCHECK(thread_checker_.CalledOnValidThread());
243
244 return core_->GetBufferForTest();
245 }
246
247 void TestVideoRenderer::WaitForPacketDone(const base::Closure& done) {
248 DCHECK(thread_checker_.CalledOnValidThread());
249
250 main_closure_ = done;
251 }
252
253 void TestVideoRenderer::OnPacketDone() {
254 DCHECK(thread_checker_.CalledOnValidThread());
255
256 if (!main_closure_.is_null()) {
257 main_closure_.Run();
258 }
259 }
260
48 } // namespace test 261 } // namespace test
49 } // namespace remoting 262 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698