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

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

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