Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc

Issue 1643123003: V4L2SVDA: Move allocation from GPU Child thread to decoder thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/v4l2_slice_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <errno.h> 5 #include <errno.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <linux/videodev2.h> 7 #include <linux/videodev2.h>
8 #include <poll.h> 8 #include <poll.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/eventfd.h> 10 #include <sys/eventfd.h>
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 input_buffer_queued_count_(0), 398 input_buffer_queued_count_(0),
399 output_streamon_(false), 399 output_streamon_(false),
400 output_buffer_queued_count_(0), 400 output_buffer_queued_count_(0),
401 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), 401 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN),
402 output_format_fourcc_(0), 402 output_format_fourcc_(0),
403 state_(kUninitialized), 403 state_(kUninitialized),
404 decoder_flushing_(false), 404 decoder_flushing_(false),
405 decoder_resetting_(false), 405 decoder_resetting_(false),
406 surface_set_change_pending_(false), 406 surface_set_change_pending_(false),
407 picture_clearing_count_(0), 407 picture_clearing_count_(0),
408 pictures_assigned_(false, false),
409 make_context_current_(make_context_current), 408 make_context_current_(make_context_current),
410 egl_display_(egl_display), 409 egl_display_(egl_display),
411 egl_context_(egl_context), 410 egl_context_(egl_context),
412 weak_this_factory_(this) { 411 weak_this_factory_(this) {
413 weak_this_ = weak_this_factory_.GetWeakPtr(); 412 weak_this_ = weak_this_factory_.GetWeakPtr();
414 } 413 }
415 414
416 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() { 415 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() {
417 DVLOGF(2); 416 DVLOGF(2);
418 417
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 539
541 void V4L2SliceVideoDecodeAccelerator::Destroy() { 540 void V4L2SliceVideoDecodeAccelerator::Destroy() {
542 DVLOGF(3); 541 DVLOGF(3);
543 DCHECK(child_task_runner_->BelongsToCurrentThread()); 542 DCHECK(child_task_runner_->BelongsToCurrentThread());
544 543
545 if (decoder_thread_.IsRunning()) { 544 if (decoder_thread_.IsRunning()) {
546 decoder_thread_task_runner_->PostTask( 545 decoder_thread_task_runner_->PostTask(
547 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask, 546 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask,
548 base::Unretained(this))); 547 base::Unretained(this)));
549 548
550 // Wake up decoder thread in case we are waiting in CreateOutputBuffers
551 // for client to provide pictures. Since this is Destroy, we won't be
552 // getting them anymore (AssignPictureBuffers won't be called).
553 pictures_assigned_.Signal();
554
555 // Wait for tasks to finish/early-exit. 549 // Wait for tasks to finish/early-exit.
556 decoder_thread_.Stop(); 550 decoder_thread_.Stop();
557 } 551 }
558 552
559 delete this; 553 delete this;
560 DVLOGF(3) << "Destroyed"; 554 DVLOGF(3) << "Destroyed";
561 } 555 }
562 556
563 void V4L2SliceVideoDecodeAccelerator::DestroyTask() { 557 void V4L2SliceVideoDecodeAccelerator::DestroyTask() {
564 DVLOGF(3); 558 DVLOGF(3);
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 DVLOGF(3) << "buffer_count=" << num_pictures 740 DVLOGF(3) << "buffer_count=" << num_pictures
747 << ", visible size=" << visible_size_.ToString() 741 << ", visible size=" << visible_size_.ToString()
748 << ", coded size=" << coded_size_.ToString(); 742 << ", coded size=" << coded_size_.ToString();
749 743
750 child_task_runner_->PostTask( 744 child_task_runner_->PostTask(
751 FROM_HERE, 745 FROM_HERE,
752 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers, 746 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers,
753 client_, num_pictures, coded_size_, 747 client_, num_pictures, coded_size_,
754 device_->GetTextureTarget())); 748 device_->GetTextureTarget()));
755 749
756 // Wait for the client to call AssignPictureBuffers() on the Child thread.
757 // We do this, because if we continue decoding without finishing buffer
758 // allocation, we may end up Resetting before AssignPictureBuffers arrives,
759 // resulting in unnecessary complications and subtle bugs.
760 pictures_assigned_.Wait();
761
762 return true; 750 return true;
763 } 751 }
764 752
765 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() { 753 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() {
766 DVLOGF(3); 754 DVLOGF(3);
767 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() || 755 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
768 !decoder_thread_.IsRunning()); 756 !decoder_thread_.IsRunning());
769 DCHECK(!input_streamon_); 757 DCHECK(!input_streamon_);
770 758
771 for (auto& input_record : input_buffer_map_) { 759 for (auto& input_record : input_buffer_map_) {
772 if (input_record.address != nullptr) 760 if (input_record.address != nullptr)
773 device_->Munmap(input_record.address, input_record.length); 761 device_->Munmap(input_record.address, input_record.length);
774 } 762 }
775 763
776 struct v4l2_requestbuffers reqbufs; 764 struct v4l2_requestbuffers reqbufs;
777 memset(&reqbufs, 0, sizeof(reqbufs)); 765 memset(&reqbufs, 0, sizeof(reqbufs));
778 reqbufs.count = 0; 766 reqbufs.count = 0;
779 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 767 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
780 reqbufs.memory = V4L2_MEMORY_MMAP; 768 reqbufs.memory = V4L2_MEMORY_MMAP;
781 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 769 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
782 770
783 input_buffer_map_.clear(); 771 input_buffer_map_.clear();
784 free_input_buffers_.clear(); 772 free_input_buffers_.clear();
785 } 773 }
786 774
787 void V4L2SliceVideoDecodeAccelerator::DismissPictures( 775 void V4L2SliceVideoDecodeAccelerator::DismissPictures(
788 std::vector<int32_t> picture_buffer_ids, 776 const std::vector<int32_t>& picture_buffer_ids,
789 base::WaitableEvent* done) { 777 base::WaitableEvent* done) {
790 DVLOGF(3); 778 DVLOGF(3);
791 DCHECK(child_task_runner_->BelongsToCurrentThread()); 779 DCHECK(child_task_runner_->BelongsToCurrentThread());
792 780
793 for (auto picture_buffer_id : picture_buffer_ids) { 781 for (auto picture_buffer_id : picture_buffer_ids) {
794 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id; 782 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id;
795 client_->DismissPictureBuffer(picture_buffer_id); 783 client_->DismissPictureBuffer(picture_buffer_id);
796 } 784 }
797 785
798 done->Signal(); 786 done->Signal();
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 TryOutputSurfaces(); 947 TryOutputSurfaces();
960 948
961 ProcessPendingEventsIfNeeded(); 949 ProcessPendingEventsIfNeeded();
962 } 950 }
963 951
964 void V4L2SliceVideoDecodeAccelerator::ProcessPendingEventsIfNeeded() { 952 void V4L2SliceVideoDecodeAccelerator::ProcessPendingEventsIfNeeded() {
965 // Process pending events, if any, in the correct order. 953 // Process pending events, if any, in the correct order.
966 // We always first process the surface set change, as it is an internal 954 // We always first process the surface set change, as it is an internal
967 // event from the decoder and interleaving it with external requests would 955 // event from the decoder and interleaving it with external requests would
968 // put the decoder in an undefined state. 956 // put the decoder in an undefined state.
969 FinishSurfaceSetChangeIfNeeded(); 957 if (surface_set_change_pending_) {
958 if (!FinishSurfaceSetChange())
959 return;
960 }
961 DCHECK(!surface_set_change_pending_);
970 962
971 // Process external (client) requests. 963 // Process external (client) requests.
972 FinishFlushIfNeeded(); 964 if (decoder_flushing_) {
973 FinishResetIfNeeded(); 965 if (!FinishFlush())
966 return;
967 }
968 DCHECK(!decoder_flushing_);
969
970 if (decoder_resetting_) {
971 if (!FinishReset())
972 return;
973 }
974 DCHECK(!decoder_resetting_);
975
976 if (state_ == kIdle)
977 state_ = kDecoding;
978
979 ScheduleDecodeBufferTaskIfNeeded();
wuchengli 2016/02/18 08:06:47 I asked offline about why we need line 976-99 now
974 } 980 }
975 981
976 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) { 982 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) {
977 DVLOGF(4) << "Reusing input buffer, index=" << index; 983 DVLOGF(4) << "Reusing input buffer, index=" << index;
978 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 984 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
979 985
980 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); 986 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size()));
981 InputRecord& input_record = input_buffer_map_[index]; 987 InputRecord& input_record = input_buffer_map_[index];
982 988
983 DCHECK(!input_record.at_device); 989 DCHECK(!input_record.at_device);
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 NOTIFY_ERROR(PLATFORM_FAILURE); 1288 NOTIFY_ERROR(PLATFORM_FAILURE);
1283 return; 1289 return;
1284 } 1290 }
1285 } 1291 }
1286 } 1292 }
1287 1293
1288 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() { 1294 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() {
1289 DVLOGF(2); 1295 DVLOGF(2);
1290 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1296 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1291 1297
1292 DCHECK_EQ(state_, kDecoding);
1293 state_ = kIdle; 1298 state_ = kIdle;
1294 1299
1295 DCHECK(!surface_set_change_pending_); 1300 DCHECK(!surface_set_change_pending_);
1296 surface_set_change_pending_ = true; 1301 surface_set_change_pending_ = true;
1297 1302
1298 FinishSurfaceSetChangeIfNeeded(); 1303 ProcessPendingEventsIfNeeded();
1299 } 1304 }
1300 1305
1301 void V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChangeIfNeeded() { 1306 bool V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChange() {
1302 DVLOGF(2); 1307 DVLOGF(2);
1303 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1308 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1304 1309
1305 if (!surface_set_change_pending_ || !surfaces_at_device_.empty()) 1310 DCHECK(surface_set_change_pending_);
1306 return; 1311 if (!surfaces_at_device_.empty())
1312 return false;
1307 1313
1308 DCHECK_EQ(state_, kIdle); 1314 DCHECK_EQ(state_, kIdle);
1309 DCHECK(decoder_display_queue_.empty()); 1315 DCHECK(decoder_display_queue_.empty());
1310 // All output buffers should've been returned from decoder and device by now. 1316 // All output buffers should've been returned from decoder and device by now.
1311 // The only remaining owner of surfaces may be display (client), and we will 1317 // The only remaining owner of surfaces may be display (client), and we will
1312 // dismiss them when destroying output buffers below. 1318 // dismiss them when destroying output buffers below.
1313 DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(), 1319 DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(),
1314 output_buffer_map_.size()); 1320 output_buffer_map_.size());
1315 1321
1316 // Keep input queue running while we switch outputs. 1322 // Keep input queue running while we switch outputs.
1317 if (!StopDevicePoll(true)) { 1323 if (!StopDevicePoll(true)) {
1318 NOTIFY_ERROR(PLATFORM_FAILURE); 1324 NOTIFY_ERROR(PLATFORM_FAILURE);
1319 return; 1325 return false;
1320 } 1326 }
1321 1327
1322 // This will return only once all buffers are dismissed and destroyed. 1328 // This will return only once all buffers are dismissed and destroyed.
1323 // This does not wait until they are displayed however, as display retains 1329 // This does not wait until they are displayed however, as display retains
1324 // references to the buffers bound to textures and will release them 1330 // references to the buffers bound to textures and will release them
1325 // after displaying. 1331 // after displaying.
1326 if (!DestroyOutputs(true)) { 1332 if (!DestroyOutputs(true)) {
1327 NOTIFY_ERROR(PLATFORM_FAILURE); 1333 NOTIFY_ERROR(PLATFORM_FAILURE);
1328 return; 1334 return false;
1329 } 1335 }
1330 1336
1331 if (!CreateOutputBuffers()) { 1337 if (!CreateOutputBuffers()) {
1332 NOTIFY_ERROR(PLATFORM_FAILURE); 1338 NOTIFY_ERROR(PLATFORM_FAILURE);
1333 return; 1339 return false;
1334 } 1340 }
1335 1341
1336 if (!StartDevicePoll()) { 1342 // At this point we can safely say the surface set has been changed, even
1337 NOTIFY_ERROR(PLATFORM_FAILURE); 1343 // though we haven't received the actual buffers via AssignPictureBuffers()
1338 return; 1344 // yet. We will not start decoding without having surfaces available,
1339 } 1345 // and will schedule a decode task once the client provides the buffers.
1340
1341 DVLOGF(3) << "Surface set change finished";
1342
1343 surface_set_change_pending_ = false; 1346 surface_set_change_pending_ = false;
1344 state_ = kDecoding; 1347 DVLOG(3) << "Surface set change finished";
1345 ScheduleDecodeBufferTaskIfNeeded(); 1348 return true;
1346 } 1349 }
1347 1350
1348 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) { 1351 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) {
1349 DVLOGF(3); 1352 DVLOGF(3);
1350 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1353 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1351 std::vector<EGLImageKHR> egl_images_to_destroy; 1354 std::vector<EGLImageKHR> egl_images_to_destroy;
1352 std::vector<int32_t> picture_buffers_to_dismiss; 1355 std::vector<int32_t> picture_buffers_to_dismiss;
1353 1356
1354 if (output_buffer_map_.empty()) 1357 if (output_buffer_map_.empty())
1355 return true; 1358 return true;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); 1428 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1426 1429
1427 return true; 1430 return true;
1428 } 1431 }
1429 1432
1430 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers( 1433 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers(
1431 const std::vector<media::PictureBuffer>& buffers) { 1434 const std::vector<media::PictureBuffer>& buffers) {
1432 DVLOGF(3); 1435 DVLOGF(3);
1433 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1436 DCHECK(child_task_runner_->BelongsToCurrentThread());
1434 1437
1438 decoder_thread_task_runner_->PostTask(
1439 FROM_HERE, base::Bind(
1440 &V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask,
wuchengli 2016/02/18 08:06:47 For the record, we had an offline discussion. I as
1441 base::Unretained(this), buffers));
1442 }
1443
1444 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask(
1445 const std::vector<media::PictureBuffer>& buffers) {
1446 DVLOGF(3);
1447 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1448 DCHECK_EQ(state_, kDecoding);
1449
1435 const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures(); 1450 const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures();
1436 1451
1437 if (buffers.size() < req_buffer_count) { 1452 if (buffers.size() < req_buffer_count) {
1438 DLOG(ERROR) << "Failed to provide requested picture buffers. " 1453 DLOG(ERROR) << "Failed to provide requested picture buffers. "
1439 << "(Got " << buffers.size() 1454 << "(Got " << buffers.size()
1440 << ", requested " << req_buffer_count << ")"; 1455 << ", requested " << req_buffer_count << ")";
1441 NOTIFY_ERROR(INVALID_ARGUMENT); 1456 NOTIFY_ERROR(INVALID_ARGUMENT);
1442 return; 1457 return;
1443 } 1458 }
1444 1459
1445 if (!make_context_current_.Run()) {
1446 DLOG(ERROR) << "could not make context current";
1447 NOTIFY_ERROR(PLATFORM_FAILURE);
1448 return;
1449 }
1450
1451 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
1452
1453 // It's safe to manipulate all the buffer state here, because the decoder
1454 // thread is waiting on pictures_assigned_.
1455
1456 // Allocate the output buffers. 1460 // Allocate the output buffers.
1457 struct v4l2_requestbuffers reqbufs; 1461 struct v4l2_requestbuffers reqbufs;
1458 memset(&reqbufs, 0, sizeof(reqbufs)); 1462 memset(&reqbufs, 0, sizeof(reqbufs));
1459 reqbufs.count = buffers.size(); 1463 reqbufs.count = buffers.size();
1460 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1464 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1461 reqbufs.memory = V4L2_MEMORY_MMAP; 1465 reqbufs.memory = V4L2_MEMORY_MMAP;
1462 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs); 1466 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs);
1463 1467
1464 if (reqbufs.count != buffers.size()) { 1468 if (reqbufs.count != buffers.size()) {
1465 DLOG(ERROR) << "Could not allocate enough output buffers"; 1469 DLOG(ERROR) << "Could not allocate enough output buffers";
1466 NOTIFY_ERROR(PLATFORM_FAILURE); 1470 NOTIFY_ERROR(PLATFORM_FAILURE);
1467 return; 1471 return;
1468 } 1472 }
1469 1473
1474 child_task_runner_->PostTask(
1475 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::CreateEGLImages,
1476 weak_this_, buffers, output_format_fourcc_,
1477 output_planes_count_));
1478 }
1479
1480 void V4L2SliceVideoDecodeAccelerator::CreateEGLImages(
1481 const std::vector<media::PictureBuffer>& buffers,
1482 uint32_t output_format_fourcc,
1483 size_t output_planes_count) {
1484 DVLOGF(3);
1485 DCHECK(child_task_runner_->BelongsToCurrentThread());
1486
1487 if (!make_context_current_.Run()) {
1488 DLOG(ERROR) << "could not make context current";
1489 NOTIFY_ERROR(PLATFORM_FAILURE);
1490 return;
1491 }
1492
1493 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
1494
1495 std::vector<EGLImageKHR> egl_images;
1496 for (size_t i = 0; i < buffers.size(); ++i) {
1497 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_,
1498 egl_context_,
1499 buffers[i].texture_id(),
1500 buffers[i].size(),
1501 i,
1502 output_format_fourcc,
1503 output_planes_count);
1504 if (egl_image == EGL_NO_IMAGE_KHR) {
1505 LOGF(ERROR) << "Could not create EGLImageKHR";
1506 for (const auto& image_to_destroy : egl_images)
1507 device_->DestroyEGLImage(egl_display_, image_to_destroy);
1508
1509 NOTIFY_ERROR(PLATFORM_FAILURE);
1510 return;
1511 }
1512
1513 egl_images.push_back(egl_image);
1514 }
1515
1516 decoder_thread_task_runner_->PostTask(
1517 FROM_HERE, base::Bind(
1518 &V4L2SliceVideoDecodeAccelerator::AssignEGLImages,
1519 base::Unretained(this), buffers, egl_images));
1520 }
1521
1522 void V4L2SliceVideoDecodeAccelerator::AssignEGLImages(
1523 const std::vector<media::PictureBuffer>& buffers,
1524 const std::vector<EGLImageKHR>& egl_images) {
1525 DVLOGF(3);
1526 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1527 DCHECK_EQ(buffers.size(), egl_images.size());
1528
1529 DCHECK(free_output_buffers_.empty());
1530 DCHECK(output_buffer_map_.empty());
1531
1470 output_buffer_map_.resize(buffers.size()); 1532 output_buffer_map_.resize(buffers.size());
1471 1533
1472 DCHECK(free_output_buffers_.empty());
1473 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 1534 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1474 DCHECK(buffers[i].size() == coded_size_); 1535 DCHECK(buffers[i].size() == coded_size_);
1475 1536
1476 OutputRecord& output_record = output_buffer_map_[i]; 1537 OutputRecord& output_record = output_buffer_map_[i];
1477 DCHECK(!output_record.at_device); 1538 DCHECK(!output_record.at_device);
1478 DCHECK(!output_record.at_client); 1539 DCHECK(!output_record.at_client);
1479 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); 1540 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
1480 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 1541 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1481 DCHECK_EQ(output_record.picture_id, -1); 1542 DCHECK_EQ(output_record.picture_id, -1);
1482 DCHECK_EQ(output_record.cleared, false); 1543 DCHECK_EQ(output_record.cleared, false);
1483 1544
1484 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, 1545 output_record.egl_image = egl_images[i];
1485 egl_context_,
1486 buffers[i].texture_id(),
1487 coded_size_,
1488 i,
1489 output_format_fourcc_,
1490 output_planes_count_);
1491 if (egl_image == EGL_NO_IMAGE_KHR) {
1492 LOGF(ERROR) << "Could not create EGLImageKHR";
1493 // Ownership of EGLImages allocated in previous iterations of this loop
1494 // has been transferred to output_buffer_map_. After we error-out here
1495 // the destructor will handle their cleanup.
1496 NOTIFY_ERROR(PLATFORM_FAILURE);
1497 return;
1498 }
1499
1500 output_record.egl_image = egl_image;
1501 output_record.picture_id = buffers[i].id(); 1546 output_record.picture_id = buffers[i].id();
1502 free_output_buffers_.push_back(i); 1547 free_output_buffers_.push_back(i);
1503 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; 1548 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id;
1504 } 1549 }
1505 1550
1506 pictures_assigned_.Signal(); 1551 if (!StartDevicePoll()) {
1552 NOTIFY_ERROR(PLATFORM_FAILURE);
1553 return;
1554 }
1555
1556 ProcessPendingEventsIfNeeded();
1507 } 1557 }
1508 1558
1509 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer( 1559 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer(
1510 int32_t picture_buffer_id) { 1560 int32_t picture_buffer_id) {
1511 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1561 DCHECK(child_task_runner_->BelongsToCurrentThread());
1512 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; 1562 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id;
1513 1563
1514 if (!make_context_current_.Run()) { 1564 if (!make_context_current_.Run()) {
1515 LOGF(ERROR) << "could not make context current"; 1565 LOGF(ERROR) << "could not make context current";
1516 NOTIFY_ERROR(PLATFORM_FAILURE); 1566 NOTIFY_ERROR(PLATFORM_FAILURE);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 DVLOGF(1) << "Failed flushing the decoder."; 1660 DVLOGF(1) << "Failed flushing the decoder.";
1611 NOTIFY_ERROR(PLATFORM_FAILURE); 1661 NOTIFY_ERROR(PLATFORM_FAILURE);
1612 return; 1662 return;
1613 } 1663 }
1614 1664
1615 // Put the decoder in an idle state, ready to resume. 1665 // Put the decoder in an idle state, ready to resume.
1616 decoder_->Reset(); 1666 decoder_->Reset();
1617 1667
1618 decoder_flushing_ = true; 1668 decoder_flushing_ = true;
1619 1669
1620 decoder_thread_task_runner_->PostTask( 1670 ProcessPendingEventsIfNeeded();
1621 FROM_HERE,
1622 base::Bind(&V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded,
1623 base::Unretained(this)));
1624 } 1671 }
1625 1672
1626 void V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded() { 1673 bool V4L2SliceVideoDecodeAccelerator::FinishFlush() {
1627 DVLOGF(3); 1674 DVLOGF(3);
1628 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1675 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1629 1676
1630 if (!decoder_flushing_ || !surfaces_at_device_.empty()) 1677 DCHECK(decoder_flushing_);
1631 return; 1678
1679 if (!surfaces_at_device_.empty())
1680 return false;
1632 1681
1633 DCHECK_EQ(state_, kIdle); 1682 DCHECK_EQ(state_, kIdle);
1634 1683
1635 // At this point, all remaining surfaces are decoded and dequeued, and since 1684 // At this point, all remaining surfaces are decoded and dequeued, and since
1636 // we have already scheduled output for them in InitiateFlush(), their 1685 // we have already scheduled output for them in InitiateFlush(), their
1637 // respective PictureReady calls have been posted (or they have been queued on 1686 // respective PictureReady calls have been posted (or they have been queued on
1638 // pending_picture_ready_). So at this time, once we SendPictureReady(), 1687 // pending_picture_ready_). So at this time, once we SendPictureReady(),
1639 // we will have all remaining PictureReady() posted to the client and we 1688 // we will have all remaining PictureReady() posted to the client and we
1640 // can post NotifyFlushDone(). 1689 // can post NotifyFlushDone().
1641 DCHECK(decoder_display_queue_.empty()); 1690 DCHECK(decoder_display_queue_.empty());
1642 1691
1643 // Decoder should have already returned all surfaces and all surfaces are 1692 // Decoder should have already returned all surfaces and all surfaces are
1644 // out of hardware. There can be no other owners of input buffers. 1693 // out of hardware. There can be no other owners of input buffers.
1645 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); 1694 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size());
1646 1695
1647 SendPictureReady(); 1696 SendPictureReady();
1648 1697
1698 decoder_flushing_ = false;
1699 DVLOGF(3) << "Flush finished";
1700
1649 child_task_runner_->PostTask(FROM_HERE, 1701 child_task_runner_->PostTask(FROM_HERE,
1650 base::Bind(&Client::NotifyFlushDone, client_)); 1702 base::Bind(&Client::NotifyFlushDone, client_));
1651 1703
1652 decoder_flushing_ = false; 1704 return true;
1653
1654 DVLOGF(3) << "Flush finished";
1655 state_ = kDecoding;
1656 ScheduleDecodeBufferTaskIfNeeded();
1657 } 1705 }
1658 1706
1659 void V4L2SliceVideoDecodeAccelerator::Reset() { 1707 void V4L2SliceVideoDecodeAccelerator::Reset() {
1660 DVLOGF(3); 1708 DVLOGF(3);
1661 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1709 DCHECK(child_task_runner_->BelongsToCurrentThread());
1662 1710
1663 decoder_thread_task_runner_->PostTask( 1711 decoder_thread_task_runner_->PostTask(
1664 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, 1712 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask,
1665 base::Unretained(this))); 1713 base::Unretained(this)));
1666 } 1714 }
(...skipping 15 matching lines...) Expand all
1682 // Put the decoder in an idle state, ready to resume. 1730 // Put the decoder in an idle state, ready to resume.
1683 decoder_->Reset(); 1731 decoder_->Reset();
1684 1732
1685 decoder_resetting_ = true; 1733 decoder_resetting_ = true;
1686 1734
1687 // Drop all remaining inputs. 1735 // Drop all remaining inputs.
1688 decoder_current_bitstream_buffer_.reset(); 1736 decoder_current_bitstream_buffer_.reset();
1689 while (!decoder_input_queue_.empty()) 1737 while (!decoder_input_queue_.empty())
1690 decoder_input_queue_.pop(); 1738 decoder_input_queue_.pop();
1691 1739
1692 FinishResetIfNeeded(); 1740 ProcessPendingEventsIfNeeded();
1693 } 1741 }
1694 1742
1695 void V4L2SliceVideoDecodeAccelerator::FinishResetIfNeeded() { 1743 bool V4L2SliceVideoDecodeAccelerator::FinishReset() {
1696 DVLOGF(3); 1744 DVLOGF(3);
1697 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1745 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1698 1746
1699 if (!decoder_resetting_ || !surfaces_at_device_.empty()) 1747 DCHECK(decoder_resetting_);
1700 return; 1748 if (!surfaces_at_device_.empty())
1749 return false;
1701 1750
1702 DCHECK_EQ(state_, kIdle); 1751 DCHECK_EQ(state_, kIdle);
1703 DCHECK(!decoder_flushing_); 1752 DCHECK(!decoder_flushing_);
1704 SendPictureReady(); 1753 SendPictureReady();
1705 1754
1706 // Drop any pending outputs. 1755 // Drop any pending outputs.
1707 while (!decoder_display_queue_.empty()) 1756 while (!decoder_display_queue_.empty())
1708 decoder_display_queue_.pop(); 1757 decoder_display_queue_.pop();
1709 1758
1710 // At this point we can have no input buffers in the decoder, because we 1759 // At this point we can have no input buffers in the decoder, because we
1711 // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s 1760 // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s
1712 // having been in kIdle since. We don't have any surfaces in the HW either - 1761 // having been in kIdle since. We don't have any surfaces in the HW either -
1713 // we just checked that surfaces_at_device_.empty(), and inputs are tied 1762 // we just checked that surfaces_at_device_.empty(), and inputs are tied
1714 // to surfaces. Since there can be no other owners of input buffers, we can 1763 // to surfaces. Since there can be no other owners of input buffers, we can
1715 // simply mark them all as available. 1764 // simply mark them all as available.
1716 DCHECK_EQ(input_buffer_queued_count_, 0); 1765 DCHECK_EQ(input_buffer_queued_count_, 0);
1717 free_input_buffers_.clear(); 1766 free_input_buffers_.clear();
1718 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { 1767 for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
1719 DCHECK(!input_buffer_map_[i].at_device); 1768 DCHECK(!input_buffer_map_[i].at_device);
1720 ReuseInputBuffer(i); 1769 ReuseInputBuffer(i);
1721 } 1770 }
1722 1771
1723 decoder_resetting_ = false; 1772 decoder_resetting_ = false;
1773 DVLOGF(3) << "Reset finished";
1724 1774
1725 child_task_runner_->PostTask(FROM_HERE, 1775 child_task_runner_->PostTask(FROM_HERE,
1726 base::Bind(&Client::NotifyResetDone, client_)); 1776 base::Bind(&Client::NotifyResetDone, client_));
1727 1777
1728 DVLOGF(3) << "Reset finished"; 1778 return true;
1729
1730 state_ = kDecoding;
1731 ScheduleDecodeBufferTaskIfNeeded();
1732 } 1779 }
1733 1780
1734 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) { 1781 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) {
1735 // We can touch decoder_state_ only if this is the decoder thread or the 1782 // We can touch decoder_state_ only if this is the decoder thread or the
1736 // decoder thread isn't running. 1783 // decoder thread isn't running.
1737 if (decoder_thread_.IsRunning() && 1784 if (decoder_thread_.IsRunning() &&
1738 !decoder_thread_task_runner_->BelongsToCurrentThread()) { 1785 !decoder_thread_task_runner_->BelongsToCurrentThread()) {
1739 decoder_thread_task_runner_->PostTask( 1786 decoder_thread_task_runner_->PostTask(
1740 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState, 1787 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState,
1741 base::Unretained(this), error)); 1788 base::Unretained(this), error));
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
2553 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { 2600 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() {
2554 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); 2601 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
2555 if (!device) 2602 if (!device)
2556 return SupportedProfiles(); 2603 return SupportedProfiles();
2557 2604
2558 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), 2605 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_),
2559 supported_input_fourccs_); 2606 supported_input_fourccs_);
2560 } 2607 }
2561 2608
2562 } // namespace content 2609 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/v4l2_slice_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698