Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1400)

Side by Side Diff: media/cast/video_sender/codecs/vp8/vp8_encoder.cc

Issue 138953009: Cast: Fix threading issues in VideoEncoderImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: bad merge now fixed Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 10 matching lines...) Expand all
21 21
22 Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config, 22 Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config,
23 uint8 max_unacked_frames) 23 uint8 max_unacked_frames)
24 : cast_config_(video_config), 24 : cast_config_(video_config),
25 use_multiple_video_buffers_( 25 use_multiple_video_buffers_(
26 cast_config_.max_number_of_video_buffers_used == 26 cast_config_.max_number_of_video_buffers_used ==
27 kNumberOfVp8VideoBuffers), 27 kNumberOfVp8VideoBuffers),
28 max_number_of_repeated_buffers_in_a_row_( 28 max_number_of_repeated_buffers_in_a_row_(
29 (max_unacked_frames > kNumberOfVp8VideoBuffers) ? 29 (max_unacked_frames > kNumberOfVp8VideoBuffers) ?
30 ((max_unacked_frames - 1) / kNumberOfVp8VideoBuffers) : 0), 30 ((max_unacked_frames - 1) / kNumberOfVp8VideoBuffers) : 0),
31 config_(new vpx_codec_enc_cfg_t()),
32 encoder_(new vpx_codec_ctx_t()),
33 // Creating a wrapper to the image - setting image data to NULL. Actual
34 // pointer will be set during encode. Setting align to 1, as it is
35 // meaningless (actual memory is not allocated).
36 raw_image_(vpx_img_wrap(NULL, IMG_FMT_I420, video_config.width,
37 video_config.height, 1, NULL)),
38 key_frame_requested_(true), 31 key_frame_requested_(true),
39 timestamp_(0), 32 timestamp_(0),
40 last_encoded_frame_id_(kStartFrameId), 33 last_encoded_frame_id_(kStartFrameId),
41 number_of_repeated_buffers_(0) { 34 number_of_repeated_buffers_(0) {
42 // TODO(pwestin): we need to figure out how to synchronize the acking with the 35 // TODO(pwestin): we need to figure out how to synchronize the acking with the
43 // internal state of the encoder, ideally the encoder will tell if we can 36 // internal state of the encoder, ideally the encoder will tell if we can
44 // send another frame. 37 // send another frame.
45 DCHECK(!use_multiple_video_buffers_ || 38 DCHECK(!use_multiple_video_buffers_ ||
46 max_number_of_repeated_buffers_in_a_row_ == 0) << "Invalid config"; 39 max_number_of_repeated_buffers_in_a_row_ == 0) << "Invalid config";
47 40
48 // VP8 have 3 buffers available for prediction, with 41 // VP8 have 3 buffers available for prediction, with
49 // max_number_of_video_buffers_used set to 1 we maximize the coding efficiency 42 // max_number_of_video_buffers_used set to 1 we maximize the coding efficiency
50 // however in this mode we can not skip frames in the receiver to catch up 43 // however in this mode we can not skip frames in the receiver to catch up
51 // after a temporary network outage; with max_number_of_video_buffers_used 44 // after a temporary network outage; with max_number_of_video_buffers_used
52 // set to 3 we allow 2 frames to be skipped by the receiver without error 45 // set to 3 we allow 2 frames to be skipped by the receiver without error
53 // propagation. 46 // propagation.
54 DCHECK(cast_config_.max_number_of_video_buffers_used == 1 || 47 DCHECK(cast_config_.max_number_of_video_buffers_used == 1 ||
55 cast_config_.max_number_of_video_buffers_used == 48 cast_config_.max_number_of_video_buffers_used ==
56 kNumberOfVp8VideoBuffers) << "Invalid argument"; 49 kNumberOfVp8VideoBuffers) << "Invalid argument";
57 50
58 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { 51 thread_checker_.DetachFromThread();
59 acked_frame_buffers_[i] = true;
60 used_buffers_frame_id_[i] = kStartFrameId;
61 }
62 InitEncode(video_config.number_of_cores);
63 } 52 }
64 53
65 Vp8Encoder::~Vp8Encoder() { 54 Vp8Encoder::~Vp8Encoder() {
66 vpx_codec_destroy(encoder_.get()); 55 vpx_codec_destroy(encoder_.get());
67 vpx_img_free(raw_image_); 56 vpx_img_free(raw_image_);
68 } 57 }
69 58
59 void Vp8Encoder::Initialize() {
60 DCHECK(thread_checker_.CalledOnValidThread());
61 config_.reset(new vpx_codec_enc_cfg_t());
62 encoder_.reset(new vpx_codec_ctx_t());
63
64 // Creating a wrapper to the image - setting image data to NULL. Actual
65 // pointer will be set during encode. Setting align to 1, as it is
66 // meaningless (actual memory is not allocated).
67 raw_image_ = vpx_img_wrap(NULL, IMG_FMT_I420, cast_config_.width,
68 cast_config_.height, 1, NULL);
69
70 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) {
71 acked_frame_buffers_[i] = true;
72 used_buffers_frame_id_[i] = kStartFrameId;
73 }
74 InitEncode(cast_config_.number_of_cores);
75 }
76
70 void Vp8Encoder::InitEncode(int number_of_cores) { 77 void Vp8Encoder::InitEncode(int number_of_cores) {
78 DCHECK(thread_checker_.CalledOnValidThread());
71 // Populate encoder configuration with default values. 79 // Populate encoder configuration with default values.
72 if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), config_.get(), 0)) { 80 if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), config_.get(), 0)) {
73 DCHECK(false) << "Invalid return value"; 81 DCHECK(false) << "Invalid return value";
74 } 82 }
75 config_->g_w = cast_config_.width; 83 config_->g_w = cast_config_.width;
76 config_->g_h = cast_config_.height; 84 config_->g_h = cast_config_.height;
77 config_->rc_target_bitrate = cast_config_.start_bitrate / 1000; // In kbit/s. 85 config_->rc_target_bitrate = cast_config_.start_bitrate / 1000; // In kbit/s.
78 86
79 // Setting the codec time base. 87 // Setting the codec time base.
80 config_->g_timebase.num = 1; 88 config_->g_timebase.num = 1;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 } 130 }
123 vpx_codec_control(encoder_.get(), VP8E_SET_STATIC_THRESHOLD, 1); 131 vpx_codec_control(encoder_.get(), VP8E_SET_STATIC_THRESHOLD, 1);
124 vpx_codec_control(encoder_.get(), VP8E_SET_NOISE_SENSITIVITY, 0); 132 vpx_codec_control(encoder_.get(), VP8E_SET_NOISE_SENSITIVITY, 0);
125 vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, -6); 133 vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, -6);
126 vpx_codec_control(encoder_.get(), VP8E_SET_MAX_INTRA_BITRATE_PCT, 134 vpx_codec_control(encoder_.get(), VP8E_SET_MAX_INTRA_BITRATE_PCT,
127 rc_max_intra_target); 135 rc_max_intra_target);
128 } 136 }
129 137
130 bool Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, 138 bool Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame,
131 transport::EncodedVideoFrame* encoded_image) { 139 transport::EncodedVideoFrame* encoded_image) {
140 DCHECK(thread_checker_.CalledOnValidThread());
132 // Image in vpx_image_t format. 141 // Image in vpx_image_t format.
133 // Input image is const. VP8's raw image is not defined as const. 142 // Input image is const. VP8's raw image is not defined as const.
134 raw_image_->planes[PLANE_Y] = 143 raw_image_->planes[PLANE_Y] =
135 const_cast<uint8*>(video_frame->data(VideoFrame::kYPlane)); 144 const_cast<uint8*>(video_frame->data(VideoFrame::kYPlane));
136 raw_image_->planes[PLANE_U] = 145 raw_image_->planes[PLANE_U] =
137 const_cast<uint8*>(video_frame->data(VideoFrame::kUPlane)); 146 const_cast<uint8*>(video_frame->data(VideoFrame::kUPlane));
138 raw_image_->planes[PLANE_V] = 147 raw_image_->planes[PLANE_V] =
139 const_cast<uint8*>(video_frame->data(VideoFrame::kVPlane)); 148 const_cast<uint8*>(video_frame->data(VideoFrame::kVPlane));
140 149
141 raw_image_->stride[VPX_PLANE_Y] = video_frame->stride(VideoFrame::kYPlane); 150 raw_image_->stride[VPX_PLANE_Y] = video_frame->stride(VideoFrame::kYPlane);
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 case kNoBuffer: 336 case kNoBuffer:
328 *flags |= VP8_EFLAG_NO_UPD_ARF; 337 *flags |= VP8_EFLAG_NO_UPD_ARF;
329 *flags |= VP8_EFLAG_NO_UPD_GF; 338 *flags |= VP8_EFLAG_NO_UPD_GF;
330 *flags |= VP8_EFLAG_NO_UPD_LAST; 339 *flags |= VP8_EFLAG_NO_UPD_LAST;
331 *flags |= VP8_EFLAG_NO_UPD_ENTROPY; 340 *flags |= VP8_EFLAG_NO_UPD_ENTROPY;
332 break; 341 break;
333 } 342 }
334 } 343 }
335 344
336 void Vp8Encoder::UpdateRates(uint32 new_bitrate) { 345 void Vp8Encoder::UpdateRates(uint32 new_bitrate) {
346 DCHECK(thread_checker_.CalledOnValidThread());
337 uint32 new_bitrate_kbit = new_bitrate / 1000; 347 uint32 new_bitrate_kbit = new_bitrate / 1000;
338 if (config_->rc_target_bitrate == new_bitrate_kbit) return; 348 if (config_->rc_target_bitrate == new_bitrate_kbit) return;
339 349
340 config_->rc_target_bitrate = new_bitrate_kbit; 350 config_->rc_target_bitrate = new_bitrate_kbit;
341 351
342 // Update encoder context. 352 // Update encoder context.
343 if (vpx_codec_enc_config_set(encoder_.get(), config_.get())) { 353 if (vpx_codec_enc_config_set(encoder_.get(), config_.get())) {
344 DCHECK(false) << "Invalid return value"; 354 DCHECK(false) << "Invalid return value";
345 } 355 }
346 } 356 }
347 357
348 void Vp8Encoder::LatestFrameIdToReference(uint32 frame_id) { 358 void Vp8Encoder::LatestFrameIdToReference(uint32 frame_id) {
359 DCHECK(thread_checker_.CalledOnValidThread());
349 if (!use_multiple_video_buffers_) return; 360 if (!use_multiple_video_buffers_) return;
350 361
351 VLOG(1) << "VP8 ok to reference frame:" << static_cast<int>(frame_id); 362 VLOG(1) << "VP8 ok to reference frame:" << static_cast<int>(frame_id);
352 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { 363 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) {
353 if (frame_id == used_buffers_frame_id_[i]) { 364 if (frame_id == used_buffers_frame_id_[i]) {
354 acked_frame_buffers_[i] = true; 365 acked_frame_buffers_[i] = true;
355 } 366 }
356 } 367 }
357 } 368 }
358 369
359 void Vp8Encoder::GenerateKeyFrame() { 370 void Vp8Encoder::GenerateKeyFrame() {
371 DCHECK(thread_checker_.CalledOnValidThread());
360 key_frame_requested_ = true; 372 key_frame_requested_ = true;
361 } 373 }
362 374
363 // Calculate the max size of the key frame relative to a normal delta frame. 375 // Calculate the max size of the key frame relative to a normal delta frame.
364 uint32 Vp8Encoder::MaxIntraTarget(uint32 optimal_buffer_size_ms) const { 376 uint32 Vp8Encoder::MaxIntraTarget(uint32 optimal_buffer_size_ms) const {
365 // Set max to the optimal buffer level (normalized by target BR), 377 // Set max to the optimal buffer level (normalized by target BR),
366 // and scaled by a scale_parameter. 378 // and scaled by a scale_parameter.
367 // Max target size = scalePar * optimalBufferSize * targetBR[Kbps]. 379 // Max target size = scalePar * optimalBufferSize * targetBR[Kbps].
368 // This values is presented in percentage of perFrameBw: 380 // This values is presented in percentage of perFrameBw:
369 // perFrameBw = targetBR[Kbps] * 1000 / frameRate. 381 // perFrameBw = targetBR[Kbps] * 1000 / frameRate.
370 // The target in % is as follows: 382 // The target in % is as follows:
371 383
372 float scale_parameter = 0.5; 384 float scale_parameter = 0.5;
373 uint32 target_pct = optimal_buffer_size_ms * scale_parameter * 385 uint32 target_pct = optimal_buffer_size_ms * scale_parameter *
374 cast_config_.max_frame_rate / 10; 386 cast_config_.max_frame_rate / 10;
375 387
376 // Don't go below 3 times the per frame bandwidth. 388 // Don't go below 3 times the per frame bandwidth.
377 return std::max(target_pct, kMinIntra); 389 return std::max(target_pct, kMinIntra);
378 } 390 }
379 391
380 } // namespace cast 392 } // namespace cast
381 } // namespace media 393 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/video_sender/codecs/vp8/vp8_encoder.h ('k') | media/cast/video_sender/video_encoder_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698