OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/renderer/media/rtc_encoding_video_capturer.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "media/base/encoded_bitstream_buffer.h" | |
9 | |
10 namespace content { | |
11 | |
12 // Client of EncodedVideoSource. This object is created and owned by the | |
13 // RtcEncodingVideoCapturer. | |
14 class RtcEncodingVideoCapturer::EncodedVideoSourceClient : | |
15 public media::EncodedVideoSource::Client { | |
16 public: | |
17 EncodedVideoSourceClient( | |
18 media::EncodedVideoSource* encoded_video_source, | |
19 media::VideoEncodingParameters params, | |
20 webrtc::VideoCodecType rtc_codec_type); | |
21 virtual ~EncodedVideoSourceClient(); | |
22 | |
23 // media::EncodedVideoSource::Client implementation. | |
24 virtual void OnOpened( | |
25 const media::VideoEncodingParameters& params) OVERRIDE; | |
26 virtual void OnClosed() OVERRIDE; | |
27 virtual void OnBufferReady( | |
28 scoped_refptr<const media::EncodedBitstreamBuffer> buffer) OVERRIDE; | |
29 virtual void OnConfigChanged( | |
30 const media::RuntimeVideoEncodingParameters& params) OVERRIDE; | |
31 | |
32 // Getters and setters for bitstream properties. | |
33 media::RuntimeVideoEncodingParameters runtime_params() const; | |
34 void set_round_trip_time(base::TimeDelta round_trip_time); | |
35 void set_callback(webrtc::EncodedImageCallback* callback); | |
36 | |
37 private: | |
38 // Convert buffer to webrtc types and invoke encode complete callback. | |
39 void ReportEncodedFrame( | |
40 scoped_refptr<const media::EncodedBitstreamBuffer> buffer); | |
41 | |
42 media::VideoEncodingParameters params_; | |
43 webrtc::VideoCodecType rtc_codec_type_; | |
44 bool finished_; | |
45 | |
46 base::Time time_base_; | |
47 base::TimeDelta round_trip_time_; | |
48 media::EncodedVideoSource* encoded_video_source_; | |
49 webrtc::EncodedImageCallback* callback_; | |
50 | |
51 DISALLOW_COPY_AND_ASSIGN(EncodedVideoSourceClient); | |
52 }; | |
53 | |
54 RtcEncodingVideoCapturer::EncodedVideoSourceClient::EncodedVideoSourceClient( | |
55 media::EncodedVideoSource* encoded_video_source, | |
56 media::VideoEncodingParameters params, | |
57 webrtc::VideoCodecType rtc_codec_type) | |
58 : params_(params), | |
59 rtc_codec_type_(rtc_codec_type), | |
60 finished_(false), | |
61 encoded_video_source_(encoded_video_source), | |
62 callback_(NULL) { | |
63 DCHECK(encoded_video_source_); | |
64 encoded_video_source_->OpenBitstream(this, params); | |
65 } | |
66 | |
67 RtcEncodingVideoCapturer::EncodedVideoSourceClient::~EncodedVideoSourceClient( | |
68 ) { | |
Ami GONE FROM CHROMIUM
2013/06/13 22:56:58
interesting wrap
hshi1
2013/06/13 23:33:40
Done.
| |
69 if (!finished_) | |
70 encoded_video_source_->CloseBitstream(); | |
71 } | |
72 | |
73 media::RuntimeVideoEncodingParameters | |
74 RtcEncodingVideoCapturer::EncodedVideoSourceClient::runtime_params() const { | |
75 return params_.runtime_params; | |
76 } | |
77 | |
78 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::set_round_trip_time( | |
79 base::TimeDelta round_trip_time) { | |
80 round_trip_time_ = round_trip_time; | |
81 } | |
82 | |
83 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::set_callback( | |
84 webrtc::EncodedImageCallback* callback) { | |
85 DCHECK(!callback_); | |
86 callback_ = callback; | |
87 } | |
88 | |
89 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnOpened( | |
90 const media::VideoEncodingParameters& params) { | |
91 params_ = params; | |
92 } | |
93 | |
94 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnClosed() { | |
95 finished_ = true; | |
96 } | |
97 | |
98 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnBufferReady( | |
99 scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { | |
100 DCHECK(!finished_ && buffer); | |
101 | |
102 // First buffer constitutes the origin of the time for this bitstream context. | |
103 if (time_base_.is_null()) | |
104 time_base_ = buffer->metadata().timestamp; | |
105 | |
106 ReportEncodedFrame(buffer); | |
107 encoded_video_source_->ReturnBitstreamBuffer(buffer); | |
108 } | |
109 | |
110 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnConfigChanged( | |
111 const media::RuntimeVideoEncodingParameters& params) { | |
112 params_.runtime_params = params; | |
113 } | |
114 | |
115 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::ReportEncodedFrame( | |
116 scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { | |
117 if (!callback_) | |
118 return; | |
119 | |
120 webrtc::EncodedImage image; | |
121 webrtc::CodecSpecificInfo codecInfo; | |
122 webrtc::RTPFragmentationHeader fragHeader; | |
123 | |
124 // TODO(hshi): remove this const_cast. Unfortunately webrtc::EncodedImage | |
125 // defines member |_buffer| of type uint8_t* even though webrtc never modifies | |
126 // the buffer contents. | |
127 image._buffer = const_cast<uint8_t*>(buffer->buffer()); | |
128 image._length = buffer->size(); | |
129 image._size = image._length; | |
130 | |
131 const media::BufferEncodingMetadata& metadata = buffer->metadata(); | |
132 base::TimeDelta capture_time = metadata.timestamp - time_base_; | |
133 image.capture_time_ms_ = capture_time.InMilliseconds(); | |
134 // Convert capture time to 90 kHz RTP timestamp. | |
135 image._timeStamp = (capture_time * 90000).InSeconds(); | |
136 if (metadata.key_frame) { | |
137 image._frameType = webrtc::kKeyFrame; | |
138 } else { | |
139 image._frameType = webrtc::kDeltaFrame; | |
140 } | |
141 image._completeFrame = true; | |
142 image._encodedWidth = params_.resolution.width(); | |
143 image._encodedHeight = params_.resolution.height(); | |
144 | |
145 // TODO(hshi): generate codec specific info for VP8. | |
146 codecInfo.codecType = rtc_codec_type_; | |
147 | |
148 // Generate header containing a single fragmentation. | |
149 fragHeader.VerifyAndAllocateFragmentationHeader(1); | |
150 fragHeader.fragmentationOffset[0] = 0; | |
151 fragHeader.fragmentationLength[0] = buffer->size(); | |
152 fragHeader.fragmentationPlType[0] = 0; | |
153 fragHeader.fragmentationTimeDiff[0] = 0; | |
154 | |
155 callback_->Encoded(image, &codecInfo, &fragHeader); | |
156 } | |
157 | |
158 // RtcEncodingVideoCapturer | |
159 RtcEncodingVideoCapturer::RtcEncodingVideoCapturer( | |
160 media::EncodedVideoSource* encoded_video_source, | |
161 webrtc::VideoCodecType codec_type) | |
162 : encoded_video_source_(encoded_video_source), | |
163 rtc_codec_type_(codec_type) { | |
164 } | |
165 | |
166 RtcEncodingVideoCapturer::~RtcEncodingVideoCapturer() { | |
167 } | |
168 | |
169 int32_t RtcEncodingVideoCapturer::InitEncode( | |
170 const webrtc::VideoCodec* codecSettings, | |
171 int32_t numberOfCores, | |
172 uint32_t maxPayloadSize) { | |
173 DCHECK(!encoded_video_source_client_); | |
174 if (codecSettings->codecType != rtc_codec_type_) | |
175 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
176 | |
177 // Convert |codecSettings| to |params|. | |
178 media::VideoEncodingParameters params; | |
179 params.codec_name = codecSettings->plName; | |
180 params.resolution = gfx::Size(codecSettings->width, codecSettings->height); | |
181 params.runtime_params.target_bitrate = codecSettings->startBitrate; | |
182 params.runtime_params.max_bitrate = codecSettings->maxBitrate; | |
183 params.runtime_params.frames_per_second = codecSettings->maxFramerate; | |
184 encoded_video_source_client_.reset(new EncodedVideoSourceClient( | |
185 encoded_video_source_, params, rtc_codec_type_)); | |
186 return WEBRTC_VIDEO_CODEC_OK; | |
187 } | |
188 | |
189 int32_t RtcEncodingVideoCapturer::Encode( | |
190 const webrtc::I420VideoFrame& /* inputImage */, | |
191 const webrtc::CodecSpecificInfo* codecSpecificInfo, | |
192 const std::vector<webrtc::VideoFrameType>* frame_types) { | |
193 // TODO(hshi): request specific frame type. | |
194 return WEBRTC_VIDEO_CODEC_OK; | |
195 } | |
196 | |
197 int32_t RtcEncodingVideoCapturer::RegisterEncodeCompleteCallback( | |
198 webrtc::EncodedImageCallback* callback) { | |
199 DCHECK(encoded_video_source_client_); | |
200 encoded_video_source_client_->set_callback(callback); | |
201 return WEBRTC_VIDEO_CODEC_OK; | |
202 } | |
203 | |
204 int32_t RtcEncodingVideoCapturer::Release() { | |
205 DCHECK(encoded_video_source_client_); | |
206 encoded_video_source_client_.reset(NULL); | |
207 return WEBRTC_VIDEO_CODEC_OK; | |
208 } | |
209 | |
210 int32_t RtcEncodingVideoCapturer::SetChannelParameters( | |
211 uint32_t /* packetLoss */, | |
212 int rtt_in_ms) { | |
213 if (!encoded_video_source_client_) | |
214 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
215 encoded_video_source_client_->set_round_trip_time( | |
216 base::TimeDelta::FromMilliseconds(rtt_in_ms)); | |
217 return WEBRTC_VIDEO_CODEC_OK; | |
218 } | |
219 | |
220 int32_t RtcEncodingVideoCapturer::SetRates(uint32_t newBitRate, | |
221 uint32_t frameRate) { | |
222 if (!encoded_video_source_client_) | |
223 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
224 // TODO(hshi): wire up runtime rate control. | |
225 return WEBRTC_VIDEO_CODEC_OK; | |
226 } | |
227 | |
228 } // namespace content | |
OLD | NEW |