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

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

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