OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |