OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <libdrm/drm_fourcc.h> | 8 #include <libdrm/drm_fourcc.h> |
9 #include <linux/videodev2.h> | 9 #include <linux/videodev2.h> |
10 #include <poll.h> | 10 #include <poll.h> |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 memset(&sub, 0, sizeof(sub)); | 275 memset(&sub, 0, sizeof(sub)); |
276 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; | 276 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; |
277 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); | 277 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); |
278 | 278 |
279 // Initialize format-specific bits. | 279 // Initialize format-specific bits. |
280 if (video_profile_ >= media::H264PROFILE_MIN && | 280 if (video_profile_ >= media::H264PROFILE_MIN && |
281 video_profile_ <= media::H264PROFILE_MAX) { | 281 video_profile_ <= media::H264PROFILE_MAX) { |
282 decoder_h264_parser_.reset(new media::H264Parser()); | 282 decoder_h264_parser_.reset(new media::H264Parser()); |
283 } | 283 } |
284 | 284 |
285 if (!StartDevicePoll()) | |
286 return false; | |
287 | |
285 if (!decoder_thread_.Start()) { | 288 if (!decoder_thread_.Start()) { |
286 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; | 289 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; |
287 NOTIFY_ERROR(PLATFORM_FAILURE); | 290 NOTIFY_ERROR(PLATFORM_FAILURE); |
288 return false; | 291 return false; |
289 } | 292 } |
290 | 293 |
291 SetDecoderState(kInitialized); | 294 SetDecoderState(kInitialized); |
292 | 295 |
293 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 296 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
294 &Client::NotifyInitializeDone, client_)); | 297 &Client::NotifyInitializeDone, client_)); |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
702 base::Unretained(this))); | 705 base::Unretained(this))); |
703 } | 706 } |
704 } | 707 } |
705 | 708 |
706 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial( | 709 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial( |
707 const void* data, size_t size, size_t* endpos) { | 710 const void* data, size_t size, size_t* endpos) { |
708 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size; | 711 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size; |
709 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 712 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
710 DCHECK_NE(decoder_state_, kUninitialized); | 713 DCHECK_NE(decoder_state_, kUninitialized); |
711 DCHECK_NE(decoder_state_, kDecoding); | 714 DCHECK_NE(decoder_state_, kDecoding); |
712 DCHECK(!device_poll_thread_.IsRunning()); | |
713 // Initial decode. We haven't been able to get output stream format info yet. | 715 // Initial decode. We haven't been able to get output stream format info yet. |
714 // Get it, and start decoding. | 716 // Get it, and start decoding. |
715 | 717 |
716 // Copy in and send to HW. | 718 // Copy in and send to HW. |
717 if (!AppendToInputFrame(data, size)) | 719 if (!AppendToInputFrame(data, size)) |
718 return false; | 720 return false; |
719 | 721 |
720 // If we only have a partial frame, don't flush and process yet. | 722 // If we only have a partial frame, don't flush and process yet. |
721 if (decoder_partial_frame_pending_) | 723 if (decoder_partial_frame_pending_) |
722 return true; | 724 return true; |
(...skipping 25 matching lines...) Expand all Loading... | |
748 | 750 |
749 // We expect to process the initial buffer once during stream init to | 751 // We expect to process the initial buffer once during stream init to |
750 // configure stream parameters, but will not consume the steam data on that | 752 // configure stream parameters, but will not consume the steam data on that |
751 // iteration. Subsequent iterations (including after reset) do not require | 753 // iteration. Subsequent iterations (including after reset) do not require |
752 // the stream init step. | 754 // the stream init step. |
753 *endpos = 0; | 755 *endpos = 0; |
754 } else { | 756 } else { |
755 *endpos = size; | 757 *endpos = size; |
756 } | 758 } |
757 | 759 |
758 // StartDevicePoll will raise the error if there is one. | |
759 if (!StartDevicePoll()) | |
760 return false; | |
761 | |
762 decoder_state_ = kDecoding; | 760 decoder_state_ = kDecoding; |
763 ScheduleDecodeBufferTaskIfNeeded(); | 761 ScheduleDecodeBufferTaskIfNeeded(); |
764 return true; | 762 return true; |
765 } | 763 } |
766 | 764 |
767 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue( | 765 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue( |
768 const void* data, size_t size) { | 766 const void* data, size_t size) { |
769 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; | 767 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; |
770 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 768 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
771 DCHECK_EQ(decoder_state_, kDecoding); | 769 DCHECK_EQ(decoder_state_, kDecoding); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
878 // Enqueue once since there's new available input for it. | 876 // Enqueue once since there's new available input for it. |
879 Enqueue(); | 877 Enqueue(); |
880 | 878 |
881 return (decoder_state_ != kError); | 879 return (decoder_state_ != kError); |
882 } | 880 } |
883 | 881 |
884 void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) { | 882 void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) { |
885 DVLOG(3) << "ServiceDeviceTask()"; | 883 DVLOG(3) << "ServiceDeviceTask()"; |
886 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 884 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
887 DCHECK_NE(decoder_state_, kUninitialized); | 885 DCHECK_NE(decoder_state_, kUninitialized); |
888 DCHECK_NE(decoder_state_, kInitialized); | |
889 DCHECK_NE(decoder_state_, kAfterReset); | 886 DCHECK_NE(decoder_state_, kAfterReset); |
890 TRACE_EVENT0("Video Decoder", "V4L2VDA::ServiceDeviceTask"); | 887 TRACE_EVENT0("Video Decoder", "V4L2VDA::ServiceDeviceTask"); |
891 | 888 |
892 if (decoder_state_ == kResetting) { | 889 if (decoder_state_ == kResetting) { |
893 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; | 890 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; |
894 return; | 891 return; |
895 } else if (decoder_state_ == kError) { | 892 } else if (decoder_state_ == kError) { |
896 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; | 893 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; |
897 return; | 894 return; |
898 } else if (decoder_state_ == kChangingResolution) { | 895 } else if (decoder_state_ == kChangingResolution) { |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1277 | 1274 |
1278 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon | 1275 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon |
1279 // sequence after flush to continue, even if we are not resetting. This would | 1276 // sequence after flush to continue, even if we are not resetting. This would |
1280 // make sense, because we don't really want to resume from a non-resume point | 1277 // make sense, because we don't really want to resume from a non-resume point |
1281 // (e.g. not from an IDR) if we are flushed. | 1278 // (e.g. not from an IDR) if we are flushed. |
1282 // MSE player however triggers a Flush() on chunk end, but never Reset(). One | 1279 // MSE player however triggers a Flush() on chunk end, but never Reset(). One |
1283 // could argue either way, or even say that Flush() is not needed/harmful when | 1280 // could argue either way, or even say that Flush() is not needed/harmful when |
1284 // transitioning to next chunk. | 1281 // transitioning to next chunk. |
1285 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze | 1282 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze |
1286 // when doing MSE. This should be harmless otherwise. | 1283 // when doing MSE. This should be harmless otherwise. |
1287 if (!StopDevicePoll(false)) | 1284 if (!StopDevicePoll(false)) { |
1285 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1288 return; | 1286 return; |
1287 } | |
1289 | 1288 |
1290 if (!StartDevicePoll()) | 1289 if (!StartDevicePoll()) { |
1290 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1291 return; | 1291 return; |
1292 } | |
1292 | 1293 |
1293 decoder_delay_bitstream_buffer_id_ = -1; | 1294 decoder_delay_bitstream_buffer_id_ = -1; |
1294 decoder_flushing_ = false; | 1295 decoder_flushing_ = false; |
1295 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; | 1296 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; |
1296 child_message_loop_proxy_->PostTask( | 1297 child_message_loop_proxy_->PostTask( |
1297 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1298 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); |
1298 | 1299 |
1299 // While we were flushing, we early-outed DecodeBufferTask()s. | 1300 // While we were flushing, we early-outed DecodeBufferTask()s. |
1300 ScheduleDecodeBufferTaskIfNeeded(); | 1301 ScheduleDecodeBufferTaskIfNeeded(); |
1301 } | 1302 } |
(...skipping 13 matching lines...) Expand all Loading... | |
1315 // because input pipe is already stopped if we are changing resolution. | 1316 // because input pipe is already stopped if we are changing resolution. |
1316 // We will come back here after we are done with the resolution change. | 1317 // We will come back here after we are done with the resolution change. |
1317 DCHECK(!resolution_change_reset_pending_); | 1318 DCHECK(!resolution_change_reset_pending_); |
1318 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) { | 1319 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) { |
1319 resolution_change_reset_pending_ = true; | 1320 resolution_change_reset_pending_ = true; |
1320 return; | 1321 return; |
1321 } | 1322 } |
1322 | 1323 |
1323 // We stop streaming and clear buffer tracking info (not preserving inputs). | 1324 // We stop streaming and clear buffer tracking info (not preserving inputs). |
1324 // StopDevicePoll() unconditionally does _not_ destroy buffers, however. | 1325 // StopDevicePoll() unconditionally does _not_ destroy buffers, however. |
1325 if (!StopDevicePoll(false)) | 1326 if (!StopDevicePoll(false)) { |
1327 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1326 return; | 1328 return; |
1329 } | |
1327 | 1330 |
1328 decoder_current_bitstream_buffer_.reset(); | 1331 decoder_current_bitstream_buffer_.reset(); |
1329 while (!decoder_input_queue_.empty()) | 1332 while (!decoder_input_queue_.empty()) |
1330 decoder_input_queue_.pop(); | 1333 decoder_input_queue_.pop(); |
1331 | 1334 |
1332 decoder_current_input_buffer_ = -1; | 1335 decoder_current_input_buffer_ = -1; |
1333 | 1336 |
1334 // If we were flushing, we'll never return any more BitstreamBuffers or | 1337 // If we were flushing, we'll never return any more BitstreamBuffers or |
1335 // PictureBuffers; they have all been dropped and returned by now. | 1338 // PictureBuffers; they have all been dropped and returned by now. |
1336 NotifyFlushDoneIfNeeded(); | 1339 NotifyFlushDoneIfNeeded(); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1400 while (!decoder_input_queue_.empty()) | 1403 while (!decoder_input_queue_.empty()) |
1401 decoder_input_queue_.pop(); | 1404 decoder_input_queue_.pop(); |
1402 decoder_flushing_ = false; | 1405 decoder_flushing_ = false; |
1403 | 1406 |
1404 // Set our state to kError. Just in case. | 1407 // Set our state to kError. Just in case. |
1405 decoder_state_ = kError; | 1408 decoder_state_ = kError; |
1406 } | 1409 } |
1407 | 1410 |
1408 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { | 1411 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { |
1409 DVLOG(3) << "StartDevicePoll()"; | 1412 DVLOG(3) << "StartDevicePoll()"; |
1410 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
1411 DCHECK(!device_poll_thread_.IsRunning()); | 1413 DCHECK(!device_poll_thread_.IsRunning()); |
1414 if (decoder_thread_.IsRunning()) | |
1415 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
1412 | 1416 |
1413 // Start up the device poll thread and schedule its first DevicePollTask(). | 1417 // Start up the device poll thread and schedule its first DevicePollTask(). |
1414 if (!device_poll_thread_.Start()) { | 1418 if (!device_poll_thread_.Start()) { |
1415 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; | 1419 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; |
1416 NOTIFY_ERROR(PLATFORM_FAILURE); | |
Pawel Osciak
2014/03/07 06:14:47
Could you please explain/add to CL description why
sheu
2014/03/07 23:51:05
D'oh. I was thinking of:
https://chromiumcoder
| |
1417 return false; | 1420 return false; |
1418 } | 1421 } |
1419 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1422 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
1420 &V4L2VideoDecodeAccelerator::DevicePollTask, | 1423 &V4L2VideoDecodeAccelerator::DevicePollTask, |
1421 base::Unretained(this), | 1424 base::Unretained(this), |
1422 0)); | 1425 0)); |
1423 | 1426 |
1424 return true; | 1427 return true; |
1425 } | 1428 } |
1426 | 1429 |
1427 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { | 1430 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { |
1428 DVLOG(3) << "StopDevicePoll()"; | 1431 DVLOG(3) << "StopDevicePoll()"; |
1429 if (decoder_thread_.IsRunning()) | 1432 if (decoder_thread_.IsRunning()) |
1430 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1433 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1431 | 1434 |
1432 // Signal the DevicePollTask() to stop, and stop the device poll thread. | 1435 // Signal the DevicePollTask() to stop, and stop the device poll thread. |
1433 if (!device_->SetDevicePollInterrupt()) { | 1436 if (!device_->SetDevicePollInterrupt()) { |
1434 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed"; | 1437 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed"; |
1435 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1436 return false; | 1438 return false; |
1437 } | 1439 } |
1438 device_poll_thread_.Stop(); | 1440 device_poll_thread_.Stop(); |
1439 // Clear the interrupt now, to be sure. | 1441 // Clear the interrupt now, to be sure. |
1440 if (!device_->ClearDevicePollInterrupt()) { | 1442 if (!device_->ClearDevicePollInterrupt()) { |
1441 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1442 return false; | 1443 return false; |
1443 } | 1444 } |
1444 | 1445 |
1445 // Stop streaming. | 1446 // Stop streaming. |
1446 if (!keep_input_state) { | 1447 if (!keep_input_state) { |
1447 if (input_streamon_) { | 1448 if (input_streamon_) { |
1448 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1449 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1449 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); | 1450 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); |
1450 } | 1451 } |
1451 input_streamon_ = false; | 1452 input_streamon_ = false; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1496 void V4L2VideoDecodeAccelerator::StartResolutionChangeIfNeeded() { | 1497 void V4L2VideoDecodeAccelerator::StartResolutionChangeIfNeeded() { |
1497 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1498 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1498 DCHECK_EQ(decoder_state_, kDecoding); | 1499 DCHECK_EQ(decoder_state_, kDecoding); |
1499 | 1500 |
1500 if (!resolution_change_pending_) | 1501 if (!resolution_change_pending_) |
1501 return; | 1502 return; |
1502 | 1503 |
1503 DVLOG(3) << "No more work, initiate resolution change"; | 1504 DVLOG(3) << "No more work, initiate resolution change"; |
1504 | 1505 |
1505 // Keep input queue. | 1506 // Keep input queue. |
1506 if (!StopDevicePoll(true)) | 1507 if (!StopDevicePoll(true)) { |
1508 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1507 return; | 1509 return; |
1510 } | |
1508 | 1511 |
1509 decoder_state_ = kChangingResolution; | 1512 decoder_state_ = kChangingResolution; |
1510 DCHECK(resolution_change_pending_); | 1513 DCHECK(resolution_change_pending_); |
1511 resolution_change_pending_ = false; | 1514 resolution_change_pending_ = false; |
1512 | 1515 |
1513 // Post a task to clean up buffers on child thread. This will also ensure | 1516 // Post a task to clean up buffers on child thread. This will also ensure |
1514 // that we won't accept ReusePictureBuffer() anymore after that. | 1517 // that we won't accept ReusePictureBuffer() anymore after that. |
1515 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1518 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
1516 &V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, | 1519 &V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, |
1517 weak_this_)); | 1520 weak_this_)); |
(...skipping 25 matching lines...) Expand all Loading... | |
1543 } | 1546 } |
1544 | 1547 |
1545 decoder_state_ = kDecoding; | 1548 decoder_state_ = kDecoding; |
1546 | 1549 |
1547 if (resolution_change_reset_pending_) { | 1550 if (resolution_change_reset_pending_) { |
1548 resolution_change_reset_pending_ = false; | 1551 resolution_change_reset_pending_ = false; |
1549 ResetTask(); | 1552 ResetTask(); |
1550 return; | 1553 return; |
1551 } | 1554 } |
1552 | 1555 |
1553 if (!StartDevicePoll()) | 1556 if (!StartDevicePoll()) { |
1557 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1554 return; | 1558 return; |
1559 } | |
1555 | 1560 |
1556 Enqueue(); | 1561 Enqueue(); |
1557 ScheduleDecodeBufferTaskIfNeeded(); | 1562 ScheduleDecodeBufferTaskIfNeeded(); |
1558 } | 1563 } |
1559 | 1564 |
1560 void V4L2VideoDecodeAccelerator::DevicePollTask(bool poll_device) { | 1565 void V4L2VideoDecodeAccelerator::DevicePollTask(bool poll_device) { |
1561 DVLOG(3) << "DevicePollTask()"; | 1566 DVLOG(3) << "DevicePollTask()"; |
1562 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); | 1567 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); |
1563 TRACE_EVENT0("Video Decoder", "V4L2VDA::DevicePollTask"); | 1568 TRACE_EVENT0("Video Decoder", "V4L2VDA::DevicePollTask"); |
1564 | 1569 |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1919 | 1924 |
1920 void V4L2VideoDecodeAccelerator::PictureCleared() { | 1925 void V4L2VideoDecodeAccelerator::PictureCleared() { |
1921 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 1926 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
1922 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1927 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1923 DCHECK_GT(picture_clearing_count_, 0); | 1928 DCHECK_GT(picture_clearing_count_, 0); |
1924 picture_clearing_count_--; | 1929 picture_clearing_count_--; |
1925 SendPictureReady(); | 1930 SendPictureReady(); |
1926 } | 1931 } |
1927 | 1932 |
1928 } // namespace content | 1933 } // namespace content |
OLD | NEW |