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

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

Issue 3305001: Move decoder into separate thread, clean up API layering, and redo update protocl (Closed)
Patch Set: Fix compile error. Created 10 years, 2 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
« no previous file with comments | « remoting/client/plugin/pepper_view.h ('k') | remoting/client/rectangle_update_decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_view.h" 5 #include "remoting/client/plugin/pepper_view.h"
6 6
7 #include "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "remoting/base/tracer.h"
9 #include "remoting/client/client_context.h"
8 #include "remoting/client/plugin/chromoting_instance.h" 10 #include "remoting/client/plugin/chromoting_instance.h"
9 #include "remoting/client/plugin/pepper_util.h" 11 #include "remoting/client/plugin/pepper_util.h"
10 #include "third_party/ppapi/cpp/graphics_2d.h" 12 #include "third_party/ppapi/cpp/graphics_2d.h"
11 #include "third_party/ppapi/cpp/image_data.h" 13 #include "third_party/ppapi/cpp/image_data.h"
12 #include "third_party/ppapi/cpp/point.h" 14 #include "third_party/ppapi/cpp/point.h"
13 #include "third_party/ppapi/cpp/size.h" 15 #include "third_party/ppapi/cpp/size.h"
14 16
15 namespace remoting { 17 namespace remoting {
16 18
17 PepperView::PepperView(ChromotingInstance* instance) 19 PepperView::PepperView(ChromotingInstance* instance, ClientContext* context)
18 : instance_(instance), 20 : instance_(instance),
19 viewport_x_(0), 21 context_(context),
20 viewport_y_(0), 22 viewport_x_(0),
21 viewport_width_(0), 23 viewport_y_(0),
22 viewport_height_(0), 24 viewport_width_(0),
23 is_static_fill_(false), 25 viewport_height_(0),
24 static_fill_color_(0) { 26 is_static_fill_(false),
27 static_fill_color_(0) {
25 } 28 }
26 29
27 PepperView::~PepperView() { 30 PepperView::~PepperView() {
28 } 31 }
29 32
30 bool PepperView::Initialize() { 33 bool PepperView::Initialize() {
31 return true; 34 return true;
32 } 35 }
33 36
34 void PepperView::TearDown() { 37 void PepperView::TearDown() {
35 } 38 }
36 39
37 void PepperView::Paint() { 40 void PepperView::Paint() {
38 if (!instance_->CurrentlyOnPluginThread()) { 41 if (!instance_->CurrentlyOnPluginThread()) {
39 RunTaskOnPluginThread(NewRunnableMethod(this, &PepperView::Paint)); 42 RunTaskOnPluginThread(NewTracedMethod(this, &PepperView::Paint));
40 return; 43 return;
41 } 44 }
42 45
46 TraceContext::tracer()->PrintString("Start Paint.");
47 // TODO(ajwong): We're assuming the native format is BGRA_PREMUL below. This
48 // is wrong.
49 if (is_static_fill_) {
50 LOG(ERROR) << "Static filling " << static_fill_color_;
51 pp::ImageData image(pp::ImageData::GetNativeImageDataFormat(),
52 pp::Size(viewport_width_, viewport_height_),
53 false);
54 if (image.is_null()) {
55 LOG(ERROR) << "Unable to allocate image of size: "
56 << viewport_width_ << "x" << viewport_height_;
57 return;
58 }
59
60 for (int y = 0; y < image.size().height(); y++) {
61 for (int x = 0; x < image.size().width(); x++) {
62 *image.GetAddr32(pp::Point(x, y)) = static_fill_color_;
63 }
64 }
65
66 // For ReplaceContents, make sure the image size matches the device context
67 // size! Otherwise, this will just silently do nothing.
68 graphics2d_.ReplaceContents(&image);
69 graphics2d_.Flush(TaskToCompletionCallback(
70 NewTracedMethod(this, &PepperView::OnPaintDone)));
71 } else {
72 // TODO(ajwong): We need to keep a backing store image of the viewport that
73 // has the data here which can be redrawn.
74 return;
75 }
76 TraceContext::tracer()->PrintString("End Paint.");
77 }
78
79 void PepperView::PaintFrame(media::VideoFrame* frame, UpdatedRects* rects) {
80 DCHECK(instance_->CurrentlyOnPluginThread());
81
82 TraceContext::tracer()->PrintString("Start Paint Frame.");
43 // TODO(ajwong): We're assuming the native format is BGRA_PREMUL below. This 83 // TODO(ajwong): We're assuming the native format is BGRA_PREMUL below. This
44 // is wrong. 84 // is wrong.
45 pp::ImageData image(pp::ImageData::GetNativeImageDataFormat(), 85 pp::ImageData image(pp::ImageData::GetNativeImageDataFormat(),
46 pp::Size(viewport_width_, viewport_height_), 86 pp::Size(viewport_width_, viewport_height_),
47 false); 87 false);
48 if (image.is_null()) { 88 if (image.is_null()) {
49 LOG(ERROR) << "Unable to allocate image of size: " 89 LOG(ERROR) << "Unable to allocate image of size: "
50 << viewport_width_ << "x" << viewport_height_; 90 << frame->width() << "x" << frame->height();
51 return; 91 return;
52 } 92 }
53 93
54 if (is_static_fill_) { 94 uint32_t* frame_data =
55 for (int y = 0; y < image.size().height(); y++) { 95 reinterpret_cast<uint32_t*>(frame->data(media::VideoFrame::kRGBPlane));
56 for (int x = 0; x < image.size().width(); x++) { 96 int frame_width = static_cast<int>(frame->width());
57 *image.GetAddr32(pp::Point(x, y)) = static_fill_color_; 97 int frame_height = static_cast<int>(frame->height());
58 } 98 int max_height = std::min(frame_height, image.size().height());
99 int max_width = std::min(frame_width, image.size().width());
100 for (int y = 0; y < max_height; y++) {
101 for (int x = 0; x < max_width; x++) {
102 // Force alpha to be set to 255.
103 *image.GetAddr32(pp::Point(x, y)) =
104 frame_data[y*frame_width + x] | 0xFF000000;
59 } 105 }
60 } else if (frame_) {
61 uint32_t* frame_data =
62 reinterpret_cast<uint32_t*>(frame_->data(media::VideoFrame::kRGBPlane));
63 int max_height = std::min(frame_height_, image.size().height());
64 int max_width = std::min(frame_width_, image.size().width());
65 for (int y = 0; y < max_height; y++) {
66 for (int x = 0; x < max_width; x++) {
67 // Force alpha to be set to 255.
68 *image.GetAddr32(pp::Point(x, y)) =
69 frame_data[y*frame_width_ + x] | 0xFF000000;
70 }
71 }
72 } else {
73 // Nothing to paint. escape!
74 //
75 // TODO(ajwong): This is an ugly control flow. fix.
76 return;
77 } 106 }
78 device_context_.ReplaceContents(&image); 107
79 device_context_.Flush(TaskToCompletionCallback( 108 // For ReplaceContents, make sure the image size matches the device context
80 NewRunnableMethod(this, &PepperView::OnPaintDone))); 109 // size! Otherwise, this will just silently do nothing.
110 graphics2d_.ReplaceContents(&image);
111 graphics2d_.Flush(TaskToCompletionCallback(
112 NewTracedMethod(this, &PepperView::OnPaintDone)));
113
114 TraceContext::tracer()->PrintString("End Paint Frame.");
81 } 115 }
82 116
83 void PepperView::SetSolidFill(uint32 color) { 117 void PepperView::SetSolidFill(uint32 color) {
84 if (!instance_->CurrentlyOnPluginThread()) { 118 if (!instance_->CurrentlyOnPluginThread()) {
85 RunTaskOnPluginThread( 119 RunTaskOnPluginThread(
86 NewRunnableMethod(this, &PepperView::SetSolidFill, color)); 120 NewTracedMethod(this, &PepperView::SetSolidFill, color));
87 return; 121 return;
88 } 122 }
89 123
90 is_static_fill_ = true; 124 is_static_fill_ = true;
91 static_fill_color_ = color; 125 static_fill_color_ = color;
92 } 126 }
93 127
94 void PepperView::UnsetSolidFill() { 128 void PepperView::UnsetSolidFill() {
95 if (!instance_->CurrentlyOnPluginThread()) { 129 if (!instance_->CurrentlyOnPluginThread()) {
96 RunTaskOnPluginThread( 130 RunTaskOnPluginThread(
97 NewRunnableMethod(this, &PepperView::UnsetSolidFill)); 131 NewTracedMethod(this, &PepperView::UnsetSolidFill));
98 return; 132 return;
99 } 133 }
100 134
101 is_static_fill_ = false; 135 is_static_fill_ = false;
102 } 136 }
103 137
104 void PepperView::SetViewport(int x, int y, int width, int height) { 138 void PepperView::SetViewport(int x, int y, int width, int height) {
105 if (!instance_->CurrentlyOnPluginThread()) { 139 if (!instance_->CurrentlyOnPluginThread()) {
106 RunTaskOnPluginThread(NewRunnableMethod(this, &PepperView::SetViewport, 140 RunTaskOnPluginThread(NewTracedMethod(this, &PepperView::SetViewport,
107 x, y, width, height)); 141 x, y, width, height));
108 return; 142 return;
109 } 143 }
110 144
111 // TODO(ajwong): Should we ignore x & y updates? What do those even mean? 145 // TODO(ajwong): Should we ignore x & y updates? What do those even mean?
112 146
113 // TODO(ajwong): What does viewport x, y mean to a plugin anyways? 147 // TODO(ajwong): What does viewport x, y mean to a plugin anyways?
114 viewport_x_ = x; 148 viewport_x_ = x;
115 viewport_y_ = y; 149 viewport_y_ = y;
116 viewport_width_ = width; 150 viewport_width_ = width;
117 viewport_height_ = height; 151 viewport_height_ = height;
118 152
119 device_context_ = 153 graphics2d_ = pp::Graphics2D(pp::Size(viewport_width_, viewport_height_),
120 pp::Graphics2D(pp::Size(viewport_width_, viewport_height_), false); 154 false);
121 if (!instance_->BindGraphics(device_context_)) { 155 if (!instance_->BindGraphics(graphics2d_)) {
122 LOG(ERROR) << "Couldn't bind the device context."; 156 LOG(ERROR) << "Couldn't bind the device context.";
123 return; 157 return;
124 } 158 }
125 } 159 }
126 160
127 void PepperView::SetHostScreenSize(int width, int height) { 161 void PepperView::AllocateFrame(media::VideoFrame::Format format,
162 size_t width,
163 size_t height,
164 base::TimeDelta timestamp,
165 base::TimeDelta duration,
166 scoped_refptr<media::VideoFrame>* frame_out,
167 Task* done) {
168 // TODO(ajwong): Implement this to be backed by an pp::ImageData rather than
169 // generic memory.
170 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32,
171 width, height,
172 base::TimeDelta(), base::TimeDelta(),
173 frame_out);
174 if (*frame_out) {
175 (*frame_out)->AddRef();
176 }
177 done->Run();
178 delete done;
179 }
180
181 void PepperView::ReleaseFrame(media::VideoFrame* frame) {
182 if (frame) {
183 LOG(WARNING) << "Frame released.";
184 frame->Release();
185 }
186 }
187
188 void PepperView::OnPartialFrameOutput(media::VideoFrame* frame,
189 UpdatedRects* rects,
190 Task* done) {
128 if (!instance_->CurrentlyOnPluginThread()) { 191 if (!instance_->CurrentlyOnPluginThread()) {
129 RunTaskOnPluginThread(NewRunnableMethod(this, 192 RunTaskOnPluginThread(NewTracedMethod(this,
130 &PepperView::SetHostScreenSize, 193 &PepperView::OnPartialFrameOutput,
131 width, height)); 194 frame, rects, done));
132 return; 195 return;
133 } 196 }
134 197
135 frame_width_ = width; 198 TraceContext::tracer()->PrintString("Calling PaintFrame");
136 frame_height_ = height; 199 // TODO(ajwong): Clean up this API to be async so we don't need to use a
137 200 // member variable as a hack.
138 // Reset |frame_| - it will be recreated by the next update stream. 201 PaintFrame(frame, rects);
139 frame_ = NULL; 202 done->Run();
140 } 203 delete done;
141
142 void PepperView::HandleBeginUpdateStream(ChromotingHostMessage* msg) {
143 if (!instance_->CurrentlyOnPluginThread()) {
144 RunTaskOnPluginThread(
145 NewRunnableMethod(this, &PepperView::HandleBeginUpdateStream,
146 msg));
147 return;
148 }
149
150 scoped_ptr<ChromotingHostMessage> deleter(msg);
151
152 // Make sure the |frame_| is initialized.
153 if (!frame_) {
154 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32,
155 frame_width_, frame_height_,
156 base::TimeDelta(), base::TimeDelta(),
157 &frame_);
158 CHECK(frame_);
159 }
160 }
161
162 void PepperView::HandleUpdateStreamPacket(ChromotingHostMessage* msg) {
163 if (!instance_->CurrentlyOnPluginThread()) {
164 RunTaskOnPluginThread(
165 NewRunnableMethod(this, &PepperView::HandleUpdateStreamPacket,
166 msg));
167 return;
168 }
169
170 // Lazily initialize the decoder.
171 SetupDecoder(msg->update_stream_packet().begin_rect().encoding());
172 if (!decoder_->IsStarted()) {
173 BeginDecoding(NewRunnableMethod(this, &PepperView::OnPartialDecodeDone),
174 NewRunnableMethod(this, &PepperView::OnDecodeDone));
175 }
176
177 Decode(msg);
178 }
179
180 void PepperView::HandleEndUpdateStream(ChromotingHostMessage* msg) {
181 if (!instance_->CurrentlyOnPluginThread()) {
182 RunTaskOnPluginThread(
183 NewRunnableMethod(this, &PepperView::HandleEndUpdateStream,
184 msg));
185 return;
186 }
187
188 scoped_ptr<ChromotingHostMessage> deleter(msg);
189 EndDecoding();
190 } 204 }
191 205
192 void PepperView::OnPaintDone() { 206 void PepperView::OnPaintDone() {
193 // TODO(ajwong):Probably should set some variable to allow repaints to 207 // TODO(ajwong):Probably should set some variable to allow repaints to
194 // actually paint. 208 // actually paint.
209 TraceContext::tracer()->PrintString("Paint flushed");
195 return; 210 return;
196 } 211 }
197 212
198 void PepperView::OnPartialDecodeDone() {
199 all_update_rects_.insert(all_update_rects_.begin() +
200 all_update_rects_.size(),
201 update_rects_.begin(), update_rects_.end());
202 Paint();
203 // TODO(ajwong): Need to block here to be synchronous.
204 }
205
206
207 void PepperView::OnDecodeDone() {
208 }
209
210 } // namespace remoting 213 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/plugin/pepper_view.h ('k') | remoting/client/rectangle_update_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698