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

Side by Side Diff: content/browser/devtools/protocol/frame_recorder.cc

Issue 888573002: DevTools: FrameRecorder: add cancelRecordingFrames command (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 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 "content/browser/devtools/protocol/frame_recorder.h" 5 #include "content/browser/devtools/protocol/frame_recorder.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/task_runner_util.h" 10 #include "base/task_runner_util.h"
11 #include "base/threading/worker_pool.h" 11 #include "base/threading/worker_pool.h"
12 #include "content/browser/renderer_host/render_view_host_impl.h" 12 #include "content/browser/renderer_host/render_view_host_impl.h"
13 #include "content/browser/renderer_host/render_widget_host_view_base.h" 13 #include "content/browser/renderer_host/render_widget_host_view_base.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "ui/gfx/codec/png_codec.h" 15 #include "ui/gfx/codec/png_codec.h"
16 #include "ui/gfx/geometry/size.h" 16 #include "ui/gfx/geometry/size.h"
17 17
18 namespace content { 18 namespace content {
19 namespace devtools { 19 namespace devtools {
20 namespace page { 20 namespace page {
21 21
22 namespace { 22 namespace {
23 23
24 static int kMaxRecordFrameCount = 180; 24 static int kMaxRecordFrameCount = 180;
25 25
26 std::string EncodeFrame(const SkBitmap& bitmap) { 26 std::pair<std::string, double> EncodeFrame(
dgozman 2015/01/29 17:53:06 Looks like you are copying encoded data a number o
eustas 2015/01/30 09:26:30 Done. Wrapped to scoped_ptr
27 const SkBitmap& bitmap, double timestamp) {
27 std::vector<unsigned char> data; 28 std::vector<unsigned char> data;
28 SkAutoLockPixels lock_image(bitmap); 29 SkAutoLockPixels lock_image(bitmap);
29 bool encoded = gfx::PNGCodec::Encode( 30 bool encoded = gfx::PNGCodec::Encode(
30 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), 31 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
31 gfx::PNGCodec::FORMAT_SkBitmap, 32 gfx::PNGCodec::FORMAT_SkBitmap,
32 gfx::Size(bitmap.width(), bitmap.height()), 33 gfx::Size(bitmap.width(), bitmap.height()),
33 bitmap.width() * bitmap.bytesPerPixel(), 34 bitmap.width() * bitmap.bytesPerPixel(),
34 false, std::vector<gfx::PNGCodec::Comment>(), &data); 35 false, std::vector<gfx::PNGCodec::Comment>(), &data);
35 36
36 if (!encoded) 37 if (!encoded)
37 return std::string(); 38 return std::make_pair(std::string(), timestamp);
38 39
39 std::string base_64_data; 40 std::string base_64_data;
40 base::Base64Encode( 41 base::Base64Encode(
41 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), 42 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()),
42 &base_64_data); 43 &base_64_data);
43 44
44 return base_64_data; 45 return std::make_pair(base_64_data, timestamp);
45 } 46 }
46 } // namespace 47 } // namespace
47 48
48 typedef DevToolsProtocolClient::Response Response; 49 typedef DevToolsProtocolClient::Response Response;
49 50
50 FrameRecorder::FrameRecorder() 51 FrameRecorder::FrameRecorder()
51 : host_(nullptr), 52 : host_(nullptr),
52 state_(Ready), 53 state_(Ready),
53 inflight_requests_count_(0), 54 inflight_requests_count_(0),
54 max_frame_count_(0), 55 max_frame_count_(0),
55 captured_frames_count_(0), 56 captured_frames_count_(0),
56 last_captured_frame_timestamp_(base::Time()), 57 last_captured_frame_timestamp_(base::Time()),
57 weak_factory_(this) { 58 weak_factory_(this) {
58 } 59 }
59 60
60 FrameRecorder::~FrameRecorder() { 61 FrameRecorder::~FrameRecorder() {
61 } 62 }
62 63
63 void FrameRecorder::SetRenderViewHost(RenderViewHostImpl* host) { 64 void FrameRecorder::SetRenderViewHost(RenderViewHostImpl* host) {
64 host_ = host; 65 host_ = host;
65 } 66 }
66 67
67 Response FrameRecorder::StartRecordingFrames(int max_frame_count) { 68 Response FrameRecorder::StartRecordingFrames(int max_frame_count) {
68 if (max_frame_count <= 0 || max_frame_count > kMaxRecordFrameCount) 69 if (max_frame_count <= 0 || max_frame_count > kMaxRecordFrameCount)
69 return Response::InvalidParams("maxFrameCount"); 70 return Response::InvalidParams("maxFrameCount");
70 if (state_ != Ready) 71 if (state_ != Ready && state_ != Encoding)
71 return Response::InternalError("Already recording"); 72 return Response::InternalError("Already recording");
73 if (state_ == Encoding) {
dgozman 2015/01/29 17:53:06 No. This should be an error. Let the caller ensure
eustas 2015/01/30 09:26:30 Workflow: (Ready) + Start -> (Recording) (Recordin
eustas 2015/01/30 09:26:30 Done.
74 std::vector<scoped_refptr<devtools::page::RecordedFrame>> no_frames;
75 callback_.Run(StopRecordingFramesResponse::Create()->set_frames(no_frames));
76 }
77 frame_encoded_callback_.Reset(
78 base::Bind(&FrameRecorder::FrameEncoded, weak_factory_.GetWeakPtr()));
72 state_ = Recording; 79 state_ = Recording;
73 max_frame_count_ = max_frame_count; 80 max_frame_count_ = max_frame_count;
74 captured_frames_count_ = 0; 81 captured_frames_count_ = 0;
75 last_captured_frame_timestamp_ = base::Time(); 82 last_captured_frame_timestamp_ = base::Time();
76 std::vector<scoped_refptr<devtools::page::RecordedFrame>> frames; 83 std::vector<scoped_refptr<devtools::page::RecordedFrame>> frames;
77 frames.reserve(max_frame_count); 84 frames.reserve(max_frame_count);
78 frames_.swap(frames); 85 frames_.swap(frames);
79 86
80 return Response::OK(); 87 return Response::OK();
81 } 88 }
82 89
83 Response FrameRecorder::StopRecordingFrames( 90 Response FrameRecorder::StopRecordingFrames(
84 StopRecordingFramesCallback callback) { 91 StopRecordingFramesCallback callback, bool cancel) {
85 if (state_ != Recording) 92 if (state_ != Recording)
dgozman 2015/01/29 17:53:06 You should be able to cancel during encoding. Perh
eustas 2015/01/30 09:26:30 Done.
86 return Response::InternalError("Not recording"); 93 return Response::InternalError("Not recording");
94 if (cancel) {
95 frame_encoded_callback_.Cancel();
96 std::vector<scoped_refptr<devtools::page::RecordedFrame>> no_frames;
97 frames_.swap(no_frames);
98 callback.Run(StopRecordingFramesResponse::Create()->set_frames(no_frames));
dgozman 2015/01/29 17:53:06 |no_frames| has been swapped and contains collecte
eustas 2015/01/30 09:26:30 Ooops.
99 state_ = Ready;
100 return Response::OK();
101 }
87 state_ = Encoding; 102 state_ = Encoding;
88 callback_ = callback; 103 callback_ = callback;
89 MaybeSendResponse(); 104 MaybeSendResponse();
90 return Response::OK(); 105 return Response::OK();
91 } 106 }
92 107
93 void FrameRecorder::OnSwapCompositorFrame() { 108 void FrameRecorder::OnSwapCompositorFrame() {
94 if (!host_ || state_ != Recording) 109 if (!host_ || state_ != Recording)
95 return; 110 return;
96 if (captured_frames_count_ >= max_frame_count_) 111 if (captured_frames_count_ >= max_frame_count_)
(...skipping 16 matching lines...) Expand all
113 inflight_requests_count_--; 128 inflight_requests_count_--;
114 base::Time timestamp = last_captured_frame_timestamp_; 129 base::Time timestamp = last_captured_frame_timestamp_;
115 last_captured_frame_timestamp_ = base::Time::Now(); 130 last_captured_frame_timestamp_ = base::Time::Now();
116 if (timestamp.is_null() || response != READBACK_SUCCESS) 131 if (timestamp.is_null() || response != READBACK_SUCCESS)
117 return; 132 return;
118 133
119 captured_frames_count_++; 134 captured_frames_count_++;
120 base::PostTaskAndReplyWithResult( 135 base::PostTaskAndReplyWithResult(
121 base::WorkerPool::GetTaskRunner(true).get(), 136 base::WorkerPool::GetTaskRunner(true).get(),
122 FROM_HERE, 137 FROM_HERE,
123 base::Bind(&EncodeFrame, bitmap), 138 base::Bind(&EncodeFrame, bitmap, timestamp.ToDoubleT()),
124 base::Bind(&FrameRecorder::FrameEncoded, weak_factory_.GetWeakPtr(), 139 frame_encoded_callback_.callback());
125 timestamp.ToDoubleT()));
126 } 140 }
127 141
128 void FrameRecorder::FrameEncoded( 142 void FrameRecorder::FrameEncoded(
129 double timestamp, const std::string& encoded_frame) { 143 const std::pair<std::string, double>& encoded_frame) {
130 frames_.push_back(RecordedFrame::Create() 144 frames_.push_back(RecordedFrame::Create()
131 ->set_data(encoded_frame) 145 ->set_data(encoded_frame.first)
132 ->set_timestamp(timestamp)); 146 ->set_timestamp(encoded_frame.second));
133 MaybeSendResponse(); 147 MaybeSendResponse();
134 } 148 }
135 149
136 void FrameRecorder::MaybeSendResponse() { 150 void FrameRecorder::MaybeSendResponse() {
137 if (state_ != Encoding) 151 if (state_ != Encoding)
138 return; 152 return;
139 if (inflight_requests_count_ || frames_.size() != captured_frames_count_) 153 if (inflight_requests_count_ || frames_.size() != captured_frames_count_)
140 return; 154 return;
141 callback_.Run(StopRecordingFramesResponse::Create()->set_frames(frames_)); 155 callback_.Run(StopRecordingFramesResponse::Create()->set_frames(frames_));
142 std::vector<scoped_refptr<devtools::page::RecordedFrame>> frames; 156 std::vector<scoped_refptr<devtools::page::RecordedFrame>> frames;
143 frames_.swap(frames); 157 frames_.swap(frames);
144 state_ = Ready; 158 state_ = Ready;
145 } 159 }
146 160
147 } // namespace page 161 } // namespace page
148 } // namespace devtools 162 } // namespace devtools
149 } // namespace content 163 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698