1 // Copyright 2018 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 "components/mirroring/service/rtp_stream.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/trace_event/trace_event.h"
11 #include "base/values.h"
12 #include "media/base/video_frame.h"
13 #include "media/cast/cast_config.h"
14 #include "media/cast/sender/audio_sender.h"
15 #include "media/cast/sender/video_sender.h"
16
17 using media::cast::FrameSenderConfig;
18 using media::cast::RtpPayloadType;
19
20 namespace mirroring {
21
22 namespace {
23
24 // The maximum time since the last video frame was received from the video
25 // source, before requesting refresh frames.
26 constexpr base::TimeDelta kRefreshInterval =
27 base::TimeDelta::FromMilliseconds(250);
28
29 // The maximum number of refresh video frames to request/receive. After this
30 // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made.
31 constexpr int kMaxConsecutiveRefreshFrames = 60;
32
33 } // namespace
34
VideoRtpStream(std::unique_ptr<media::cast::VideoSender> video_sender,base::WeakPtr<RtpStreamClient> client)35 VideoRtpStream::VideoRtpStream(
36 std::unique_ptr<media::cast::VideoSender> video_sender,
37 base::WeakPtr<RtpStreamClient> client)
38 : video_sender_(std::move(video_sender)),
39 client_(client),
40 consecutive_refresh_count_(0),
41 expecting_a_refresh_frame_(false) {
42 DCHECK(video_sender_);
43 DCHECK(client);
44
45 refresh_timer_.Start(FROM_HERE, kRefreshInterval,
46 base::BindRepeating(&VideoRtpStream::OnRefreshTimerFired,
47 this->AsWeakPtr()));
48 }
49
~VideoRtpStream()50 VideoRtpStream::~VideoRtpStream() {}
51
InsertVideoFrame(scoped_refptr<media::VideoFrame> video_frame)52 void VideoRtpStream::InsertVideoFrame(
53 scoped_refptr<media::VideoFrame> video_frame) {
54 DCHECK(client_);
55 if (!video_frame->metadata()->reference_time.has_value()) {
56 client_->OnError("Missing REFERENCE_TIME.");
57 return;
58 }
59
60 base::TimeTicks reference_time = *video_frame->metadata()->reference_time;
61 DCHECK(!reference_time.is_null());
62 if (expecting_a_refresh_frame_) {
63 // There is uncertainty as to whether the video frame was in response to a
64 // refresh request. However, if it was not, more video frames will soon
65 // follow, and before the refresh timer can fire again. Thus, the
66 // behavior resulting from this logic will be correct.
67 expecting_a_refresh_frame_ = false;
68 } else {
69 consecutive_refresh_count_ = 0;
70 // The following re-starts the timer, scheduling it to fire at
71 // kRefreshInterval from now.
72 refresh_timer_.Reset();
73 }
74
75 if (!(video_frame->format() == media::PIXEL_FORMAT_I420 ||
76 video_frame->format() == media::PIXEL_FORMAT_YV12 ||
77 video_frame->format() == media::PIXEL_FORMAT_I420A)) {
78 client_->OnError("Incompatible video frame format.");
79 return;
80 }
81
82 // Used by chrome/browser/media/cast_mirroring_performance_browsertest.cc
83 TRACE_EVENT_INSTANT2("cast_perf_test", "ConsumeVideoFrame",
84 TRACE_EVENT_SCOPE_THREAD, "timestamp",
85 (reference_time - base::TimeTicks()).InMicroseconds(),
86 "time_delta", video_frame->timestamp().InMicroseconds());
87
88 video_sender_->InsertRawVideoFrame(std::move(video_frame), reference_time);
89 }
90
SetTargetPlayoutDelay(base::TimeDelta playout_delay)91 void VideoRtpStream::SetTargetPlayoutDelay(base::TimeDelta playout_delay) {
92 video_sender_->SetTargetPlayoutDelay(playout_delay);
93 }
94
OnRefreshTimerFired()95 void VideoRtpStream::OnRefreshTimerFired() {
96 ++consecutive_refresh_count_;
97 if (consecutive_refresh_count_ >= kMaxConsecutiveRefreshFrames)
98 refresh_timer_.Stop(); // Stop timer until receiving a non-refresh frame.
99
100 DVLOG(1) << "CastVideoSink is requesting another refresh frame "
101 "(consecutive count="
102 << consecutive_refresh_count_ << ").";
103 expecting_a_refresh_frame_ = true;
104 client_->RequestRefreshFrame();
105 }
106
107 //------------------------------------------------------------------
108 // AudioRtpStream
109 //------------------------------------------------------------------
110
AudioRtpStream(std::unique_ptr<media::cast::AudioSender> audio_sender,base::WeakPtr<RtpStreamClient> client)111 AudioRtpStream::AudioRtpStream(
112 std::unique_ptr<media::cast::AudioSender> audio_sender,
113 base::WeakPtr<RtpStreamClient> client)
114 : audio_sender_(std::move(audio_sender)), client_(std::move(client)) {
115 DCHECK(audio_sender_);
116 DCHECK(client_);
117 }
118
~AudioRtpStream()119 AudioRtpStream::~AudioRtpStream() {}
120
InsertAudio(std::unique_ptr<media::AudioBus> audio_bus,const base::TimeTicks & capture_time)121 void AudioRtpStream::InsertAudio(std::unique_ptr<media::AudioBus> audio_bus,
122 const base::TimeTicks& capture_time) {
123 audio_sender_->InsertAudio(std::move(audio_bus), capture_time);
124 }
125
SetTargetPlayoutDelay(base::TimeDelta playout_delay)126 void AudioRtpStream::SetTargetPlayoutDelay(base::TimeDelta playout_delay) {
127 audio_sender_->SetTargetPlayoutDelay(playout_delay);
128 }
129
130 } // namespace mirroring
131