OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/common/gpu/client/gl_surface_capturer_host.h" | |
6 | |
7 #include "content/common/gpu/client/gpu_channel_host.h" | |
8 #include "content/common/gpu/gpu_messages.h" | |
9 #include "ipc/ipc_message_macros.h" | |
10 | |
11 namespace content { | |
12 | |
13 namespace { | |
14 | |
15 enum { | |
16 kNumCaptureBuffers = 2, | |
17 kMaxCaptureSize = 4096, | |
18 }; | |
19 | |
20 } // anonymous namespace | |
21 | |
22 GLSurfaceCapturerHost::GLSurfaceCapturerHost(int32 capturer_route_id, | |
23 SurfaceCapturer::Client* client, | |
24 CommandBufferProxyImpl* impl) | |
25 : thread_checker_(), | |
26 capturer_route_id_(capturer_route_id), | |
27 weak_this_factory_(this), | |
28 client_ptr_factory_(client), | |
29 client_(client), | |
30 impl_(impl), | |
31 channel_(impl_->channel()), | |
32 next_frame_id_(0) { | |
33 DCHECK(thread_checker_.CalledOnValidThread()); | |
34 channel_->AddRoute(capturer_route_id_, weak_this_factory_.GetWeakPtr()); | |
35 impl_->AddDeletionObserver(this); | |
36 } | |
37 | |
38 void GLSurfaceCapturerHost::OnChannelError() { | |
39 DLOG(ERROR) << "OnChannelError()"; | |
40 DCHECK(thread_checker_.CalledOnValidThread()); | |
41 OnNotifyError(kPlatformFailureError); | |
42 if (channel_) { | |
43 weak_this_factory_.InvalidateWeakPtrs(); | |
44 channel_->RemoveRoute(capturer_route_id_); | |
45 channel_ = NULL; | |
46 } | |
47 } | |
48 | |
49 bool GLSurfaceCapturerHost::OnMessageReceived(const IPC::Message& message) { | |
50 bool handled = true; | |
51 IPC_BEGIN_MESSAGE_MAP(GLSurfaceCapturerHost, message) | |
52 IPC_MESSAGE_HANDLER(SurfaceCapturerHostMsg_NotifyCaptureParameters, | |
53 OnNotifyCaptureParameters) | |
54 IPC_MESSAGE_HANDLER(SurfaceCapturerHostMsg_NotifyCopyCaptureDone, | |
55 OnNotifyCopyCaptureDone) | |
56 IPC_MESSAGE_HANDLER(SurfaceCapturerHostMsg_NotifyError, OnNotifyError) | |
57 IPC_MESSAGE_UNHANDLED(handled = false) | |
58 IPC_END_MESSAGE_MAP() | |
59 return handled; | |
60 } | |
61 | |
62 void GLSurfaceCapturerHost::Initialize(media::VideoFrame::Format format) { | |
63 DCHECK(thread_checker_.CalledOnValidThread()); | |
64 Send(new SurfaceCapturerMsg_Initialize(capturer_route_id_, format)); | |
65 } | |
66 | |
67 void GLSurfaceCapturerHost::TryCapture() { | |
68 DCHECK(thread_checker_.CalledOnValidThread()); | |
69 Send(new SurfaceCapturerMsg_TryCapture(capturer_route_id_)); | |
70 } | |
71 | |
72 void GLSurfaceCapturerHost::CopyCaptureToVideoFrame( | |
73 const scoped_refptr<media::VideoFrame>& frame) { | |
74 DCHECK(thread_checker_.CalledOnValidThread()); | |
75 if (!channel_) | |
76 return; | |
77 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) { | |
78 DLOG(ERROR) << "CopyCaptureToVideoFrame(): cannot capture to frame not " | |
79 "backed by shared memory"; | |
80 OnNotifyError(kPlatformFailureError); | |
81 return; | |
82 } | |
83 base::SharedMemoryHandle handle = | |
84 channel_->ShareToGpuProcess(frame->shared_memory_handle()); | |
85 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) { | |
86 DLOG(ERROR) << "CopyCaptureToVideoFrame(): failed to duplicate buffer " | |
87 "handle for GPU process"; | |
88 OnNotifyError(kPlatformFailureError); | |
89 return; | |
90 } | |
91 | |
92 const size_t plane_count = media::VideoFrame::NumPlanes(frame->format()); | |
93 size_t frame_size = 0; | |
94 for (size_t i = 0; i < plane_count; ++i) { | |
95 DCHECK_EQ(reinterpret_cast<void*>(frame->data(i)), | |
96 reinterpret_cast<void*>((frame->data(0) + frame_size))) | |
97 << "plane=" << i; | |
98 frame_size += frame->stride(i) * frame->rows(i); | |
99 } | |
100 | |
101 Send(new SurfaceCapturerMsg_CopyCaptureToVideoFrame( | |
102 capturer_route_id_, next_frame_id_, handle, frame_size)); | |
103 frame_map_[next_frame_id_] = frame; | |
104 next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF; | |
105 } | |
106 | |
107 void GLSurfaceCapturerHost::Destroy() { | |
108 DCHECK(thread_checker_.CalledOnValidThread()); | |
109 client_ = NULL; | |
piman
2013/08/28 21:59:44
client_ptr_factory_.InvalidateWeakPtrs()
(but see
sheu
2013/08/28 22:20:18
Done.
| |
110 Send(new SurfaceCapturerMsg_Destroy(capturer_route_id_)); | |
111 } | |
112 | |
113 void GLSurfaceCapturerHost::OnWillDeleteImpl() { | |
114 DCHECK(thread_checker_.CalledOnValidThread()); | |
115 impl_ = NULL; | |
116 OnChannelError(); | |
117 } | |
118 | |
119 GLSurfaceCapturerHost::~GLSurfaceCapturerHost() { | |
120 DCHECK(thread_checker_.CalledOnValidThread()); | |
121 weak_this_factory_.InvalidateWeakPtrs(); | |
122 if (channel_) | |
123 channel_->RemoveRoute(capturer_route_id_); | |
124 if (impl_) | |
125 impl_->RemoveDeletionObserver(this); | |
126 } | |
127 | |
128 void GLSurfaceCapturerHost::NotifyError(Error error) { | |
129 DCHECK(thread_checker_.CalledOnValidThread()); | |
130 base::MessageLoopProxy::current()->PostTask( | |
131 FROM_HERE, | |
132 base::Bind(&SurfaceCapturer::Client::NotifyError, | |
piman
2013/08/28 21:59:44
Why not PostTask(&GLSurfaceCapturerHost::OnNotifyE
sheu
2013/08/28 22:20:18
Done.
| |
133 client_ptr_factory_.GetWeakPtr(), | |
134 error)); | |
135 } | |
136 | |
137 void GLSurfaceCapturerHost::OnNotifyCaptureParameters( | |
138 const gfx::Size& buffer_size, | |
139 const gfx::Rect& visible_rect) { | |
140 DVLOG(2) << "OnNotifyCaptureParameters(): " | |
141 "buffer_size=" << buffer_size.ToString() | |
142 << ", visible_rect=" << visible_rect.ToString(); | |
143 DCHECK(thread_checker_.CalledOnValidThread()); | |
144 if (buffer_size.width() < 1 || buffer_size.width() > kMaxCaptureSize || | |
145 buffer_size.height() < 1 || buffer_size.height() > kMaxCaptureSize || | |
146 visible_rect.x() < 0 || visible_rect.x() > kMaxCaptureSize - 1 || | |
147 visible_rect.y() < 0 || visible_rect.y() > kMaxCaptureSize - 1 || | |
148 visible_rect.width() < 1 || visible_rect.width() > kMaxCaptureSize || | |
149 visible_rect.height() < 1 || visible_rect.height() > kMaxCaptureSize) { | |
150 DLOG(ERROR) << "OnNotifyCaptureParameters(): parameters out of bounds: " | |
151 "buffer_size=" << buffer_size.ToString() | |
152 << ", visible_rect=" << visible_rect.ToString(); | |
153 OnNotifyError(kPlatformFailureError); | |
154 return; | |
155 } | |
156 if (client_) | |
157 client_->NotifyCaptureParameters(buffer_size, visible_rect); | |
158 } | |
159 | |
160 void GLSurfaceCapturerHost::OnNotifyCopyCaptureDone(int32 frame_id) { | |
161 DVLOG(3) << "OnNotifyCopyCaptureDone(): frame_id=" << frame_id; | |
162 DCHECK(thread_checker_.CalledOnValidThread()); | |
163 FrameMap::iterator iter = frame_map_.find(frame_id); | |
164 if (iter == frame_map_.end()) { | |
165 DLOG(ERROR) << "OnNotifyCopyCaptureDone(): invalid frame_id=" << frame_id; | |
166 OnNotifyError(kPlatformFailureError); | |
167 return; | |
168 } | |
169 if (client_) | |
170 client_->NotifyCopyCaptureDone(iter->second); | |
171 frame_map_.erase(iter); | |
172 } | |
173 | |
174 void GLSurfaceCapturerHost::OnNotifyError(Error error) { | |
175 DVLOG(2) << "OnNotifyError(): error=" << error; | |
176 DCHECK(thread_checker_.CalledOnValidThread()); | |
177 if (client_) { | |
178 client_->NotifyError(error); | |
179 client_ = NULL; | |
180 client_ptr_factory_.InvalidateWeakPtrs(); | |
181 } | |
182 } | |
183 | |
184 void GLSurfaceCapturerHost::Send(IPC::Message* message) { | |
185 DCHECK(thread_checker_.CalledOnValidThread()); | |
186 uint32 type = message->type(); | |
187 if (!channel_) { | |
188 DLOG(ERROR) << "Send(): no channel"; | |
189 delete message; | |
190 NotifyError(kPlatformFailureError); | |
191 } else if (!channel_->Send(message)) { | |
192 DLOG(ERROR) << "Send(): failed: message->type()=" << type; | |
193 NotifyError(kPlatformFailureError); | |
194 } | |
195 } | |
196 | |
197 } // namespace content | |
OLD | NEW |