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/media/gl_surface_capturer.h" | |
6 | |
7 #include "base/message_loop/message_loop_proxy.h" | |
8 #include "content/common/gpu/gpu_channel.h" | |
9 #include "content/common/gpu/gpu_messages.h" | |
10 #include "ipc/ipc_message_macros.h" | |
11 | |
12 namespace content { | |
13 | |
14 namespace { | |
15 | |
16 enum { | |
17 kMaxCaptureSize = 4096, | |
18 }; | |
19 | |
20 } // anonymous namespace | |
21 | |
22 GLSurfaceCapturer::GLSurfaceCapturer(int32 route_id, GpuCommandBufferStub* stub) | |
23 : thread_checker_(), | |
24 route_id_(route_id), | |
25 stub_(stub), | |
26 output_format_(media::VideoFrame::INVALID) { | |
27 DCHECK(thread_checker_.CalledOnValidThread()); | |
28 stub_->AddDestructionObserver(this); | |
29 stub_->channel()->AddRoute(route_id_, this); | |
30 } | |
31 | |
32 GLSurfaceCapturer::~GLSurfaceCapturer() { | |
33 DCHECK(thread_checker_.CalledOnValidThread()); | |
34 if (surface_capturer_) | |
35 surface_capturer_.release()->Destroy(); | |
36 | |
37 stub_->channel()->RemoveRoute(route_id_); | |
38 stub_->RemoveDestructionObserver(this); | |
39 } | |
40 | |
41 bool GLSurfaceCapturer::OnMessageReceived(const IPC::Message& message) { | |
42 bool handled = true; | |
43 IPC_BEGIN_MESSAGE_MAP(GLSurfaceCapturer, message) | |
44 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Initialize, OnInitialize) | |
45 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_TryCapture, OnTryCapture) | |
46 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_CopyCaptureToVideoFrame, | |
47 OnCopyCaptureToVideoFrame) | |
48 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Destroy, OnDestroy) | |
49 IPC_MESSAGE_UNHANDLED(handled = false) | |
50 IPC_END_MESSAGE_MAP() | |
51 return handled; | |
52 } | |
53 | |
54 void GLSurfaceCapturer::NotifyCaptureParameters(const gfx::Size& buffer_size, | |
55 const gfx::Rect& visible_rect) { | |
56 DCHECK(thread_checker_.CalledOnValidThread()); | |
57 if (buffer_size.width() > kMaxCaptureSize || | |
Cris Neckar
2013/08/26 22:40:03
Aren't these signed ints underneath. Negatives wou
sheu
2013/08/27 01:20:03
Done.
| |
58 buffer_size.height() > kMaxCaptureSize || | |
59 visible_rect.x() > kMaxCaptureSize || | |
60 visible_rect.y() > kMaxCaptureSize || | |
61 visible_rect.width() > kMaxCaptureSize || | |
62 visible_rect.height() > kMaxCaptureSize) { | |
63 DLOG(ERROR) << "NotifyCaptureParameters(): parameters out of bounds: " | |
64 "buffer_size=" << buffer_size.ToString() | |
65 << ", visible_rect=" << visible_rect.ToString(); | |
66 NotifyError(SurfaceCapturer::kInvalidArgumentError); | |
67 return; | |
68 } | |
69 output_buffer_size_ = buffer_size; | |
70 output_visible_rect_ = visible_rect; | |
71 Send(new SurfaceCapturerHostMsg_NotifyCaptureParameters( | |
72 route_id_, buffer_size, visible_rect)); | |
73 } | |
74 | |
75 void GLSurfaceCapturer::NotifyCopyCaptureDone( | |
76 const scoped_refptr<media::VideoFrame>& frame) { | |
77 DCHECK(thread_checker_.CalledOnValidThread()); | |
78 FrameIdMap::iterator iter = frame_id_map_.find(frame); | |
79 if (iter == frame_id_map_.end()) { | |
80 DLOG(ERROR) << "NotifyCopyCaptureDone(): invalid frame"; | |
81 NotifyError(SurfaceCapturer::kInvalidArgumentError); | |
82 return; | |
83 } | |
84 Send(new SurfaceCapturerHostMsg_NotifyCopyCaptureDone(route_id_, | |
85 iter->second)); | |
86 frame_id_map_.erase(iter); | |
87 } | |
88 | |
89 void GLSurfaceCapturer::NotifyError(SurfaceCapturer::Error error) { | |
90 DCHECK(thread_checker_.CalledOnValidThread()); | |
91 Send(new SurfaceCapturerHostMsg_NotifyError(route_id_, error)); | |
92 } | |
93 | |
94 void GLSurfaceCapturer::OnWillDestroyStub() { | |
95 DCHECK(thread_checker_.CalledOnValidThread()); | |
96 delete this; | |
97 } | |
98 | |
99 void GLSurfaceCapturer::OnInitialize(media::VideoFrame::Format format) { | |
100 DVLOG(2) << "OnInitialize(): format=" << format; | |
101 DCHECK(thread_checker_.CalledOnValidThread()); | |
102 DCHECK(!surface_capturer_); | |
103 | |
104 // TODO(sheu): actually create a surface capturer. | |
105 | |
106 if (!surface_capturer_) { | |
107 NOTIMPLEMENTED() << "OnInitialize(): GL surface capturing not available"; | |
108 NotifyError(SurfaceCapturer::kPlatformFailureError); | |
109 return; | |
110 } | |
111 | |
112 output_format_ = format; | |
113 surface_capturer_->Initialize(output_format_); | |
114 } | |
115 | |
116 void GLSurfaceCapturer::OnTryCapture() { | |
117 DVLOG(3) << "OnTryCapture()"; | |
118 DCHECK(thread_checker_.CalledOnValidThread()); | |
119 if (!surface_capturer_) | |
120 return; | |
121 surface_capturer_->TryCapture(); | |
122 } | |
123 | |
124 static void DeleteShm(scoped_ptr<base::SharedMemory> shm) { | |
125 // Just let shm fall out of scope. | |
126 } | |
127 | |
128 void GLSurfaceCapturer::OnCopyCaptureToVideoFrame( | |
129 int32 frame_id, | |
130 base::SharedMemoryHandle buffer_shm, | |
131 uint32_t buffer_size) { | |
132 DVLOG(3) << "OnCopyCaptureToVideoFrame(): frame_id=" << frame_id | |
133 << ", buffer_size=" << buffer_size; | |
134 DCHECK(thread_checker_.CalledOnValidThread()); | |
135 if (!surface_capturer_) | |
136 return; | |
137 if (frame_id < 0) { | |
138 DLOG(ERROR) << "OnCopyCaptureToVideoFrame(): invalid frame_id=" << frame_id; | |
139 NotifyError(SurfaceCapturer::kPlatformFailureError); | |
140 return; | |
141 } | |
142 | |
143 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(buffer_shm, false)); | |
144 if (!shm->Map(buffer_size)) { | |
145 DLOG(ERROR) << "OnCopyCaptureToVideoFrame(): could not map " | |
146 "frame_id=" << frame_id; | |
147 NotifyError(SurfaceCapturer::kPlatformFailureError); | |
148 return; | |
149 } | |
150 scoped_refptr<media::VideoFrame> frame = | |
151 media::VideoFrame::WrapExternalSharedMemory( | |
152 output_format_, | |
153 output_buffer_size_, | |
154 output_visible_rect_, | |
155 output_visible_rect_.size(), | |
156 reinterpret_cast<uint8*>(shm->memory()), | |
157 buffer_size, | |
158 buffer_shm, | |
159 base::TimeDelta(), | |
160 base::Bind(&DeleteShm, base::Passed(&shm))); | |
161 if (!frame) { | |
162 DLOG(ERROR) << "OnCopyCaptureToVideoFrame(): could not create frame for" | |
163 "frame_id=" << frame_id; | |
164 NotifyError(SurfaceCapturer::kPlatformFailureError); | |
165 return; | |
166 } | |
167 frame_id_map_[frame] = frame_id; | |
168 surface_capturer_->CopyCaptureToVideoFrame(frame); | |
169 } | |
170 | |
171 void GLSurfaceCapturer::OnDestroy() { | |
172 DVLOG(2) << "OnDestroy()"; | |
173 DCHECK(thread_checker_.CalledOnValidThread()); | |
174 delete this; | |
175 } | |
176 | |
177 void GLSurfaceCapturer::Send(IPC::Message* message) { | |
178 DCHECK(thread_checker_.CalledOnValidThread()); | |
179 uint32 type = message->type(); | |
180 if (!stub_->channel()->Send(message)) { | |
181 DLOG(ERROR) << "Send(): send failed: message->type()=" << type; | |
182 NotifyError(SurfaceCapturer::kPlatformFailureError); | |
183 } | |
184 } | |
185 | |
186 } // namespace content | |
OLD | NEW |