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 "media/cast/video_sender/video_encoder.h" | 5 #include "media/cast/video_sender/video_encoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
| 9 #include "base/callback.h" |
8 #include "base/logging.h" | 10 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
10 #include "media/base/video_frame.h" | 12 #include "media/base/video_frame.h" |
11 #include "media/cast/cast_defines.h" | 13 #include "media/cast/cast_defines.h" |
12 #include "media/cast/video_sender/video_encoder_impl.h" | 14 #include "media/cast/video_sender/video_encoder_impl.h" |
13 | 15 |
14 namespace media { | 16 namespace media { |
15 namespace cast { | 17 namespace cast { |
16 | 18 |
| 19 namespace { |
| 20 |
| 21 typedef base::Callback<void(Vp8Encoder*)> PassEncoderCallback; |
| 22 |
17 void LogFrameEncodedEvent(const base::TimeTicks& now, | 23 void LogFrameEncodedEvent(const base::TimeTicks& now, |
18 CastEnvironment* const cast_environment, | 24 scoped_refptr<CastEnvironment> cast_environment, |
19 const base::TimeTicks& capture_time) { | 25 const base::TimeTicks& capture_time) { |
| 26 DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN)); |
20 cast_environment->Logging()->InsertFrameEvent(now, kVideoFrameEncoded, | 27 cast_environment->Logging()->InsertFrameEvent(now, kVideoFrameEncoded, |
21 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); | 28 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); |
22 } | 29 } |
23 | 30 |
| 31 void InitializeVp8EncoderOnEncoderThread( |
| 32 const scoped_refptr<CastEnvironment>& environment, |
| 33 Vp8Encoder* vp8_encoder) { |
| 34 DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO_ENCODER)); |
| 35 vp8_encoder->Initialize(); |
| 36 } |
| 37 |
| 38 void EncodeVideoFrameOnEncoderThread( |
| 39 scoped_refptr<CastEnvironment> environment, |
| 40 Vp8Encoder* vp8_encoder, |
| 41 const scoped_refptr<media::VideoFrame>& video_frame, |
| 42 const base::TimeTicks& capture_time, |
| 43 const VideoEncoderImpl::CodecDynamicConfig& dynamic_config, |
| 44 const VideoEncoderImpl::FrameEncodedCallback& frame_encoded_callback) { |
| 45 DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO_ENCODER)); |
| 46 if (dynamic_config.key_frame_requested) { |
| 47 vp8_encoder->GenerateKeyFrame(); |
| 48 } |
| 49 vp8_encoder->LatestFrameIdToReference( |
| 50 dynamic_config.latest_frame_id_to_reference); |
| 51 vp8_encoder->UpdateRates(dynamic_config.bit_rate); |
| 52 |
| 53 scoped_ptr<transport::EncodedVideoFrame> encoded_frame( |
| 54 new transport::EncodedVideoFrame()); |
| 55 bool retval = vp8_encoder->Encode(video_frame, encoded_frame.get()); |
| 56 |
| 57 base::TimeTicks now = environment->Clock()->NowTicks(); |
| 58 environment->PostTask( |
| 59 CastEnvironment::MAIN, FROM_HERE, |
| 60 base::Bind(LogFrameEncodedEvent, now, environment, capture_time)); |
| 61 |
| 62 if (!retval) { |
| 63 VLOG(1) << "Encoding failed"; |
| 64 return; |
| 65 } |
| 66 if (encoded_frame->data.size() <= 0) { |
| 67 VLOG(1) << "Encoding resulted in an empty frame"; |
| 68 return; |
| 69 } |
| 70 environment->PostTask( |
| 71 CastEnvironment::MAIN, FROM_HERE, |
| 72 base::Bind( |
| 73 frame_encoded_callback, |
| 74 base::Passed(&encoded_frame), |
| 75 capture_time)); |
| 76 } |
| 77 |
| 78 } // namespace |
| 79 |
24 VideoEncoderImpl::VideoEncoderImpl( | 80 VideoEncoderImpl::VideoEncoderImpl( |
25 scoped_refptr<CastEnvironment> cast_environment, | 81 scoped_refptr<CastEnvironment> cast_environment, |
26 const VideoSenderConfig& video_config, | 82 const VideoSenderConfig& video_config, |
27 uint8 max_unacked_frames) | 83 uint8 max_unacked_frames) |
28 : video_config_(video_config), | 84 : video_config_(video_config), |
29 cast_environment_(cast_environment), | 85 cast_environment_(cast_environment), |
30 skip_next_frame_(false), | 86 skip_next_frame_(false), |
31 skip_count_(0) { | 87 skip_count_(0) { |
32 if (video_config.codec == transport::kVp8) { | 88 if (video_config.codec == transport::kVp8) { |
33 vp8_encoder_.reset(new Vp8Encoder(video_config, max_unacked_frames)); | 89 vp8_encoder_.reset(new Vp8Encoder(video_config, max_unacked_frames)); |
| 90 cast_environment_->PostTask( |
| 91 CastEnvironment::VIDEO_ENCODER, FROM_HERE, |
| 92 base::Bind( |
| 93 &InitializeVp8EncoderOnEncoderThread, |
| 94 cast_environment, |
| 95 vp8_encoder_.get())); |
34 } else { | 96 } else { |
35 DCHECK(false) << "Invalid config"; // Codec not supported. | 97 DCHECK(false) << "Invalid config"; // Codec not supported. |
36 } | 98 } |
37 | 99 |
38 dynamic_config_.key_frame_requested = false; | 100 dynamic_config_.key_frame_requested = false; |
39 dynamic_config_.latest_frame_id_to_reference = kStartFrameId; | 101 dynamic_config_.latest_frame_id_to_reference = kStartFrameId; |
40 dynamic_config_.bit_rate = video_config.start_bitrate; | 102 dynamic_config_.bit_rate = video_config.start_bitrate; |
41 } | 103 } |
42 | 104 |
43 VideoEncoderImpl::~VideoEncoderImpl() {} | 105 VideoEncoderImpl::~VideoEncoderImpl() { |
| 106 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 107 if (vp8_encoder_) { |
| 108 cast_environment_->PostTask( |
| 109 CastEnvironment::VIDEO_ENCODER, FROM_HERE, |
| 110 base::Bind(&base::DeletePointer<Vp8Encoder>, vp8_encoder_.release())); |
| 111 } |
| 112 } |
44 | 113 |
45 bool VideoEncoderImpl::EncodeVideoFrame( | 114 bool VideoEncoderImpl::EncodeVideoFrame( |
46 const scoped_refptr<media::VideoFrame>& video_frame, | 115 const scoped_refptr<media::VideoFrame>& video_frame, |
47 const base::TimeTicks& capture_time, | 116 const base::TimeTicks& capture_time, |
48 const FrameEncodedCallback& frame_encoded_callback) { | 117 const FrameEncodedCallback& frame_encoded_callback) { |
49 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 118 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
50 if (video_config_.codec != transport::kVp8) return false; | 119 if (video_config_.codec != transport::kVp8) return false; |
51 | 120 |
52 if (skip_next_frame_) { | 121 if (skip_next_frame_) { |
53 ++skip_count_; | 122 ++skip_count_; |
54 skip_next_frame_ = false; | 123 skip_next_frame_ = false; |
55 VLOG(1) << "Skip encoding frame"; | 124 VLOG(1) << "Skip encoding frame"; |
56 return false; | 125 return false; |
57 } | 126 } |
58 | 127 |
59 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 128 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
60 cast_environment_->Logging()->InsertFrameEvent(now, kVideoFrameSentToEncoder, | 129 cast_environment_->Logging()->InsertFrameEvent(now, kVideoFrameSentToEncoder, |
61 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); | 130 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); |
62 cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER, FROM_HERE, | 131 cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER, FROM_HERE, |
63 base::Bind(&VideoEncoderImpl::EncodeVideoFrameEncoderThread, | 132 base::Bind(&EncodeVideoFrameOnEncoderThread, |
64 base::Unretained(this), video_frame, capture_time, | 133 cast_environment_, |
65 dynamic_config_, frame_encoded_callback)); | 134 vp8_encoder_.get(), |
| 135 video_frame, |
| 136 capture_time, |
| 137 dynamic_config_, |
| 138 frame_encoded_callback)); |
66 | 139 |
67 dynamic_config_.key_frame_requested = false; | 140 dynamic_config_.key_frame_requested = false; |
68 return true; | 141 return true; |
69 } | 142 } |
70 | 143 |
71 void VideoEncoderImpl::EncodeVideoFrameEncoderThread( | |
72 const scoped_refptr<media::VideoFrame>& video_frame, | |
73 const base::TimeTicks& capture_time, | |
74 const CodecDynamicConfig& dynamic_config, | |
75 const FrameEncodedCallback& frame_encoded_callback) { | |
76 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_ENCODER)); | |
77 if (dynamic_config.key_frame_requested) { | |
78 vp8_encoder_->GenerateKeyFrame(); | |
79 } | |
80 vp8_encoder_->LatestFrameIdToReference( | |
81 dynamic_config.latest_frame_id_to_reference); | |
82 vp8_encoder_->UpdateRates(dynamic_config.bit_rate); | |
83 | |
84 scoped_ptr<transport::EncodedVideoFrame> encoded_frame( | |
85 new transport::EncodedVideoFrame()); | |
86 bool retval = vp8_encoder_->Encode(video_frame, encoded_frame.get()); | |
87 | |
88 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | |
89 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | |
90 base::Bind(LogFrameEncodedEvent, now, cast_environment_, capture_time)); | |
91 | |
92 if (!retval) { | |
93 VLOG(1) << "Encoding failed"; | |
94 return; | |
95 } | |
96 if (encoded_frame->data.size() <= 0) { | |
97 VLOG(1) << "Encoding resulted in an empty frame"; | |
98 return; | |
99 } | |
100 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | |
101 base::Bind(frame_encoded_callback, | |
102 base::Passed(&encoded_frame), capture_time)); | |
103 } | |
104 | |
105 // Inform the encoder about the new target bit rate. | 144 // Inform the encoder about the new target bit rate. |
106 void VideoEncoderImpl::SetBitRate(int new_bit_rate) { | 145 void VideoEncoderImpl::SetBitRate(int new_bit_rate) { |
107 dynamic_config_.bit_rate = new_bit_rate; | 146 dynamic_config_.bit_rate = new_bit_rate; |
108 } | 147 } |
109 | 148 |
110 // Inform the encoder to not encode the next frame. | 149 // Inform the encoder to not encode the next frame. |
111 void VideoEncoderImpl::SkipNextFrame(bool skip_next_frame) { | 150 void VideoEncoderImpl::SkipNextFrame(bool skip_next_frame) { |
112 skip_next_frame_ = skip_next_frame; | 151 skip_next_frame_ = skip_next_frame; |
113 } | 152 } |
114 | 153 |
115 // Inform the encoder to encode the next frame as a key frame. | 154 // Inform the encoder to encode the next frame as a key frame. |
116 void VideoEncoderImpl::GenerateKeyFrame() { | 155 void VideoEncoderImpl::GenerateKeyFrame() { |
117 dynamic_config_.key_frame_requested = true; | 156 dynamic_config_.key_frame_requested = true; |
118 } | 157 } |
119 | 158 |
120 // Inform the encoder to only reference frames older or equal to frame_id; | 159 // Inform the encoder to only reference frames older or equal to frame_id; |
121 void VideoEncoderImpl::LatestFrameIdToReference(uint32 frame_id) { | 160 void VideoEncoderImpl::LatestFrameIdToReference(uint32 frame_id) { |
122 dynamic_config_.latest_frame_id_to_reference = frame_id; | 161 dynamic_config_.latest_frame_id_to_reference = frame_id; |
123 } | 162 } |
124 | 163 |
125 int VideoEncoderImpl::NumberOfSkippedFrames() const { | 164 int VideoEncoderImpl::NumberOfSkippedFrames() const { |
126 return skip_count_; | 165 return skip_count_; |
127 } | 166 } |
128 | 167 |
129 } // namespace cast | 168 } // namespace cast |
130 } // namespace media | 169 } // namespace media |
OLD | NEW |