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
3 // found in the LICENSE file.
4 #include "media/cast/cast_sender_impl.h"
7 #include "base/callback.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/base/video_frame.h"
15 // The LocalVideoFrameInput class posts all incoming video frames to the main
16 // cast thread for processing.
17 class LocalVideoFrameInput : public VideoFrameInput {
19 LocalVideoFrameInput(scoped_refptr<CastEnvironment> cast_environment,
20 base::WeakPtr<VideoSender> video_sender)
21 : cast_environment_(cast_environment), video_sender_(video_sender) {}
23 virtual void InsertRawVideoFrame(
24 const scoped_refptr<media::VideoFrame>& video_frame,
25 const base::TimeTicks& capture_time) OVERRIDE {
26 cast_environment_->PostTask(CastEnvironment::MAIN,
28 base::Bind(&VideoSender::InsertRawVideoFrame,
35 virtual ~LocalVideoFrameInput() {}
38 friend class base::RefCountedThreadSafe<LocalVideoFrameInput>;
40 scoped_refptr<CastEnvironment> cast_environment_;
41 base::WeakPtr<VideoSender> video_sender_;
43 DISALLOW_COPY_AND_ASSIGN(LocalVideoFrameInput);
46 // The LocalAudioFrameInput class posts all incoming audio frames to the main
47 // cast thread for processing. Therefore frames can be inserted from any thread.
48 class LocalAudioFrameInput : public AudioFrameInput {
50 LocalAudioFrameInput(scoped_refptr<CastEnvironment> cast_environment,
51 base::WeakPtr<AudioSender> audio_sender)
52 : cast_environment_(cast_environment), audio_sender_(audio_sender) {}
54 virtual void InsertAudio(scoped_ptr<AudioBus> audio_bus,
55 const base::TimeTicks& recorded_time) OVERRIDE {
56 cast_environment_->PostTask(CastEnvironment::MAIN,
58 base::Bind(&AudioSender::InsertAudio,
60 base::Passed(&audio_bus),
65 virtual ~LocalAudioFrameInput() {}
68 friend class base::RefCountedThreadSafe<LocalAudioFrameInput>;
70 scoped_refptr<CastEnvironment> cast_environment_;
71 base::WeakPtr<AudioSender> audio_sender_;
73 DISALLOW_COPY_AND_ASSIGN(LocalAudioFrameInput);
76 scoped_ptr<CastSender> CastSender::Create(
77 scoped_refptr<CastEnvironment> cast_environment,
78 transport::CastTransportSender* const transport_sender) {
79 CHECK(cast_environment);
80 return scoped_ptr<CastSender>(
81 new CastSenderImpl(cast_environment, transport_sender));
84 CastSenderImpl::CastSenderImpl(
85 scoped_refptr<CastEnvironment> cast_environment,
86 transport::CastTransportSender* const transport_sender)
87 : cast_environment_(cast_environment),
88 transport_sender_(transport_sender),
90 CHECK(cast_environment);
93 void CastSenderImpl::InitializeAudio(
94 const AudioSenderConfig& audio_config,
95 const CastInitializationCallback& cast_initialization_cb) {
96 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
97 CHECK(audio_config.use_external_encoder ||
98 cast_environment_->HasAudioThread());
100 VLOG(1) << "CastSenderImpl@" << this << "::InitializeAudio()";
103 new AudioSender(cast_environment_, audio_config, transport_sender_));
105 const CastInitializationStatus status = audio_sender_->InitializationResult();
106 if (status == STATUS_AUDIO_INITIALIZED) {
107 ssrc_of_audio_sender_ = audio_config.incoming_feedback_ssrc;
109 new LocalAudioFrameInput(cast_environment_, audio_sender_->AsWeakPtr());
111 cast_initialization_cb.Run(status);
114 void CastSenderImpl::InitializeVideo(
115 const VideoSenderConfig& video_config,
116 const CastInitializationCallback& cast_initialization_cb,
117 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
118 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) {
119 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
120 CHECK(video_config.use_external_encoder ||
121 cast_environment_->HasVideoThread());
123 VLOG(1) << "CastSenderImpl@" << this << "::InitializeVideo()";
125 video_sender_.reset(new VideoSender(cast_environment_,
128 create_video_encode_mem_cb,
131 const CastInitializationStatus status = video_sender_->InitializationResult();
132 if (status == STATUS_VIDEO_INITIALIZED) {
133 ssrc_of_video_sender_ = video_config.incoming_feedback_ssrc;
135 new LocalVideoFrameInput(cast_environment_, video_sender_->AsWeakPtr());
137 cast_initialization_cb.Run(status);
140 CastSenderImpl::~CastSenderImpl() {
141 VLOG(1) << "CastSenderImpl@" << this << "::~CastSenderImpl()";
144 // ReceivedPacket handle the incoming packets to the cast sender
145 // it's only expected to receive RTCP feedback packets from the remote cast
146 // receiver. The class verifies that that it is a RTCP packet and based on the
147 // SSRC of the incoming packet route the packet to the correct sender; audio or
150 // Definition of SSRC as defined in RFC 3550.
151 // Synchronization source (SSRC): The source of a stream of RTP
152 // packets, identified by a 32-bit numeric SSRC identifier carried in
153 // the RTP header so as not to be dependent upon the network address.
154 // All packets from a synchronization source form part of the same
155 // timing and sequence number space, so a receiver groups packets by
156 // synchronization source for playback. Examples of synchronization
157 // sources include the sender of a stream of packets derived from a
158 // signal source such as a microphone or a camera, or an RTP mixer
159 // (see below). A synchronization source may change its data format,
160 // e.g., audio encoding, over time. The SSRC identifier is a
161 // randomly chosen value meant to be globally unique within a
162 // particular RTP session (see Section 8). A participant need not
163 // use the same SSRC identifier for all the RTP sessions in a
164 // multimedia session; the binding of the SSRC identifiers is
165 // provided through RTCP (see Section 6.5.1). If a participant
166 // generates multiple streams in one RTP session, for example from
167 // separate video cameras, each MUST be identified as a different
169 void CastSenderImpl::ReceivedPacket(scoped_ptr<Packet> packet) {
170 DCHECK(cast_environment_);
171 size_t length = packet->size();
172 const uint8_t* data = &packet->front();
173 if (!Rtcp::IsRtcpPacket(data, length)) {
174 VLOG(1) << "CastSenderImpl@" << this << "::ReceivedPacket() -- "
175 << "Received an invalid (non-RTCP?) packet in the cast sender.";
178 uint32 ssrc_of_sender = Rtcp::GetSsrcOfSender(data, length);
179 if (ssrc_of_sender == ssrc_of_audio_sender_) {
180 if (!audio_sender_) {
184 cast_environment_->PostTask(CastEnvironment::MAIN,
186 base::Bind(&AudioSender::IncomingRtcpPacket,
187 audio_sender_->AsWeakPtr(),
188 base::Passed(&packet)));
189 } else if (ssrc_of_sender == ssrc_of_video_sender_) {
190 if (!video_sender_) {
194 cast_environment_->PostTask(CastEnvironment::MAIN,
196 base::Bind(&VideoSender::IncomingRtcpPacket,
197 video_sender_->AsWeakPtr(),
198 base::Passed(&packet)));
200 VLOG(1) << "CastSenderImpl@" << this << "::ReceivedPacket() -- "
201 << "Received a RTCP packet with a non matching sender SSRC "
206 scoped_refptr<AudioFrameInput> CastSenderImpl::audio_frame_input() {
207 return audio_frame_input_;
210 scoped_refptr<VideoFrameInput> CastSenderImpl::video_frame_input() {
211 return video_frame_input_;
214 transport::PacketReceiverCallback CastSenderImpl::packet_receiver() {
215 return base::Bind(&CastSenderImpl::ReceivedPacket,
216 weak_factory_.GetWeakPtr());