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

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: . 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 stats_.time_rendered = base::TimeTicks::Now();
Jamie 2016/06/24 23:53:21 Unless you feel strongly otherwise, I think this w
Sergey Ulanov 2016/06/25 05:34:03 Done.
44 if (perf_tracker_)
45 perf_tracker_->RecordVideoFrameStats(stats_);
46 if (!done_.is_null())
47 done_.Run();
48 }
42 49
43 const VideoPacket* packet() const { return packet_.get(); } 50 void OnDecoded() { stats_.time_decoded = base::TimeTicks::Now(); }
51 VideoPacket* packet() { return packet_.get(); }
44 52
45 private: 53 private:
46 std::unique_ptr<VideoPacket> packet_; 54 std::unique_ptr<VideoPacket> packet_;
47 base::ScopedClosureRunner done_runner_; 55 protocol::PerformanceTracker* perf_tracker_;
56 protocol::FrameStats stats_;
57 base::Closure done_;
48 }; 58 };
49 59
50
51 class PepperVideoRenderer3D::Picture { 60 class PepperVideoRenderer3D::Picture {
52 public: 61 public:
53 Picture(pp::VideoDecoder* decoder, PP_VideoPicture picture) 62 Picture(pp::VideoDecoder* decoder, PP_VideoPicture picture)
54 : decoder_(decoder), picture_(picture) {} 63 : decoder_(decoder), picture_(picture) {}
55 ~Picture() { decoder_->RecyclePicture(picture_); } 64 ~Picture() { decoder_->RecyclePicture(picture_); }
56 65
57 const PP_VideoPicture& picture() { return picture_; } 66 const PP_VideoPicture& picture() { return picture_; }
58 67
59 private: 68 private:
60 pp::VideoDecoder* decoder_; 69 pp::VideoDecoder* decoder_;
61 PP_VideoPicture picture_; 70 PP_VideoPicture picture_;
62 }; 71 };
63 72
64 PepperVideoRenderer3D::PepperVideoRenderer3D() : callback_factory_(this) {} 73 PepperVideoRenderer3D::PepperVideoRenderer3D() : callback_factory_(this) {}
65 74
66 PepperVideoRenderer3D::~PepperVideoRenderer3D() { 75 PepperVideoRenderer3D::~PepperVideoRenderer3D() {
67 if (shader_program_) 76 if (shader_program_)
68 gles2_if_->DeleteProgram(graphics_.pp_resource(), shader_program_); 77 gles2_if_->DeleteProgram(graphics_.pp_resource(), shader_program_);
69
70 STLDeleteElements(&pending_packets_);
71 } 78 }
72 79
73 bool PepperVideoRenderer3D::Initialize( 80 bool PepperVideoRenderer3D::Initialize(
74 pp::Instance* instance, 81 pp::Instance* instance,
75 const ClientContext& context, 82 const ClientContext& context,
76 EventHandler* event_handler, 83 EventHandler* event_handler,
77 protocol::PerformanceTracker* perf_tracker) { 84 protocol::PerformanceTracker* perf_tracker) {
78 DCHECK(event_handler); 85 DCHECK(event_handler);
79 DCHECK(!event_handler_); 86 DCHECK(!event_handler_);
80 87
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 protocol::FrameConsumer* PepperVideoRenderer3D::GetFrameConsumer() { 189 protocol::FrameConsumer* PepperVideoRenderer3D::GetFrameConsumer() {
183 // GetFrameConsumer() is used only for WebRTC-based connections which are not 190 // GetFrameConsumer() is used only for WebRTC-based connections which are not
184 // supported by the plugin. 191 // supported by the plugin.
185 NOTREACHED(); 192 NOTREACHED();
186 return nullptr; 193 return nullptr;
187 } 194 }
188 195
189 void PepperVideoRenderer3D::ProcessVideoPacket( 196 void PepperVideoRenderer3D::ProcessVideoPacket(
190 std::unique_ptr<VideoPacket> packet, 197 std::unique_ptr<VideoPacket> packet,
191 const base::Closure& done) { 198 const base::Closure& done) {
192 base::ScopedClosureRunner done_runner(done); 199 VideoPacket* packet_ptr = packet.get();
193 200 std::unique_ptr<FrameTracker> frame_tracker(
194 perf_tracker_->RecordVideoPacketStats(*packet); 201 new FrameTracker(std::move(packet), perf_tracker_, done));
195 202
196 // Don't need to do anything if the packet is empty. Host sends empty video 203 // Don't need to do anything if the packet is empty. Host sends empty video
197 // packets when the screen is not changing. 204 // packets when the screen is not changing.
198 if (!packet->data().size()) 205 if (!packet_ptr->data().size())
199 return; 206 return;
200 207
201 if (!frame_received_) { 208 if (!frame_received_) {
202 event_handler_->OnVideoFirstFrameReceived(); 209 event_handler_->OnVideoFirstFrameReceived();
203 frame_received_ = true; 210 frame_received_ = true;
204 } 211 }
205 212
206 if (packet->format().has_screen_width() && 213 if (packet_ptr->format().has_screen_width() &&
207 packet->format().has_screen_height()) { 214 packet_ptr->format().has_screen_height()) {
208 frame_size_.set(packet->format().screen_width(), 215 frame_size_.set(packet_ptr->format().screen_width(),
209 packet->format().screen_height()); 216 packet_ptr->format().screen_height());
210 } 217 }
211 218
212 // Report the dirty region, for debugging, if requested. 219 // Report the dirty region, for debugging, if requested.
213 if (debug_dirty_region_) { 220 if (debug_dirty_region_) {
214 webrtc::DesktopRegion dirty_region; 221 webrtc::DesktopRegion dirty_region;
215 for (int i = 0; i < packet->dirty_rects_size(); ++i) { 222 for (int i = 0; i < packet_ptr->dirty_rects_size(); ++i) {
216 Rect remoting_rect = packet->dirty_rects(i); 223 Rect remoting_rect = packet_ptr->dirty_rects(i);
217 dirty_region.AddRect(webrtc::DesktopRect::MakeXYWH( 224 dirty_region.AddRect(webrtc::DesktopRect::MakeXYWH(
218 remoting_rect.x(), remoting_rect.y(), 225 remoting_rect.x(), remoting_rect.y(), remoting_rect.width(),
219 remoting_rect.width(), remoting_rect.height())); 226 remoting_rect.height()));
220 } 227 }
221 event_handler_->OnVideoFrameDirtyRegion(dirty_region); 228 event_handler_->OnVideoFrameDirtyRegion(dirty_region);
222 } 229 }
223 230
224 pending_packets_.push_back( 231 pending_frames_.push_back(std::move(frame_tracker));
225 new PendingPacket(std::move(packet), done_runner.Release()));
226 DecodeNextPacket(); 232 DecodeNextPacket();
227 } 233 }
228 234
229 void PepperVideoRenderer3D::OnInitialized(int32_t result) { 235 void PepperVideoRenderer3D::OnInitialized(int32_t result) {
230 // Assume that VP8 and VP9 codecs are always supported by the browser. 236 // Assume that VP8 and VP9 codecs are always supported by the browser.
231 CHECK_EQ(result, PP_OK) << "VideoDecoder::Initialize() failed: " << result; 237 CHECK_EQ(result, PP_OK) << "VideoDecoder::Initialize() failed: " << result;
232 initialization_finished_ = true; 238 initialization_finished_ = true;
233 239
234 // Start decoding in case a frame was received during decoder initialization. 240 // Start decoding in case a frame was received during decoder initialization.
235 DecodeNextPacket(); 241 DecodeNextPacket();
236 } 242 }
237 243
238 void PepperVideoRenderer3D::DecodeNextPacket() { 244 void PepperVideoRenderer3D::DecodeNextPacket() {
239 if (!initialization_finished_ || decode_pending_ || pending_packets_.empty()) 245 if (!initialization_finished_ || decode_pending_ || pending_frames_.empty())
240 return; 246 return;
241 247
242 const VideoPacket* packet = pending_packets_.front()->packet(); 248 const VideoPacket* packet = pending_frames_.front()->packet();
243 249
244 int32_t result = video_decoder_.Decode( 250 int32_t result = video_decoder_.Decode(
245 packet->frame_id(), packet->data().size(), packet->data().data(), 251 packet->frame_id(), packet->data().size(), packet->data().data(),
246 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnDecodeDone)); 252 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnDecodeDone));
247 CHECK_EQ(result, PP_OK_COMPLETIONPENDING); 253 CHECK_EQ(result, PP_OK_COMPLETIONPENDING);
248 decode_pending_ = true; 254 decode_pending_ = true;
249 } 255 }
250 256
251 void PepperVideoRenderer3D::OnDecodeDone(int32_t result) { 257 void PepperVideoRenderer3D::OnDecodeDone(int32_t result) {
252 DCHECK(decode_pending_); 258 DCHECK(decode_pending_);
253 decode_pending_ = false; 259 decode_pending_ = false;
254 260
255 if (result != PP_OK) { 261 if (result != PP_OK) {
256 LOG(ERROR) << "VideoDecoder::Decode() returned " << result; 262 LOG(ERROR) << "VideoDecoder::Decode() returned " << result;
257 event_handler_->OnVideoDecodeError(); 263 event_handler_->OnVideoDecodeError();
258 return; 264 return;
259 } 265 }
260 266
261 delete pending_packets_.front(); 267 pending_frames_.front()->OnDecoded();
262 pending_packets_.pop_front(); 268 // Move the frame from |pending_frames_| to |decoded_frames_|.
269 decoded_frames_.splice(decoded_frames_.end(), pending_frames_,
270 pending_frames_.begin());
263 271
264 DecodeNextPacket(); 272 DecodeNextPacket();
265 GetNextPicture(); 273 GetNextPicture();
266 } 274 }
267 275
268 void PepperVideoRenderer3D::GetNextPicture() { 276 void PepperVideoRenderer3D::GetNextPicture() {
269 if (get_picture_pending_) 277 if (get_picture_pending_)
270 return; 278 return;
271 279
272 int32_t result = 280 int32_t result =
273 video_decoder_.GetPicture(callback_factory_.NewCallbackWithOutput( 281 video_decoder_.GetPicture(callback_factory_.NewCallbackWithOutput(
274 &PepperVideoRenderer3D::OnPictureReady)); 282 &PepperVideoRenderer3D::OnPictureReady));
275 CHECK_EQ(result, PP_OK_COMPLETIONPENDING); 283 CHECK_EQ(result, PP_OK_COMPLETIONPENDING);
276 get_picture_pending_ = true; 284 get_picture_pending_ = true;
277 } 285 }
278 286
279 void PepperVideoRenderer3D::OnPictureReady(int32_t result, 287 void PepperVideoRenderer3D::OnPictureReady(int32_t result,
280 PP_VideoPicture picture) { 288 PP_VideoPicture picture) {
281 DCHECK(get_picture_pending_); 289 DCHECK(get_picture_pending_);
282 get_picture_pending_ = false; 290 get_picture_pending_ = false;
283 291
284 if (result != PP_OK) { 292 if (result != PP_OK) {
285 LOG(ERROR) << "VideoDecoder::GetPicture() returned " << result; 293 LOG(ERROR) << "VideoDecoder::GetPicture() returned " << result;
286 event_handler_->OnVideoDecodeError(); 294 event_handler_->OnVideoDecodeError();
287 return; 295 return;
288 } 296 }
289 297
290 perf_tracker_->OnFrameDecoded(picture.decode_id);
291
292 // Workaround crbug.com/542945 by filling in visible_rect if it isn't set. 298 // Workaround crbug.com/542945 by filling in visible_rect if it isn't set.
293 if (picture.visible_rect.size.width == 0 || 299 if (picture.visible_rect.size.width == 0 ||
294 picture.visible_rect.size.height == 0) { 300 picture.visible_rect.size.height == 0) {
295 static bool warning_logged = false; 301 static bool warning_logged = false;
296 if (!warning_logged) { 302 if (!warning_logged) {
297 LOG(WARNING) << "PPB_VideoDecoder doesn't set visible_rect."; 303 LOG(WARNING) << "PPB_VideoDecoder doesn't set visible_rect.";
298 warning_logged = true; 304 warning_logged = true;
299 } 305 }
300 306
301 picture.visible_rect.size.width = 307 picture.visible_rect.size.width =
302 std::min(frame_size_.width(), picture.texture_size.width); 308 std::min(frame_size_.width(), picture.texture_size.width);
303 picture.visible_rect.size.height = 309 picture.visible_rect.size.height =
304 std::min(frame_size_.height(), picture.texture_size.height); 310 std::min(frame_size_.height(), picture.texture_size.height);
305 } 311 }
306 312
313 DCHECK_EQ(static_cast<int32_t>(picture.decode_id),
314 decoded_frames_.front()->packet()->frame_id());
315
316 // Move the frame from |decoded_frames_| to |next_picture_frames_|.
317 next_picture_frames_.splice(next_picture_frames_.end(), decoded_frames_,
318 decoded_frames_.begin());
319
307 next_picture_.reset(new Picture(&video_decoder_, picture)); 320 next_picture_.reset(new Picture(&video_decoder_, picture));
308 321
309 PaintIfNeeded(); 322 PaintIfNeeded();
310 GetNextPicture(); 323 GetNextPicture();
311 } 324 }
312 325
313 void PepperVideoRenderer3D::PaintIfNeeded() { 326 void PepperVideoRenderer3D::PaintIfNeeded() {
314 bool need_repaint = next_picture_ || (force_repaint_ && current_picture_); 327 bool need_repaint = next_picture_ || (force_repaint_ && current_picture_);
315 if (paint_pending_ || !need_repaint) 328 if (paint_pending_ || !need_repaint)
316 return; 329 return;
317 330
318 if (next_picture_) 331 if (next_picture_) {
319 current_picture_ = std::move(next_picture_); 332 current_picture_ = std::move(next_picture_);
333 current_picture_frames_.splice(current_picture_frames_.end(),
334 next_picture_frames_);
335 }
320 336
321 force_repaint_ = false; 337 force_repaint_ = false;
322 338
323 const PP_VideoPicture& picture = current_picture_->picture(); 339 const PP_VideoPicture& picture = current_picture_->picture();
324 PP_Resource graphics_3d = graphics_.pp_resource(); 340 PP_Resource graphics_3d = graphics_.pp_resource();
325 341
326 EnsureProgramForTexture(picture.texture_target); 342 EnsureProgramForTexture(picture.texture_target);
327 343
328 gles2_if_->UseProgram(graphics_3d, shader_program_); 344 gles2_if_->UseProgram(graphics_3d, shader_program_);
329 345
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 int32_t result = graphics_.SwapBuffers( 391 int32_t result = graphics_.SwapBuffers(
376 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnPaintDone)); 392 callback_factory_.NewCallback(&PepperVideoRenderer3D::OnPaintDone));
377 CHECK_EQ(result, PP_OK_COMPLETIONPENDING); 393 CHECK_EQ(result, PP_OK_COMPLETIONPENDING);
378 paint_pending_ = true; 394 paint_pending_ = true;
379 } 395 }
380 396
381 void PepperVideoRenderer3D::OnPaintDone(int32_t result) { 397 void PepperVideoRenderer3D::OnPaintDone(int32_t result) {
382 CHECK_EQ(result, PP_OK) << "Graphics3D::SwapBuffers() failed"; 398 CHECK_EQ(result, PP_OK) << "Graphics3D::SwapBuffers() failed";
383 399
384 paint_pending_ = false; 400 paint_pending_ = false;
385 perf_tracker_->OnFramePainted(current_picture_->picture().decode_id); 401 current_picture_frames_.clear();
386 PaintIfNeeded(); 402 PaintIfNeeded();
387 } 403 }
388 404
389 void PepperVideoRenderer3D::EnsureProgramForTexture(uint32_t texture_target) { 405 void PepperVideoRenderer3D::EnsureProgramForTexture(uint32_t texture_target) {
390 static const char kVertexShader[] = 406 static const char kVertexShader[] =
391 "varying vec2 v_texCoord; \n" 407 "varying vec2 v_texCoord; \n"
392 "attribute vec4 a_position; \n" 408 "attribute vec4 a_position; \n"
393 "attribute vec2 a_texCoord; \n" 409 "attribute vec2 a_texCoord; \n"
394 "uniform vec2 v_scale; \n" 410 "uniform vec2 v_scale; \n"
395 "void main() \n" 411 "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); 509 gles2_if_->AttachShader(graphics_.pp_resource(), shader_program_, shader);
494 gles2_if_->DeleteShader(graphics_.pp_resource(), shader); 510 gles2_if_->DeleteShader(graphics_.pp_resource(), shader);
495 } 511 }
496 512
497 void PepperVideoRenderer3D::CheckGLError() { 513 void PepperVideoRenderer3D::CheckGLError() {
498 GLenum error = gles2_if_->GetError(graphics_.pp_resource()); 514 GLenum error = gles2_if_->GetError(graphics_.pp_resource());
499 CHECK_EQ(error, static_cast<GLenum>(GL_NO_ERROR)) << "GL error: " << error; 515 CHECK_EQ(error, static_cast<GLenum>(GL_NO_ERROR)) << "GL error: " << error;
500 } 516 }
501 517
502 } // namespace remoting 518 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698