OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/renderer/media/rtc_video_encoder.h" | 5 #include "content/renderer/media/rtc_video_encoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_vector.h" |
11 #include "base/message_loop/message_loop_proxy.h" | 11 #include "base/message_loop/message_loop_proxy.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
15 #include "media/base/bitstream_buffer.h" | 15 #include "media/base/bitstream_buffer.h" |
16 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
17 #include "media/base/video_util.h" | 17 #include "media/base/video_util.h" |
18 #include "media/filters/gpu_video_accelerator_factories.h" | 18 #include "media/filters/gpu_video_accelerator_factories.h" |
19 #include "media/filters/h264_parser.h" | |
19 #include "media/video/video_encode_accelerator.h" | 20 #include "media/video/video_encode_accelerator.h" |
20 #include "third_party/webrtc/system_wrappers/interface/tick_util.h" | 21 #include "third_party/webrtc/system_wrappers/interface/tick_util.h" |
21 | 22 |
22 #define NOTIFY_ERROR(x) \ | 23 #define NOTIFY_ERROR(x) \ |
23 do { \ | 24 do { \ |
24 DLOG(ERROR) << "calling NotifyError(): " << x; \ | 25 DLOG(ERROR) << "calling NotifyError(): " << x; \ |
25 NotifyError(x); \ | 26 NotifyError(x); \ |
26 } while (0) | 27 } while (0) |
27 | 28 |
28 namespace content { | 29 namespace content { |
29 | 30 |
31 namespace { | |
32 | |
33 // Populates struct webrtc::RTPFragmentationHeader for H264 codec. | |
34 // Each entry specifies the offset and length (excluding start code) of a NALU. | |
35 // Returns true if successful. | |
36 bool GetRTPFragmentationHeaderH264( | |
37 webrtc::RTPFragmentationHeader& header, uint8_t* data, uint32_t length) { | |
38 media::H264Parser parser; | |
39 parser.SetStream(data, length); | |
40 | |
41 std::vector<media::H264NALU> nalu_vector; | |
42 while (true) { | |
43 media::H264NALU nalu; | |
44 media::H264Parser::Result result; | |
45 result = parser.AdvanceToNextNALU(&nalu); | |
46 if (result == media::H264Parser::kOk) { | |
47 nalu_vector.push_back(nalu); | |
48 } else if (result == media::H264Parser::kEOStream) { | |
49 break; | |
50 } else { | |
51 DLOG(ERROR) << "Unexpected H264 parser result"; | |
52 return false; | |
53 } | |
54 } | |
55 | |
56 header.VerifyAndAllocateFragmentationHeader(nalu_vector.size()); | |
57 for (size_t i = 0; i < nalu_vector.size(); ++i) { | |
58 header.fragmentationOffset[i] = nalu_vector[i].data - data; | |
59 header.fragmentationLength[i] = nalu_vector[i].size; | |
60 header.fragmentationPlType[i] = 0; | |
61 header.fragmentationTimeDiff[i] = 0; | |
62 } | |
63 return true; | |
64 } | |
65 | |
66 } // namespace | |
67 | |
30 // This private class of RTCVideoEncoder does the actual work of communicating | 68 // This private class of RTCVideoEncoder does the actual work of communicating |
31 // with a media::VideoEncodeAccelerator for handling video encoding. It can | 69 // with a media::VideoEncodeAccelerator for handling video encoding. It can |
32 // be created on any thread, but should subsequently be posted to (and Destroy() | 70 // be created on any thread, but should subsequently be posted to (and Destroy() |
33 // called on) a single thread. Callbacks to RTCVideoEncoder are posted to the | 71 // called on) a single thread. Callbacks to RTCVideoEncoder are posted to the |
34 // thread on which the instance was constructed. | 72 // thread on which the instance was constructed. |
35 // | 73 // |
36 // This class separates state related to the thread that RTCVideoEncoder | 74 // This class separates state related to the thread that RTCVideoEncoder |
37 // operates on (presently the libjingle worker thread) from the thread that | 75 // operates on (presently the libjingle worker thread) from the thread that |
38 // |gpu_factories_| provides for accelerator operations (presently the media | 76 // |gpu_factories_| provides for accelerator operations (presently the media |
39 // thread). The RTCVideoEncoder class can be deleted directly by WebRTC, while | 77 // thread). The RTCVideoEncoder class can be deleted directly by WebRTC, while |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
641 int32 bitstream_buffer_id, | 679 int32 bitstream_buffer_id, |
642 uint16 picture_id) { | 680 uint16 picture_id) { |
643 DCHECK(thread_checker_.CalledOnValidThread()); | 681 DCHECK(thread_checker_.CalledOnValidThread()); |
644 DVLOG(3) << "ReturnEncodedImage(): " | 682 DVLOG(3) << "ReturnEncodedImage(): " |
645 << "bitstream_buffer_id=" << bitstream_buffer_id | 683 << "bitstream_buffer_id=" << bitstream_buffer_id |
646 << ", picture_id=" << picture_id; | 684 << ", picture_id=" << picture_id; |
647 | 685 |
648 if (!encoded_image_callback_) | 686 if (!encoded_image_callback_) |
649 return; | 687 return; |
650 | 688 |
689 webrtc::RTPFragmentationHeader header; | |
690 memset(&header, 0, sizeof(header)); | |
691 switch (video_codec_type_) { | |
692 case webrtc::kVideoCodecVP8: | |
693 case webrtc::kVideoCodecGeneric: | |
694 // Generate a header describing a single fragment. | |
695 // Note that webrtc treats the generic-type payload as an opaque buffer. | |
696 header.VerifyAndAllocateFragmentationHeader(1); | |
697 header.fragmentationOffset[0] = 0; | |
698 header.fragmentationLength[0] = image->_length; | |
699 header.fragmentationPlType[0] = 0; | |
700 header.fragmentationTimeDiff[0] = 0; | |
701 break; | |
702 case webrtc::kVideoCodecH264: | |
703 if (!GetRTPFragmentationHeaderH264( | |
704 header, image->_buffer, image->_length)) { | |
705 LOG(ERROR) << "Failed to get RTP fragmentation header for H264"; | |
Pawel Osciak
2014/08/14 10:51:40
s/LOG/DLOG/
hshi1
2014/08/14 17:25:00
Done.
| |
706 NotifyError(WEBRTC_VIDEO_CODEC_ERROR); | |
Pawel Osciak
2014/08/14 10:51:40
Please use NOTIFY_ERROR()
hshi1
2014/08/14 17:25:00
Actually I can't use the macro NOTIFY_ERROR() beca
| |
707 return; | |
708 } | |
709 break; | |
710 default: | |
711 NOTREACHED() << "Invalid video codec type"; | |
712 return; | |
713 } | |
714 | |
651 webrtc::CodecSpecificInfo info; | 715 webrtc::CodecSpecificInfo info; |
652 memset(&info, 0, sizeof(info)); | 716 memset(&info, 0, sizeof(info)); |
653 info.codecType = video_codec_type_; | 717 info.codecType = video_codec_type_; |
654 if (video_codec_type_ == webrtc::kVideoCodecVP8) { | 718 if (video_codec_type_ == webrtc::kVideoCodecVP8) { |
655 info.codecSpecific.VP8.pictureId = picture_id; | 719 info.codecSpecific.VP8.pictureId = picture_id; |
656 info.codecSpecific.VP8.tl0PicIdx = -1; | 720 info.codecSpecific.VP8.tl0PicIdx = -1; |
657 info.codecSpecific.VP8.keyIdx = -1; | 721 info.codecSpecific.VP8.keyIdx = -1; |
658 } | 722 } |
659 | 723 |
660 // Generate a header describing a single fragment. | |
661 webrtc::RTPFragmentationHeader header; | |
662 memset(&header, 0, sizeof(header)); | |
663 header.VerifyAndAllocateFragmentationHeader(1); | |
664 header.fragmentationOffset[0] = 0; | |
665 header.fragmentationLength[0] = image->_length; | |
666 header.fragmentationPlType[0] = 0; | |
667 header.fragmentationTimeDiff[0] = 0; | |
668 | |
669 int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header); | 724 int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header); |
670 if (retval < 0) { | 725 if (retval < 0) { |
671 DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned " | 726 DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned " |
672 << retval; | 727 << retval; |
673 } | 728 } |
674 | 729 |
675 // The call through webrtc::EncodedImageCallback is synchronous, so we can | 730 // The call through webrtc::EncodedImageCallback is synchronous, so we can |
676 // immediately recycle the output buffer back to the Impl. | 731 // immediately recycle the output buffer back to the Impl. |
677 gpu_factories_->GetTaskRunner()->PostTask( | 732 gpu_factories_->GetTaskRunner()->PostTask( |
678 FROM_HERE, | 733 FROM_HERE, |
(...skipping 16 matching lines...) Expand all Loading... | |
695 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", | 750 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", |
696 init_retval == WEBRTC_VIDEO_CODEC_OK); | 751 init_retval == WEBRTC_VIDEO_CODEC_OK); |
697 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { | 752 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { |
698 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", | 753 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", |
699 video_codec_profile_, | 754 video_codec_profile_, |
700 media::VIDEO_CODEC_PROFILE_MAX + 1); | 755 media::VIDEO_CODEC_PROFILE_MAX + 1); |
701 } | 756 } |
702 } | 757 } |
703 | 758 |
704 } // namespace content | 759 } // namespace content |
OLD | NEW |