| 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/sender/video_sender.h" | 5 #include "media/cast/sender/video_sender.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <cstring> | 9 #include <cstring> |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 // The target maximum utilization of the encoder and network resources. This is | 36 // The target maximum utilization of the encoder and network resources. This is |
| 37 // used to attenuate the actual measured utilization values in order to provide | 37 // used to attenuate the actual measured utilization values in order to provide |
| 38 // "breathing room" (i.e., to ensure there will be sufficient CPU and bandwidth | 38 // "breathing room" (i.e., to ensure there will be sufficient CPU and bandwidth |
| 39 // available to handle the occasional more-complex frames). | 39 // available to handle the occasional more-complex frames). |
| 40 const int kTargetUtilizationPercentage = 75; | 40 const int kTargetUtilizationPercentage = 75; |
| 41 | 41 |
| 42 // Extract capture begin/end timestamps from |video_frame|'s metadata and log | 42 // Extract capture begin/end timestamps from |video_frame|'s metadata and log |
| 43 // it. | 43 // it. |
| 44 void LogVideoCaptureTimestamps(CastEnvironment* cast_environment, | 44 void LogVideoCaptureTimestamps(CastEnvironment* cast_environment, |
| 45 const media::VideoFrame& video_frame, | 45 const media::VideoFrame& video_frame, |
| 46 RtpTimestamp rtp_timestamp) { | 46 RtpTimeTicks rtp_timestamp) { |
| 47 scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); | 47 scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); |
| 48 capture_begin_event->type = FRAME_CAPTURE_BEGIN; | 48 capture_begin_event->type = FRAME_CAPTURE_BEGIN; |
| 49 capture_begin_event->media_type = VIDEO_EVENT; | 49 capture_begin_event->media_type = VIDEO_EVENT; |
| 50 capture_begin_event->rtp_timestamp = rtp_timestamp; | 50 capture_begin_event->rtp_timestamp = rtp_timestamp; |
| 51 | 51 |
| 52 scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); | 52 scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); |
| 53 capture_end_event->type = FRAME_CAPTURE_END; | 53 capture_end_event->type = FRAME_CAPTURE_END; |
| 54 capture_end_event->media_type = VIDEO_EVENT; | 54 capture_end_event->media_type = VIDEO_EVENT; |
| 55 capture_end_event->rtp_timestamp = rtp_timestamp; | 55 capture_end_event->rtp_timestamp = rtp_timestamp; |
| 56 capture_end_event->width = video_frame.visible_rect().width(); | 56 capture_end_event->width = video_frame.visible_rect().width(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 void VideoSender::InsertRawVideoFrame( | 142 void VideoSender::InsertRawVideoFrame( |
| 143 const scoped_refptr<media::VideoFrame>& video_frame, | 143 const scoped_refptr<media::VideoFrame>& video_frame, |
| 144 const base::TimeTicks& reference_time) { | 144 const base::TimeTicks& reference_time) { |
| 145 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 145 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 146 | 146 |
| 147 if (!video_encoder_) { | 147 if (!video_encoder_) { |
| 148 NOTREACHED(); | 148 NOTREACHED(); |
| 149 return; | 149 return; |
| 150 } | 150 } |
| 151 | 151 |
| 152 const RtpTimestamp rtp_timestamp = | 152 const RtpTimeTicks rtp_timestamp = |
| 153 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency); | 153 RtpTimeTicks::FromTimeDelta(video_frame->timestamp(), kVideoFrequency); |
| 154 LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, | 154 LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, |
| 155 rtp_timestamp); | 155 rtp_timestamp); |
| 156 | 156 |
| 157 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 157 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 158 TRACE_EVENT_INSTANT2( | 158 TRACE_EVENT_INSTANT2( |
| 159 "cast_perf_test", "InsertRawVideoFrame", | 159 "cast_perf_test", "InsertRawVideoFrame", |
| 160 TRACE_EVENT_SCOPE_THREAD, | 160 TRACE_EVENT_SCOPE_THREAD, |
| 161 "timestamp", reference_time.ToInternalValue(), | 161 "timestamp", reference_time.ToInternalValue(), |
| 162 "rtp_timestamp", rtp_timestamp); | 162 "rtp_timestamp", rtp_timestamp.lower_32_bits()); |
| 163 | 163 |
| 164 // Drop the frame if either its RTP or reference timestamp is not an increase | 164 // Drop the frame if either its RTP or reference timestamp is not an increase |
| 165 // over the last frame's. This protects: 1) the duration calculations that | 165 // over the last frame's. This protects: 1) the duration calculations that |
| 166 // assume timestamps are monotonically non-decreasing, and 2) assumptions made | 166 // assume timestamps are monotonically non-decreasing, and 2) assumptions made |
| 167 // deeper in the implementation where each frame's RTP timestamp needs to be | 167 // deeper in the implementation where each frame's RTP timestamp needs to be |
| 168 // unique. | 168 // unique. |
| 169 if (!last_enqueued_frame_reference_time_.is_null() && | 169 if (!last_enqueued_frame_reference_time_.is_null() && |
| 170 (!IsNewerRtpTimestamp(rtp_timestamp, | 170 (rtp_timestamp <= last_enqueued_frame_rtp_timestamp_ || |
| 171 last_enqueued_frame_rtp_timestamp_) || | |
| 172 reference_time <= last_enqueued_frame_reference_time_)) { | 171 reference_time <= last_enqueued_frame_reference_time_)) { |
| 173 VLOG(1) << "Dropping video frame: RTP or reference time did not increase."; | 172 VLOG(1) << "Dropping video frame: RTP or reference time did not increase."; |
| 174 TRACE_EVENT_INSTANT2("cast.stream", "Video Frame Drop", | 173 TRACE_EVENT_INSTANT2("cast.stream", "Video Frame Drop", |
| 175 TRACE_EVENT_SCOPE_THREAD, | 174 TRACE_EVENT_SCOPE_THREAD, |
| 176 "rtp_timestamp", rtp_timestamp, | 175 "rtp_timestamp", rtp_timestamp.lower_32_bits(), |
| 177 "reason", "time did not increase"); | 176 "reason", "time did not increase"); |
| 178 return; | 177 return; |
| 179 } | 178 } |
| 180 | 179 |
| 181 // Two video frames are needed to compute the exact media duration added by | 180 // Two video frames are needed to compute the exact media duration added by |
| 182 // the next frame. If there are no frames in the encoder, compute a guess | 181 // the next frame. If there are no frames in the encoder, compute a guess |
| 183 // based on the configured |max_frame_rate_|. Any error introduced by this | 182 // based on the configured |max_frame_rate_|. Any error introduced by this |
| 184 // guess will be eliminated when |duration_in_encoder_| is updated in | 183 // guess will be eliminated when |duration_in_encoder_| is updated in |
| 185 // OnEncodedVideoFrame(). | 184 // OnEncodedVideoFrame(). |
| 186 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ? | 185 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ? |
| 187 reference_time - last_enqueued_frame_reference_time_ : | 186 reference_time - last_enqueued_frame_reference_time_ : |
| (...skipping 10 matching lines...) Expand all Loading... |
| 198 } | 197 } |
| 199 | 198 |
| 200 // Some encoder implementations have a frame window for analysis. Since we | 199 // Some encoder implementations have a frame window for analysis. Since we |
| 201 // are dropping this frame, unless we instruct the encoder to flush all the | 200 // are dropping this frame, unless we instruct the encoder to flush all the |
| 202 // frames that have been enqueued for encoding, frames_in_encoder_ and | 201 // frames that have been enqueued for encoding, frames_in_encoder_ and |
| 203 // last_enqueued_frame_reference_time_ will never be updated and we will | 202 // last_enqueued_frame_reference_time_ will never be updated and we will |
| 204 // drop every subsequent frame for the rest of the session. | 203 // drop every subsequent frame for the rest of the session. |
| 205 video_encoder_->EmitFrames(); | 204 video_encoder_->EmitFrames(); |
| 206 | 205 |
| 207 TRACE_EVENT_INSTANT2("cast.stream", "Video Frame Drop", | 206 TRACE_EVENT_INSTANT2("cast.stream", "Video Frame Drop", |
| 208 TRACE_EVENT_SCOPE_THREAD, | 207 TRACE_EVENT_SCOPE_THREAD, |
| 209 "rtp_timestamp", rtp_timestamp, | 208 "rtp_timestamp", rtp_timestamp.lower_32_bits(), |
| 210 "reason", "too much in flight"); | 209 "reason", "too much in flight"); |
| 211 return; | 210 return; |
| 212 } | 211 } |
| 213 | 212 |
| 214 if (video_frame->visible_rect().IsEmpty()) { | 213 if (video_frame->visible_rect().IsEmpty()) { |
| 215 VLOG(1) << "Rejecting empty video frame."; | 214 VLOG(1) << "Rejecting empty video frame."; |
| 216 return; | 215 return; |
| 217 } | 216 } |
| 218 | 217 |
| 219 const int bitrate = congestion_control_->GetBitrate( | 218 const int bitrate = congestion_control_->GetBitrate( |
| 220 reference_time + target_playout_delay_, target_playout_delay_, | 219 reference_time + target_playout_delay_, target_playout_delay_, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 233 video_frame.get()); | 232 video_frame.get()); |
| 234 | 233 |
| 235 if (video_encoder_->EncodeVideoFrame( | 234 if (video_encoder_->EncodeVideoFrame( |
| 236 video_frame, | 235 video_frame, |
| 237 reference_time, | 236 reference_time, |
| 238 base::Bind(&VideoSender::OnEncodedVideoFrame, | 237 base::Bind(&VideoSender::OnEncodedVideoFrame, |
| 239 weak_factory_.GetWeakPtr(), | 238 weak_factory_.GetWeakPtr(), |
| 240 video_frame, | 239 video_frame, |
| 241 bitrate))) { | 240 bitrate))) { |
| 242 TRACE_EVENT_ASYNC_BEGIN1("cast.stream", "Video Encode", video_frame.get(), | 241 TRACE_EVENT_ASYNC_BEGIN1("cast.stream", "Video Encode", video_frame.get(), |
| 243 "rtp_timestamp", rtp_timestamp); | 242 "rtp_timestamp", rtp_timestamp.lower_32_bits()); |
| 244 frames_in_encoder_++; | 243 frames_in_encoder_++; |
| 245 duration_in_encoder_ += duration_added_by_next_frame; | 244 duration_in_encoder_ += duration_added_by_next_frame; |
| 246 last_enqueued_frame_rtp_timestamp_ = rtp_timestamp; | 245 last_enqueued_frame_rtp_timestamp_ = rtp_timestamp; |
| 247 last_enqueued_frame_reference_time_ = reference_time; | 246 last_enqueued_frame_reference_time_ = reference_time; |
| 248 } else { | 247 } else { |
| 249 VLOG(1) << "Encoder rejected a frame. Skipping..."; | 248 VLOG(1) << "Encoder rejected a frame. Skipping..."; |
| 250 TRACE_EVENT_INSTANT1("cast.stream", "Video Encode Reject", | 249 TRACE_EVENT_INSTANT1("cast.stream", "Video Encode Reject", |
| 251 TRACE_EVENT_SCOPE_THREAD, | 250 TRACE_EVENT_SCOPE_THREAD, |
| 252 "rtp_timestamp", rtp_timestamp); | 251 "rtp_timestamp", rtp_timestamp.lower_32_bits()); |
| 253 } | 252 } |
| 254 } | 253 } |
| 255 | 254 |
| 256 scoped_ptr<VideoFrameFactory> VideoSender::CreateVideoFrameFactory() { | 255 scoped_ptr<VideoFrameFactory> VideoSender::CreateVideoFrameFactory() { |
| 257 return video_encoder_ ? video_encoder_->CreateVideoFrameFactory() : nullptr; | 256 return video_encoder_ ? video_encoder_->CreateVideoFrameFactory() : nullptr; |
| 258 } | 257 } |
| 259 | 258 |
| 260 int VideoSender::GetNumberOfFramesInEncoder() const { | 259 int VideoSender::GetNumberOfFramesInEncoder() const { |
| 261 return frames_in_encoder_; | 260 return frames_in_encoder_; |
| 262 } | 261 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 media::VideoFrameMetadata::RESOURCE_UTILIZATION, | 355 media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
| 357 encoded_frame->dependency == EncodedFrame::KEY ? | 356 encoded_frame->dependency == EncodedFrame::KEY ? |
| 358 std::min(1.0, attenuated_utilization) : attenuated_utilization); | 357 std::min(1.0, attenuated_utilization) : attenuated_utilization); |
| 359 } | 358 } |
| 360 | 359 |
| 361 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); | 360 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); |
| 362 } | 361 } |
| 363 | 362 |
| 364 } // namespace cast | 363 } // namespace cast |
| 365 } // namespace media | 364 } // namespace media |
| OLD | NEW |