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 // TODO (pwestin): add a link to the design document describing the generic | 5 // TODO (pwestin): add a link to the design document describing the generic |
6 // protocol and the VP8 specific details. | 6 // protocol and the VP8 specific details. |
7 #include "media/cast/video_sender/codecs/vp8/vp8_encoder.h" | 7 #include "media/cast/video_sender/codecs/vp8/vp8_encoder.h" |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 return; | 128 return; |
129 } | 129 } |
130 vpx_codec_control(encoder_.get(), VP8E_SET_STATIC_THRESHOLD, 1); | 130 vpx_codec_control(encoder_.get(), VP8E_SET_STATIC_THRESHOLD, 1); |
131 vpx_codec_control(encoder_.get(), VP8E_SET_NOISE_SENSITIVITY, 0); | 131 vpx_codec_control(encoder_.get(), VP8E_SET_NOISE_SENSITIVITY, 0); |
132 vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, -6); | 132 vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, -6); |
133 vpx_codec_control( | 133 vpx_codec_control( |
134 encoder_.get(), VP8E_SET_MAX_INTRA_BITRATE_PCT, rc_max_intra_target); | 134 encoder_.get(), VP8E_SET_MAX_INTRA_BITRATE_PCT, rc_max_intra_target); |
135 } | 135 } |
136 | 136 |
137 bool Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, | 137 bool Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, |
138 transport::EncodedVideoFrame* encoded_image) { | 138 transport::EncodedFrame* encoded_image) { |
139 DCHECK(thread_checker_.CalledOnValidThread()); | 139 DCHECK(thread_checker_.CalledOnValidThread()); |
140 // Image in vpx_image_t format. | 140 // Image in vpx_image_t format. |
141 // Input image is const. VP8's raw image is not defined as const. | 141 // Input image is const. VP8's raw image is not defined as const. |
142 raw_image_->planes[PLANE_Y] = | 142 raw_image_->planes[PLANE_Y] = |
143 const_cast<uint8*>(video_frame->data(VideoFrame::kYPlane)); | 143 const_cast<uint8*>(video_frame->data(VideoFrame::kYPlane)); |
144 raw_image_->planes[PLANE_U] = | 144 raw_image_->planes[PLANE_U] = |
145 const_cast<uint8*>(video_frame->data(VideoFrame::kUPlane)); | 145 const_cast<uint8*>(video_frame->data(VideoFrame::kUPlane)); |
146 raw_image_->planes[PLANE_V] = | 146 raw_image_->planes[PLANE_V] = |
147 const_cast<uint8*>(video_frame->data(VideoFrame::kVPlane)); | 147 const_cast<uint8*>(video_frame->data(VideoFrame::kVPlane)); |
148 | 148 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 duration, | 192 duration, |
193 flags, | 193 flags, |
194 VPX_DL_REALTIME) != VPX_CODEC_OK) { | 194 VPX_DL_REALTIME) != VPX_CODEC_OK) { |
195 LOG(ERROR) << "Failed to encode for once."; | 195 LOG(ERROR) << "Failed to encode for once."; |
196 return false; | 196 return false; |
197 } | 197 } |
198 | 198 |
199 // Get encoded frame. | 199 // Get encoded frame. |
200 const vpx_codec_cx_pkt_t* pkt = NULL; | 200 const vpx_codec_cx_pkt_t* pkt = NULL; |
201 vpx_codec_iter_t iter = NULL; | 201 vpx_codec_iter_t iter = NULL; |
202 size_t total_size = 0; | 202 bool is_key_frame = false; |
203 while ((pkt = vpx_codec_get_cx_data(encoder_.get(), &iter)) != NULL) { | 203 while ((pkt = vpx_codec_get_cx_data(encoder_.get(), &iter)) != NULL) { |
204 if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { | 204 if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) |
205 total_size += pkt->data.frame.sz; | 205 continue; |
206 encoded_image->data.reserve(total_size); | 206 encoded_image->data.assign( |
207 encoded_image->data.insert( | 207 static_cast<const uint8*>(pkt->data.frame.buf), |
208 encoded_image->data.end(), | 208 static_cast<const uint8*>(pkt->data.frame.buf) + pkt->data.frame.sz); |
209 static_cast<const uint8*>(pkt->data.frame.buf), | 209 is_key_frame = !!(pkt->data.frame.flags & VPX_FRAME_IS_KEY); |
210 static_cast<const uint8*>(pkt->data.frame.buf) + pkt->data.frame.sz); | 210 break; // Done, since all data is provided in one CX_FRAME_PKT packet. |
211 if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { | |
212 encoded_image->key_frame = true; | |
213 } else { | |
214 encoded_image->key_frame = false; | |
215 } | |
216 } | |
217 } | 211 } |
218 // Don't update frame_id for zero size frames. | 212 // Don't update frame_id for zero size frames. |
219 if (total_size == 0) | 213 if (encoded_image->data.empty()) |
220 return true; | 214 return true; |
221 | 215 |
222 // Populate the encoded frame. | 216 // Populate the encoded frame. |
223 encoded_image->codec = transport::kVp8; | |
224 encoded_image->last_referenced_frame_id = latest_frame_id_to_reference; | |
225 encoded_image->frame_id = ++last_encoded_frame_id_; | 217 encoded_image->frame_id = ++last_encoded_frame_id_; |
| 218 if (is_key_frame) { |
| 219 encoded_image->dependency = transport::EncodedFrame::KEY; |
| 220 encoded_image->referenced_frame_id = encoded_image->frame_id; |
| 221 } else { |
| 222 encoded_image->dependency = transport::EncodedFrame::DEPENDENT; |
| 223 encoded_image->referenced_frame_id = latest_frame_id_to_reference; |
| 224 } |
226 | 225 |
227 VLOG(1) << "VP8 encoded frame:" << static_cast<int>(encoded_image->frame_id) | 226 DVLOG(1) << "VP8 encoded frame_id " << encoded_image->frame_id |
228 << " sized:" << total_size; | 227 << ", sized:" << encoded_image->data.size(); |
229 | 228 |
230 if (encoded_image->key_frame) { | 229 if (is_key_frame) { |
231 key_frame_requested_ = false; | 230 key_frame_requested_ = false; |
232 | 231 |
233 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { | 232 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { |
234 used_buffers_frame_id_[i] = encoded_image->frame_id; | 233 used_buffers_frame_id_[i] = encoded_image->frame_id; |
235 } | 234 } |
236 // We can pick any buffer as last_used_vp8_buffer_ since we update | 235 // We can pick any buffer as last_used_vp8_buffer_ since we update |
237 // them all. | 236 // them all. |
238 last_used_vp8_buffer_ = buffer_to_update; | 237 last_used_vp8_buffer_ = buffer_to_update; |
239 } else { | 238 } else { |
240 if (buffer_to_update != kNoBuffer) { | 239 if (buffer_to_update != kNoBuffer) { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 float scale_parameter = 0.5; | 406 float scale_parameter = 0.5; |
408 uint32 target_pct = optimal_buffer_size_ms * scale_parameter * | 407 uint32 target_pct = optimal_buffer_size_ms * scale_parameter * |
409 cast_config_.max_frame_rate / 10; | 408 cast_config_.max_frame_rate / 10; |
410 | 409 |
411 // Don't go below 3 times the per frame bandwidth. | 410 // Don't go below 3 times the per frame bandwidth. |
412 return std::max(target_pct, kMinIntra); | 411 return std::max(target_pct, kMinIntra); |
413 } | 412 } |
414 | 413 |
415 } // namespace cast | 414 } // namespace cast |
416 } // namespace media | 415 } // namespace media |
OLD | NEW |