OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
9 #include <poll.h> | 9 #include <poll.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <sys/eventfd.h> | 11 #include <sys/eventfd.h> |
12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
14 | 14 |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
20 #include "base/thread_task_runner_handle.h" | 20 #include "base/thread_task_runner_handle.h" |
21 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
22 #include "build/build_config.h" | 22 #include "build/build_config.h" |
23 #include "content/common/gpu/media/shared_memory_region.h" | 23 #include "content/common/gpu/media/shared_memory_region.h" |
24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | 24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
25 #include "media/base/media_switches.h" | 25 #include "media/base/media_switches.h" |
26 #include "media/filters/h264_parser.h" | 26 #include "media/filters/h264_parser.h" |
27 #include "ui/gfx/geometry/rect.h" | 27 #include "ui/gfx/geometry/rect.h" |
28 #include "ui/gl/gl_context.h" | |
29 #include "ui/gl/scoped_binders.h" | 28 #include "ui/gl/scoped_binders.h" |
30 | 29 |
31 #define NOTIFY_ERROR(x) \ | 30 #define NOTIFY_ERROR(x) \ |
32 do { \ | 31 do { \ |
33 LOG(ERROR) << "Setting error state:" << x; \ | 32 LOG(ERROR) << "Setting error state:" << x; \ |
34 SetErrorState(x); \ | 33 SetErrorState(x); \ |
35 } while (0) | 34 } while (0) |
36 | 35 |
37 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ | 36 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ |
38 do { \ | 37 do { \ |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 146 |
148 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( | 147 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( |
149 bool cleared, | 148 bool cleared, |
150 const media::Picture& picture) | 149 const media::Picture& picture) |
151 : cleared(cleared), picture(picture) {} | 150 : cleared(cleared), picture(picture) {} |
152 | 151 |
153 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 152 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
154 | 153 |
155 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( | 154 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( |
156 EGLDisplay egl_display, | 155 EGLDisplay egl_display, |
157 const GetGLContextCallback& get_gl_context_cb, | 156 EGLContext egl_context, |
158 const MakeGLContextCurrentCallback& make_context_current_cb, | 157 const base::WeakPtr<Client>& io_client, |
159 const scoped_refptr<V4L2Device>& device) | 158 const base::Callback<bool(void)>& make_context_current, |
| 159 const scoped_refptr<V4L2Device>& device, |
| 160 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
160 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 161 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 162 io_task_runner_(io_task_runner), |
| 163 io_client_(io_client), |
161 decoder_thread_("V4L2DecoderThread"), | 164 decoder_thread_("V4L2DecoderThread"), |
162 decoder_state_(kUninitialized), | 165 decoder_state_(kUninitialized), |
163 device_(device), | 166 device_(device), |
164 decoder_delay_bitstream_buffer_id_(-1), | 167 decoder_delay_bitstream_buffer_id_(-1), |
165 decoder_current_input_buffer_(-1), | 168 decoder_current_input_buffer_(-1), |
166 decoder_decode_buffer_tasks_scheduled_(0), | 169 decoder_decode_buffer_tasks_scheduled_(0), |
167 decoder_frames_at_client_(0), | 170 decoder_frames_at_client_(0), |
168 decoder_flushing_(false), | 171 decoder_flushing_(false), |
169 resolution_change_reset_pending_(false), | 172 resolution_change_reset_pending_(false), |
170 decoder_partial_frame_pending_(false), | 173 decoder_partial_frame_pending_(false), |
171 input_streamon_(false), | 174 input_streamon_(false), |
172 input_buffer_queued_count_(0), | 175 input_buffer_queued_count_(0), |
173 output_streamon_(false), | 176 output_streamon_(false), |
174 output_buffer_queued_count_(0), | 177 output_buffer_queued_count_(0), |
175 output_dpb_size_(0), | 178 output_dpb_size_(0), |
176 output_planes_count_(0), | 179 output_planes_count_(0), |
177 picture_clearing_count_(0), | 180 picture_clearing_count_(0), |
178 pictures_assigned_(false, false), | 181 pictures_assigned_(false, false), |
179 device_poll_thread_("V4L2DevicePollThread"), | 182 device_poll_thread_("V4L2DevicePollThread"), |
| 183 make_context_current_(make_context_current), |
180 egl_display_(egl_display), | 184 egl_display_(egl_display), |
181 get_gl_context_cb_(get_gl_context_cb), | 185 egl_context_(egl_context), |
182 make_context_current_cb_(make_context_current_cb), | |
183 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 186 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
184 output_format_fourcc_(0), | 187 output_format_fourcc_(0), |
185 weak_this_factory_(this) { | 188 weak_this_factory_(this) { |
186 weak_this_ = weak_this_factory_.GetWeakPtr(); | 189 weak_this_ = weak_this_factory_.GetWeakPtr(); |
187 } | 190 } |
188 | 191 |
189 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { | 192 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { |
190 DCHECK(!decoder_thread_.IsRunning()); | 193 DCHECK(!decoder_thread_.IsRunning()); |
191 DCHECK(!device_poll_thread_.IsRunning()); | 194 DCHECK(!device_poll_thread_.IsRunning()); |
192 | 195 |
193 DestroyInputBuffers(); | 196 DestroyInputBuffers(); |
194 DestroyOutputBuffers(); | 197 DestroyOutputBuffers(); |
195 | 198 |
196 // These maps have members that should be manually destroyed, e.g. file | 199 // These maps have members that should be manually destroyed, e.g. file |
197 // descriptors, mmap() segments, etc. | 200 // descriptors, mmap() segments, etc. |
198 DCHECK(input_buffer_map_.empty()); | 201 DCHECK(input_buffer_map_.empty()); |
199 DCHECK(output_buffer_map_.empty()); | 202 DCHECK(output_buffer_map_.empty()); |
200 } | 203 } |
201 | 204 |
202 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, | 205 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, |
203 Client* client) { | 206 Client* client) { |
204 DVLOG(3) << "Initialize()"; | 207 DVLOG(3) << "Initialize()"; |
205 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 208 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
206 DCHECK_EQ(decoder_state_, kUninitialized); | 209 DCHECK_EQ(decoder_state_, kUninitialized); |
207 | 210 |
208 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { | |
209 NOTREACHED() << "GL callbacks are required for this VDA"; | |
210 return false; | |
211 } | |
212 | |
213 if (config.is_encrypted) { | 211 if (config.is_encrypted) { |
214 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 212 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
215 return false; | 213 return false; |
216 } | 214 } |
217 | 215 |
218 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( | 216 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( |
219 config.profile, arraysize(supported_input_fourccs_), | 217 config.profile, arraysize(supported_input_fourccs_), |
220 supported_input_fourccs_)) { | 218 supported_input_fourccs_)) { |
221 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; | 219 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; |
222 return false; | 220 return false; |
223 } | 221 } |
224 | 222 |
225 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 223 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
226 client_ = client_ptr_factory_->GetWeakPtr(); | 224 client_ = client_ptr_factory_->GetWeakPtr(); |
227 // If we haven't been set up to decode on separate thread via | |
228 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for | |
229 // decode tasks. | |
230 if (!decode_task_runner_) { | |
231 decode_task_runner_ = child_task_runner_; | |
232 DCHECK(!decode_client_); | |
233 decode_client_ = client_; | |
234 } | |
235 | 225 |
236 video_profile_ = config.profile; | 226 video_profile_ = config.profile; |
237 | 227 |
238 if (egl_display_ == EGL_NO_DISPLAY) { | 228 if (egl_display_ == EGL_NO_DISPLAY) { |
239 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; | 229 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; |
240 return false; | 230 return false; |
241 } | 231 } |
242 | 232 |
243 // We need the context to be initialized to query extensions. | 233 // We need the context to be initialized to query extensions. |
244 if (!make_context_current_cb_.Run()) { | 234 if (!make_context_current_.Run()) { |
245 LOG(ERROR) << "Initialize(): could not make context current"; | 235 LOG(ERROR) << "Initialize(): could not make context current"; |
246 return false; | 236 return false; |
247 } | 237 } |
248 | 238 |
249 // TODO(posciak): crbug.com/450898. | 239 // TODO(posciak): crbug.com/450898. |
250 #if defined(ARCH_CPU_ARMEL) | 240 #if defined(ARCH_CPU_ARMEL) |
251 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { | 241 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { |
252 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; | 242 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; |
253 return false; | 243 return false; |
254 } | 244 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), | 285 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), |
296 base::Unretained(this))); | 286 base::Unretained(this))); |
297 | 287 |
298 return true; | 288 return true; |
299 } | 289 } |
300 | 290 |
301 void V4L2VideoDecodeAccelerator::Decode( | 291 void V4L2VideoDecodeAccelerator::Decode( |
302 const media::BitstreamBuffer& bitstream_buffer) { | 292 const media::BitstreamBuffer& bitstream_buffer) { |
303 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() | 293 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() |
304 << ", size=" << bitstream_buffer.size(); | 294 << ", size=" << bitstream_buffer.size(); |
305 DCHECK(decode_task_runner_->BelongsToCurrentThread()); | 295 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
306 | 296 |
307 if (bitstream_buffer.id() < 0) { | 297 if (bitstream_buffer.id() < 0) { |
308 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 298 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
309 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 299 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
310 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 300 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
311 NOTIFY_ERROR(INVALID_ARGUMENT); | 301 NOTIFY_ERROR(INVALID_ARGUMENT); |
312 return; | 302 return; |
313 } | 303 } |
314 | 304 |
315 // DecodeTask() will take care of running a DecodeBufferTask(). | 305 // DecodeTask() will take care of running a DecodeBufferTask(). |
(...skipping 11 matching lines...) Expand all Loading... |
327 output_dpb_size_ + kDpbOutputBufferExtraCount; | 317 output_dpb_size_ + kDpbOutputBufferExtraCount; |
328 | 318 |
329 if (buffers.size() < req_buffer_count) { | 319 if (buffers.size() < req_buffer_count) { |
330 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 320 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
331 " buffers. (Got " << buffers.size() | 321 " buffers. (Got " << buffers.size() |
332 << ", requested " << req_buffer_count << ")"; | 322 << ", requested " << req_buffer_count << ")"; |
333 NOTIFY_ERROR(INVALID_ARGUMENT); | 323 NOTIFY_ERROR(INVALID_ARGUMENT); |
334 return; | 324 return; |
335 } | 325 } |
336 | 326 |
337 gfx::GLContext* gl_context = get_gl_context_cb_.Run(); | 327 if (!make_context_current_.Run()) { |
338 if (!gl_context || !make_context_current_cb_.Run()) { | |
339 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 328 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
340 NOTIFY_ERROR(PLATFORM_FAILURE); | 329 NOTIFY_ERROR(PLATFORM_FAILURE); |
341 return; | 330 return; |
342 } | 331 } |
343 | 332 |
344 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 333 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
345 | 334 |
346 // It's safe to manipulate all the buffer state here, because the decoder | 335 // It's safe to manipulate all the buffer state here, because the decoder |
347 // thread is waiting on pictures_assigned_. | 336 // thread is waiting on pictures_assigned_. |
348 | 337 |
(...skipping 19 matching lines...) Expand all Loading... |
368 | 357 |
369 OutputRecord& output_record = output_buffer_map_[i]; | 358 OutputRecord& output_record = output_buffer_map_[i]; |
370 DCHECK(!output_record.at_device); | 359 DCHECK(!output_record.at_device); |
371 DCHECK(!output_record.at_client); | 360 DCHECK(!output_record.at_client); |
372 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 361 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
373 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 362 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
374 DCHECK_EQ(output_record.picture_id, -1); | 363 DCHECK_EQ(output_record.picture_id, -1); |
375 DCHECK_EQ(output_record.cleared, false); | 364 DCHECK_EQ(output_record.cleared, false); |
376 | 365 |
377 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, | 366 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, |
378 gl_context->GetHandle(), | 367 egl_context_, |
379 buffers[i].texture_id(), | 368 buffers[i].texture_id(), |
380 coded_size_, | 369 coded_size_, |
381 i, | 370 i, |
382 output_format_fourcc_, | 371 output_format_fourcc_, |
383 output_planes_count_); | 372 output_planes_count_); |
384 if (egl_image == EGL_NO_IMAGE_KHR) { | 373 if (egl_image == EGL_NO_IMAGE_KHR) { |
385 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 374 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
386 // Ownership of EGLImages allocated in previous iterations of this loop | 375 // Ownership of EGLImages allocated in previous iterations of this loop |
387 // has been transferred to output_buffer_map_. After we error-out here | 376 // has been transferred to output_buffer_map_. After we error-out here |
388 // the destructor will handle their cleanup. | 377 // the destructor will handle their cleanup. |
389 NOTIFY_ERROR(PLATFORM_FAILURE); | 378 NOTIFY_ERROR(PLATFORM_FAILURE); |
390 return; | 379 return; |
391 } | 380 } |
392 | 381 |
393 output_record.egl_image = egl_image; | 382 output_record.egl_image = egl_image; |
394 output_record.picture_id = buffers[i].id(); | 383 output_record.picture_id = buffers[i].id(); |
395 free_output_buffers_.push(i); | 384 free_output_buffers_.push(i); |
396 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i | 385 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i |
397 << "]: picture_id=" << output_record.picture_id; | 386 << "]: picture_id=" << output_record.picture_id; |
398 } | 387 } |
399 | 388 |
400 pictures_assigned_.Signal(); | 389 pictures_assigned_.Signal(); |
401 } | 390 } |
402 | 391 |
403 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { | 392 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { |
404 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 393 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
405 // Must be run on child thread, as we'll insert a sync in the EGL context. | 394 // Must be run on child thread, as we'll insert a sync in the EGL context. |
406 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 395 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
407 | 396 |
408 if (!make_context_current_cb_.Run()) { | 397 if (!make_context_current_.Run()) { |
409 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 398 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
410 NOTIFY_ERROR(PLATFORM_FAILURE); | 399 NOTIFY_ERROR(PLATFORM_FAILURE); |
411 return; | 400 return; |
412 } | 401 } |
413 | 402 |
414 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; | 403 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; |
415 // TODO(posciak): crbug.com/450898. | 404 // TODO(posciak): crbug.com/450898. |
416 #if defined(ARCH_CPU_ARMEL) | 405 #if defined(ARCH_CPU_ARMEL) |
417 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 406 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
418 if (egl_sync == EGL_NO_SYNC_KHR) { | 407 if (egl_sync == EGL_NO_SYNC_KHR) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 // DestroyTask() will cause the decoder_thread_ to flush all tasks. | 448 // DestroyTask() will cause the decoder_thread_ to flush all tasks. |
460 decoder_thread_.Stop(); | 449 decoder_thread_.Stop(); |
461 } else { | 450 } else { |
462 // Otherwise, call the destroy task directly. | 451 // Otherwise, call the destroy task directly. |
463 DestroyTask(); | 452 DestroyTask(); |
464 } | 453 } |
465 | 454 |
466 delete this; | 455 delete this; |
467 } | 456 } |
468 | 457 |
469 bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( | 458 bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } |
470 const base::WeakPtr<Client>& decode_client, | |
471 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { | |
472 decode_client_ = decode_client_; | |
473 decode_task_runner_ = decode_task_runner; | |
474 return true; | |
475 } | |
476 | 459 |
477 // static | 460 // static |
478 media::VideoDecodeAccelerator::SupportedProfiles | 461 media::VideoDecodeAccelerator::SupportedProfiles |
479 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { | 462 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { |
480 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 463 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
481 if (!device) | 464 if (!device) |
482 return SupportedProfiles(); | 465 return SupportedProfiles(); |
483 | 466 |
484 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 467 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
485 supported_input_fourccs_); | 468 supported_input_fourccs_); |
486 } | 469 } |
487 | 470 |
488 void V4L2VideoDecodeAccelerator::DecodeTask( | 471 void V4L2VideoDecodeAccelerator::DecodeTask( |
489 const media::BitstreamBuffer& bitstream_buffer) { | 472 const media::BitstreamBuffer& bitstream_buffer) { |
490 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); | 473 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); |
491 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 474 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
492 DCHECK_NE(decoder_state_, kUninitialized); | 475 DCHECK_NE(decoder_state_, kUninitialized); |
493 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", | 476 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", |
494 bitstream_buffer.id()); | 477 bitstream_buffer.id()); |
495 | 478 |
496 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 479 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
497 decode_client_, decode_task_runner_, | 480 io_client_, io_task_runner_, |
498 scoped_ptr<SharedMemoryRegion>( | 481 scoped_ptr<SharedMemoryRegion>( |
499 new SharedMemoryRegion(bitstream_buffer, true)), | 482 new SharedMemoryRegion(bitstream_buffer, true)), |
500 bitstream_buffer.id())); | 483 bitstream_buffer.id())); |
501 if (!bitstream_record->shm->Map()) { | 484 if (!bitstream_record->shm->Map()) { |
502 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; | 485 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; |
503 NOTIFY_ERROR(UNREADABLE_INPUT); | 486 NOTIFY_ERROR(UNREADABLE_INPUT); |
504 return; | 487 return; |
505 } | 488 } |
506 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); | 489 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); |
507 | 490 |
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 DVLOG(2) << "FlushTask(): early out: kError state"; | 1263 DVLOG(2) << "FlushTask(): early out: kError state"; |
1281 return; | 1264 return; |
1282 } | 1265 } |
1283 | 1266 |
1284 // We don't support stacked flushing. | 1267 // We don't support stacked flushing. |
1285 DCHECK(!decoder_flushing_); | 1268 DCHECK(!decoder_flushing_); |
1286 | 1269 |
1287 // Queue up an empty buffer -- this triggers the flush. | 1270 // Queue up an empty buffer -- this triggers the flush. |
1288 decoder_input_queue_.push( | 1271 decoder_input_queue_.push( |
1289 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1272 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
1290 decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); | 1273 io_client_, io_task_runner_, nullptr, kFlushBufferId))); |
1291 decoder_flushing_ = true; | 1274 decoder_flushing_ = true; |
1292 SendPictureReady(); // Send all pending PictureReady. | 1275 SendPictureReady(); // Send all pending PictureReady. |
1293 | 1276 |
1294 ScheduleDecodeBufferTaskIfNeeded(); | 1277 ScheduleDecodeBufferTaskIfNeeded(); |
1295 } | 1278 } |
1296 | 1279 |
1297 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1280 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
1298 if (!decoder_flushing_) | 1281 if (!decoder_flushing_) |
1299 return; | 1282 return; |
1300 | 1283 |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2003 | 1986 |
2004 void V4L2VideoDecodeAccelerator::SendPictureReady() { | 1987 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
2005 DVLOG(3) << "SendPictureReady()"; | 1988 DVLOG(3) << "SendPictureReady()"; |
2006 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1989 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2007 bool resetting_or_flushing = | 1990 bool resetting_or_flushing = |
2008 (decoder_state_ == kResetting || decoder_flushing_); | 1991 (decoder_state_ == kResetting || decoder_flushing_); |
2009 while (pending_picture_ready_.size() > 0) { | 1992 while (pending_picture_ready_.size() > 0) { |
2010 bool cleared = pending_picture_ready_.front().cleared; | 1993 bool cleared = pending_picture_ready_.front().cleared; |
2011 const media::Picture& picture = pending_picture_ready_.front().picture; | 1994 const media::Picture& picture = pending_picture_ready_.front().picture; |
2012 if (cleared && picture_clearing_count_ == 0) { | 1995 if (cleared && picture_clearing_count_ == 0) { |
2013 // This picture is cleared. It can be posted to a thread different than | 1996 // This picture is cleared. Post it to IO thread to reduce latency. This |
2014 // the main GPU thread to reduce latency. This should be the case after | 1997 // should be the case after all pictures are cleared at the beginning. |
2015 // all pictures are cleared at the beginning. | 1998 io_task_runner_->PostTask( |
2016 decode_task_runner_->PostTask( | 1999 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); |
2017 FROM_HERE, | |
2018 base::Bind(&Client::PictureReady, decode_client_, picture)); | |
2019 pending_picture_ready_.pop(); | 2000 pending_picture_ready_.pop(); |
2020 } else if (!cleared || resetting_or_flushing) { | 2001 } else if (!cleared || resetting_or_flushing) { |
2021 DVLOG(3) << "SendPictureReady()" | 2002 DVLOG(3) << "SendPictureReady()" |
2022 << ". cleared=" << pending_picture_ready_.front().cleared | 2003 << ". cleared=" << pending_picture_ready_.front().cleared |
2023 << ", decoder_state_=" << decoder_state_ | 2004 << ", decoder_state_=" << decoder_state_ |
2024 << ", decoder_flushing_=" << decoder_flushing_ | 2005 << ", decoder_flushing_=" << decoder_flushing_ |
2025 << ", picture_clearing_count_=" << picture_clearing_count_; | 2006 << ", picture_clearing_count_=" << picture_clearing_count_; |
2026 // If the picture is not cleared, post it to the child thread because it | 2007 // If the picture is not cleared, post it to the child thread because it |
2027 // has to be cleared in the child thread. A picture only needs to be | 2008 // has to be cleared in the child thread. A picture only needs to be |
2028 // cleared once. If the decoder is resetting or flushing, send all | 2009 // cleared once. If the decoder is resetting or flushing, send all |
(...skipping 17 matching lines...) Expand all Loading... |
2046 | 2027 |
2047 void V4L2VideoDecodeAccelerator::PictureCleared() { | 2028 void V4L2VideoDecodeAccelerator::PictureCleared() { |
2048 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2029 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
2049 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2030 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2050 DCHECK_GT(picture_clearing_count_, 0); | 2031 DCHECK_GT(picture_clearing_count_, 0); |
2051 picture_clearing_count_--; | 2032 picture_clearing_count_--; |
2052 SendPictureReady(); | 2033 SendPictureReady(); |
2053 } | 2034 } |
2054 | 2035 |
2055 } // namespace content | 2036 } // namespace content |
OLD | NEW |