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

Side by Side Diff: content/common/gpu/client/gpu_video_encode_accelerator_host.cc

Issue 1656433002: Sample code: IPC Transport object for GPU Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: GpuMemoryBufferService + Transport object. TODO: Eliminate ChildThreadImpl dependency Created 4 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/common/gpu/client/gpu_video_encode_accelerator_host.h" 5 #include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/thread_task_runner_handle.h"
9 #include "content/common/gpu/client/gpu_channel_host.h" 11 #include "content/common/gpu/client/gpu_channel_host.h"
10 #include "content/common/gpu/gpu_messages.h" 12 #include "content/common/gpu/client/ipc/command_buffer_ipc_transport.h"
11 #include "content/common/gpu/media/gpu_video_accelerator_util.h" 13 #include "content/common/gpu/media/gpu_video_accelerator_util.h"
14 #include "content/common/gpu/video_encode_params.h"
12 #include "media/base/video_frame.h" 15 #include "media/base/video_frame.h"
13 #include "media/video/video_encode_accelerator.h" 16 #include "media/video/video_encode_accelerator.h"
14 #include "ui/gfx/gpu_memory_buffer.h" 17 #include "ui/gfx/gpu_memory_buffer.h"
15 18
16 namespace content { 19 namespace content {
17 20
18 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost( 21 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
19 GpuChannelHost* channel, 22 GpuChannelHost* channel,
23 scoped_ptr<GpuVideoEncodeAcceleratorHostIPCTransport> transport,
20 CommandBufferProxyImpl* impl) 24 CommandBufferProxyImpl* impl)
21 : channel_(channel), 25 : channel_(channel),
22 encoder_route_id_(MSG_ROUTING_NONE), 26 transport_(std::move(transport)),
23 client_(NULL), 27 client_(nullptr),
24 impl_(impl), 28 impl_(impl),
25 next_frame_id_(0), 29 next_frame_id_(0),
26 weak_this_factory_(this) { 30 weak_this_factory_(this) {
27 DCHECK(channel_); 31 DCHECK(channel_);
28 DCHECK(impl_); 32 DCHECK(impl_);
29 impl_->AddDeletionObserver(this); 33 impl_->AddDeletionObserver(this);
34 transport_->SetClient(this);
30 } 35 }
31 36
32 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() { 37 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
33 DCHECK(CalledOnValidThread()); 38 DCHECK(CalledOnValidThread());
34 if (channel_ && encoder_route_id_ != MSG_ROUTING_NONE) 39 // TODO(fsamuel): Figure out message routing here.
35 channel_->RemoveRoute(encoder_route_id_); 40 // if (channel_ && encoder_route_id_ != MSG_ROUTING_NONE)
41 // channel_->RemoveRoute(encoder_route_id_);
36 if (impl_) 42 if (impl_)
37 impl_->RemoveDeletionObserver(this); 43 impl_->RemoveDeletionObserver(this);
38 } 44 }
39 45
40 bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
41 const IPC::Message& message) {
42 bool handled = true;
43 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message)
44 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
45 OnRequireBitstreamBuffers)
46 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
47 OnNotifyInputDone)
48 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
49 OnBitstreamBufferReady)
50 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError,
51 OnNotifyError)
52 IPC_MESSAGE_UNHANDLED(handled = false)
53 IPC_END_MESSAGE_MAP()
54 DCHECK(handled);
55 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
56 // have been called above.
57 return handled;
58 }
59
60 void GpuVideoEncodeAcceleratorHost::OnChannelError() {
61 DCHECK(CalledOnValidThread());
62 if (channel_) {
63 if (encoder_route_id_ != MSG_ROUTING_NONE)
64 channel_->RemoveRoute(encoder_route_id_);
65 channel_ = NULL;
66 }
67 PostNotifyError(FROM_HERE, kPlatformFailureError, "OnChannelError()");
68 }
69
70 media::VideoEncodeAccelerator::SupportedProfiles 46 media::VideoEncodeAccelerator::SupportedProfiles
71 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() { 47 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
72 DCHECK(CalledOnValidThread()); 48 DCHECK(CalledOnValidThread());
73 if (!channel_) 49 if (!channel_)
74 return media::VideoEncodeAccelerator::SupportedProfiles(); 50 return media::VideoEncodeAccelerator::SupportedProfiles();
75 return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles( 51 return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
76 channel_->gpu_info().video_encode_accelerator_supported_profiles); 52 channel_->gpu_info().video_encode_accelerator_supported_profiles);
77 } 53 }
78 54
79 bool GpuVideoEncodeAcceleratorHost::Initialize( 55 bool GpuVideoEncodeAcceleratorHost::Initialize(
80 media::VideoPixelFormat input_format, 56 media::VideoPixelFormat input_format,
81 const gfx::Size& input_visible_size, 57 const gfx::Size& input_visible_size,
82 media::VideoCodecProfile output_profile, 58 media::VideoCodecProfile output_profile,
83 uint32_t initial_bitrate, 59 uint32_t initial_bitrate,
84 Client* client) { 60 media::VideoEncodeAccelerator::Client* client) {
85 DCHECK(CalledOnValidThread()); 61 DCHECK(CalledOnValidThread());
86 client_ = client; 62 client_ = client;
87 if (!impl_) { 63 if (!impl_) {
88 DLOG(ERROR) << "impl_ destroyed"; 64 DLOG(ERROR) << "impl_ destroyed";
89 return false; 65 return false;
90 } 66 }
91 67
92 int32_t route_id = channel_->GenerateRouteID();
93 channel_->AddRoute(route_id, weak_this_factory_.GetWeakPtr());
94
95 bool succeeded = false; 68 bool succeeded = false;
96 Send(new GpuCommandBufferMsg_CreateVideoEncoder( 69 impl_->transport()->CreateVideoEncoder(transport_.get(), input_format,
97 impl_->route_id(), input_format, input_visible_size, output_profile, 70 input_visible_size, output_profile,
98 initial_bitrate, route_id, &succeeded)); 71 initial_bitrate, &succeeded);
99 if (!succeeded) { 72 if (!succeeded) {
100 DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoEncoder()) failed"; 73 DLOG(ERROR) << "CreateVidoEncoder() failed";
101 channel_->RemoveRoute(route_id);
102 return false; 74 return false;
103 } 75 }
104 encoder_route_id_ = route_id;
105 return true; 76 return true;
106 } 77 }
107 78
108 void GpuVideoEncodeAcceleratorHost::Encode( 79 void GpuVideoEncodeAcceleratorHost::Encode(
109 const scoped_refptr<media::VideoFrame>& frame, 80 const scoped_refptr<media::VideoFrame>& frame,
110 bool force_keyframe) { 81 bool force_keyframe) {
111 DCHECK(CalledOnValidThread()); 82 DCHECK(CalledOnValidThread());
112 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame->format()); 83 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame->format());
113 if (!channel_) 84 if (!channel_)
114 return; 85 return;
(...skipping 26 matching lines...) Expand all
141 base::SharedMemoryHandle handle = 112 base::SharedMemoryHandle handle =
142 channel_->ShareToGpuProcess(buffer.handle()); 113 channel_->ShareToGpuProcess(buffer.handle());
143 if (!base::SharedMemory::IsHandleValid(handle)) { 114 if (!base::SharedMemory::IsHandleValid(handle)) {
144 PostNotifyError( 115 PostNotifyError(
145 FROM_HERE, kPlatformFailureError, 116 FROM_HERE, kPlatformFailureError,
146 base::StringPrintf("UseOutputBitstreamBuffer(): failed to duplicate " 117 base::StringPrintf("UseOutputBitstreamBuffer(): failed to duplicate "
147 "buffer handle for GPU process: buffer.id()=%d", 118 "buffer handle for GPU process: buffer.id()=%d",
148 buffer.id())); 119 buffer.id()));
149 return; 120 return;
150 } 121 }
151 Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer( 122 transport_->UseOutputBitstreamBuffer(buffer.id(), handle, buffer.size());
152 encoder_route_id_, buffer.id(), handle, buffer.size()));
153 } 123 }
154 124
155 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange( 125 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
156 uint32_t bitrate, 126 uint32_t bitrate,
157 uint32_t framerate) { 127 uint32_t framerate) {
158 DCHECK(CalledOnValidThread()); 128 DCHECK(CalledOnValidThread());
159 if (!channel_) 129 if (!channel_)
160 return; 130 return;
161 131 transport_->RequestEncodingParametersChange(bitrate, framerate);
162 Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
163 encoder_route_id_, bitrate, framerate));
164 } 132 }
165 133
166 void GpuVideoEncodeAcceleratorHost::Destroy() { 134 void GpuVideoEncodeAcceleratorHost::Destroy() {
167 DCHECK(CalledOnValidThread()); 135 DCHECK(CalledOnValidThread());
168 if (channel_) 136 if (channel_)
169 Send(new AcceleratedVideoEncoderMsg_Destroy(encoder_route_id_)); 137 transport_->Destroy();
170 client_ = NULL; 138 client_ = nullptr;
171 delete this; 139 delete this;
172 } 140 }
173 141
174 void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() { 142 void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() {
175 DCHECK(CalledOnValidThread()); 143 DCHECK(CalledOnValidThread());
176 impl_ = NULL; 144 impl_ = nullptr;
177
178 // The CommandBufferProxyImpl is going away; error out this VEA.
179 OnChannelError();
180 } 145 }
181 146
182 void GpuVideoEncodeAcceleratorHost::EncodeGpuMemoryBufferFrame( 147 void GpuVideoEncodeAcceleratorHost::EncodeGpuMemoryBufferFrame(
183 const scoped_refptr<media::VideoFrame>& frame, 148 const scoped_refptr<media::VideoFrame>& frame,
184 bool force_keyframe){ 149 bool force_keyframe){
185 DCHECK_EQ(media::VideoFrame::NumPlanes(media::PIXEL_FORMAT_I420), 150 DCHECK_EQ(media::VideoFrame::NumPlanes(media::PIXEL_FORMAT_I420),
186 frame->gpu_memory_buffer_handles().size()); 151 frame->gpu_memory_buffer_handles().size());
187 AcceleratedVideoEncoderMsg_Encode_Params2 params; 152 VideoEncodeParams2 params;
188 params.frame_id = next_frame_id_; 153 params.frame_id = next_frame_id_;
189 params.timestamp = frame->timestamp(); 154 params.timestamp = frame->timestamp();
190 bool requires_sync_point = false; 155 bool requires_sync_point = false;
191 for (const auto& handle : frame->gpu_memory_buffer_handles()) { 156 for (const auto& handle : frame->gpu_memory_buffer_handles()) {
192 gfx::GpuMemoryBufferHandle new_handle = 157 gfx::GpuMemoryBufferHandle new_handle =
193 channel_->ShareGpuMemoryBufferToGpuProcess(handle, 158 channel_->ShareGpuMemoryBufferToGpuProcess(handle,
194 &requires_sync_point); 159 &requires_sync_point);
195 if (new_handle.is_null()) { 160 if (new_handle.is_null()) {
196 PostNotifyError(FROM_HERE, kPlatformFailureError, 161 PostNotifyError(FROM_HERE, kPlatformFailureError,
197 "EncodeGpuMemoryBufferFrame(): failed to share gpu " 162 "EncodeGpuMemoryBufferFrame(): failed to share gpu "
198 "memory buffer handle for gpu process"); 163 "memory buffer handle for gpu process");
199 return; 164 return;
200 } 165 }
201 params.gpu_memory_buffer_handles.push_back(new_handle); 166 params.gpu_memory_buffer_handles.push_back(new_handle);
202 } 167 }
203 params.size = frame->coded_size(); 168 params.size = frame->coded_size();
204 params.force_keyframe = force_keyframe; 169 params.force_keyframe = force_keyframe;
205 170 transport_->Encode2(params);
206 Send(new AcceleratedVideoEncoderMsg_Encode2(encoder_route_id_, params));
207 } 171 }
208 172
209 void GpuVideoEncodeAcceleratorHost::EncodeSharedMemoryFrame( 173 void GpuVideoEncodeAcceleratorHost::EncodeSharedMemoryFrame(
210 const scoped_refptr<media::VideoFrame>& frame, 174 const scoped_refptr<media::VideoFrame>& frame,
211 bool force_keyframe){ 175 bool force_keyframe){
212 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) { 176 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
213 PostNotifyError(FROM_HERE, kPlatformFailureError, 177 PostNotifyError(FROM_HERE, kPlatformFailureError,
214 "EncodeSharedMemory(): cannot encode frame with invalid " 178 "EncodeSharedMemory(): cannot encode frame with invalid "
215 "shared memory handle"); 179 "shared memory handle");
216 return; 180 return;
217 } 181 }
218 182
219 AcceleratedVideoEncoderMsg_Encode_Params params; 183 VideoEncodeParams params;
220 params.frame_id = next_frame_id_; 184 params.frame_id = next_frame_id_;
221 params.timestamp = frame->timestamp(); 185 params.timestamp = frame->timestamp();
222 params.buffer_handle = 186 params.buffer_handle =
223 channel_->ShareToGpuProcess(frame->shared_memory_handle()); 187 channel_->ShareToGpuProcess(frame->shared_memory_handle());
224 if (!base::SharedMemory::IsHandleValid(params.buffer_handle)) { 188 if (!base::SharedMemory::IsHandleValid(params.buffer_handle)) {
225 PostNotifyError(FROM_HERE, kPlatformFailureError, 189 PostNotifyError(FROM_HERE, kPlatformFailureError,
226 "Encode(): failed to duplicate shared memory buffer handle " 190 "Encode(): failed to duplicate shared memory buffer handle "
227 "for GPU process"); 191 "for GPU process");
228 return; 192 return;
229 } 193 }
230 params.buffer_offset = 194 params.buffer_offset =
231 base::checked_cast<uint32_t>(frame->shared_memory_offset()); 195 base::checked_cast<uint32_t>(frame->shared_memory_offset());
232 params.buffer_size = 196 params.buffer_size =
233 media::VideoFrame::AllocationSize(frame->format(), frame->coded_size()); 197 media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
234 params.force_keyframe = force_keyframe; 198 params.force_keyframe = force_keyframe;
235 199 transport_->Encode(params);
236 Send(new AcceleratedVideoEncoderMsg_Encode(encoder_route_id_, params));
237 } 200 }
238 201
239 void GpuVideoEncodeAcceleratorHost::PostNotifyError( 202 void GpuVideoEncodeAcceleratorHost::PostNotifyError(
240 const tracked_objects::Location& location, Error error, 203 const tracked_objects::Location& location, Error error,
241 const std::string& message) { 204 const std::string& message) {
242 DCHECK(CalledOnValidThread()); 205 DCHECK(CalledOnValidThread());
243 DLOG(ERROR) << "Error from " << location.function_name() 206 DLOG(ERROR) << "Error from " << location.function_name()
244 << "(" << location.file_name() << ":" 207 << "(" << location.file_name() << ":"
245 << location.line_number() << ") " 208 << location.line_number() << ") "
246 << message << " (error = " << error << ")"; 209 << message << " (error = " << error << ")";
247 // Post the error notification back to this thread, to avoid re-entrancy. 210 // Post the error notification back to this thread, to avoid re-entrancy.
248 base::ThreadTaskRunnerHandle::Get()->PostTask( 211 base::ThreadTaskRunnerHandle::Get()->PostTask(
249 FROM_HERE, base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError, 212 FROM_HERE, base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError,
250 weak_this_factory_.GetWeakPtr(), error)); 213 weak_this_factory_.GetWeakPtr(), error));
251 } 214 }
252 215
253 void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
254 DCHECK(CalledOnValidThread());
255 uint32_t message_type = message->type();
256 if (!channel_->Send(message)) {
257 PostNotifyError(FROM_HERE, kPlatformFailureError,
258 base::StringPrintf("Send(%d) failed", message_type));
259 }
260 }
261
262 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers( 216 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
263 uint32_t input_count, 217 uint32_t input_count,
264 const gfx::Size& input_coded_size, 218 const gfx::Size& input_coded_size,
265 uint32_t output_buffer_size) { 219 uint32_t output_buffer_size) {
266 DCHECK(CalledOnValidThread()); 220 DCHECK(CalledOnValidThread());
267 DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count 221 DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count
268 << ", input_coded_size=" << input_coded_size.ToString() 222 << ", input_coded_size=" << input_coded_size.ToString()
269 << ", output_buffer_size=" << output_buffer_size; 223 << ", output_buffer_size=" << output_buffer_size;
270 if (client_) { 224 if (client_) {
271 client_->RequireBitstreamBuffers( 225 client_->RequireBitstreamBuffers(
(...skipping 11 matching lines...) Expand all
283 // theoretical" - Android's std::hash_map crashes if we don't do this. 237 // theoretical" - Android's std::hash_map crashes if we don't do this.
284 scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id]; 238 scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id];
285 if (!frame_map_.erase(frame_id)) { 239 if (!frame_map_.erase(frame_id)) {
286 DLOG(ERROR) << "OnNotifyInputDone(): " 240 DLOG(ERROR) << "OnNotifyInputDone(): "
287 "invalid frame_id=" << frame_id; 241 "invalid frame_id=" << frame_id;
288 // See OnNotifyError for why this needs to be the last thing in this 242 // See OnNotifyError for why this needs to be the last thing in this
289 // function. 243 // function.
290 OnNotifyError(kPlatformFailureError); 244 OnNotifyError(kPlatformFailureError);
291 return; 245 return;
292 } 246 }
293 frame = NULL; // Not necessary but nice to be explicit; see fun-fact above. 247 frame =
248 nullptr; // Not necessary but nice to be explicit; see fun-fact above.
294 } 249 }
295 250
296 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady( 251 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
297 int32_t bitstream_buffer_id, 252 int32_t bitstream_buffer_id,
298 uint32_t payload_size, 253 uint32_t payload_size,
299 bool key_frame) { 254 bool key_frame) {
300 DCHECK(CalledOnValidThread()); 255 DCHECK(CalledOnValidThread());
301 DVLOG(3) << "OnBitstreamBufferReady(): " 256 DVLOG(3) << "OnBitstreamBufferReady(): "
302 "bitstream_buffer_id=" << bitstream_buffer_id 257 "bitstream_buffer_id=" << bitstream_buffer_id
303 << ", payload_size=" << payload_size 258 << ", payload_size=" << payload_size
304 << ", key_frame=" << key_frame; 259 << ", key_frame=" << key_frame;
305 if (client_) 260 if (client_)
306 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame); 261 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
307 } 262 }
308 263
309 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) { 264 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) {
310 DCHECK(CalledOnValidThread()); 265 DCHECK(CalledOnValidThread());
311 DVLOG(2) << "OnNotifyError(): error=" << error; 266 DVLOG(2) << "OnNotifyError(): error=" << error;
312 if (!client_) 267 if (!client_)
313 return; 268 return;
314 weak_this_factory_.InvalidateWeakPtrs(); 269 weak_this_factory_.InvalidateWeakPtrs();
315 270
316 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the 271 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
317 // last thing done on this stack! 272 // last thing done on this stack!
318 media::VideoEncodeAccelerator::Client* client = NULL; 273 media::VideoEncodeAccelerator::Client* client = nullptr;
319 std::swap(client_, client); 274 std::swap(client_, client);
320 client->NotifyError(error); 275 client->NotifyError(error);
321 } 276 }
322 277
323 } // namespace content 278 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698