OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <fcntl.h> | 5 #include <fcntl.h> |
6 #include <linux/videodev2.h> | 6 #include <linux/videodev2.h> |
7 #include <poll.h> | 7 #include <poll.h> |
8 #include <sys/eventfd.h> | 8 #include <sys/eventfd.h> |
9 #include <sys/ioctl.h> | 9 #include <sys/ioctl.h> |
10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
14 #include "base/callback.h" | 14 #include "base/callback.h" |
15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/message_loop/message_loop_proxy.h" | |
18 #include "base/numerics/safe_conversions.h" | 17 #include "base/numerics/safe_conversions.h" |
19 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
20 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" | 19 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" |
21 #include "media/base/bind_to_current_loop.h" | 20 #include "media/base/bind_to_current_loop.h" |
22 #include "media/base/media_switches.h" | 21 #include "media/base/media_switches.h" |
23 #include "ui/gl/scoped_binders.h" | 22 #include "ui/gl/scoped_binders.h" |
24 | 23 |
25 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " | 24 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " |
26 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " | 25 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " |
27 | 26 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 at_client(false), | 154 at_client(false), |
156 picture_id(-1), | 155 picture_id(-1), |
157 egl_image(EGL_NO_IMAGE_KHR), | 156 egl_image(EGL_NO_IMAGE_KHR), |
158 egl_sync(EGL_NO_SYNC_KHR), | 157 egl_sync(EGL_NO_SYNC_KHR), |
159 cleared(false) { | 158 cleared(false) { |
160 } | 159 } |
161 | 160 |
162 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { | 161 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { |
163 BitstreamBufferRef( | 162 BitstreamBufferRef( |
164 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 163 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
165 const scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 164 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
166 base::SharedMemory* shm, | 165 base::SharedMemory* shm, |
167 size_t size, | 166 size_t size, |
168 int32 input_id); | 167 int32 input_id); |
169 ~BitstreamBufferRef(); | 168 ~BitstreamBufferRef(); |
170 const base::WeakPtr<VideoDecodeAccelerator::Client> client; | 169 const base::WeakPtr<VideoDecodeAccelerator::Client> client; |
171 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; | 170 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; |
172 const scoped_ptr<base::SharedMemory> shm; | 171 const scoped_ptr<base::SharedMemory> shm; |
173 const size_t size; | 172 const size_t size; |
174 off_t bytes_used; | 173 off_t bytes_used; |
175 const int32 input_id; | 174 const int32 input_id; |
176 }; | 175 }; |
177 | 176 |
178 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 177 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
179 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 178 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
180 const scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 179 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
181 base::SharedMemory* shm, | 180 base::SharedMemory* shm, |
182 size_t size, | 181 size_t size, |
183 int32 input_id) | 182 int32 input_id) |
184 : client(client), | 183 : client(client), |
185 client_message_loop_proxy(client_message_loop_proxy), | 184 client_task_runner(client_task_runner), |
186 shm(shm), | 185 shm(shm), |
187 size(size), | 186 size(size), |
188 bytes_used(0), | 187 bytes_used(0), |
189 input_id(input_id) { | 188 input_id(input_id) { |
190 } | 189 } |
191 | 190 |
192 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 191 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
193 if (input_id >= 0) { | 192 if (input_id >= 0) { |
194 DVLOGF(5) << "returning input_id: " << input_id; | 193 DVLOGF(5) << "returning input_id: " << input_id; |
195 client_message_loop_proxy->PostTask( | 194 client_task_runner->PostTask( |
196 FROM_HERE, | 195 FROM_HERE, |
197 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, | 196 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, |
198 client, input_id)); | 197 client, input_id)); |
199 } | 198 } |
200 } | 199 } |
201 | 200 |
202 struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { | 201 struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { |
203 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); | 202 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); |
204 ~EGLSyncKHRRef(); | 203 ~EGLSyncKHRRef(); |
205 EGLDisplay const egl_display; | 204 EGLDisplay const egl_display; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 | 372 |
374 V4L2VP8Picture::~V4L2VP8Picture() { | 373 V4L2VP8Picture::~V4L2VP8Picture() { |
375 } | 374 } |
376 | 375 |
377 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( | 376 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( |
378 const scoped_refptr<V4L2Device>& device, | 377 const scoped_refptr<V4L2Device>& device, |
379 EGLDisplay egl_display, | 378 EGLDisplay egl_display, |
380 EGLContext egl_context, | 379 EGLContext egl_context, |
381 const base::WeakPtr<Client>& io_client, | 380 const base::WeakPtr<Client>& io_client, |
382 const base::Callback<bool(void)>& make_context_current, | 381 const base::Callback<bool(void)>& make_context_current, |
383 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) | 382 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
384 : input_planes_count_(0), | 383 : input_planes_count_(0), |
385 output_planes_count_(0), | 384 output_planes_count_(0), |
386 child_message_loop_proxy_(base::MessageLoopProxy::current()), | 385 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
387 io_message_loop_proxy_(io_message_loop_proxy), | 386 io_task_runner_(io_task_runner), |
388 io_client_(io_client), | 387 io_client_(io_client), |
389 device_(device), | 388 device_(device), |
390 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"), | 389 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"), |
391 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"), | 390 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"), |
392 input_streamon_(false), | 391 input_streamon_(false), |
393 input_buffer_queued_count_(0), | 392 input_buffer_queued_count_(0), |
394 output_streamon_(false), | 393 output_streamon_(false), |
395 output_buffer_queued_count_(0), | 394 output_buffer_queued_count_(0), |
396 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 395 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
397 output_format_fourcc_(0), | 396 output_format_fourcc_(0), |
398 state_(kUninitialized), | 397 state_(kUninitialized), |
399 decoder_flushing_(false), | 398 decoder_flushing_(false), |
400 decoder_resetting_(false), | 399 decoder_resetting_(false), |
401 surface_set_change_pending_(false), | 400 surface_set_change_pending_(false), |
402 picture_clearing_count_(0), | 401 picture_clearing_count_(0), |
403 pictures_assigned_(false, false), | 402 pictures_assigned_(false, false), |
404 make_context_current_(make_context_current), | 403 make_context_current_(make_context_current), |
405 egl_display_(egl_display), | 404 egl_display_(egl_display), |
406 egl_context_(egl_context), | 405 egl_context_(egl_context), |
407 weak_this_factory_(this) { | 406 weak_this_factory_(this) { |
408 weak_this_ = weak_this_factory_.GetWeakPtr(); | 407 weak_this_ = weak_this_factory_.GetWeakPtr(); |
409 } | 408 } |
410 | 409 |
411 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() { | 410 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() { |
412 DVLOGF(2); | 411 DVLOGF(2); |
413 | 412 |
414 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 413 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
415 DCHECK(!decoder_thread_.IsRunning()); | 414 DCHECK(!decoder_thread_.IsRunning()); |
416 DCHECK(!device_poll_thread_.IsRunning()); | 415 DCHECK(!device_poll_thread_.IsRunning()); |
417 | 416 |
418 DCHECK(input_buffer_map_.empty()); | 417 DCHECK(input_buffer_map_.empty()); |
419 DCHECK(output_buffer_map_.empty()); | 418 DCHECK(output_buffer_map_.empty()); |
420 } | 419 } |
421 | 420 |
422 void V4L2SliceVideoDecodeAccelerator::NotifyError(Error error) { | 421 void V4L2SliceVideoDecodeAccelerator::NotifyError(Error error) { |
423 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { | 422 if (!child_task_runner_->BelongsToCurrentThread()) { |
424 child_message_loop_proxy_->PostTask( | 423 child_task_runner_->PostTask( |
425 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::NotifyError, | 424 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::NotifyError, |
426 weak_this_, error)); | 425 weak_this_, error)); |
427 return; | 426 return; |
428 } | 427 } |
429 | 428 |
430 if (client_) { | 429 if (client_) { |
431 client_->NotifyError(error); | 430 client_->NotifyError(error); |
432 client_ptr_factory_.reset(); | 431 client_ptr_factory_.reset(); |
433 } | 432 } |
434 } | 433 } |
435 | 434 |
436 bool V4L2SliceVideoDecodeAccelerator::Initialize( | 435 bool V4L2SliceVideoDecodeAccelerator::Initialize( |
437 media::VideoCodecProfile profile, | 436 media::VideoCodecProfile profile, |
438 VideoDecodeAccelerator::Client* client) { | 437 VideoDecodeAccelerator::Client* client) { |
439 DVLOGF(3) << "profile: " << profile; | 438 DVLOGF(3) << "profile: " << profile; |
440 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 439 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
441 DCHECK_EQ(state_, kUninitialized); | 440 DCHECK_EQ(state_, kUninitialized); |
442 | 441 |
443 client_ptr_factory_.reset( | 442 client_ptr_factory_.reset( |
444 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); | 443 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); |
445 client_ = client_ptr_factory_->GetWeakPtr(); | 444 client_ = client_ptr_factory_->GetWeakPtr(); |
446 | 445 |
447 video_profile_ = profile; | 446 video_profile_ = profile; |
448 | 447 |
449 if (video_profile_ >= media::H264PROFILE_MIN && | 448 if (video_profile_ >= media::H264PROFILE_MIN && |
450 video_profile_ <= media::H264PROFILE_MAX) { | 449 video_profile_ <= media::H264PROFILE_MAX) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
492 return false; | 491 return false; |
493 } | 492 } |
494 | 493 |
495 if (!SetupFormats()) | 494 if (!SetupFormats()) |
496 return false; | 495 return false; |
497 | 496 |
498 if (!decoder_thread_.Start()) { | 497 if (!decoder_thread_.Start()) { |
499 DLOG(ERROR) << "Initialize(): device thread failed to start"; | 498 DLOG(ERROR) << "Initialize(): device thread failed to start"; |
500 return false; | 499 return false; |
501 } | 500 } |
502 decoder_thread_proxy_ = decoder_thread_.message_loop_proxy(); | 501 decoder_thread_proxy_ = decoder_thread_.task_runner(); |
no sievers
2015/05/12 18:11:30
nit: consider renaming |decoder_thread_proxy_|
Sami
2015/05/13 18:17:52
Done.
| |
503 | 502 |
504 state_ = kInitialized; | 503 state_ = kInitialized; |
505 | 504 |
506 // InitializeTask will NOTIFY_ERROR on failure. | 505 // InitializeTask will NOTIFY_ERROR on failure. |
507 decoder_thread_proxy_->PostTask( | 506 decoder_thread_proxy_->PostTask( |
508 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask, | 507 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask, |
509 base::Unretained(this))); | 508 base::Unretained(this))); |
510 | 509 |
511 DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized"; | 510 DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized"; |
512 return true; | 511 return true; |
513 } | 512 } |
514 | 513 |
515 void V4L2SliceVideoDecodeAccelerator::InitializeTask() { | 514 void V4L2SliceVideoDecodeAccelerator::InitializeTask() { |
516 DVLOGF(3); | 515 DVLOGF(3); |
517 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 516 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
518 DCHECK_EQ(state_, kInitialized); | 517 DCHECK_EQ(state_, kInitialized); |
519 | 518 |
520 if (!CreateInputBuffers()) | 519 if (!CreateInputBuffers()) |
521 NOTIFY_ERROR(PLATFORM_FAILURE); | 520 NOTIFY_ERROR(PLATFORM_FAILURE); |
522 | 521 |
523 // Output buffers will be created once decoder gives us information | 522 // Output buffers will be created once decoder gives us information |
524 // about their size and required count. | 523 // about their size and required count. |
525 state_ = kDecoding; | 524 state_ = kDecoding; |
526 } | 525 } |
527 | 526 |
528 void V4L2SliceVideoDecodeAccelerator::Destroy() { | 527 void V4L2SliceVideoDecodeAccelerator::Destroy() { |
529 DVLOGF(3); | 528 DVLOGF(3); |
530 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 529 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
531 | 530 |
532 if (decoder_thread_.IsRunning()) { | 531 if (decoder_thread_.IsRunning()) { |
533 decoder_thread_proxy_->PostTask( | 532 decoder_thread_proxy_->PostTask( |
534 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask, | 533 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask, |
535 base::Unretained(this))); | 534 base::Unretained(this))); |
536 | 535 |
537 // Wait for tasks to finish/early-exit. | 536 // Wait for tasks to finish/early-exit. |
538 decoder_thread_.Stop(); | 537 decoder_thread_.Stop(); |
539 } | 538 } |
540 | 539 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 PLOG(ERROR) << "Could not allocate enough output buffers"; | 716 PLOG(ERROR) << "Could not allocate enough output buffers"; |
718 return false; | 717 return false; |
719 } | 718 } |
720 | 719 |
721 output_buffer_map_.resize(reqbufs.count); | 720 output_buffer_map_.resize(reqbufs.count); |
722 | 721 |
723 DVLOGF(3) << "buffer_count=" << output_buffer_map_.size() | 722 DVLOGF(3) << "buffer_count=" << output_buffer_map_.size() |
724 << ", visible size=" << visible_size_.ToString() | 723 << ", visible size=" << visible_size_.ToString() |
725 << ", coded size=" << coded_size_.ToString(); | 724 << ", coded size=" << coded_size_.ToString(); |
726 | 725 |
727 child_message_loop_proxy_->PostTask( | 726 child_task_runner_->PostTask( |
728 FROM_HERE, | 727 FROM_HERE, |
729 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers, | 728 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers, |
730 client_, output_buffer_map_.size(), coded_size_, | 729 client_, output_buffer_map_.size(), coded_size_, |
731 device_->GetTextureTarget())); | 730 device_->GetTextureTarget())); |
732 | 731 |
733 // Wait for the client to call AssignPictureBuffers() on the Child thread. | 732 // Wait for the client to call AssignPictureBuffers() on the Child thread. |
734 // We do this, because if we continue decoding without finishing buffer | 733 // We do this, because if we continue decoding without finishing buffer |
735 // allocation, we may end up Resetting before AssignPictureBuffers arrives, | 734 // allocation, we may end up Resetting before AssignPictureBuffers arrives, |
736 // resulting in unnecessary complications and subtle bugs. | 735 // resulting in unnecessary complications and subtle bugs. |
737 pictures_assigned_.Wait(); | 736 pictures_assigned_.Wait(); |
(...skipping 20 matching lines...) Expand all Loading... | |
758 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 757 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
759 | 758 |
760 input_buffer_map_.clear(); | 759 input_buffer_map_.clear(); |
761 free_input_buffers_.clear(); | 760 free_input_buffers_.clear(); |
762 } | 761 } |
763 | 762 |
764 void V4L2SliceVideoDecodeAccelerator::DismissPictures( | 763 void V4L2SliceVideoDecodeAccelerator::DismissPictures( |
765 std::vector<int32> picture_buffer_ids, | 764 std::vector<int32> picture_buffer_ids, |
766 base::WaitableEvent* done) { | 765 base::WaitableEvent* done) { |
767 DVLOGF(3); | 766 DVLOGF(3); |
768 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 767 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
769 | 768 |
770 for (auto picture_buffer_id : picture_buffer_ids) { | 769 for (auto picture_buffer_id : picture_buffer_ids) { |
771 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id; | 770 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id; |
772 client_->DismissPictureBuffer(picture_buffer_id); | 771 client_->DismissPictureBuffer(picture_buffer_id); |
773 } | 772 } |
774 | 773 |
775 done->Signal(); | 774 done->Signal(); |
776 } | 775 } |
777 | 776 |
778 void V4L2SliceVideoDecodeAccelerator::DevicePollTask(bool poll_device) { | 777 void V4L2SliceVideoDecodeAccelerator::DevicePollTask(bool poll_device) { |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1152 decoder_display_queue_.pop(); | 1151 decoder_display_queue_.pop(); |
1153 | 1152 |
1154 DVLOGF(3) << "Device poll stopped"; | 1153 DVLOGF(3) << "Device poll stopped"; |
1155 return true; | 1154 return true; |
1156 } | 1155 } |
1157 | 1156 |
1158 void V4L2SliceVideoDecodeAccelerator::Decode( | 1157 void V4L2SliceVideoDecodeAccelerator::Decode( |
1159 const media::BitstreamBuffer& bitstream_buffer) { | 1158 const media::BitstreamBuffer& bitstream_buffer) { |
1160 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1159 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
1161 << ", size=" << bitstream_buffer.size(); | 1160 << ", size=" << bitstream_buffer.size(); |
1162 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 1161 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
1163 | 1162 |
1164 decoder_thread_proxy_->PostTask( | 1163 decoder_thread_proxy_->PostTask( |
1165 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeTask, | 1164 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeTask, |
1166 base::Unretained(this), bitstream_buffer)); | 1165 base::Unretained(this), bitstream_buffer)); |
1167 } | 1166 } |
1168 | 1167 |
1169 void V4L2SliceVideoDecodeAccelerator::DecodeTask( | 1168 void V4L2SliceVideoDecodeAccelerator::DecodeTask( |
1170 const media::BitstreamBuffer& bitstream_buffer) { | 1169 const media::BitstreamBuffer& bitstream_buffer) { |
1171 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1170 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
1172 << " size=" << bitstream_buffer.size(); | 1171 << " size=" << bitstream_buffer.size(); |
1173 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1172 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
1174 | 1173 |
1175 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 1174 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
1176 io_client_, io_message_loop_proxy_, | 1175 io_client_, io_task_runner_, |
1177 new base::SharedMemory(bitstream_buffer.handle(), true), | 1176 new base::SharedMemory(bitstream_buffer.handle(), true), |
1178 bitstream_buffer.size(), bitstream_buffer.id())); | 1177 bitstream_buffer.size(), bitstream_buffer.id())); |
1179 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | 1178 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { |
1180 LOGF(ERROR) << "Could not map bitstream_buffer"; | 1179 LOGF(ERROR) << "Could not map bitstream_buffer"; |
1181 NOTIFY_ERROR(UNREADABLE_INPUT); | 1180 NOTIFY_ERROR(UNREADABLE_INPUT); |
1182 return; | 1181 return; |
1183 } | 1182 } |
1184 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); | 1183 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); |
1185 | 1184 |
1186 decoder_input_queue_.push( | 1185 decoder_input_queue_.push( |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1333 | 1332 |
1334 for (auto output_record : output_buffer_map_) { | 1333 for (auto output_record : output_buffer_map_) { |
1335 DCHECK(!output_record.at_device); | 1334 DCHECK(!output_record.at_device); |
1336 | 1335 |
1337 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { | 1336 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
1338 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) | 1337 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) |
1339 DVLOGF(1) << "eglDestroySyncKHR failed."; | 1338 DVLOGF(1) << "eglDestroySyncKHR failed."; |
1340 } | 1339 } |
1341 | 1340 |
1342 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { | 1341 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { |
1343 child_message_loop_proxy_->PostTask( | 1342 child_task_runner_->PostTask( |
1344 FROM_HERE, | 1343 FROM_HERE, |
1345 base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage), device_, | 1344 base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage), device_, |
1346 egl_display_, output_record.egl_image)); | 1345 egl_display_, output_record.egl_image)); |
1347 } | 1346 } |
1348 | 1347 |
1349 picture_buffers_to_dismiss.push_back(output_record.picture_id); | 1348 picture_buffers_to_dismiss.push_back(output_record.picture_id); |
1350 } | 1349 } |
1351 | 1350 |
1352 if (dismiss) { | 1351 if (dismiss) { |
1353 DVLOGF(2) << "Scheduling picture dismissal"; | 1352 DVLOGF(2) << "Scheduling picture dismissal"; |
1354 base::WaitableEvent done(false, false); | 1353 base::WaitableEvent done(false, false); |
1355 child_message_loop_proxy_->PostTask( | 1354 child_task_runner_->PostTask( |
1356 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DismissPictures, | 1355 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DismissPictures, |
1357 weak_this_, picture_buffers_to_dismiss, &done)); | 1356 weak_this_, picture_buffers_to_dismiss, &done)); |
1358 done.Wait(); | 1357 done.Wait(); |
1359 } | 1358 } |
1360 | 1359 |
1361 // At this point client can't call ReusePictureBuffer on any of the pictures | 1360 // At this point client can't call ReusePictureBuffer on any of the pictures |
1362 // anymore, so it's safe to destroy. | 1361 // anymore, so it's safe to destroy. |
1363 return DestroyOutputBuffers(); | 1362 return DestroyOutputBuffers(); |
1364 } | 1363 } |
1365 | 1364 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1400 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1399 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1401 reqbufs.memory = V4L2_MEMORY_MMAP; | 1400 reqbufs.memory = V4L2_MEMORY_MMAP; |
1402 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 1401 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
1403 | 1402 |
1404 return true; | 1403 return true; |
1405 } | 1404 } |
1406 | 1405 |
1407 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers( | 1406 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers( |
1408 const std::vector<media::PictureBuffer>& buffers) { | 1407 const std::vector<media::PictureBuffer>& buffers) { |
1409 DVLOGF(3); | 1408 DVLOGF(3); |
1410 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1409 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1411 | 1410 |
1412 if (buffers.size() != output_buffer_map_.size()) { | 1411 if (buffers.size() != output_buffer_map_.size()) { |
1413 DLOG(ERROR) << "Failed to provide requested picture buffers. " | 1412 DLOG(ERROR) << "Failed to provide requested picture buffers. " |
1414 << "(Got " << buffers.size() | 1413 << "(Got " << buffers.size() |
1415 << ", requested " << output_buffer_map_.size() << ")"; | 1414 << ", requested " << output_buffer_map_.size() << ")"; |
1416 NOTIFY_ERROR(INVALID_ARGUMENT); | 1415 NOTIFY_ERROR(INVALID_ARGUMENT); |
1417 return; | 1416 return; |
1418 } | 1417 } |
1419 | 1418 |
1420 if (!make_context_current_.Run()) { | 1419 if (!make_context_current_.Run()) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1459 output_record.picture_id = buffers[i].id(); | 1458 output_record.picture_id = buffers[i].id(); |
1460 free_output_buffers_.push_back(i); | 1459 free_output_buffers_.push_back(i); |
1461 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; | 1460 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; |
1462 } | 1461 } |
1463 | 1462 |
1464 pictures_assigned_.Signal(); | 1463 pictures_assigned_.Signal(); |
1465 } | 1464 } |
1466 | 1465 |
1467 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer( | 1466 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer( |
1468 int32 picture_buffer_id) { | 1467 int32 picture_buffer_id) { |
1469 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1468 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1470 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; | 1469 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; |
1471 | 1470 |
1472 if (!make_context_current_.Run()) { | 1471 if (!make_context_current_.Run()) { |
1473 LOGF(ERROR) << "could not make context current"; | 1472 LOGF(ERROR) << "could not make context current"; |
1474 NOTIFY_ERROR(PLATFORM_FAILURE); | 1473 NOTIFY_ERROR(PLATFORM_FAILURE); |
1475 return; | 1474 return; |
1476 } | 1475 } |
1477 | 1476 |
1478 EGLSyncKHR egl_sync = | 1477 EGLSyncKHR egl_sync = |
1479 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 1478 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1522 DCHECK(!output_record.at_device); | 1521 DCHECK(!output_record.at_device); |
1523 output_record.at_client = false; | 1522 output_record.at_client = false; |
1524 output_record.egl_sync = egl_sync_ref->egl_sync; | 1523 output_record.egl_sync = egl_sync_ref->egl_sync; |
1525 // Take ownership of the EGLSync. | 1524 // Take ownership of the EGLSync. |
1526 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; | 1525 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; |
1527 surfaces_at_display_.erase(it); | 1526 surfaces_at_display_.erase(it); |
1528 } | 1527 } |
1529 | 1528 |
1530 void V4L2SliceVideoDecodeAccelerator::Flush() { | 1529 void V4L2SliceVideoDecodeAccelerator::Flush() { |
1531 DVLOGF(3); | 1530 DVLOGF(3); |
1532 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1531 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1533 | 1532 |
1534 decoder_thread_proxy_->PostTask( | 1533 decoder_thread_proxy_->PostTask( |
1535 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, | 1534 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, |
1536 base::Unretained(this))); | 1535 base::Unretained(this))); |
1537 } | 1536 } |
1538 | 1537 |
1539 void V4L2SliceVideoDecodeAccelerator::FlushTask() { | 1538 void V4L2SliceVideoDecodeAccelerator::FlushTask() { |
1540 DVLOGF(3); | 1539 DVLOGF(3); |
1541 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1540 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
1542 | 1541 |
1543 if (!decoder_input_queue_.empty()) { | 1542 if (!decoder_input_queue_.empty()) { |
1544 // We are not done with pending inputs, so queue an empty buffer, | 1543 // We are not done with pending inputs, so queue an empty buffer, |
1545 // which - when reached - will trigger flush sequence. | 1544 // which - when reached - will trigger flush sequence. |
1546 decoder_input_queue_.push( | 1545 decoder_input_queue_.push( |
1547 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1546 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
1548 io_client_, io_message_loop_proxy_, nullptr, 0, kFlushBufferId))); | 1547 io_client_, io_task_runner_, nullptr, 0, kFlushBufferId))); |
1549 return; | 1548 return; |
1550 } | 1549 } |
1551 | 1550 |
1552 // No more inputs pending, so just finish flushing here. | 1551 // No more inputs pending, so just finish flushing here. |
1553 InitiateFlush(); | 1552 InitiateFlush(); |
1554 } | 1553 } |
1555 | 1554 |
1556 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { | 1555 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { |
1557 DVLOGF(3); | 1556 DVLOGF(3); |
1558 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1557 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1597 // we will have all remaining PictureReady() posted to the client and we | 1596 // we will have all remaining PictureReady() posted to the client and we |
1598 // can post NotifyFlushDone(). | 1597 // can post NotifyFlushDone(). |
1599 DCHECK(decoder_display_queue_.empty()); | 1598 DCHECK(decoder_display_queue_.empty()); |
1600 | 1599 |
1601 // Decoder should have already returned all surfaces and all surfaces are | 1600 // Decoder should have already returned all surfaces and all surfaces are |
1602 // out of hardware. There can be no other owners of input buffers. | 1601 // out of hardware. There can be no other owners of input buffers. |
1603 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); | 1602 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); |
1604 | 1603 |
1605 SendPictureReady(); | 1604 SendPictureReady(); |
1606 | 1605 |
1607 child_message_loop_proxy_->PostTask( | 1606 child_task_runner_->PostTask(FROM_HERE, |
1608 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1607 base::Bind(&Client::NotifyFlushDone, client_)); |
1609 | 1608 |
1610 decoder_flushing_ = false; | 1609 decoder_flushing_ = false; |
1611 | 1610 |
1612 DVLOGF(3) << "Flush finished"; | 1611 DVLOGF(3) << "Flush finished"; |
1613 state_ = kDecoding; | 1612 state_ = kDecoding; |
1614 ScheduleDecodeBufferTaskIfNeeded(); | 1613 ScheduleDecodeBufferTaskIfNeeded(); |
1615 } | 1614 } |
1616 | 1615 |
1617 void V4L2SliceVideoDecodeAccelerator::Reset() { | 1616 void V4L2SliceVideoDecodeAccelerator::Reset() { |
1618 DVLOGF(3); | 1617 DVLOGF(3); |
1619 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1618 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1620 | 1619 |
1621 decoder_thread_proxy_->PostTask( | 1620 decoder_thread_proxy_->PostTask( |
1622 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, | 1621 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, |
1623 base::Unretained(this))); | 1622 base::Unretained(this))); |
1624 } | 1623 } |
1625 | 1624 |
1626 void V4L2SliceVideoDecodeAccelerator::ResetTask() { | 1625 void V4L2SliceVideoDecodeAccelerator::ResetTask() { |
1627 DVLOGF(3); | 1626 DVLOGF(3); |
1628 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1627 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
1629 | 1628 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1673 // simply mark them all as available. | 1672 // simply mark them all as available. |
1674 DCHECK_EQ(input_buffer_queued_count_, 0); | 1673 DCHECK_EQ(input_buffer_queued_count_, 0); |
1675 free_input_buffers_.clear(); | 1674 free_input_buffers_.clear(); |
1676 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 1675 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
1677 DCHECK(!input_buffer_map_[i].at_device); | 1676 DCHECK(!input_buffer_map_[i].at_device); |
1678 ReuseInputBuffer(i); | 1677 ReuseInputBuffer(i); |
1679 } | 1678 } |
1680 | 1679 |
1681 decoder_resetting_ = false; | 1680 decoder_resetting_ = false; |
1682 | 1681 |
1683 child_message_loop_proxy_->PostTask( | 1682 child_task_runner_->PostTask(FROM_HERE, |
1684 FROM_HERE, base::Bind(&Client::NotifyResetDone, client_)); | 1683 base::Bind(&Client::NotifyResetDone, client_)); |
1685 | 1684 |
1686 DVLOGF(3) << "Reset finished"; | 1685 DVLOGF(3) << "Reset finished"; |
1687 | 1686 |
1688 state_ = kDecoding; | 1687 state_ = kDecoding; |
1689 ScheduleDecodeBufferTaskIfNeeded(); | 1688 ScheduleDecodeBufferTaskIfNeeded(); |
1690 } | 1689 } |
1691 | 1690 |
1692 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) { | 1691 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) { |
1693 // We can touch decoder_state_ only if this is the decoder thread or the | 1692 // We can touch decoder_state_ only if this is the decoder thread or the |
1694 // decoder thread isn't running. | 1693 // decoder thread isn't running. |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2448 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2447 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
2449 bool resetting_or_flushing = (decoder_resetting_ || decoder_flushing_); | 2448 bool resetting_or_flushing = (decoder_resetting_ || decoder_flushing_); |
2450 while (!pending_picture_ready_.empty()) { | 2449 while (!pending_picture_ready_.empty()) { |
2451 bool cleared = pending_picture_ready_.front().cleared; | 2450 bool cleared = pending_picture_ready_.front().cleared; |
2452 const media::Picture& picture = pending_picture_ready_.front().picture; | 2451 const media::Picture& picture = pending_picture_ready_.front().picture; |
2453 if (cleared && picture_clearing_count_ == 0) { | 2452 if (cleared && picture_clearing_count_ == 0) { |
2454 DVLOGF(4) << "Posting picture ready to IO for: " | 2453 DVLOGF(4) << "Posting picture ready to IO for: " |
2455 << picture.picture_buffer_id(); | 2454 << picture.picture_buffer_id(); |
2456 // This picture is cleared. Post it to IO thread to reduce latency. This | 2455 // This picture is cleared. Post it to IO thread to reduce latency. This |
2457 // should be the case after all pictures are cleared at the beginning. | 2456 // should be the case after all pictures are cleared at the beginning. |
2458 io_message_loop_proxy_->PostTask( | 2457 io_task_runner_->PostTask( |
2459 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); | 2458 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); |
2460 pending_picture_ready_.pop(); | 2459 pending_picture_ready_.pop(); |
2461 } else if (!cleared || resetting_or_flushing) { | 2460 } else if (!cleared || resetting_or_flushing) { |
2462 DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared | 2461 DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared |
2463 << ", decoder_resetting_=" << decoder_resetting_ | 2462 << ", decoder_resetting_=" << decoder_resetting_ |
2464 << ", decoder_flushing_=" << decoder_flushing_ | 2463 << ", decoder_flushing_=" << decoder_flushing_ |
2465 << ", picture_clearing_count_=" << picture_clearing_count_; | 2464 << ", picture_clearing_count_=" << picture_clearing_count_; |
2466 DVLOGF(4) << "Posting picture ready to GPU for: " | 2465 DVLOGF(4) << "Posting picture ready to GPU for: " |
2467 << picture.picture_buffer_id(); | 2466 << picture.picture_buffer_id(); |
2468 // If the picture is not cleared, post it to the child thread because it | 2467 // If the picture is not cleared, post it to the child thread because it |
2469 // has to be cleared in the child thread. A picture only needs to be | 2468 // has to be cleared in the child thread. A picture only needs to be |
2470 // cleared once. If the decoder is resetting or flushing, send all | 2469 // cleared once. If the decoder is resetting or flushing, send all |
2471 // pictures to ensure PictureReady arrive before reset or flush done. | 2470 // pictures to ensure PictureReady arrive before reset or flush done. |
2472 child_message_loop_proxy_->PostTaskAndReply( | 2471 child_task_runner_->PostTaskAndReply( |
2473 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), | 2472 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), |
2474 // Unretained is safe. If Client::PictureReady gets to run, |this| is | 2473 // Unretained is safe. If Client::PictureReady gets to run, |this| is |
2475 // alive. Destroy() will wait the decode thread to finish. | 2474 // alive. Destroy() will wait the decode thread to finish. |
2476 base::Bind(&V4L2SliceVideoDecodeAccelerator::PictureCleared, | 2475 base::Bind(&V4L2SliceVideoDecodeAccelerator::PictureCleared, |
2477 base::Unretained(this))); | 2476 base::Unretained(this))); |
2478 picture_clearing_count_++; | 2477 picture_clearing_count_++; |
2479 pending_picture_ready_.pop(); | 2478 pending_picture_ready_.pop(); |
2480 } else { | 2479 } else { |
2481 // This picture is cleared. But some pictures are about to be cleared on | 2480 // This picture is cleared. But some pictures are about to be cleared on |
2482 // the child thread. To preserve the order, do not send this until those | 2481 // the child thread. To preserve the order, do not send this until those |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2533 profile.profile = media::VP8PROFILE_ANY; | 2532 profile.profile = media::VP8PROFILE_ANY; |
2534 profiles.push_back(profile); | 2533 profiles.push_back(profile); |
2535 break; | 2534 break; |
2536 } | 2535 } |
2537 } | 2536 } |
2538 | 2537 |
2539 return profiles; | 2538 return profiles; |
2540 } | 2539 } |
2541 | 2540 |
2542 } // namespace content | 2541 } // namespace content |
OLD | NEW |