OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_decode_accelerator_host.h" | 5 #include "content/common/gpu/client/gpu_video_decode_accelerator_host.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "content/common/gpu/client/gpu_channel_host.h" | 10 #include "content/common/gpu/client/gpu_channel_host.h" |
11 #include "content/common/gpu/gpu_messages.h" | 11 #include "content/common/gpu/gpu_messages.h" |
12 #include "content/common/view_messages.h" | 12 #include "content/common/view_messages.h" |
13 #include "ipc/ipc_message_macros.h" | 13 #include "ipc/ipc_message_macros.h" |
14 #include "ipc/ipc_message_utils.h" | 14 #include "ipc/ipc_message_utils.h" |
15 | 15 |
16 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
17 #include "content/public/common/sandbox_init.h" | 17 #include "content/public/common/sandbox_init.h" |
18 #endif // OS_WIN | 18 #endif // OS_WIN |
19 | 19 |
20 #define NOTIFY_ERROR(error) \ | |
21 PostNotifyError(error); \ | |
22 DLOG(ERROR) | |
23 | |
20 using media::VideoDecodeAccelerator; | 24 using media::VideoDecodeAccelerator; |
21 namespace content { | 25 namespace content { |
22 | 26 |
23 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost( | 27 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost( |
24 GpuChannelHost* channel, | 28 GpuChannelHost* channel, |
25 int32 decoder_route_id, | |
26 CommandBufferProxyImpl* impl) | 29 CommandBufferProxyImpl* impl) |
27 : channel_(channel), | 30 : channel_(channel), |
28 decoder_route_id_(decoder_route_id), | 31 decoder_route_id_(-1), |
29 client_(NULL), | 32 client_(NULL), |
30 impl_(impl) { | 33 impl_(impl), |
34 weak_this_factory_(this) { | |
31 DCHECK(channel_); | 35 DCHECK(channel_); |
32 channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this)); | 36 DCHECK(impl_); |
33 impl_->AddDeletionObserver(this); | 37 impl_->AddDeletionObserver(this); |
34 } | 38 } |
35 | 39 |
36 void GpuVideoDecodeAcceleratorHost::OnChannelError() { | 40 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() { |
37 DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()"; | 41 DCHECK(CalledOnValidThread()); |
38 if (channel_) { | 42 |
43 if (channel_) | |
39 channel_->RemoveRoute(decoder_route_id_); | 44 channel_->RemoveRoute(decoder_route_id_); |
40 channel_ = NULL; | 45 if (impl_) |
41 } | 46 impl_->RemoveDeletionObserver(this); |
42 // See OnErrorNotification for why this needs to be the last thing in this | |
43 // function. | |
44 OnErrorNotification(PLATFORM_FAILURE); | |
45 } | 47 } |
46 | 48 |
47 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) { | 49 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) { |
48 DCHECK(CalledOnValidThread()); | 50 DCHECK(CalledOnValidThread()); |
49 bool handled = true; | 51 bool handled = true; |
50 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg) | 52 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg) |
51 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed, | 53 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed, |
52 OnBitstreamBufferProcessed) | 54 OnBitstreamBufferProcessed) |
53 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers, | 55 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers, |
54 OnProvidePictureBuffer) | 56 OnProvidePictureBuffer) |
55 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady, | 57 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady, |
56 OnPictureReady) | 58 OnPictureReady) |
57 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone, | 59 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone, |
58 OnFlushDone) | 60 OnFlushDone) |
59 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone, | 61 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone, |
60 OnResetDone) | 62 OnResetDone) |
61 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification, | 63 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification, |
62 OnErrorNotification) | 64 OnNotifyError) |
63 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer, | 65 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer, |
64 OnDismissPictureBuffer) | 66 OnDismissPictureBuffer) |
65 IPC_MESSAGE_UNHANDLED(handled = false) | 67 IPC_MESSAGE_UNHANDLED(handled = false) |
66 IPC_END_MESSAGE_MAP() | 68 IPC_END_MESSAGE_MAP() |
67 DCHECK(handled); | 69 DCHECK(handled); |
68 // See OnErrorNotification for why |this| mustn't be used after | 70 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might |
69 // OnErrorNotification might have been called above. | 71 // have been called above. |
70 return handled; | 72 return handled; |
71 } | 73 } |
72 | 74 |
75 void GpuVideoDecodeAcceleratorHost::OnChannelError() { | |
76 DCHECK(CalledOnValidThread()); | |
77 if (channel_) { | |
78 channel_->RemoveRoute(decoder_route_id_); | |
79 channel_ = NULL; | |
80 weak_this_factory_.InvalidateWeakPtrs(); | |
81 } | |
82 NOTIFY_ERROR(PLATFORM_FAILURE) << "OnChannelError()"; | |
Ami GONE FROM CHROMIUM
2014/03/17 03:17:54
This will be a no-op since the posted error notifi
sheu
2014/03/18 22:38:35
I suppose. Making this a DLOG(ERROR) instead.
| |
83 } | |
84 | |
73 bool GpuVideoDecodeAcceleratorHost::Initialize(media::VideoCodecProfile profile, | 85 bool GpuVideoDecodeAcceleratorHost::Initialize(media::VideoCodecProfile profile, |
74 Client* client) { | 86 Client* client) { |
87 DCHECK(CalledOnValidThread()); | |
75 client_ = client; | 88 client_ = client; |
89 | |
90 if (!impl_) | |
91 return false; | |
92 Send(new GpuCommandBufferMsg_CreateVideoDecoder( | |
93 impl_->GetRouteID(), profile, &decoder_route_id_)); | |
94 if (decoder_route_id_ < 0) { | |
95 NOTIFY_ERROR(PLATFORM_FAILURE) | |
96 << "Send(GpuCommandBufferMsg_CreateVideoDecoder()) failed"; | |
97 return false; | |
98 } | |
99 | |
100 channel_->AddRoute(decoder_route_id_, weak_this_factory_.GetWeakPtr()); | |
76 return true; | 101 return true; |
77 } | 102 } |
78 | 103 |
79 void GpuVideoDecodeAcceleratorHost::Decode( | 104 void GpuVideoDecodeAcceleratorHost::Decode( |
80 const media::BitstreamBuffer& bitstream_buffer) { | 105 const media::BitstreamBuffer& bitstream_buffer) { |
81 DCHECK(CalledOnValidThread()); | 106 DCHECK(CalledOnValidThread()); |
82 // Can happen if a decode task was posted before an error was delivered. | |
83 if (!channel_) | 107 if (!channel_) |
84 return; | 108 return; |
85 | 109 |
86 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess( | 110 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess( |
87 bitstream_buffer.handle()); | 111 bitstream_buffer.handle()); |
88 if (!base::SharedMemory::IsHandleValid(handle)) { | 112 if (!base::SharedMemory::IsHandleValid(handle)) { |
89 NOTREACHED() << "Failed to duplicate buffer handler"; | 113 NOTREACHED() << "Failed to duplicate buffer handler"; |
90 return; | 114 return; |
91 } | 115 } |
92 | 116 |
93 Send(new AcceleratedVideoDecoderMsg_Decode( | 117 Send(new AcceleratedVideoDecoderMsg_Decode( |
94 decoder_route_id_, handle, bitstream_buffer.id(), | 118 decoder_route_id_, handle, bitstream_buffer.id(), |
95 bitstream_buffer.size())); | 119 bitstream_buffer.size())); |
96 } | 120 } |
97 | 121 |
98 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers( | 122 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers( |
99 const std::vector<media::PictureBuffer>& buffers) { | 123 const std::vector<media::PictureBuffer>& buffers) { |
100 DCHECK(CalledOnValidThread()); | 124 DCHECK(CalledOnValidThread()); |
125 if (!channel_) | |
126 return; | |
101 // Rearrange data for IPC command. | 127 // Rearrange data for IPC command. |
102 std::vector<int32> buffer_ids; | 128 std::vector<int32> buffer_ids; |
103 std::vector<uint32> texture_ids; | 129 std::vector<uint32> texture_ids; |
104 for (uint32 i = 0; i < buffers.size(); i++) { | 130 for (uint32 i = 0; i < buffers.size(); i++) { |
105 const media::PictureBuffer& buffer = buffers[i]; | 131 const media::PictureBuffer& buffer = buffers[i]; |
106 if (buffer.size() != picture_buffer_dimensions_) { | 132 if (buffer.size() != picture_buffer_dimensions_) { |
107 OnErrorNotification(INVALID_ARGUMENT); | 133 NOTIFY_ERROR(INVALID_ARGUMENT) << "buffer.size() invalid: expected " |
134 << picture_buffer_dimensions_.ToString() | |
135 << ", got " << buffer.size().ToString(); | |
108 return; | 136 return; |
109 } | 137 } |
110 texture_ids.push_back(buffer.texture_id()); | 138 texture_ids.push_back(buffer.texture_id()); |
111 buffer_ids.push_back(buffer.id()); | 139 buffer_ids.push_back(buffer.id()); |
112 } | 140 } |
113 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers( | 141 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers( |
114 decoder_route_id_, buffer_ids, texture_ids)); | 142 decoder_route_id_, buffer_ids, texture_ids)); |
115 } | 143 } |
116 | 144 |
117 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer( | 145 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer( |
118 int32 picture_buffer_id) { | 146 int32 picture_buffer_id) { |
119 DCHECK(CalledOnValidThread()); | 147 DCHECK(CalledOnValidThread()); |
148 if (!channel_) | |
149 return; | |
120 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer( | 150 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer( |
121 decoder_route_id_, picture_buffer_id)); | 151 decoder_route_id_, picture_buffer_id)); |
122 } | 152 } |
123 | 153 |
124 void GpuVideoDecodeAcceleratorHost::Flush() { | 154 void GpuVideoDecodeAcceleratorHost::Flush() { |
125 DCHECK(CalledOnValidThread()); | 155 DCHECK(CalledOnValidThread()); |
156 if (!channel_) | |
157 return; | |
126 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_)); | 158 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_)); |
127 } | 159 } |
128 | 160 |
129 void GpuVideoDecodeAcceleratorHost::Reset() { | 161 void GpuVideoDecodeAcceleratorHost::Reset() { |
130 DCHECK(CalledOnValidThread()); | 162 DCHECK(CalledOnValidThread()); |
163 if (!channel_) | |
164 return; | |
131 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_)); | 165 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_)); |
132 } | 166 } |
133 | 167 |
134 void GpuVideoDecodeAcceleratorHost::Destroy() { | 168 void GpuVideoDecodeAcceleratorHost::Destroy() { |
135 DCHECK(CalledOnValidThread()); | 169 DCHECK(CalledOnValidThread()); |
170 if (channel_) | |
171 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_)); | |
136 client_ = NULL; | 172 client_ = NULL; |
137 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_)); | |
138 delete this; | 173 delete this; |
139 } | 174 } |
140 | 175 |
141 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() { | 176 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() { |
177 DCHECK(CalledOnValidThread()); | |
142 impl_ = NULL; | 178 impl_ = NULL; |
143 | 179 |
144 // The CommandBufferProxyImpl is going away; error out this VDA. | 180 // The CommandBufferProxyImpl is going away; error out this VDA. |
145 OnChannelError(); | 181 OnChannelError(); |
146 } | 182 } |
147 | 183 |
148 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() { | 184 void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error) { |
149 DCHECK(CalledOnValidThread()); | 185 DCHECK(CalledOnValidThread()); |
150 | 186 DVLOG(2) << "PostNotifyError(): error=" << error; |
151 if (channel_) | 187 base::MessageLoopProxy::current()->PostTask( |
152 channel_->RemoveRoute(decoder_route_id_); | 188 FROM_HERE, |
153 if (impl_) | 189 base::Bind(&GpuVideoDecodeAcceleratorHost::OnNotifyError, |
154 impl_->RemoveDeletionObserver(this); | 190 weak_this_factory_.GetWeakPtr(), |
191 error)); | |
155 } | 192 } |
156 | 193 |
157 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) { | 194 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) { |
195 DCHECK(CalledOnValidThread()); | |
158 // After OnChannelError is called, the client should no longer send | 196 // After OnChannelError is called, the client should no longer send |
159 // messages to the gpu channel through this object. But queued posted tasks | 197 // messages to the gpu channel through this object. But queued posted tasks |
160 // can still be draining, so we're forgiving and simply ignore them. | 198 // can still be draining, so we're forgiving and simply ignore them. |
Ami GONE FROM CHROMIUM
2014/03/17 03:17:54
Ditto comments from GVEAH.
| |
161 bool error = false; | |
162 uint32 message_type = message->type(); | 199 uint32 message_type = message->type(); |
163 if (!channel_) { | 200 if (!channel_->Send(message)) |
164 delete message; | 201 NOTIFY_ERROR(PLATFORM_FAILURE) << "Send(" << message_type << ") failed"; |
165 DLOG(ERROR) << "Send(" << message_type << ") after error ignored"; | |
166 error = true; | |
167 } else if (!channel_->Send(message)) { | |
168 DLOG(ERROR) << "Send(" << message_type << ") failed"; | |
169 error = true; | |
170 } | |
171 // See OnErrorNotification for why this needs to be the last thing in this | |
172 // function. | |
173 if (error) | |
174 OnErrorNotification(PLATFORM_FAILURE); | |
175 } | 202 } |
176 | 203 |
177 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed( | 204 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed( |
178 int32 bitstream_buffer_id) { | 205 int32 bitstream_buffer_id) { |
179 DCHECK(CalledOnValidThread()); | 206 DCHECK(CalledOnValidThread()); |
180 if (client_) | 207 if (client_) |
181 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); | 208 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); |
182 } | 209 } |
183 | 210 |
184 void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer( | 211 void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer( |
(...skipping 29 matching lines...) Expand all Loading... | |
214 if (client_) | 241 if (client_) |
215 client_->NotifyFlushDone(); | 242 client_->NotifyFlushDone(); |
216 } | 243 } |
217 | 244 |
218 void GpuVideoDecodeAcceleratorHost::OnResetDone() { | 245 void GpuVideoDecodeAcceleratorHost::OnResetDone() { |
219 DCHECK(CalledOnValidThread()); | 246 DCHECK(CalledOnValidThread()); |
220 if (client_) | 247 if (client_) |
221 client_->NotifyResetDone(); | 248 client_->NotifyResetDone(); |
222 } | 249 } |
223 | 250 |
224 void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) { | 251 void GpuVideoDecodeAcceleratorHost::OnNotifyError(uint32 error) { |
225 DCHECK(CalledOnValidThread()); | 252 DCHECK(CalledOnValidThread()); |
226 if (!client_) | 253 if (!client_) |
227 return; | 254 return; |
228 | 255 |
229 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the | 256 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the |
230 // last thing done on this stack! | 257 // last thing done on this stack! |
231 media::VideoDecodeAccelerator::Client* client = NULL; | 258 media::VideoDecodeAccelerator::Client* client = NULL; |
232 std::swap(client, client_); | 259 std::swap(client, client_); |
233 client->NotifyError( | 260 client->NotifyError(static_cast<media::VideoDecodeAccelerator::Error>(error)); |
234 static_cast<media::VideoDecodeAccelerator::Error>(error)); | |
235 } | 261 } |
236 | 262 |
237 } // namespace content | 263 } // namespace content |
OLD | NEW |