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