OLD | NEW |
---|---|
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 "media/gpu/ipc/service/gpu_video_encode_accelerator.h" | 5 #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
13 #include "base/memory/shared_memory.h" | 13 #include "base/memory/shared_memory.h" |
14 #include "base/numerics/safe_math.h" | 14 #include "base/numerics/safe_math.h" |
15 #include "base/sys_info.h" | 15 #include "base/sys_info.h" |
16 #include "base/trace_event/trace_event.h" | |
16 #include "build/build_config.h" | 17 #include "build/build_config.h" |
17 #include "gpu/ipc/service/gpu_channel.h" | 18 #include "gpu/ipc/service/gpu_channel.h" |
18 #include "gpu/ipc/service/gpu_channel_manager.h" | 19 #include "gpu/ipc/service/gpu_channel_manager.h" |
19 #include "ipc/ipc_message_macros.h" | 20 #include "ipc/ipc_message_macros.h" |
20 #include "media/base/bind_to_current_loop.h" | 21 #include "media/base/bind_to_current_loop.h" |
21 #include "media/base/limits.h" | 22 #include "media/base/limits.h" |
22 #include "media/base/video_frame.h" | 23 #include "media/base/video_frame.h" |
23 #include "media/gpu/gpu_video_accelerator_util.h" | 24 #include "media/gpu/gpu_video_accelerator_util.h" |
24 #include "media/gpu/ipc/common/media_messages.h" | 25 #include "media/gpu/ipc/common/media_messages.h" |
25 | 26 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 | 93 |
93 #if defined(OS_WIN) | 94 #if defined(OS_WIN) |
94 std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() { | 95 std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() { |
95 return base::WrapUnique<media::VideoEncodeAccelerator>( | 96 return base::WrapUnique<media::VideoEncodeAccelerator>( |
96 new MediaFoundationVideoEncodeAccelerator()); | 97 new MediaFoundationVideoEncodeAccelerator()); |
97 } | 98 } |
98 #endif | 99 #endif |
99 | 100 |
100 } // anonymous namespace | 101 } // anonymous namespace |
101 | 102 |
103 class GpuVideoEncodeAccelerator::MessageFilter : public IPC::MessageFilter { | |
104 public: | |
105 MessageFilter(GpuVideoEncodeAccelerator* owner, int32_t host_route_id) | |
106 : owner_(owner), host_route_id_(host_route_id), sender_(nullptr) {} | |
107 | |
108 void OnChannelError() override { sender_ = nullptr; } | |
109 | |
110 void OnChannelClosing() override { sender_ = nullptr; } | |
111 | |
112 void OnFilterAdded(IPC::Channel* channel) override { sender_ = channel; } | |
113 | |
114 void OnFilterRemoved() override { owner_->OnFilterRemoved(); } | |
115 | |
116 bool OnMessageReceived(const IPC::Message& msg) override { | |
117 if (msg.routing_id() != host_route_id_) | |
118 return false; | |
119 | |
120 IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg) | |
121 IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_Encode, owner_, | |
122 GpuVideoEncodeAccelerator::OnEncode) | |
123 IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer, | |
124 owner_, | |
125 GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer) | |
126 IPC_MESSAGE_FORWARD( | |
127 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, owner_, | |
128 GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange) | |
129 IPC_MESSAGE_UNHANDLED(return false) | |
130 IPC_END_MESSAGE_MAP() | |
131 return true; | |
132 } | |
133 | |
134 bool SendOnIOThread(IPC::Message* message) { | |
135 if (!sender_ || message->is_sync()) { | |
136 delete message; | |
137 DCHECK(!message->is_sync()); | |
Pawel Osciak
2016/10/27 01:45:19
We just deleted message...
emircan
2016/10/27 17:53:30
Thanks for the notice. I just swapped the lines.
| |
138 return false; | |
139 } | |
140 return sender_->Send(message); | |
141 } | |
142 | |
143 protected: | |
144 ~MessageFilter() override {} | |
145 | |
146 private: | |
147 GpuVideoEncodeAccelerator* const owner_; | |
148 const int32_t host_route_id_; | |
149 // The sender to which this filter was added. | |
150 IPC::Sender* sender_; | |
151 | |
152 DISALLOW_COPY_AND_ASSIGN(MessageFilter); | |
153 }; | |
154 | |
102 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator( | 155 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator( |
103 int32_t host_route_id, | 156 int32_t host_route_id, |
104 gpu::GpuCommandBufferStub* stub) | 157 gpu::GpuCommandBufferStub* stub, |
158 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | |
105 : host_route_id_(host_route_id), | 159 : host_route_id_(host_route_id), |
106 stub_(stub), | 160 stub_(stub), |
107 input_format_(PIXEL_FORMAT_UNKNOWN), | 161 input_format_(PIXEL_FORMAT_UNKNOWN), |
108 output_buffer_size_(0), | 162 output_buffer_size_(0), |
163 filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL, | |
164 base::WaitableEvent::InitialState::NOT_SIGNALED), | |
165 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
166 io_task_runner_(io_task_runner), | |
109 weak_this_factory_(this) { | 167 weak_this_factory_(this) { |
110 stub_->AddDestructionObserver(this); | 168 stub_->AddDestructionObserver(this); |
111 make_context_current_ = | 169 make_context_current_ = |
112 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 170 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
113 } | 171 } |
114 | 172 |
115 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() { | 173 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() { |
116 // This class can only be self-deleted from OnWillDestroyStub(), which means | 174 // This class can only be self-deleted from OnWillDestroyStub(), which means |
117 // the VEA has already been destroyed in there. | 175 // the VEA has already been destroyed in there. |
118 DCHECK(!encoder_); | 176 DCHECK(!encoder_); |
119 } | 177 } |
120 | 178 |
121 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format, | 179 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format, |
122 const gfx::Size& input_visible_size, | 180 const gfx::Size& input_visible_size, |
123 VideoCodecProfile output_profile, | 181 VideoCodecProfile output_profile, |
124 uint32_t initial_bitrate) { | 182 uint32_t initial_bitrate) { |
125 DVLOG(1) << __FUNCTION__ | 183 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
184 DVLOG(1) << __func__ | |
126 << " input_format=" << VideoPixelFormatToString(input_format) | 185 << " input_format=" << VideoPixelFormatToString(input_format) |
127 << ", input_visible_size=" << input_visible_size.ToString() | 186 << ", input_visible_size=" << input_visible_size.ToString() |
128 << ", output_profile=" << GetProfileName(output_profile) | 187 << ", output_profile=" << GetProfileName(output_profile) |
129 << ", initial_bitrate=" << initial_bitrate; | 188 << ", initial_bitrate=" << initial_bitrate; |
130 DCHECK(!encoder_); | 189 DCHECK(!encoder_); |
131 | 190 |
132 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) { | 191 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) { |
133 DLOG(ERROR) << __FUNCTION__ << " failed to add route"; | 192 DLOG(ERROR) << __func__ << " failed to add route"; |
134 return false; | 193 return false; |
135 } | 194 } |
136 | 195 |
137 if (input_visible_size.width() > limits::kMaxDimension || | 196 if (input_visible_size.width() > limits::kMaxDimension || |
138 input_visible_size.height() > limits::kMaxDimension || | 197 input_visible_size.height() > limits::kMaxDimension || |
139 input_visible_size.GetArea() > limits::kMaxCanvas) { | 198 input_visible_size.GetArea() > limits::kMaxCanvas) { |
140 DLOG(ERROR) << __FUNCTION__ << "too large input_visible_size " | 199 DLOG(ERROR) << __func__ << "too large input_visible_size " |
141 << input_visible_size.ToString(); | 200 << input_visible_size.ToString(); |
142 return false; | 201 return false; |
143 } | 202 } |
144 | 203 |
145 const gpu::GpuPreferences& gpu_preferences = | 204 const gpu::GpuPreferences& gpu_preferences = |
146 stub_->channel()->gpu_channel_manager()->gpu_preferences(); | 205 stub_->channel()->gpu_channel_manager()->gpu_preferences(); |
147 | 206 |
148 // Try all possible encoders and use the first successful encoder. | 207 // Try all possible encoders and use the first successful encoder. |
149 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { | 208 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { |
150 encoder_ = factory_function.Run(); | 209 encoder_ = factory_function.Run(); |
151 if (encoder_ && | 210 if (encoder_ && |
152 encoder_->Initialize(input_format, input_visible_size, output_profile, | 211 encoder_->Initialize(input_format, input_visible_size, output_profile, |
153 initial_bitrate, this)) { | 212 initial_bitrate, this)) { |
154 input_format_ = input_format; | 213 input_format_ = input_format; |
155 input_visible_size_ = input_visible_size; | 214 input_visible_size_ = input_visible_size; |
215 // Attempt to set up performing encoding tasks on IO thread, if supported | |
216 // by the VEA. | |
217 if (encoder_->TryToSetupEncodeOnSeparateThread( | |
218 weak_this_factory_.GetWeakPtr(), io_task_runner_)) { | |
219 filter_ = new MessageFilter(this, host_route_id_); | |
220 stub_->channel()->AddFilter(filter_.get()); | |
221 } | |
156 return true; | 222 return true; |
157 } | 223 } |
158 } | 224 } |
159 encoder_.reset(); | 225 encoder_.reset(); |
160 DLOG(ERROR) << __FUNCTION__ << " VEA initialization failed"; | 226 DLOG(ERROR) << __func__ << " VEA initialization failed"; |
161 return false; | 227 return false; |
162 } | 228 } |
163 | 229 |
164 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) { | 230 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) { |
165 bool handled = true; | 231 bool handled = true; |
166 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message) | 232 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message) |
167 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode) | 233 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode) |
168 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer, | 234 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer, |
169 OnUseOutputBitstreamBuffer) | 235 OnUseOutputBitstreamBuffer) |
170 IPC_MESSAGE_HANDLER( | 236 IPC_MESSAGE_HANDLER( |
171 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, | 237 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, |
172 OnRequestEncodingParametersChange) | 238 OnRequestEncodingParametersChange) |
173 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy) | 239 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy) |
174 IPC_MESSAGE_UNHANDLED(handled = false) | 240 IPC_MESSAGE_UNHANDLED(handled = false) |
175 IPC_END_MESSAGE_MAP() | 241 IPC_END_MESSAGE_MAP() |
176 return handled; | 242 return handled; |
177 } | 243 } |
178 | 244 |
179 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers( | 245 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers( |
180 unsigned int input_count, | 246 unsigned int input_count, |
181 const gfx::Size& input_coded_size, | 247 const gfx::Size& input_coded_size, |
182 size_t output_buffer_size) { | 248 size_t output_buffer_size) { |
183 Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers( | 249 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
184 host_route_id_, input_count, input_coded_size, output_buffer_size)); | 250 if (!Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers( |
251 host_route_id_, input_count, input_coded_size, output_buffer_size))) { | |
252 DLOG(ERROR) << __func__ << " failed."; | |
253 } | |
185 input_coded_size_ = input_coded_size; | 254 input_coded_size_ = input_coded_size; |
186 output_buffer_size_ = output_buffer_size; | 255 output_buffer_size_ = output_buffer_size; |
187 } | 256 } |
188 | 257 |
189 void GpuVideoEncodeAccelerator::BitstreamBufferReady( | 258 void GpuVideoEncodeAccelerator::BitstreamBufferReady( |
190 int32_t bitstream_buffer_id, | 259 int32_t bitstream_buffer_id, |
191 size_t payload_size, | 260 size_t payload_size, |
192 bool key_frame, | 261 bool key_frame, |
193 base::TimeDelta timestamp) { | 262 base::TimeDelta timestamp) { |
194 Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady( | 263 DCHECK(CheckIfCalledOnCorrectThread()); |
195 host_route_id_, bitstream_buffer_id, payload_size, key_frame, timestamp)); | 264 if (!Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady( |
265 host_route_id_, bitstream_buffer_id, payload_size, key_frame, | |
266 timestamp))) { | |
267 DLOG(ERROR) << __func__ << " failed."; | |
268 } | |
196 } | 269 } |
197 | 270 |
198 void GpuVideoEncodeAccelerator::NotifyError( | 271 void GpuVideoEncodeAccelerator::NotifyError( |
199 VideoEncodeAccelerator::Error error) { | 272 VideoEncodeAccelerator::Error error) { |
200 Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_, error)); | 273 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
274 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_, | |
275 error))) { | |
276 DLOG(ERROR) << __func__ << " failed."; | |
277 } | |
201 } | 278 } |
202 | 279 |
203 void GpuVideoEncodeAccelerator::OnWillDestroyStub() { | 280 void GpuVideoEncodeAccelerator::OnWillDestroyStub() { |
281 DVLOG(2) << __func__; | |
282 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
204 DCHECK(stub_); | 283 DCHECK(stub_); |
284 | |
285 // The stub is going away, so we have to stop and destroy VEA here before | |
286 // returning. We cannot destroy the VEA before the IO thread message filter is | |
287 // removed however, since we cannot service incoming messages with VEA gone. | |
288 // We cannot simply check for existence of VEA on IO thread though, because | |
289 // we don't want to synchronize the IO thread with the ChildThread. | |
290 // So we have to wait for the RemoveFilter callback here instead and remove | |
291 // the VEA after it arrives and before returning. | |
292 if (filter_) { | |
293 stub_->channel()->RemoveFilter(filter_.get()); | |
294 filter_removed_.Wait(); | |
295 } | |
296 | |
205 stub_->channel()->RemoveRoute(host_route_id_); | 297 stub_->channel()->RemoveRoute(host_route_id_); |
206 stub_->RemoveDestructionObserver(this); | 298 stub_->RemoveDestructionObserver(this); |
207 encoder_.reset(); | 299 encoder_.reset(); |
208 delete this; | 300 delete this; |
209 } | 301 } |
210 | 302 |
211 // static | 303 // static |
212 gpu::VideoEncodeAcceleratorSupportedProfiles | 304 gpu::VideoEncodeAcceleratorSupportedProfiles |
213 GpuVideoEncodeAccelerator::GetSupportedProfiles( | 305 GpuVideoEncodeAccelerator::GetSupportedProfiles( |
214 const gpu::GpuPreferences& gpu_preferences) { | 306 const gpu::GpuPreferences& gpu_preferences) { |
215 VideoEncodeAccelerator::SupportedProfiles profiles; | 307 VideoEncodeAccelerator::SupportedProfiles profiles; |
216 | 308 |
217 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { | 309 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { |
218 std::unique_ptr<VideoEncodeAccelerator> encoder = factory_function.Run(); | 310 std::unique_ptr<VideoEncodeAccelerator> encoder = factory_function.Run(); |
219 if (!encoder) | 311 if (!encoder) |
220 continue; | 312 continue; |
221 VideoEncodeAccelerator::SupportedProfiles vea_profiles = | 313 VideoEncodeAccelerator::SupportedProfiles vea_profiles = |
222 encoder->GetSupportedProfiles(); | 314 encoder->GetSupportedProfiles(); |
223 GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles, | 315 GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles, |
224 &profiles); | 316 &profiles); |
225 } | 317 } |
226 return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles); | 318 return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles); |
227 } | 319 } |
228 | 320 |
321 void GpuVideoEncodeAccelerator::OnFilterRemoved() { | |
322 DVLOG(2) << __func__; | |
323 | |
324 // We're destroying; cancel all callbacks. | |
325 weak_this_factory_.InvalidateWeakPtrs(); | |
326 filter_removed_.Signal(); | |
327 } | |
328 | |
229 // static | 329 // static |
230 std::vector<GpuVideoEncodeAccelerator::VEAFactoryFunction> | 330 std::vector<GpuVideoEncodeAccelerator::VEAFactoryFunction> |
231 GpuVideoEncodeAccelerator::GetVEAFactoryFunctions( | 331 GpuVideoEncodeAccelerator::GetVEAFactoryFunctions( |
232 const gpu::GpuPreferences& gpu_preferences) { | 332 const gpu::GpuPreferences& gpu_preferences) { |
233 std::vector<VEAFactoryFunction> vea_factory_functions; | 333 std::vector<VEAFactoryFunction> vea_factory_functions; |
234 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) | 334 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) |
235 vea_factory_functions.push_back(base::Bind(&CreateV4L2VEA)); | 335 vea_factory_functions.push_back(base::Bind(&CreateV4L2VEA)); |
236 #endif | 336 #endif |
237 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 337 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
238 if (!gpu_preferences.disable_vaapi_accelerated_video_encode) | 338 if (!gpu_preferences.disable_vaapi_accelerated_video_encode) |
239 vea_factory_functions.push_back(base::Bind(&CreateVaapiVEA)); | 339 vea_factory_functions.push_back(base::Bind(&CreateVaapiVEA)); |
240 #endif | 340 #endif |
241 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC) | 341 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC) |
242 if (!gpu_preferences.disable_web_rtc_hw_encoding) | 342 if (!gpu_preferences.disable_web_rtc_hw_encoding) |
243 vea_factory_functions.push_back(base::Bind(&CreateAndroidVEA)); | 343 vea_factory_functions.push_back(base::Bind(&CreateAndroidVEA)); |
244 #endif | 344 #endif |
245 #if defined(OS_MACOSX) | 345 #if defined(OS_MACOSX) |
246 vea_factory_functions.push_back(base::Bind(&CreateVTVEA)); | 346 vea_factory_functions.push_back(base::Bind(&CreateVTVEA)); |
247 #endif | 347 #endif |
248 #if defined(OS_WIN) | 348 #if defined(OS_WIN) |
249 if (base::FeatureList::IsEnabled(kMediaFoundationH264Encoding)) | 349 if (base::FeatureList::IsEnabled(kMediaFoundationH264Encoding)) |
250 vea_factory_functions.push_back(base::Bind(&CreateMediaFoundationVEA)); | 350 vea_factory_functions.push_back(base::Bind(&CreateMediaFoundationVEA)); |
251 #endif | 351 #endif |
252 return vea_factory_functions; | 352 return vea_factory_functions; |
253 } | 353 } |
254 | 354 |
255 void GpuVideoEncodeAccelerator::OnEncode( | 355 void GpuVideoEncodeAccelerator::OnEncode( |
256 const AcceleratedVideoEncoderMsg_Encode_Params& params) { | 356 const AcceleratedVideoEncoderMsg_Encode_Params& params) { |
257 DVLOG(3) << __FUNCTION__ << " frame_id = " << params.frame_id | 357 DVLOG(3) << __func__ << " frame_id = " << params.frame_id |
258 << ", buffer_size=" << params.buffer_size | 358 << ", buffer_size=" << params.buffer_size |
259 << ", force_keyframe=" << params.force_keyframe; | 359 << ", force_keyframe=" << params.force_keyframe; |
360 DCHECK(CheckIfCalledOnCorrectThread()); | |
260 DCHECK_EQ(PIXEL_FORMAT_I420, input_format_); | 361 DCHECK_EQ(PIXEL_FORMAT_I420, input_format_); |
362 TRACE_EVENT0("gpu", "GpuVideoEncodeAccelerator::OnEncode"); | |
261 | 363 |
262 // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle| | 364 // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle| |
263 // is cleaned properly in case of an early return. | 365 // is cleaned properly in case of an early return. |
264 std::unique_ptr<base::SharedMemory> shm( | 366 std::unique_ptr<base::SharedMemory> shm( |
265 new base::SharedMemory(params.buffer_handle, true)); | 367 new base::SharedMemory(params.buffer_handle, true)); |
266 | 368 |
267 if (!encoder_) | 369 if (!encoder_) |
268 return; | 370 return; |
269 | 371 |
270 if (params.frame_id < 0) { | 372 if (params.frame_id < 0) { |
271 DLOG(ERROR) << __FUNCTION__ << " invalid frame_id=" << params.frame_id; | 373 DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id; |
272 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 374 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
273 return; | 375 return; |
274 } | 376 } |
275 | 377 |
276 const uint32_t aligned_offset = | 378 const uint32_t aligned_offset = |
277 params.buffer_offset % base::SysInfo::VMAllocationGranularity(); | 379 params.buffer_offset % base::SysInfo::VMAllocationGranularity(); |
278 base::CheckedNumeric<off_t> map_offset = params.buffer_offset; | 380 base::CheckedNumeric<off_t> map_offset = params.buffer_offset; |
279 map_offset -= aligned_offset; | 381 map_offset -= aligned_offset; |
280 base::CheckedNumeric<size_t> map_size = params.buffer_size; | 382 base::CheckedNumeric<size_t> map_size = params.buffer_size; |
281 map_size += aligned_offset; | 383 map_size += aligned_offset; |
282 | 384 |
283 if (!map_offset.IsValid() || !map_size.IsValid()) { | 385 if (!map_offset.IsValid() || !map_size.IsValid()) { |
284 DLOG(ERROR) << __FUNCTION__ << " invalid map_offset or map_size"; | 386 DLOG(ERROR) << __func__ << " invalid map_offset or map_size"; |
285 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 387 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
286 return; | 388 return; |
287 } | 389 } |
288 | 390 |
289 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) { | 391 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) { |
290 DLOG(ERROR) << __FUNCTION__ | 392 DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id; |
291 << " could not map frame_id=" << params.frame_id; | |
292 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 393 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
293 return; | 394 return; |
294 } | 395 } |
295 | 396 |
296 uint8_t* shm_memory = | 397 uint8_t* shm_memory = |
297 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset; | 398 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset; |
298 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory( | 399 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory( |
299 input_format_, input_coded_size_, gfx::Rect(input_visible_size_), | 400 input_format_, input_coded_size_, gfx::Rect(input_visible_size_), |
300 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle, | 401 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle, |
301 params.buffer_offset, params.timestamp); | 402 params.buffer_offset, params.timestamp); |
302 if (!frame) { | 403 if (!frame) { |
303 DLOG(ERROR) << __FUNCTION__ << " could not create a frame"; | 404 DLOG(ERROR) << __func__ << " could not create a frame"; |
304 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 405 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
305 return; | 406 return; |
306 } | 407 } |
307 frame->AddDestructionObserver(BindToCurrentLoop(base::Bind( | 408 frame->AddDestructionObserver(BindToCurrentLoop(base::Bind( |
308 &GpuVideoEncodeAccelerator::EncodeFrameFinished, | 409 &GpuVideoEncodeAccelerator::EncodeFrameFinished, |
309 weak_this_factory_.GetWeakPtr(), params.frame_id, base::Passed(&shm)))); | 410 weak_this_factory_.GetWeakPtr(), params.frame_id, base::Passed(&shm)))); |
310 encoder_->Encode(frame, params.force_keyframe); | 411 encoder_->Encode(frame, params.force_keyframe); |
311 } | 412 } |
312 | 413 |
313 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( | 414 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( |
314 int32_t buffer_id, | 415 int32_t buffer_id, |
315 base::SharedMemoryHandle buffer_handle, | 416 base::SharedMemoryHandle buffer_handle, |
316 uint32_t buffer_size) { | 417 uint32_t buffer_size) { |
317 DVLOG(3) << __FUNCTION__ << " buffer_id=" << buffer_id | 418 DVLOG(3) << __func__ << " buffer_id=" << buffer_id |
318 << ", buffer_size=" << buffer_size; | 419 << ", buffer_size=" << buffer_size; |
420 DCHECK(CheckIfCalledOnCorrectThread()); | |
319 if (!encoder_) | 421 if (!encoder_) |
320 return; | 422 return; |
321 if (buffer_id < 0) { | 423 if (buffer_id < 0) { |
322 DLOG(ERROR) << __FUNCTION__ << " invalid buffer_id=" << buffer_id; | 424 DLOG(ERROR) << __func__ << " invalid buffer_id=" << buffer_id; |
323 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 425 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
324 return; | 426 return; |
325 } | 427 } |
326 if (buffer_size < output_buffer_size_) { | 428 if (buffer_size < output_buffer_size_) { |
327 DLOG(ERROR) << __FUNCTION__ | 429 DLOG(ERROR) << __func__ << " buffer too small for buffer_id=" << buffer_id; |
328 << " buffer too small for buffer_id=" << buffer_id; | |
329 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 430 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
330 return; | 431 return; |
331 } | 432 } |
332 encoder_->UseOutputBitstreamBuffer( | 433 encoder_->UseOutputBitstreamBuffer( |
333 BitstreamBuffer(buffer_id, buffer_handle, buffer_size)); | 434 BitstreamBuffer(buffer_id, buffer_handle, buffer_size)); |
334 } | 435 } |
335 | 436 |
336 void GpuVideoEncodeAccelerator::OnDestroy() { | 437 void GpuVideoEncodeAccelerator::OnDestroy() { |
337 DVLOG(2) << __FUNCTION__; | 438 DVLOG(2) << __func__; |
439 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
338 OnWillDestroyStub(); | 440 OnWillDestroyStub(); |
339 } | 441 } |
340 | 442 |
341 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange( | 443 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange( |
342 uint32_t bitrate, | 444 uint32_t bitrate, |
343 uint32_t framerate) { | 445 uint32_t framerate) { |
344 DVLOG(2) << __FUNCTION__ << " bitrate=" << bitrate | 446 DVLOG(2) << __func__ << " bitrate=" << bitrate << ", framerate=" << framerate; |
345 << ", framerate=" << framerate; | 447 DCHECK(CheckIfCalledOnCorrectThread()); |
346 if (!encoder_) | 448 if (!encoder_) |
347 return; | 449 return; |
348 encoder_->RequestEncodingParametersChange(bitrate, framerate); | 450 encoder_->RequestEncodingParametersChange(bitrate, framerate); |
349 } | 451 } |
350 | 452 |
351 void GpuVideoEncodeAccelerator::EncodeFrameFinished( | 453 void GpuVideoEncodeAccelerator::EncodeFrameFinished( |
352 int32_t frame_id, | 454 int32_t frame_id, |
353 std::unique_ptr<base::SharedMemory> shm) { | 455 std::unique_ptr<base::SharedMemory> shm) { |
354 Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_, | 456 DCHECK(CheckIfCalledOnCorrectThread()); |
355 frame_id)); | 457 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_, |
458 frame_id))) { | |
459 DLOG(ERROR) << __func__ << " failed."; | |
460 } | |
356 // Just let |shm| fall out of scope. | 461 // Just let |shm| fall out of scope. |
357 } | 462 } |
358 | 463 |
359 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) { | 464 bool GpuVideoEncodeAccelerator::Send(IPC::Message* message) { |
360 stub_->channel()->Send(message); | 465 if (filter_ && io_task_runner_->BelongsToCurrentThread()) { |
466 return filter_->SendOnIOThread(message); | |
467 } | |
468 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
469 return stub_->channel()->Send(message); | |
470 } | |
471 | |
472 bool GpuVideoEncodeAccelerator::CheckIfCalledOnCorrectThread() { | |
473 return (filter_ && io_task_runner_->BelongsToCurrentThread()) || | |
474 (!filter_ && main_task_runner_->BelongsToCurrentThread()); | |
361 } | 475 } |
362 | 476 |
363 } // namespace media | 477 } // namespace media |
OLD | NEW |