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 "base/thread_task_runner_handle.h" |
10 #include "build/build_config.h" | 11 #include "build/build_config.h" |
11 #include "content/common/gpu/client/gpu_channel_host.h" | 12 #include "content/common/gpu/client/gpu_channel_host.h" |
12 #include "content/common/gpu/gpu_messages.h" | 13 #include "content/common/gpu/client/ipc/chrome/chrome_command_buffer_ipc_transpo
rt.h" |
13 #include "content/common/view_messages.h" | 14 #include "content/common/gpu/video_decode_params.h" |
14 #include "ipc/ipc_message_macros.h" | |
15 #include "ipc/ipc_message_utils.h" | |
16 | 15 |
17 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
18 #include "content/public/common/sandbox_init.h" | 17 #include "content/public/common/sandbox_init.h" |
19 #endif // OS_WIN | 18 #endif // OS_WIN |
20 | 19 |
21 using media::VideoDecodeAccelerator; | 20 using media::VideoDecodeAccelerator; |
| 21 |
22 namespace content { | 22 namespace content { |
23 | 23 |
24 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost( | 24 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost( |
25 GpuChannelHost* channel, | 25 GpuChannelHost* channel, |
| 26 scoped_ptr<GpuVideoDecodeAcceleratorHostIPCTransport> transport, |
26 CommandBufferProxyImpl* impl) | 27 CommandBufferProxyImpl* impl) |
27 : channel_(channel), | 28 : channel_(channel), |
28 decoder_route_id_(MSG_ROUTING_NONE), | 29 transport_(std::move(transport)), |
29 client_(NULL), | 30 client_(nullptr), |
30 impl_(impl), | 31 impl_(impl), |
31 weak_this_factory_(this) { | 32 weak_this_factory_(this) { |
32 DCHECK(channel_); | |
33 DCHECK(impl_); | 33 DCHECK(impl_); |
34 impl_->AddDeletionObserver(this); | 34 impl_->AddDeletionObserver(this); |
| 35 transport_->SetClient(this); |
35 } | 36 } |
36 | 37 |
37 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() { | 38 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() { |
38 DCHECK(CalledOnValidThread()); | 39 DCHECK(CalledOnValidThread()); |
39 | 40 transport_.reset(); |
40 if (channel_ && decoder_route_id_ != MSG_ROUTING_NONE) | |
41 channel_->RemoveRoute(decoder_route_id_); | |
42 if (impl_) | 41 if (impl_) |
43 impl_->RemoveDeletionObserver(this); | 42 impl_->RemoveDeletionObserver(this); |
44 } | 43 } |
45 | 44 |
46 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) { | 45 bool GpuVideoDecodeAcceleratorHost::Initialize( |
47 DCHECK(CalledOnValidThread()); | 46 const Config& config, |
48 bool handled = true; | 47 media::VideoDecodeAccelerator::Client* client) { |
49 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg) | |
50 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_CdmAttached, | |
51 OnCdmAttached) | |
52 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed, | |
53 OnBitstreamBufferProcessed) | |
54 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers, | |
55 OnProvidePictureBuffer) | |
56 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady, | |
57 OnPictureReady) | |
58 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone, | |
59 OnFlushDone) | |
60 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone, | |
61 OnResetDone) | |
62 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification, | |
63 OnNotifyError) | |
64 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer, | |
65 OnDismissPictureBuffer) | |
66 IPC_MESSAGE_UNHANDLED(handled = false) | |
67 IPC_END_MESSAGE_MAP() | |
68 DCHECK(handled); | |
69 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might | |
70 // have been called above. | |
71 return handled; | |
72 } | |
73 | |
74 void GpuVideoDecodeAcceleratorHost::OnChannelError() { | |
75 DCHECK(CalledOnValidThread()); | |
76 if (channel_) { | |
77 if (decoder_route_id_ != MSG_ROUTING_NONE) | |
78 channel_->RemoveRoute(decoder_route_id_); | |
79 channel_ = NULL; | |
80 } | |
81 DLOG(ERROR) << "OnChannelError()"; | |
82 PostNotifyError(PLATFORM_FAILURE); | |
83 } | |
84 | |
85 bool GpuVideoDecodeAcceleratorHost::Initialize(const Config& config, | |
86 Client* client) { | |
87 DCHECK(CalledOnValidThread()); | 48 DCHECK(CalledOnValidThread()); |
88 client_ = client; | 49 client_ = client; |
89 | 50 |
90 if (!impl_) | 51 if (!impl_) |
91 return false; | 52 return false; |
92 | 53 |
93 int32_t route_id = channel_->GenerateRouteID(); | |
94 channel_->AddRoute(route_id, weak_this_factory_.GetWeakPtr()); | |
95 | |
96 bool succeeded = false; | 54 bool succeeded = false; |
97 Send(new GpuCommandBufferMsg_CreateVideoDecoder(impl_->route_id(), config, | 55 impl_->transport()->CreateVideoDecoder(transport_.get(), config, &succeeded); |
98 route_id, &succeeded)); | |
99 | |
100 if (!succeeded) { | 56 if (!succeeded) { |
101 DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoDecoder()) failed"; | 57 DLOG(ERROR) << "CreateVideoDecoder() failed"; |
102 PostNotifyError(PLATFORM_FAILURE); | 58 PostNotifyError(PLATFORM_FAILURE); |
103 channel_->RemoveRoute(route_id); | |
104 return false; | 59 return false; |
105 } | 60 } |
106 decoder_route_id_ = route_id; | |
107 return true; | 61 return true; |
108 } | 62 } |
109 | 63 |
110 void GpuVideoDecodeAcceleratorHost::SetCdm(int cdm_id) { | 64 void GpuVideoDecodeAcceleratorHost::SetCdm(int cdm_id) { |
111 DCHECK(CalledOnValidThread()); | 65 DCHECK(CalledOnValidThread()); |
112 if (!channel_) | 66 transport_->SetCdm(cdm_id); |
113 return; | |
114 Send(new AcceleratedVideoDecoderMsg_SetCdm(decoder_route_id_, cdm_id)); | |
115 } | 67 } |
116 | 68 |
117 void GpuVideoDecodeAcceleratorHost::Decode( | 69 void GpuVideoDecodeAcceleratorHost::Decode( |
118 const media::BitstreamBuffer& bitstream_buffer) { | 70 const media::BitstreamBuffer& bitstream_buffer) { |
119 DCHECK(CalledOnValidThread()); | 71 DCHECK(CalledOnValidThread()); |
120 if (!channel_) | |
121 return; | |
122 | 72 |
123 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess( | 73 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess( |
124 bitstream_buffer.handle()); | 74 bitstream_buffer.handle()); |
125 if (!base::SharedMemory::IsHandleValid(handle)) { | 75 if (!base::SharedMemory::IsHandleValid(handle)) { |
126 NOTREACHED() << "Failed to duplicate buffer handler"; | 76 NOTREACHED() << "Failed to duplicate buffer handler"; |
127 return; | 77 return; |
128 } | 78 } |
129 | 79 |
130 AcceleratedVideoDecoderMsg_Decode_Params params; | 80 VideoDecodeParams params; |
131 params.bitstream_buffer_id = bitstream_buffer.id(); | 81 params.bitstream_buffer_id = bitstream_buffer.id(); |
132 params.buffer_handle = handle; | 82 params.buffer_handle = handle; |
133 params.size = bitstream_buffer.size(); | 83 params.size = bitstream_buffer.size(); |
134 params.presentation_timestamp = bitstream_buffer.presentation_timestamp(); | 84 params.presentation_timestamp = bitstream_buffer.presentation_timestamp(); |
135 params.key_id = bitstream_buffer.key_id(); | 85 params.key_id = bitstream_buffer.key_id(); |
136 params.iv = bitstream_buffer.iv(); | 86 params.iv = bitstream_buffer.iv(); |
137 params.subsamples = bitstream_buffer.subsamples(); | 87 params.subsamples = bitstream_buffer.subsamples(); |
138 | 88 |
139 Send(new AcceleratedVideoDecoderMsg_Decode(decoder_route_id_, params)); | 89 transport_->Decode(params); |
140 } | 90 } |
141 | 91 |
142 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers( | 92 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers( |
143 const std::vector<media::PictureBuffer>& buffers) { | 93 const std::vector<media::PictureBuffer>& buffers) { |
144 DCHECK(CalledOnValidThread()); | 94 DCHECK(CalledOnValidThread()); |
145 if (!channel_) | 95 if (!channel_) |
146 return; | 96 return; |
147 // Rearrange data for IPC command. | 97 // Rearrange data for IPC command. |
148 std::vector<int32_t> buffer_ids; | 98 std::vector<int32_t> buffer_ids; |
149 std::vector<uint32_t> texture_ids; | 99 std::vector<uint32_t> texture_ids; |
150 for (uint32_t i = 0; i < buffers.size(); i++) { | 100 for (uint32_t i = 0; i < buffers.size(); i++) { |
151 const media::PictureBuffer& buffer = buffers[i]; | 101 const media::PictureBuffer& buffer = buffers[i]; |
152 if (buffer.size() != picture_buffer_dimensions_) { | 102 if (buffer.size() != picture_buffer_dimensions_) { |
153 DLOG(ERROR) << "buffer.size() invalid: expected " | 103 DLOG(ERROR) << "buffer.size() invalid: expected " |
154 << picture_buffer_dimensions_.ToString() | 104 << picture_buffer_dimensions_.ToString() |
155 << ", got " << buffer.size().ToString(); | 105 << ", got " << buffer.size().ToString(); |
156 PostNotifyError(INVALID_ARGUMENT); | 106 PostNotifyError(INVALID_ARGUMENT); |
157 return; | 107 return; |
158 } | 108 } |
159 texture_ids.push_back(buffer.texture_id()); | 109 texture_ids.push_back(buffer.texture_id()); |
160 buffer_ids.push_back(buffer.id()); | 110 buffer_ids.push_back(buffer.id()); |
161 } | 111 } |
162 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers( | 112 transport_->AssignPictureBuffers(buffer_ids, texture_ids); |
163 decoder_route_id_, buffer_ids, texture_ids)); | |
164 } | 113 } |
165 | 114 |
166 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer( | 115 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer( |
167 int32_t picture_buffer_id) { | 116 int32_t picture_buffer_id) { |
168 DCHECK(CalledOnValidThread()); | 117 DCHECK(CalledOnValidThread()); |
169 if (!channel_) | 118 if (!channel_) |
170 return; | 119 return; |
171 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer( | 120 transport_->ReusePictureBuffer(picture_buffer_id); |
172 decoder_route_id_, picture_buffer_id)); | |
173 } | 121 } |
174 | 122 |
175 void GpuVideoDecodeAcceleratorHost::Flush() { | 123 void GpuVideoDecodeAcceleratorHost::Flush() { |
176 DCHECK(CalledOnValidThread()); | 124 DCHECK(CalledOnValidThread()); |
177 if (!channel_) | 125 if (!channel_) |
178 return; | 126 return; |
179 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_)); | 127 transport_->Flush(); |
180 } | 128 } |
181 | 129 |
182 void GpuVideoDecodeAcceleratorHost::Reset() { | 130 void GpuVideoDecodeAcceleratorHost::Reset() { |
183 DCHECK(CalledOnValidThread()); | 131 DCHECK(CalledOnValidThread()); |
184 if (!channel_) | 132 if (!channel_) |
185 return; | 133 return; |
186 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_)); | 134 transport_->Reset(); |
187 } | 135 } |
188 | 136 |
189 void GpuVideoDecodeAcceleratorHost::Destroy() { | 137 void GpuVideoDecodeAcceleratorHost::Destroy() { |
190 DCHECK(CalledOnValidThread()); | 138 DCHECK(CalledOnValidThread()); |
191 if (channel_) | 139 if (channel_) |
192 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_)); | 140 transport_->Destroy(); |
193 client_ = NULL; | 141 client_ = nullptr; |
194 delete this; | 142 delete this; |
195 } | 143 } |
196 | 144 |
197 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() { | 145 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() { |
198 DCHECK(CalledOnValidThread()); | 146 DCHECK(CalledOnValidThread()); |
199 impl_ = NULL; | 147 impl_ = nullptr; |
200 | |
201 // The CommandBufferProxyImpl is going away; error out this VDA. | |
202 OnChannelError(); | |
203 } | 148 } |
204 | 149 |
205 void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error) { | 150 void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error) { |
206 DCHECK(CalledOnValidThread()); | 151 DCHECK(CalledOnValidThread()); |
207 DVLOG(2) << "PostNotifyError(): error=" << error; | 152 DVLOG(2) << "PostNotifyError(): error=" << error; |
208 base::ThreadTaskRunnerHandle::Get()->PostTask( | 153 base::ThreadTaskRunnerHandle::Get()->PostTask( |
209 FROM_HERE, base::Bind(&GpuVideoDecodeAcceleratorHost::OnNotifyError, | 154 FROM_HERE, base::Bind(&GpuVideoDecodeAcceleratorHost::OnNotifyError, |
210 weak_this_factory_.GetWeakPtr(), error)); | 155 weak_this_factory_.GetWeakPtr(), error)); |
211 } | 156 } |
212 | 157 |
213 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) { | |
214 DCHECK(CalledOnValidThread()); | |
215 uint32_t message_type = message->type(); | |
216 if (!channel_->Send(message)) { | |
217 DLOG(ERROR) << "Send(" << message_type << ") failed"; | |
218 PostNotifyError(PLATFORM_FAILURE); | |
219 } | |
220 } | |
221 | |
222 void GpuVideoDecodeAcceleratorHost::OnCdmAttached(bool success) { | 158 void GpuVideoDecodeAcceleratorHost::OnCdmAttached(bool success) { |
223 DCHECK(CalledOnValidThread()); | 159 DCHECK(CalledOnValidThread()); |
224 if (client_) | 160 if (client_) |
225 client_->NotifyCdmAttached(success); | 161 client_->NotifyCdmAttached(success); |
226 } | 162 } |
227 | 163 |
228 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed( | 164 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed( |
229 int32_t bitstream_buffer_id) { | 165 int32_t bitstream_buffer_id) { |
230 DCHECK(CalledOnValidThread()); | 166 DCHECK(CalledOnValidThread()); |
231 if (client_) | 167 if (client_) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 } | 213 } |
278 | 214 |
279 void GpuVideoDecodeAcceleratorHost::OnNotifyError(uint32_t error) { | 215 void GpuVideoDecodeAcceleratorHost::OnNotifyError(uint32_t error) { |
280 DCHECK(CalledOnValidThread()); | 216 DCHECK(CalledOnValidThread()); |
281 if (!client_) | 217 if (!client_) |
282 return; | 218 return; |
283 weak_this_factory_.InvalidateWeakPtrs(); | 219 weak_this_factory_.InvalidateWeakPtrs(); |
284 | 220 |
285 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the | 221 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the |
286 // last thing done on this stack! | 222 // last thing done on this stack! |
287 media::VideoDecodeAccelerator::Client* client = NULL; | 223 media::VideoDecodeAccelerator::Client* client = nullptr; |
288 std::swap(client, client_); | 224 std::swap(client, client_); |
289 client->NotifyError(static_cast<media::VideoDecodeAccelerator::Error>(error)); | 225 client->NotifyError(static_cast<media::VideoDecodeAccelerator::Error>(error)); |
290 } | 226 } |
291 | 227 |
292 } // namespace content | 228 } // namespace content |
OLD | NEW |