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

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

Issue 185403020: Make VEA client of command buffer; move sync. IPC to VDA/VEA::Initialize() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 85629196 fischman@ comments. Created 6 years, 9 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 | Annotate | Revision Log
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/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop/message_loop_proxy.h" 8 #include "base/message_loop/message_loop_proxy.h"
9 #include "content/common/gpu/client/gpu_channel_host.h" 9 #include "content/common/gpu/client/gpu_channel_host.h"
10 #include "content/common/gpu/gpu_messages.h" 10 #include "content/common/gpu/gpu_messages.h"
11 #include "content/common/gpu/media/gpu_video_encode_accelerator.h" 11 #include "content/common/gpu/media/gpu_video_encode_accelerator.h"
12 #include "media/base/video_frame.h" 12 #include "media/base/video_frame.h"
13 13
14 namespace content { 14 namespace content {
15 15
16 #define NOTIFY_ERROR(error) \
17 PostNotifyError(error); \
18 DLOG(ERROR)
19
16 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost( 20 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
17 const scoped_refptr<GpuChannelHost>& gpu_channel_host, 21 GpuChannelHost* channel,
18 int32 route_id) 22 CommandBufferProxyImpl* impl)
19 : client_(NULL), 23 : channel_(channel),
20 channel_(gpu_channel_host), 24 encoder_route_id_(-1),
21 route_id_(route_id), 25 client_(NULL),
22 next_frame_id_(0) { 26 impl_(impl),
23 channel_->AddRoute(route_id_, AsWeakPtr()); 27 next_frame_id_(0),
28 weak_this_factory_(this) {
29 DCHECK(channel_);
30 DCHECK(impl_);
31 impl_->AddDeletionObserver(this);
24 } 32 }
25 33
26 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() { 34 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
35 DCHECK(CalledOnValidThread());
27 if (channel_) 36 if (channel_)
28 channel_->RemoveRoute(route_id_); 37 channel_->RemoveRoute(encoder_route_id_);
38 if (impl_)
39 impl_->RemoveDeletionObserver(this);
29 } 40 }
30 41
31 // static 42 // static
32 std::vector<media::VideoEncodeAccelerator::SupportedProfile> 43 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
33 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() { 44 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
34 return GpuVideoEncodeAccelerator::GetSupportedProfiles(); 45 return GpuVideoEncodeAccelerator::GetSupportedProfiles();
35 } 46 }
36 47
37 bool GpuVideoEncodeAcceleratorHost::OnMessageReceived( 48 bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
38 const IPC::Message& message) { 49 const IPC::Message& message) {
39 bool handled = true; 50 bool handled = true;
40 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message) 51 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message)
41 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInitializeDone,
42 OnNotifyInitializeDone)
43 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers, 52 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
44 OnRequireBitstreamBuffers) 53 OnRequireBitstreamBuffers)
45 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone, 54 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
46 OnNotifyInputDone) 55 OnNotifyInputDone)
47 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady, 56 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
48 OnBitstreamBufferReady) 57 OnBitstreamBufferReady)
49 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError, 58 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError,
50 OnNotifyError) 59 OnNotifyError)
51 IPC_MESSAGE_UNHANDLED(handled = false) 60 IPC_MESSAGE_UNHANDLED(handled = false)
52 IPC_END_MESSAGE_MAP() 61 IPC_END_MESSAGE_MAP()
53 DCHECK(handled); 62 DCHECK(handled);
54 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might 63 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
55 // have been called above. 64 // have been called above.
56 return handled; 65 return handled;
57 } 66 }
58 67
59 void GpuVideoEncodeAcceleratorHost::OnChannelError() { 68 void GpuVideoEncodeAcceleratorHost::OnChannelError() {
69 DCHECK(CalledOnValidThread());
70 if (channel_) {
71 channel_->RemoveRoute(encoder_route_id_);
72 channel_ = NULL;
73 weak_this_factory_.InvalidateWeakPtrs();
74 }
60 DLOG(ERROR) << "OnChannelError()"; 75 DLOG(ERROR) << "OnChannelError()";
Ami GONE FROM CHROMIUM 2014/03/18 23:53:19 Don't you want to notify the client in case of cha
sheu 2014/03/19 20:38:24 Oh, right. I was thinking for some reason this wa
61 if (channel_) {
62 channel_->RemoveRoute(route_id_);
63 channel_ = NULL;
64 }
65 // See OnNotifyError for why this needs to be the last thing in this
66 // function.
67 OnNotifyError(kPlatformFailureError);
68 } 76 }
69 77
70 void GpuVideoEncodeAcceleratorHost::Initialize( 78 bool GpuVideoEncodeAcceleratorHost::Initialize(
71 media::VideoFrame::Format input_format, 79 media::VideoFrame::Format input_format,
72 const gfx::Size& input_visible_size, 80 const gfx::Size& input_visible_size,
73 media::VideoCodecProfile output_profile, 81 media::VideoCodecProfile output_profile,
74 uint32 initial_bitrate, 82 uint32 initial_bitrate,
75 Client* client) { 83 Client* client) {
84 DCHECK(CalledOnValidThread());
76 client_ = client; 85 client_ = client;
77 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client_)); 86 if (!impl_) {
78 Send(new AcceleratedVideoEncoderMsg_Initialize(route_id_, 87 DLOG(ERROR) << "impl_ destroyed";
79 input_format, 88 return false;
80 input_visible_size, 89 }
81 output_profile, 90 Send(new GpuCommandBufferMsg_CreateVideoEncoder(impl_->GetRouteID(),
82 initial_bitrate)); 91 input_format,
92 input_visible_size,
93 output_profile,
94 initial_bitrate,
95 &encoder_route_id_));
96 if (encoder_route_id_ < 0) {
97 DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoEncoder()) failed";
98 return false;
99 }
100 channel_->AddRoute(encoder_route_id_, weak_this_factory_.GetWeakPtr());
101 return true;
83 } 102 }
84 103
85 void GpuVideoEncodeAcceleratorHost::Encode( 104 void GpuVideoEncodeAcceleratorHost::Encode(
86 const scoped_refptr<media::VideoFrame>& frame, 105 const scoped_refptr<media::VideoFrame>& frame,
87 bool force_keyframe) { 106 bool force_keyframe) {
107 DCHECK(CalledOnValidThread());
88 if (!channel_) 108 if (!channel_)
89 return; 109 return;
110
90 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) { 111 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
91 DLOG(ERROR) << "Encode(): cannot encode frame not backed by shared memory"; 112 NOTIFY_ERROR(kPlatformFailureError)
92 NotifyError(kPlatformFailureError); 113 << "Encode(): cannot encode frame not backed by shared memory";
93 return; 114 return;
94 } 115 }
95 base::SharedMemoryHandle handle = 116 base::SharedMemoryHandle handle =
96 channel_->ShareToGpuProcess(frame->shared_memory_handle()); 117 channel_->ShareToGpuProcess(frame->shared_memory_handle());
97 if (!base::SharedMemory::IsHandleValid(handle)) { 118 if (!base::SharedMemory::IsHandleValid(handle)) {
98 DLOG(ERROR) << "Encode(): failed to duplicate buffer handle for GPU " 119 NOTIFY_ERROR(kPlatformFailureError)
99 "process"; 120 << "Encode(): failed to duplicate buffer handle for GPU process";
100 NotifyError(kPlatformFailureError);
101 return; 121 return;
102 } 122 }
103 123
104 // We assume that planar frame data passed here is packed and contiguous. 124 // We assume that planar frame data passed here is packed and contiguous.
105 const size_t plane_count = media::VideoFrame::NumPlanes(frame->format()); 125 const size_t plane_count = media::VideoFrame::NumPlanes(frame->format());
106 size_t frame_size = 0; 126 size_t frame_size = 0;
107 for (size_t i = 0; i < plane_count; ++i) { 127 for (size_t i = 0; i < plane_count; ++i) {
108 // Cast DCHECK parameters to void* to avoid printing uint8* as a string. 128 // Cast DCHECK parameters to void* to avoid printing uint8* as a string.
109 DCHECK_EQ(reinterpret_cast<void*>(frame->data(i)), 129 DCHECK_EQ(reinterpret_cast<void*>(frame->data(i)),
110 reinterpret_cast<void*>((frame->data(0) + frame_size))) 130 reinterpret_cast<void*>((frame->data(0) + frame_size)))
111 << "plane=" << i; 131 << "plane=" << i;
112 frame_size += frame->stride(i) * frame->rows(i); 132 frame_size += frame->stride(i) * frame->rows(i);
113 } 133 }
114 134
115 Send(new AcceleratedVideoEncoderMsg_Encode( 135 Send(new AcceleratedVideoEncoderMsg_Encode(
116 route_id_, next_frame_id_, handle, frame_size, force_keyframe)); 136 encoder_route_id_, next_frame_id_, handle, frame_size, force_keyframe));
117 frame_map_[next_frame_id_] = frame; 137 frame_map_[next_frame_id_] = frame;
118 138
119 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. 139 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
120 next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF; 140 next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF;
121 } 141 }
122 142
123 void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer( 143 void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer(
124 const media::BitstreamBuffer& buffer) { 144 const media::BitstreamBuffer& buffer) {
145 DCHECK(CalledOnValidThread());
125 if (!channel_) 146 if (!channel_)
126 return; 147 return;
148
127 base::SharedMemoryHandle handle = 149 base::SharedMemoryHandle handle =
128 channel_->ShareToGpuProcess(buffer.handle()); 150 channel_->ShareToGpuProcess(buffer.handle());
129 if (!base::SharedMemory::IsHandleValid(handle)) { 151 if (!base::SharedMemory::IsHandleValid(handle)) {
130 DLOG(ERROR) << "UseOutputBitstreamBuffer(): failed to duplicate buffer " 152 NOTIFY_ERROR(kPlatformFailureError)
131 "handle for GPU process: buffer.id()=" << buffer.id(); 153 << "UseOutputBitstreamBuffer(): failed to duplicate buffer handle "
132 NotifyError(kPlatformFailureError); 154 "for GPU process: buffer.id()=" << buffer.id();
133 return; 155 return;
134 } 156 }
135 Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer( 157 Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer(
136 route_id_, buffer.id(), handle, buffer.size())); 158 encoder_route_id_, buffer.id(), handle, buffer.size()));
137 } 159 }
138 160
139 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange( 161 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
140 uint32 bitrate, 162 uint32 bitrate,
141 uint32 framerate) { 163 uint32 framerate) {
164 DCHECK(CalledOnValidThread());
165 if (!channel_)
166 return;
167
142 Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange( 168 Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
143 route_id_, bitrate, framerate)); 169 encoder_route_id_, bitrate, framerate));
144 } 170 }
145 171
146 void GpuVideoEncodeAcceleratorHost::Destroy() { 172 void GpuVideoEncodeAcceleratorHost::Destroy() {
147 Send(new GpuChannelMsg_DestroyVideoEncoder(route_id_)); 173 DCHECK(CalledOnValidThread());
174 if (channel_)
175 Send(new AcceleratedVideoEncoderMsg_Destroy(encoder_route_id_));
176 client_ = NULL;
148 delete this; 177 delete this;
149 } 178 }
150 179
151 void GpuVideoEncodeAcceleratorHost::NotifyError(Error error) { 180 void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() {
152 DVLOG(2) << "NotifyError(): error=" << error; 181 DCHECK(CalledOnValidThread());
182 impl_ = NULL;
183
184 // The CommandBufferProxyImpl is going away; error out this VEA.
185 OnChannelError();
186 }
187
188 void GpuVideoEncodeAcceleratorHost::PostNotifyError(Error error) {
189 DCHECK(CalledOnValidThread());
190 DVLOG(2) << "PostNotifyError(): error=" << error;
191 // Post the error notification back to this thread, to avoid re-entrancy.
153 base::MessageLoopProxy::current()->PostTask( 192 base::MessageLoopProxy::current()->PostTask(
154 FROM_HERE, 193 FROM_HERE,
155 base::Bind(&media::VideoEncodeAccelerator::Client::NotifyError, 194 base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError,
156 client_ptr_factory_->GetWeakPtr(), 195 weak_this_factory_.GetWeakPtr(),
157 error)); 196 error));
158 } 197 }
159 198
160 void GpuVideoEncodeAcceleratorHost::OnNotifyInitializeDone() { 199 void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
161 DVLOG(2) << "OnNotifyInitializeDone()"; 200 DCHECK(CalledOnValidThread());
162 if (client_) 201 uint32 message_type = message->type();
163 client_->NotifyInitializeDone(); 202 if (!channel_->Send(message)) {
203 NOTIFY_ERROR(kPlatformFailureError) << "Send(" << message_type
204 << ") failed";
205 }
164 } 206 }
165 207
166 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers( 208 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
167 uint32 input_count, 209 uint32 input_count,
168 const gfx::Size& input_coded_size, 210 const gfx::Size& input_coded_size,
169 uint32 output_buffer_size) { 211 uint32 output_buffer_size) {
212 DCHECK(CalledOnValidThread());
170 DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count 213 DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count
171 << ", input_coded_size=" << input_coded_size.ToString() 214 << ", input_coded_size=" << input_coded_size.ToString()
172 << ", output_buffer_size=" << output_buffer_size; 215 << ", output_buffer_size=" << output_buffer_size;
173 if (client_) { 216 if (client_) {
174 client_->RequireBitstreamBuffers( 217 client_->RequireBitstreamBuffers(
175 input_count, input_coded_size, output_buffer_size); 218 input_count, input_coded_size, output_buffer_size);
176 } 219 }
177 } 220 }
178 221
179 void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) { 222 void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) {
223 DCHECK(CalledOnValidThread());
180 DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id; 224 DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id;
181 // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a 225 // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a
182 // frame can trigger a further encode to be kicked off and thus an .insert() 226 // frame can trigger a further encode to be kicked off and thus an .insert()
183 // back into the map, we separate the frame's dtor running from the .erase() 227 // back into the map, we separate the frame's dtor running from the .erase()
184 // running by holding on to the frame temporarily. This isn't "just 228 // running by holding on to the frame temporarily. This isn't "just
185 // theoretical" - Android's std::hash_map crashes if we don't do this. 229 // theoretical" - Android's std::hash_map crashes if we don't do this.
186 scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id]; 230 scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id];
187 if (!frame_map_.erase(frame_id)) { 231 if (!frame_map_.erase(frame_id)) {
188 DLOG(ERROR) << "OnNotifyInputDone(): " 232 DLOG(ERROR) << "OnNotifyInputDone(): "
189 "invalid frame_id=" << frame_id; 233 "invalid frame_id=" << frame_id;
190 // See OnNotifyError for why this needs to be the last thing in this 234 // See OnNotifyError for why this needs to be the last thing in this
191 // function. 235 // function.
192 OnNotifyError(kPlatformFailureError); 236 OnNotifyError(kPlatformFailureError);
193 return; 237 return;
194 } 238 }
195 frame = NULL; // Not necessary but nice to be explicit; see fun-fact above. 239 frame = NULL; // Not necessary but nice to be explicit; see fun-fact above.
196 } 240 }
197 241
198 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady( 242 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
199 int32 bitstream_buffer_id, 243 int32 bitstream_buffer_id,
200 uint32 payload_size, 244 uint32 payload_size,
201 bool key_frame) { 245 bool key_frame) {
246 DCHECK(CalledOnValidThread());
202 DVLOG(3) << "OnBitstreamBufferReady(): " 247 DVLOG(3) << "OnBitstreamBufferReady(): "
203 "bitstream_buffer_id=" << bitstream_buffer_id 248 "bitstream_buffer_id=" << bitstream_buffer_id
204 << ", payload_size=" << payload_size 249 << ", payload_size=" << payload_size
205 << ", key_frame=" << key_frame; 250 << ", key_frame=" << key_frame;
206 if (client_) 251 if (client_)
207 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame); 252 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
208 } 253 }
209 254
210 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) { 255 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) {
256 DCHECK(CalledOnValidThread());
211 DVLOG(2) << "OnNotifyError(): error=" << error; 257 DVLOG(2) << "OnNotifyError(): error=" << error;
212 if (!client_) 258 if (!client_)
213 return; 259 return;
214 client_ptr_factory_.reset();
215 260
216 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the 261 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
217 // last thing done on this stack! 262 // last thing done on this stack!
218 media::VideoEncodeAccelerator::Client* client = NULL; 263 media::VideoEncodeAccelerator::Client* client = NULL;
219 std::swap(client_, client); 264 std::swap(client_, client);
220 client->NotifyError(error); 265 client->NotifyError(error);
221 } 266 }
222 267
223 void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
224 if (!channel_) {
225 DLOG(ERROR) << "Send(): no channel";
226 delete message;
227 NotifyError(kPlatformFailureError);
228 } else if (!channel_->Send(message)) {
229 DLOG(ERROR) << "Send(): sending failed: message->type()="
230 << message->type();
231 NotifyError(kPlatformFailureError);
232 }
233 }
234
235 } // namespace content 268 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698