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