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

Side by Side Diff: remoting/client/plugin/pepper_video_renderer_3d.cc

Issue 2096643003: Rework PerformanceTracker to make it usable with WebRTC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address feedback Created 4 years, 6 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/client/plugin/pepper_video_renderer_3d.h" 5 #include "remoting/client/plugin/pepper_video_renderer_3d.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <algorithm>
9 #include <utility> 10 #include <utility>
10 11
11 #include "base/callback_helpers.h"
12 #include "base/stl_util.h"
13 #include "ppapi/c/pp_codecs.h" 12 #include "ppapi/c/pp_codecs.h"
14 #include "ppapi/c/ppb_opengles2.h" 13 #include "ppapi/c/ppb_opengles2.h"
15 #include "ppapi/c/ppb_video_decoder.h" 14 #include "ppapi/c/ppb_video_decoder.h"
16 #include "ppapi/cpp/instance.h" 15 #include "ppapi/cpp/instance.h"
17 #include "ppapi/lib/gl/include/GLES2/gl2.h" 16 #include "ppapi/lib/gl/include/GLES2/gl2.h"
18 #include "ppapi/lib/gl/include/GLES2/gl2ext.h" 17 #include "ppapi/lib/gl/include/GLES2/gl2ext.h"
19 #include "remoting/proto/video.pb.h" 18 #include "remoting/proto/video.pb.h"
19 #include "remoting/protocol/frame_stats.h"
20 #include "remoting/protocol/performance_tracker.h" 20 #include "remoting/protocol/performance_tracker.h"
21 #include "remoting/protocol/session_config.h" 21 #include "remoting/protocol/session_config.h"
22 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" 22 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
23 23
24 namespace remoting { 24 namespace remoting {
25 25
26 // The implementation here requires that the decoder allocates at least 3 26 // The implementation here requires that the decoder allocates at least 3
27 // pictures. PPB_VideoDecoder didn't support this parameter prior to 27 // pictures. PPB_VideoDecoder didn't support this parameter prior to
28 // 1.1, so we have to pass 0 for backwards compatibility with older versions of 28 // 1.1, so we have to pass 0 for backwards compatibility with older versions of
29 // the browser. Currently all API implementations allocate more than 3 buffers 29 // the browser. Currently all API implementations allocate more than 3 buffers
30 // by default. 30 // by default.
31 // 31 const uint32_t kMinimumPictureCount = 3;
32 // TODO(sergeyu): Change this to 3 once PPB_VideoDecoder v1.1 is enabled on
33 // stable channel (crbug.com/520323).
34 const uint32_t kMinimumPictureCount = 0; // 3
35 32
36 class PepperVideoRenderer3D::PendingPacket { 33 class PepperVideoRenderer3D::FrameTracker {
37 public: 34 public:
38 PendingPacket(std::unique_ptr<VideoPacket> packet, const base::Closure& done) 35 FrameTracker(std::unique_ptr<VideoPacket> packet,
39 : packet_(std::move(packet)), done_runner_(done) {} 36 protocol::PerformanceTracker* perf_tracker,
37 const base::Closure& done)
38 : packet_(std::move(packet)), perf_tracker_(perf_tracker), done_(done) {
39 stats_ = protocol::FrameStats::GetForVideoPacket(*packet_);
40 }
40 41
41 ~PendingPacket() {} 42 ~FrameTracker() {
43 if (perf_tracker_)
44 perf_tracker_->RecordVideoFrameStats(stats_);
45 if (!done_.is_null())
46 done_.Run();
47 }
42 48
43 const VideoPacket* packet() const { return packet_.get(); } 49 void OnDecoded() { stats_.time_decoded = base::TimeTicks::Now(); }
50 void OnRendered() { stats_.time_rendered = base::TimeTicks::Now(); }
51
52 VideoPacket* packet() { return packet_.get(); }
44 53
45 private: 54 private:
46 std::unique_ptr<VideoPacket> packet_; 55 std::unique_ptr<VideoPacket> packet_;
47 base::ScopedClosureRunner done_runner_; 56 protocol::PerformanceTracker* perf_tracker_;
57 protocol::FrameStats stats_;
58 base::Closure done_;
48 }; 59 };
49 60
50
51 class PepperVideoRenderer3D::Picture { 61 class PepperVideoRenderer3D::Picture {
52 public: 62 public:
53 Picture(pp::VideoDecoder* decoder, PP_VideoPicture picture) 63 Picture(pp::VideoDecoder* decoder, PP_VideoPicture picture)
54 : decoder_(decoder), picture_(picture) {} 64 : decoder_(decoder), picture_(picture) {}
55 ~Picture() { decoder_->RecyclePicture(picture_); } 65 ~Picture() { decoder_->RecyclePicture(picture_); }
56 66
57 const PP_VideoPicture& picture() { return picture_; } 67 const PP_VideoPicture& picture() { return picture_; }
58 68
59 private: 69 private:
60 pp::VideoDecoder* decoder_; 70 pp::VideoDecoder* decoder_;
61 PP_VideoPicture picture_; 71 PP_VideoPicture picture_;
62 }; 72 };
63 73
64 PepperVideoRenderer3D::PepperVideoRenderer3D() : callback_factory_(this) {} 74 PepperVideoRenderer3D::PepperVideoRenderer3D() : callback_factory_(this) {}
65 75
66 PepperVideoRenderer3D::~PepperVideoRenderer3D() { 76 PepperVideoRenderer3D::~PepperVideoRenderer3D() {
67 if (shader_program_) 77 if (shader_program_)
68 gles2_if_->DeleteProgram(graphics_.pp_resource(), shader_program_); 78 gles2_if_->DeleteProgram(graphics_.pp_resource(), shader_program_);
69
70 STLDeleteElements(&pending_packets_);
71 } 79 }
72 80
73 bool PepperVideoRenderer3D::Initialize( 81 bool PepperVideoRenderer3D::Initialize(
74 pp::Instance* instance, 82 pp::Instance* instance,
75 const ClientContext& context, 83 const ClientContext& context,
76 EventHandler* event_handler, 84 EventHandler* event_handler,
77 protocol::PerformanceTracker* perf_tracker) { 85 protocol::PerformanceTracker* perf_tracker) {
78 DCHECK(event_handler); 86 DCHECK(event_handler);
79 DCHECK(!event_handler_); 87 DCHECK(!event_handler_);
80 88
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 protocol::FrameConsumer* PepperVideoRenderer3D::GetFrameConsumer() { 190 protocol::FrameConsumer* PepperVideoRenderer3D::GetFrameConsumer() {
183 // GetFrameConsumer() is used only for WebRTC-based connections which are not 191 // GetFrameConsumer() is used only for WebRTC-based connections which are not
184 // supported by the plugin. 192 // supported by the plugin.
185 NOTREACHED(); 193 NOTREACHED();
186 return nullptr; 194 return nullptr;
187 } 195 }
188 196
189 void PepperVideoRenderer3D::ProcessVideoPacket( 197 void PepperVideoRenderer3D::ProcessVideoPacket(
190 std::unique_ptr<VideoPacket> packet, 198 std::unique_ptr<VideoPacket> packet,
191 const base::Closure& done) { 199 const base::Closure& done) {
192 base::ScopedClosureRunner done_runner(done); 200 VideoPacket* packet_ptr = packet.get();
193 201 std::unique_ptr<FrameTracker> frame_tracker(
194 perf_tracker_->RecordVideoPacketStats(*packet); 202 new FrameTracker(std::move(packet), perf_tracker_, done));
195 203
196 // Don't need to do anything if the packet is empty. Host sends empty video 204 // Don't need to do anything if the packet is empty. Host sends empty video
197 // packets when the screen is not changing. 205 // packets when the screen is not changing.
198 if (!packet->data().size()) 206 if (!packet_ptr->data().size())
199 return; 207 return;
200 208
201 if (!frame_received_) { 209 if (!frame_received_) {
202 event_handler_->OnVideoFirstFrameReceived(); 210 event_handler_->OnVideoFirstFrameReceived();
203 frame_received_ = true; 211 frame_received_ = true;
204 } 212 }
205 213
206 if (packet->format().has_screen_width() && 214 if (packet_ptr->format().has_screen_width() &&
207 packet->format().has_screen_height()) { 215 packet_ptr->format().has_screen_height()) {
208 frame_size_.set(packet->format().screen_width(), 216 frame_size_.set(packet_ptr->format().screen_width(),
209 packet->format().screen_height()); 217 packet_ptr->format().screen_height());
210 } 218 }
211 219
212 // Report the dirty region, for debugging, if requested. 220 // Report the dirty region, for debugging, if requested.
213 if (debug_dirty_region_) { 221 if (debug_dirty_region_) {
214 webrtc::DesktopRegion dirty_region; 222 webrtc::DesktopRegion dirty_region;
215 for (int i = 0; i < packet->dirty_rects_size(); ++i) { 223 for (int i = 0; i < packet_ptr->dirty_rects_size(); ++i) {
216 Rect remoting_rect = packet->dirty_rects(i); 224 Rect remoting_rect = packet_ptr->dirty_rects(i);
217 dirty_region.AddRect(webrtc::DesktopRect::MakeXYWH( 225 dirty_region.AddRect(webrtc::DesktopRect::MakeXYWH(
218 remoting_rect.x(), remoting_rect.y(), 226 remoting_rect.x(), remoting_rect.y(), remoting_rect.width(),
219 remoting_rect.width(), remoting_rect.height())); 227 remoting_rect.height()));
220 } 228 }
221 event_handler_->OnVideoFrameDirtyRegion(dirty_region); 229 event_handler_->OnVideoFrameDirtyRegion(dirty_region);
222 } 230 }
223 231
224 pending_packets_.push_back( 232 pending_frames_.push_back(std::move(frame_tracker));
225 new PendingPacket(std::move(packet), done_runner.Release()));
226 DecodeNextPacket(); 233 DecodeNextPacket();
227 } 234 }
228 235
229 void PepperVideoRenderer3D::OnInitialized(int32_t result) { 236 void PepperVideoRenderer3D::OnInitialized(int32_t result) {
230 // Assume that VP8 and VP9 codecs are always supported by the browser. 237 // Assume that VP8 and VP9 codecs are always supported by the browser.
231 CHECK_EQ(result, PP_OK) << "VideoDecoder::Initialize() failed: " << result; 238 CHECK_EQ(result, PP_OK) << "VideoDecoder::Initialize() failed: " << result;
232 initialization_finished_ = true; 239 initialization_finished_ = true;
233 240
234 // Start decoding in case a frame was received during decoder initialization. 241 // Start decoding in case a frame was received during decoder initialization.
235 DecodeNextPacket(); 242 DecodeNextPacket();
236 } 243 }
237 244
238 void PepperVideoRenderer3D::DecodeNextPacket() { 245 void PepperVideoRenderer3D::DecodeNextPacket() {
239 if (!initialization_finished_ || decode_pending_ || pending_packets_.empty()) 246 if (!initialization_finished_ || decode_pending_ || pending_frames_.empty())
240 return; 247 return;
241 248
242 const VideoPacket* packet = pending_packets_.front()->packet(); 249 const VideoPacket* packet = pending_frames_.front()->packet();
243 250
244 int32_t result = video_decoder_.Decode( 251 int32_t result = video_decoder_.Decode(
245 packet->frame_id(), packet->data().size(), packet->data().data(), 252 packet->frame_id(), packet->data().size(), packet->data().data(),
246 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnDecodeDone)); 253 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnDecodeDone));
247 CHECK_EQ(result, PP_OK_COMPLETIONPENDING); 254 CHECK_EQ(result, PP_OK_COMPLETIONPENDING);
248 decode_pending_ = true; 255 decode_pending_ = true;
249 } 256 }
250 257
251 void PepperVideoRenderer3D::OnDecodeDone(int32_t result) { 258 void PepperVideoRenderer3D::OnDecodeDone(int32_t result) {
252 DCHECK(decode_pending_); 259 DCHECK(decode_pending_);
253 decode_pending_ = false; 260 decode_pending_ = false;
254 261
255 if (result != PP_OK) { 262 if (result != PP_OK) {
256 LOG(ERROR) << "VideoDecoder::Decode() returned " << result; 263 LOG(ERROR) << "VideoDecoder::Decode() returned " << result;
257 event_handler_->OnVideoDecodeError(); 264 event_handler_->OnVideoDecodeError();
258 return; 265 return;
259 } 266 }
260 267
261 delete pending_packets_.front(); 268 pending_frames_.front()->OnDecoded();
262 pending_packets_.pop_front(); 269 // Move the frame from |pending_frames_| to |decoded_frames_|.
270 decoded_frames_.splice(decoded_frames_.end(), pending_frames_,
271 pending_frames_.begin());
263 272
264 DecodeNextPacket(); 273 DecodeNextPacket();
265 GetNextPicture(); 274 GetNextPicture();
266 } 275 }
267 276
268 void PepperVideoRenderer3D::GetNextPicture() { 277 void PepperVideoRenderer3D::GetNextPicture() {
269 if (get_picture_pending_) 278 if (get_picture_pending_)
270 return; 279 return;
271 280
272 int32_t result = 281 int32_t result =
273 video_decoder_.GetPicture(callback_factory_.NewCallbackWithOutput( 282 video_decoder_.GetPicture(callback_factory_.NewCallbackWithOutput(
274 &PepperVideoRenderer3D::OnPictureReady)); 283 &PepperVideoRenderer3D::OnPictureReady));
275 CHECK_EQ(result, PP_OK_COMPLETIONPENDING); 284 CHECK_EQ(result, PP_OK_COMPLETIONPENDING);
276 get_picture_pending_ = true; 285 get_picture_pending_ = true;
277 } 286 }
278 287
279 void PepperVideoRenderer3D::OnPictureReady(int32_t result, 288 void PepperVideoRenderer3D::OnPictureReady(int32_t result,
280 PP_VideoPicture picture) { 289 PP_VideoPicture picture) {
281 DCHECK(get_picture_pending_); 290 DCHECK(get_picture_pending_);
282 get_picture_pending_ = false; 291 get_picture_pending_ = false;
283 292
284 if (result != PP_OK) { 293 if (result != PP_OK) {
285 LOG(ERROR) << "VideoDecoder::GetPicture() returned " << result; 294 LOG(ERROR) << "VideoDecoder::GetPicture() returned " << result;
286 event_handler_->OnVideoDecodeError(); 295 event_handler_->OnVideoDecodeError();
287 return; 296 return;
288 } 297 }
289 298
290 perf_tracker_->OnFrameDecoded(picture.decode_id);
291
292 // Workaround crbug.com/542945 by filling in visible_rect if it isn't set. 299 // Workaround crbug.com/542945 by filling in visible_rect if it isn't set.
293 if (picture.visible_rect.size.width == 0 || 300 if (picture.visible_rect.size.width == 0 ||
294 picture.visible_rect.size.height == 0) { 301 picture.visible_rect.size.height == 0) {
295 static bool warning_logged = false; 302 static bool warning_logged = false;
296 if (!warning_logged) { 303 if (!warning_logged) {
297 LOG(WARNING) << "PPB_VideoDecoder doesn't set visible_rect."; 304 LOG(WARNING) << "PPB_VideoDecoder doesn't set visible_rect.";
298 warning_logged = true; 305 warning_logged = true;
299 } 306 }
300 307
301 picture.visible_rect.size.width = 308 picture.visible_rect.size.width =
302 std::min(frame_size_.width(), picture.texture_size.width); 309 std::min(frame_size_.width(), picture.texture_size.width);
303 picture.visible_rect.size.height = 310 picture.visible_rect.size.height =
304 std::min(frame_size_.height(), picture.texture_size.height); 311 std::min(frame_size_.height(), picture.texture_size.height);
305 } 312 }
306 313
314 DCHECK_EQ(static_cast<int32_t>(picture.decode_id),
315 decoded_frames_.front()->packet()->frame_id());
316
317 // Move the frame from |decoded_frames_| to |next_picture_frames_|.
318 next_picture_frames_.splice(next_picture_frames_.end(), decoded_frames_,
319 decoded_frames_.begin());
320
307 next_picture_.reset(new Picture(&video_decoder_, picture)); 321 next_picture_.reset(new Picture(&video_decoder_, picture));
308 322
309 PaintIfNeeded(); 323 PaintIfNeeded();
310 GetNextPicture(); 324 GetNextPicture();
311 } 325 }
312 326
313 void PepperVideoRenderer3D::PaintIfNeeded() { 327 void PepperVideoRenderer3D::PaintIfNeeded() {
314 bool need_repaint = next_picture_ || (force_repaint_ && current_picture_); 328 bool need_repaint = next_picture_ || (force_repaint_ && current_picture_);
315 if (paint_pending_ || !need_repaint) 329 if (paint_pending_ || !need_repaint)
316 return; 330 return;
317 331
318 if (next_picture_) 332 if (next_picture_) {
319 current_picture_ = std::move(next_picture_); 333 current_picture_ = std::move(next_picture_);
334 current_picture_frames_.splice(current_picture_frames_.end(),
335 next_picture_frames_);
336 }
320 337
321 force_repaint_ = false; 338 force_repaint_ = false;
322 339
323 const PP_VideoPicture& picture = current_picture_->picture(); 340 const PP_VideoPicture& picture = current_picture_->picture();
324 PP_Resource graphics_3d = graphics_.pp_resource(); 341 PP_Resource graphics_3d = graphics_.pp_resource();
325 342
326 EnsureProgramForTexture(picture.texture_target); 343 EnsureProgramForTexture(picture.texture_target);
327 344
328 gles2_if_->UseProgram(graphics_3d, shader_program_); 345 gles2_if_->UseProgram(graphics_3d, shader_program_);
329 346
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 int32_t result = graphics_.SwapBuffers( 392 int32_t result = graphics_.SwapBuffers(
376 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnPaintDone)); 393 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnPaintDone));
377 CHECK_EQ(result, PP_OK_COMPLETIONPENDING); 394 CHECK_EQ(result, PP_OK_COMPLETIONPENDING);
378 paint_pending_ = true; 395 paint_pending_ = true;
379 } 396 }
380 397
381 void PepperVideoRenderer3D::OnPaintDone(int32_t result) { 398 void PepperVideoRenderer3D::OnPaintDone(int32_t result) {
382 CHECK_EQ(result, PP_OK) << "Graphics3D::SwapBuffers() failed"; 399 CHECK_EQ(result, PP_OK) << "Graphics3D::SwapBuffers() failed";
383 400
384 paint_pending_ = false; 401 paint_pending_ = false;
385 perf_tracker_->OnFramePainted(current_picture_->picture().decode_id); 402
403 for (const auto& tracker : current_picture_frames_) {
404 tracker->OnRendered();
405 }
406 current_picture_frames_.clear();
407
386 PaintIfNeeded(); 408 PaintIfNeeded();
387 } 409 }
388 410
389 void PepperVideoRenderer3D::EnsureProgramForTexture(uint32_t texture_target) { 411 void PepperVideoRenderer3D::EnsureProgramForTexture(uint32_t texture_target) {
390 static const char kVertexShader[] = 412 static const char kVertexShader[] =
391 "varying vec2 v_texCoord; \n" 413 "varying vec2 v_texCoord; \n"
392 "attribute vec4 a_position; \n" 414 "attribute vec4 a_position; \n"
393 "attribute vec2 a_texCoord; \n" 415 "attribute vec2 a_texCoord; \n"
394 "uniform vec2 v_scale; \n" 416 "uniform vec2 v_scale; \n"
395 "void main() \n" 417 "void main() \n"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 gles2_if_->AttachShader(graphics_.pp_resource(), shader_program_, shader); 515 gles2_if_->AttachShader(graphics_.pp_resource(), shader_program_, shader);
494 gles2_if_->DeleteShader(graphics_.pp_resource(), shader); 516 gles2_if_->DeleteShader(graphics_.pp_resource(), shader);
495 } 517 }
496 518
497 void PepperVideoRenderer3D::CheckGLError() { 519 void PepperVideoRenderer3D::CheckGLError() {
498 GLenum error = gles2_if_->GetError(graphics_.pp_resource()); 520 GLenum error = gles2_if_->GetError(graphics_.pp_resource());
499 CHECK_EQ(error, static_cast<GLenum>(GL_NO_ERROR)) << "GL error: " << error; 521 CHECK_EQ(error, static_cast<GLenum>(GL_NO_ERROR)) << "GL error: " << error;
500 } 522 }
501 523
502 } // namespace remoting 524 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/plugin/pepper_video_renderer_3d.h ('k') | remoting/client/software_video_renderer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698