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> |
11 #include <sys/eventfd.h> | 11 #include <sys/eventfd.h> |
12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
14 | 14 |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/debug/trace_event.h" | 16 #include "base/debug/trace_event.h" |
17 #include "base/memory/shared_memory.h" | 17 #include "base/memory/shared_memory.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/message_loop/message_loop_proxy.h" | 19 #include "base/message_loop/message_loop_proxy.h" |
20 #include "base/posix/eintr_wrapper.h" | 20 #include "base/posix/eintr_wrapper.h" |
21 #include "content/common/gpu/media/h264_parser.h" | |
22 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | 21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
| 22 #include "media/filters/h264_parser.h" |
23 #include "ui/gl/scoped_binders.h" | 23 #include "ui/gl/scoped_binders.h" |
24 | 24 |
25 namespace content { | 25 namespace content { |
26 | 26 |
27 #define NOTIFY_ERROR(x) \ | 27 #define NOTIFY_ERROR(x) \ |
28 do { \ | 28 do { \ |
29 SetDecoderState(kError); \ | 29 SetDecoderState(kError); \ |
30 DLOG(ERROR) << "calling NotifyError(): " << x; \ | 30 DLOG(ERROR) << "calling NotifyError(): " << x; \ |
31 NotifyError(x); \ | 31 NotifyError(x); \ |
32 } while (0) | 32 } while (0) |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 | 323 |
324 // Subscribe to the resolution change event. | 324 // Subscribe to the resolution change event. |
325 struct v4l2_event_subscription sub; | 325 struct v4l2_event_subscription sub; |
326 memset(&sub, 0, sizeof(sub)); | 326 memset(&sub, 0, sizeof(sub)); |
327 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; | 327 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; |
328 IOCTL_OR_ERROR_RETURN_FALSE(fd_, VIDIOC_SUBSCRIBE_EVENT, &sub); | 328 IOCTL_OR_ERROR_RETURN_FALSE(fd_, VIDIOC_SUBSCRIBE_EVENT, &sub); |
329 | 329 |
330 // Initialize format-specific bits. | 330 // Initialize format-specific bits. |
331 if (video_profile_ >= media::H264PROFILE_MIN && | 331 if (video_profile_ >= media::H264PROFILE_MIN && |
332 video_profile_ <= media::H264PROFILE_MAX) { | 332 video_profile_ <= media::H264PROFILE_MAX) { |
333 decoder_h264_parser_.reset(new content::H264Parser()); | 333 decoder_h264_parser_.reset(new media::H264Parser()); |
334 } | 334 } |
335 | 335 |
336 if (!decoder_thread_.Start()) { | 336 if (!decoder_thread_.Start()) { |
337 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; | 337 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; |
338 NOTIFY_ERROR(PLATFORM_FAILURE); | 338 NOTIFY_ERROR(PLATFORM_FAILURE); |
339 return false; | 339 return false; |
340 } | 340 } |
341 | 341 |
342 SetDecoderState(kInitialized); | 342 SetDecoderState(kInitialized); |
343 | 343 |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 | 645 |
646 bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment( | 646 bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment( |
647 const uint8* data, | 647 const uint8* data, |
648 size_t size, | 648 size_t size, |
649 size_t* endpos) { | 649 size_t* endpos) { |
650 if (video_profile_ >= media::H264PROFILE_MIN && | 650 if (video_profile_ >= media::H264PROFILE_MIN && |
651 video_profile_ <= media::H264PROFILE_MAX) { | 651 video_profile_ <= media::H264PROFILE_MAX) { |
652 // For H264, we need to feed HW one frame at a time. This is going to take | 652 // For H264, we need to feed HW one frame at a time. This is going to take |
653 // some parsing of our input stream. | 653 // some parsing of our input stream. |
654 decoder_h264_parser_->SetStream(data, size); | 654 decoder_h264_parser_->SetStream(data, size); |
655 content::H264NALU nalu; | 655 media::H264NALU nalu; |
656 content::H264Parser::Result result; | 656 media::H264Parser::Result result; |
657 *endpos = 0; | 657 *endpos = 0; |
658 | 658 |
659 // Keep on peeking the next NALs while they don't indicate a frame | 659 // Keep on peeking the next NALs while they don't indicate a frame |
660 // boundary. | 660 // boundary. |
661 for (;;) { | 661 for (;;) { |
662 bool end_of_frame = false; | 662 bool end_of_frame = false; |
663 result = decoder_h264_parser_->AdvanceToNextNALU(&nalu); | 663 result = decoder_h264_parser_->AdvanceToNextNALU(&nalu); |
664 if (result == content::H264Parser::kInvalidStream || | 664 if (result == media::H264Parser::kInvalidStream || |
665 result == content::H264Parser::kUnsupportedStream) | 665 result == media::H264Parser::kUnsupportedStream) |
666 return false; | 666 return false; |
667 if (result == content::H264Parser::kEOStream) { | 667 if (result == media::H264Parser::kEOStream) { |
668 // We've reached the end of the buffer before finding a frame boundary. | 668 // We've reached the end of the buffer before finding a frame boundary. |
669 decoder_partial_frame_pending_ = true; | 669 decoder_partial_frame_pending_ = true; |
670 return true; | 670 return true; |
671 } | 671 } |
672 switch (nalu.nal_unit_type) { | 672 switch (nalu.nal_unit_type) { |
673 case content::H264NALU::kNonIDRSlice: | 673 case media::H264NALU::kNonIDRSlice: |
674 case content::H264NALU::kIDRSlice: | 674 case media::H264NALU::kIDRSlice: |
675 if (nalu.size < 1) | 675 if (nalu.size < 1) |
676 return false; | 676 return false; |
677 // For these two, if the "first_mb_in_slice" field is zero, start a | 677 // For these two, if the "first_mb_in_slice" field is zero, start a |
678 // new frame and return. This field is Exp-Golomb coded starting on | 678 // new frame and return. This field is Exp-Golomb coded starting on |
679 // the eighth data bit of the NAL; a zero value is encoded with a | 679 // the eighth data bit of the NAL; a zero value is encoded with a |
680 // leading '1' bit in the byte, which we can detect as the byte being | 680 // leading '1' bit in the byte, which we can detect as the byte being |
681 // (unsigned) greater than or equal to 0x80. | 681 // (unsigned) greater than or equal to 0x80. |
682 if (nalu.data[1] >= 0x80) { | 682 if (nalu.data[1] >= 0x80) { |
683 end_of_frame = true; | 683 end_of_frame = true; |
684 break; | 684 break; |
685 } | 685 } |
686 break; | 686 break; |
687 case content::H264NALU::kSPS: | 687 case media::H264NALU::kSPS: |
688 case content::H264NALU::kPPS: | 688 case media::H264NALU::kPPS: |
689 case content::H264NALU::kEOSeq: | 689 case media::H264NALU::kEOSeq: |
690 case content::H264NALU::kEOStream: | 690 case media::H264NALU::kEOStream: |
691 // These unconditionally signal a frame boundary. | 691 // These unconditionally signal a frame boundary. |
692 end_of_frame = true; | 692 end_of_frame = true; |
693 break; | 693 break; |
694 default: | 694 default: |
695 // For all others, keep going. | 695 // For all others, keep going. |
696 break; | 696 break; |
697 } | 697 } |
698 if (end_of_frame) { | 698 if (end_of_frame) { |
699 if (!decoder_partial_frame_pending_ && *endpos == 0) { | 699 if (!decoder_partial_frame_pending_ && *endpos == 0) { |
700 // The frame was previously restarted, and we haven't filled the | 700 // The frame was previously restarted, and we haven't filled the |
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 | 1408 |
1409 // We might have received a resolution change event while we were waiting | 1409 // We might have received a resolution change event while we were waiting |
1410 // for the reset to finish. The codec will not post another event if the | 1410 // for the reset to finish. The codec will not post another event if the |
1411 // resolution after reset remains the same as the one to which were just | 1411 // resolution after reset remains the same as the one to which were just |
1412 // about to switch, so preserve the event across reset so we can address | 1412 // about to switch, so preserve the event across reset so we can address |
1413 // it after resuming. | 1413 // it after resuming. |
1414 | 1414 |
1415 // Reset format-specific bits. | 1415 // Reset format-specific bits. |
1416 if (video_profile_ >= media::H264PROFILE_MIN && | 1416 if (video_profile_ >= media::H264PROFILE_MIN && |
1417 video_profile_ <= media::H264PROFILE_MAX) { | 1417 video_profile_ <= media::H264PROFILE_MAX) { |
1418 decoder_h264_parser_.reset(new content::H264Parser()); | 1418 decoder_h264_parser_.reset(new media::H264Parser()); |
1419 } | 1419 } |
1420 | 1420 |
1421 // Jobs drained, we're finished resetting. | 1421 // Jobs drained, we're finished resetting. |
1422 DCHECK_EQ(decoder_state_, kResetting); | 1422 DCHECK_EQ(decoder_state_, kResetting); |
1423 decoder_state_ = kAfterReset; | 1423 decoder_state_ = kAfterReset; |
1424 decoder_partial_frame_pending_ = false; | 1424 decoder_partial_frame_pending_ = false; |
1425 decoder_delay_bitstream_buffer_id_ = -1; | 1425 decoder_delay_bitstream_buffer_id_ = -1; |
1426 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1426 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
1427 &Client::NotifyResetDone, client_)); | 1427 &Client::NotifyResetDone, client_)); |
1428 | 1428 |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 | 1984 |
1985 void V4L2VideoDecodeAccelerator::PictureCleared() { | 1985 void V4L2VideoDecodeAccelerator::PictureCleared() { |
1986 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 1986 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
1987 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1987 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1988 DCHECK_GT(picture_clearing_count_, 0); | 1988 DCHECK_GT(picture_clearing_count_, 0); |
1989 picture_clearing_count_--; | 1989 picture_clearing_count_--; |
1990 SendPictureReady(); | 1990 SendPictureReady(); |
1991 } | 1991 } |
1992 | 1992 |
1993 } // namespace content | 1993 } // namespace content |
OLD | NEW |